A lot of work on the type system. Experimental language module.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@516 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
33c9ebbdc8
commit
765ad025b9
8 changed files with 609 additions and 96 deletions
|
|
@ -427,7 +427,8 @@ yylex1(void) {
|
|||
if (strcmp(yytext,"%apply") == 0) return(APPLY);
|
||||
if (strcmp(yytext,"%clear") == 0) return(CLEAR);
|
||||
if (strcmp(yytext,"%doconly") == 0) return(DOCONLY);
|
||||
|
||||
if (strcmp(yytext,"%map") == 0) return(MAP);
|
||||
|
||||
/* Have an unknown identifier, as a last step, we'll */
|
||||
/* do a typedef lookup on it. */
|
||||
yylval.tok.text = NewString(yytext);
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ static DOH *top = 0;
|
|||
static DOH *ATTR_TAG = 0;
|
||||
static DOH *ATTR_CHILD = 0;
|
||||
static DOH *ATTR_PARENT = 0;
|
||||
static DOH *ATTR_SIBLING = 0;
|
||||
static DOH *ATTR_NEXT = 0;
|
||||
static DOH *ATTR_PREV = 0;
|
||||
static DOH *ATTR_NAME = 0;
|
||||
static DOH *ATTR_VALUE = 0;
|
||||
static DOH *ATTR_TYPE = 0;
|
||||
|
|
@ -52,7 +53,24 @@ static DOH *TAG_VARIABLE = 0;
|
|||
o = child;
|
||||
while (o) {
|
||||
Setattr(o,ATTR_PARENT,parent);
|
||||
o = Getattr(o,ATTR_SIBLING);
|
||||
o = Getattr(o,ATTR_NEXT);
|
||||
}
|
||||
}
|
||||
|
||||
/* Create all back links so we get a doubly-linked lists */
|
||||
static void create_backlinks(DOH *top) {
|
||||
DOH *prev = 0;
|
||||
DOH *obj;
|
||||
|
||||
if (!top) return;
|
||||
obj = top;
|
||||
while (obj) {
|
||||
if (prev) {
|
||||
Setattr(obj,ATTR_PREV,prev);
|
||||
}
|
||||
create_backlinks(Getattr(obj,ATTR_CHILD));
|
||||
prev = obj;
|
||||
obj = Getattr(obj,ATTR_NEXT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,11 +79,13 @@ static DOH *TAG_VARIABLE = 0;
|
|||
int yyparse();
|
||||
DOH *tp;
|
||||
|
||||
if (!ATTR_SIBLING) {
|
||||
if (!ATTR_NEXT) {
|
||||
ATTR_PARENT = NewString("parent");
|
||||
DohIntern(ATTR_PARENT);
|
||||
ATTR_SIBLING = NewString("sibling");
|
||||
DohIntern(ATTR_SIBLING);
|
||||
ATTR_NEXT = NewString("next");
|
||||
DohIntern(ATTR_NEXT);
|
||||
ATTR_PREV = NewString("prev");
|
||||
DohIntern(ATTR_PREV);
|
||||
ATTR_CHILD = NewString("child");
|
||||
DohIntern(ATTR_CHILD);
|
||||
ATTR_TAG = NewString("tag");
|
||||
|
|
@ -76,7 +96,7 @@ static DOH *TAG_VARIABLE = 0;
|
|||
DohIntern(ATTR_VALUE);
|
||||
ATTR_TYPE = NewString("type");
|
||||
DohIntern(ATTR_TYPE);
|
||||
ATTR_PARMS = NewString("parameters");
|
||||
ATTR_PARMS = NewString("parms");
|
||||
DohIntern(ATTR_PARMS);
|
||||
ATTR_PARM = NewString("parm");
|
||||
DohIntern(ATTR_PARM);
|
||||
|
|
@ -98,6 +118,7 @@ static DOH *TAG_VARIABLE = 0;
|
|||
yyparse();
|
||||
Setattr(tp, ATTR_CHILD, top);
|
||||
setparent(tp,top);
|
||||
create_backlinks(tp);
|
||||
return tp;
|
||||
}
|
||||
|
||||
|
|
@ -114,15 +135,17 @@ static DOH *TAG_VARIABLE = 0;
|
|||
static DOH *parmstotype(DOH *parms) {
|
||||
int i, l;
|
||||
DOH *p, *r;
|
||||
r = NewString("(");
|
||||
DOHList *ty;
|
||||
|
||||
ty = NewList();
|
||||
p = parms;
|
||||
while (p) {
|
||||
Append(r,Getattr(p,ATTR_TYPE));
|
||||
p = Getattr(p,ATTR_SIBLING);
|
||||
if (p)
|
||||
Append(r,",");
|
||||
Append(ty,Getattr(p,ATTR_TYPE));
|
||||
p = Getattr(p,ATTR_NEXT);
|
||||
}
|
||||
Append(r,")");
|
||||
r = NewString("");
|
||||
SwigType_add_function(r,ty);
|
||||
Delete(ty);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
@ -212,7 +235,7 @@ static int promote(int t1, int t2) {
|
|||
%token <tok> ADDMETHODS ALPHA_MODE APPLY CHECKOUT CLEAR CONSTANT DOCONLY DOC_DISABLE DOC_ENABLE ECHO EXCEPT
|
||||
%token <tok> ILLEGAL IMPORT INCLUDE INIT INLINE LOCALSTYLE MACRO MODULE NAME NATIVE NEW PRAGMA
|
||||
%token <tok> RAW_MODE READONLY READWRITE RENAME SECTION STYLE SUBSECTION SUBSUBSECTION TEXT TITLE
|
||||
%token <tok> TYPE TYPEMAP USERDIRECTIVE WEXTERN WRAPPER
|
||||
%token <tok> TYPE TYPEMAP USERDIRECTIVE WEXTERN WRAPPER MAP
|
||||
|
||||
/* Operators */
|
||||
%left <tok> LOR
|
||||
|
|
@ -237,8 +260,8 @@ static int promote(int t1, int t2) {
|
|||
%type <tmname> tm_name
|
||||
%type <tok> tm_method
|
||||
%type <node> statement swig_directive c_declaration
|
||||
%type <node> file_include code_block doc_directive except_directive pragma_directive modifier_directive native_directive typemap_directive
|
||||
%type <node> variable_decl function_decl enum_decl typedef_decl stail edecl typedeflist
|
||||
%type <node> file_include code_block doc_directive except_directive pragma_directive modifier_directive native_directive typemap_directive map_directive
|
||||
%type <node> variable_decl function_decl enum_decl typedef_decl stail edecl typedeflist map_element
|
||||
%type <nodelist> enumlist interface
|
||||
%type <node> inherit base_list
|
||||
%type <tok> base_specifier access_specifier cpp_end ctor_end opt_id
|
||||
|
|
@ -261,21 +284,21 @@ interface : interface statement {
|
|||
o = $2;
|
||||
while (o) {
|
||||
o2 = o;
|
||||
o = Getattr(o,ATTR_SIBLING);
|
||||
o = Getattr(o,ATTR_NEXT);
|
||||
}
|
||||
$$.last = o2;
|
||||
} else {
|
||||
if ($2) {
|
||||
o = $1.last;
|
||||
if (o) {
|
||||
Setattr(o,ATTR_SIBLING,$2);
|
||||
Setattr(o,ATTR_NEXT,$2);
|
||||
} else {
|
||||
Setattr($1.node,ATTR_SIBLING,$2);
|
||||
Setattr($1.node,ATTR_NEXT,$2);
|
||||
}
|
||||
o = $2;
|
||||
while (o) {
|
||||
o2 = o;
|
||||
o = Getattr(o,ATTR_SIBLING);
|
||||
o = Getattr(o,ATTR_NEXT);
|
||||
}
|
||||
$1.last = o2;
|
||||
}
|
||||
|
|
@ -369,6 +392,7 @@ swig_directive : MODULE idstring {
|
|||
| modifier_directive { $$ = $1; }
|
||||
| native_directive { $$ = $1; }
|
||||
| typemap_directive { $$ = $1; }
|
||||
| map_directive { $$ = $1; }
|
||||
| TYPE ID idlist SEMI { $$ = 0; }
|
||||
;
|
||||
|
||||
|
|
@ -412,20 +436,20 @@ modifier_directive : READONLY { $$ = new_node("readonlydirective",$1.filename, $
|
|||
|
||||
code_block : HBLOCK {
|
||||
$$ = new_node("headerblock",$1.filename,$1.line);
|
||||
Setattr($$,"text", $1.text);
|
||||
Setattr($$,"code", $1.text);
|
||||
}
|
||||
| WRAPPER HBLOCK {
|
||||
$$ = new_node("wrapperblock",$2.filename,$2.line);
|
||||
Setattr($$,"text",$2.text);
|
||||
Setattr($$,"code",$2.text);
|
||||
}
|
||||
| INIT HBLOCK {
|
||||
$$ = new_node("initblock",$2.filename,$2.line);
|
||||
Setattr($$,"text",$2.text);
|
||||
Setattr($$,"code",$2.text);
|
||||
}
|
||||
| INLINE HBLOCK {
|
||||
DOH *pp;
|
||||
$$ = new_node("headerblock",$2.filename,$2.line);
|
||||
Setattr($$,"text", $2.text);
|
||||
Setattr($$,"code", $2.text);
|
||||
Seek($2.text,0,SEEK_SET);
|
||||
pp = Preprocessor_parse($2.text);
|
||||
Seek(pp,0,SEEK_SET);
|
||||
|
|
@ -569,7 +593,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
|
|||
Setattr(o,ATTR_PARMS,Getattr(l,ATTR_PARMS));
|
||||
if (!$$) $$ = o;
|
||||
if (prev) {
|
||||
Setattr(prev,ATTR_SIBLING,o);
|
||||
Setattr(prev,ATTR_NEXT,o);
|
||||
}
|
||||
prev = o;
|
||||
}
|
||||
|
|
@ -590,7 +614,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
|
|||
Setattr(o,ATTR_TYPE,Getattr(l,ATTR_TYPE));
|
||||
Setattr(o,ATTR_PARMS,Getattr(l,ATTR_PARMS));
|
||||
if (!$$) $$ = o;
|
||||
if (prev) Setattr(prev,ATTR_SIBLING,o);
|
||||
if (prev) Setattr(prev,ATTR_NEXT,o);
|
||||
prev = o;
|
||||
}
|
||||
}
|
||||
|
|
@ -609,7 +633,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
|
|||
Setattr(o,ATTR_NAME,Getattr(l,ATTR_NAME));
|
||||
Setattr(o,ATTR_TYPE,Getattr(l,ATTR_TYPE));
|
||||
if (!$$) $$ = o;
|
||||
if (prev) Setattr(prev,ATTR_SIBLING,o);
|
||||
if (prev) Setattr(prev,ATTR_NEXT,o);
|
||||
prev = o;
|
||||
}
|
||||
}
|
||||
|
|
@ -627,7 +651,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
|
|||
Setattr(o,ATTR_NAME,Getattr(l,ATTR_NAME));
|
||||
Setattr(o,ATTR_TYPE,Getattr(l,ATTR_TYPE));
|
||||
if (!$$) $$ = o;
|
||||
if (prev) Setattr(prev,ATTR_SIBLING,o);
|
||||
if (prev) Setattr(prev,ATTR_NEXT,o);
|
||||
prev = o;
|
||||
}
|
||||
}
|
||||
|
|
@ -649,7 +673,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
|
|||
Setattr(o,"srcname",Getattr($9,ATTR_NAME));
|
||||
Setattr(o,"srctype",Getattr($9,ATTR_TYPE));
|
||||
if (!$$) $$ = o;
|
||||
if (prev) Setattr(prev,ATTR_SIBLING,o);
|
||||
if (prev) Setattr(prev,ATTR_NEXT,o);
|
||||
prev = o;
|
||||
}
|
||||
}
|
||||
|
|
@ -670,7 +694,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE {
|
|||
Setattr(o,"srcname",Getattr($7,ATTR_NAME));
|
||||
Setattr(o,"srctype",Getattr($7,ATTR_TYPE));
|
||||
if (!$$) $$ = o;
|
||||
if (prev) Setattr(prev,ATTR_SIBLING,o);
|
||||
if (prev) Setattr(prev,ATTR_NEXT,o);
|
||||
prev = o;
|
||||
}
|
||||
}
|
||||
|
|
@ -782,6 +806,52 @@ tm_args : LPAREN parms RPAREN {
|
|||
;
|
||||
|
||||
|
||||
map_directive : MAP ID LPAREN parms RPAREN LBRACE map_element RBRACE {
|
||||
$$ = new_node("map", $1.filename, $1.line);
|
||||
Setattr($$,ATTR_NAME,$2.text);
|
||||
Setattr($$,ATTR_PARMS,$4);
|
||||
if ($7) {
|
||||
Setattr($$,ATTR_CHILD,$7);
|
||||
setparent($$,$7);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
map_element : variable_decl map_element {
|
||||
DOH *o, *o2;
|
||||
$$ = $1;
|
||||
o = $1;
|
||||
while (o) {
|
||||
o2 = o;
|
||||
o = Getattr(o,ATTR_NEXT);
|
||||
}
|
||||
Setattr(o2,ATTR_NEXT,$2);
|
||||
}
|
||||
| function_decl map_element {
|
||||
DOH *o, *o2;
|
||||
$$ = $1;
|
||||
o = $1;
|
||||
while (o) {
|
||||
o2 = o;
|
||||
o = Getattr(o,ATTR_NEXT);
|
||||
}
|
||||
Setattr(o2,ATTR_NEXT,$2);
|
||||
}
|
||||
| STRING COLON LBRACE {
|
||||
DOH *text = LParse_skip_balanced('{','}');
|
||||
$$ = new_node("mapelement",$1.filename, $1.line);
|
||||
Setattr($$,ATTR_NAME,$1.text);
|
||||
Setattr($$,"code",text);
|
||||
$1.text = $$;
|
||||
} map_element {
|
||||
$$ = $1.text;
|
||||
if ($5)
|
||||
Setattr($$,ATTR_NEXT,$5);
|
||||
}
|
||||
| empty {
|
||||
$$ = 0;
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
/* =============================================================================
|
||||
|
|
@ -812,7 +882,7 @@ variable_decl : storage_spec type declaration array2 def_args stail {
|
|||
Setattr($$,ATTR_VALUE,$5.text);
|
||||
}
|
||||
if ($6) {
|
||||
Setattr($$,ATTR_SIBLING,$6);
|
||||
Setattr($$,ATTR_NEXT,$6);
|
||||
o = $6;
|
||||
while (o) {
|
||||
t = Copy($2);
|
||||
|
|
@ -821,7 +891,7 @@ variable_decl : storage_spec type declaration array2 def_args stail {
|
|||
if ($1.ivalue) {
|
||||
Setattr(o,ATTR_STORAGE,$1.text);
|
||||
}
|
||||
o = Getattr(o,ATTR_SIBLING);
|
||||
o = Getattr(o,ATTR_NEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -850,7 +920,7 @@ function_decl : storage_spec type declaration LPAREN parms RPAREN cpp_const sta
|
|||
Setattr($$,ATTR_STORAGE, $1.text);
|
||||
}
|
||||
if ($8) {
|
||||
Setattr($$,ATTR_SIBLING,$8);
|
||||
Setattr($$,ATTR_NEXT,$8);
|
||||
o = $8;
|
||||
while (o) {
|
||||
t = Copy($2);
|
||||
|
|
@ -859,7 +929,7 @@ function_decl : storage_spec type declaration LPAREN parms RPAREN cpp_const sta
|
|||
if ($1.ivalue) {
|
||||
Setattr(o,ATTR_STORAGE,$1.text);
|
||||
}
|
||||
o = Getattr(o,ATTR_SIBLING);
|
||||
o = Getattr(o,ATTR_NEXT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -922,7 +992,7 @@ stail : SEMI { $$ = 0; }
|
|||
if ($4.text)
|
||||
Setattr($$,ATTR_VALUE,$4.text);
|
||||
if ($5)
|
||||
Setattr($$,ATTR_SIBLING, $5);
|
||||
Setattr($$,ATTR_NEXT, $5);
|
||||
}
|
||||
| COMMA declaration LPAREN parms RPAREN stail {
|
||||
DOH *t = NewString("");
|
||||
|
|
@ -932,7 +1002,7 @@ stail : SEMI { $$ = 0; }
|
|||
Setattr($$,ATTR_PARMS,$4);
|
||||
Setattr($$,ATTR_TYPE, t);
|
||||
if ($6)
|
||||
Setattr($$,ATTR_SIBLING,$6);
|
||||
Setattr($$,ATTR_NEXT,$6);
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -983,7 +1053,7 @@ enum_decl : storage_spec ENUM ename LBRACE enumlist RBRACE SEMI {
|
|||
o = new_node("typedef",$7.filename,$7.line);
|
||||
Setattr(o,ATTR_NAME,$7.text);
|
||||
Setattr(o,ATTR_TYPE,$3.text);
|
||||
Setattr($$,ATTR_SIBLING,o);
|
||||
Setattr($$,ATTR_NEXT,o);
|
||||
}
|
||||
}
|
||||
;
|
||||
|
|
@ -995,22 +1065,9 @@ ename : ID { $$ = $1; }
|
|||
;
|
||||
|
||||
enumlist : enumlist COMMA edecl {
|
||||
Setattr($1.last,ATTR_SIBLING,$3);
|
||||
Setattr($1.last,ATTR_NEXT,$3);
|
||||
$1.last = $3;
|
||||
$$ = $1;
|
||||
/*
|
||||
DOH *o;
|
||||
if ($3) {
|
||||
o = Getattr($1,LASTATTR_SIBLING);
|
||||
if (o) {
|
||||
Setattr(o,ATTR_SIBLING,$3);
|
||||
} else {
|
||||
Setattr($1,ATTR_SIBLING,$3);
|
||||
}
|
||||
Setattr($1,LASTSIBLING,$3);;
|
||||
}
|
||||
$$ = $1;
|
||||
*/
|
||||
}
|
||||
| edecl {
|
||||
$$.node = $1;
|
||||
|
|
@ -1050,7 +1107,7 @@ typedef_decl : TYPEDEF type declaration array2 typedeflist SEMI {
|
|||
SwigType_push(ty,Getattr(d,"array"));
|
||||
Setattr(o,ATTR_TYPE,ty);
|
||||
Setattr(o,ATTR_NAME,Getattr(d,ATTR_NAME));
|
||||
Setattr(prev,ATTR_SIBLING,o);
|
||||
Setattr(prev,ATTR_NEXT,o);
|
||||
prev = o;
|
||||
}
|
||||
Delete($5);
|
||||
|
|
@ -1162,7 +1219,7 @@ cpp_class : storage_spec cpptype ID inherit LBRACE interface RBRACE opt_id S
|
|||
t = Copy($3.text);
|
||||
SwigType_push(t,$8.decl);
|
||||
Setattr(o,ATTR_TYPE,t);
|
||||
Setattr($$,ATTR_SIBLING,o);
|
||||
Setattr($$,ATTR_NEXT,o);
|
||||
prev = o;
|
||||
for (i = 0; i < Len($9); i++) {
|
||||
d = Getitem($9,i);
|
||||
|
|
@ -1172,7 +1229,7 @@ cpp_class : storage_spec cpptype ID inherit LBRACE interface RBRACE opt_id S
|
|||
SwigType_push(t,Getattr(d,"array"));
|
||||
Setattr(o,ATTR_TYPE,t);
|
||||
Setattr(o,ATTR_NAME,Getattr(d,ATTR_NAME));
|
||||
Setattr(prev,ATTR_SIBLING,o);
|
||||
Setattr(prev,ATTR_NEXT,o);
|
||||
prev = o;
|
||||
}
|
||||
Delete($9);
|
||||
|
|
@ -1301,7 +1358,7 @@ cpp_other :/* A dummy class name */
|
|||
$$ = new_node("addmethods",$1.filename,$1.line);
|
||||
if ($1.text)
|
||||
Setattr($$,ATTR_NAME,$1.text);
|
||||
if ($4.node) {
|
||||
if ($4.node) {
|
||||
Setattr($$,ATTR_CHILD,$4.node);
|
||||
setparent($$,$4.node);
|
||||
}
|
||||
|
|
@ -1318,17 +1375,21 @@ opt_id : ID { $$ = $1; }
|
|||
/* -- Function parameter lists -- */
|
||||
|
||||
parms : parm ptail {
|
||||
if ($2)
|
||||
Setattr($1,ATTR_SIBLING,$2);
|
||||
$$ = $1;
|
||||
}
|
||||
if ($2) {
|
||||
Setattr($1,ATTR_NEXT,$2);
|
||||
Setattr($2,ATTR_PREV,$1);
|
||||
}
|
||||
$$ = $1;
|
||||
}
|
||||
| empty { $$ = 0; }
|
||||
;
|
||||
|
||||
ptail : COMMA parm ptail {
|
||||
if ($3)
|
||||
Setattr($2,ATTR_SIBLING,$3);
|
||||
$$ = $2;
|
||||
if ($3) {
|
||||
Setattr($2,ATTR_NEXT,$3);
|
||||
Setattr($3,ATTR_PREV,$2);
|
||||
}
|
||||
$$ = $2;
|
||||
}
|
||||
| empty { $$ = 0; }
|
||||
;
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@
|
|||
#define CPLUS_PRIVATE 2
|
||||
#define CPLUS_PROTECTED 3
|
||||
|
||||
static DOHFile *runtime = 0;
|
||||
static DOHFile *headers = 0;
|
||||
static DOHFile *wrappers = 0;
|
||||
static DOHFile *init = 0;
|
||||
|
|
@ -26,6 +27,15 @@ static DOHString *ModuleName = 0;
|
|||
static int NativeMode = 0;
|
||||
static DOHString *NewName = 0;
|
||||
static DOHHash *RenameHash = 0;
|
||||
static DOHHash *Rules = 0;
|
||||
|
||||
/* Object oriented flags */
|
||||
|
||||
static int InClass = 0;
|
||||
static DOHString *ClassType = 0;
|
||||
static DOHString *ClassName = 0;
|
||||
static DOHString *ClassRename = 0;
|
||||
static int AddMethods = 0;
|
||||
|
||||
/* -------- File inclusion directions -------- */
|
||||
|
||||
|
|
@ -76,18 +86,22 @@ emit_scope(DOH *obj, void *clientdata) {
|
|||
|
||||
|
||||
/* -------- Code blocks -------- */
|
||||
|
||||
/* %{ ... %} directive */
|
||||
static int
|
||||
emit_headerblock(DOH *obj, void *clientdata) {
|
||||
Dump(Getattr(obj,"code"),headers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* %wrapper %{ ... %} directive */
|
||||
static int
|
||||
emit_wrapperblock(DOH *obj, void *clientdata) {
|
||||
Dump(Getattr(obj,"code"),wrappers);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* %init %{ ... %} directive */
|
||||
static int
|
||||
emit_initblock(DOH *obj, void *clientdata) {
|
||||
Dump(Getattr(obj,"code"),init);
|
||||
|
|
@ -96,18 +110,121 @@ emit_initblock(DOH *obj, void *clientdata) {
|
|||
|
||||
/* ------ Basic C declarations ----- */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* function
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
emit_function(DOH *obj, void *clientdata) {
|
||||
Printf(stdout,"function\n");
|
||||
DOHString *name, *scriptname, *type, *storage;
|
||||
DOHList *parms;
|
||||
DOHHash *p;
|
||||
SwigWrapper *wf;
|
||||
int numarg = 0, numopt = 0;
|
||||
int i;
|
||||
|
||||
if (ExternMode) return 0;
|
||||
|
||||
name = Getattr(obj,"name"); /* Name of the function */
|
||||
type = Getattr(obj,"type"); /* Return type */
|
||||
parms = Getattr(obj,"parms"); /* Parameters */
|
||||
storage = Getattr(obj,"storage"); /* Storage class */
|
||||
|
||||
/* See if the function is being renamed */
|
||||
if (NewName) scriptname = NewName;
|
||||
else scriptname = name;
|
||||
|
||||
/* Is this a member function? */
|
||||
if (InClass) {
|
||||
/* Handle member functions */
|
||||
/* goto function_exit; */
|
||||
}
|
||||
|
||||
wf = NewSwigWrapper();
|
||||
/* Printf(wf->def,"void %s(args) {\n", Swig_name_wrapper(scriptname));*/
|
||||
|
||||
Printv(wf->def,
|
||||
"static PyObject *", Swig_name_wrapper(scriptname), "(PyObject *self, PyObject *args) {\n",
|
||||
0);
|
||||
|
||||
/* Mapping test */
|
||||
|
||||
{
|
||||
DOH *rules;
|
||||
int mlen = 0;
|
||||
rules = Swig_map_match(Rules,"input",parms, &mlen);
|
||||
Printf(stdout,"match(%d)\n", mlen);
|
||||
}
|
||||
|
||||
/* Loop over all of the function arguments and build pieces of the wrapper function */
|
||||
{
|
||||
DOHString *formatstr; /* Format string for parsing arguments */
|
||||
DOHString *argstr; /* List of arguments */
|
||||
formatstr = NewString("");
|
||||
argstr = NewString("");
|
||||
|
||||
for (p = parms, i=0; p; p = Swig_next(p), i++) {
|
||||
DOHString *pdecl, *pname, *ptype, *value;
|
||||
pname = NewStringf("_arg%d",i);
|
||||
|
||||
ptype = Getattr(p,"type");
|
||||
|
||||
if (SwigType_isarray(ptype)) {
|
||||
int i;
|
||||
int nd;
|
||||
nd = SwigType_array_ndim(ptype);
|
||||
for (i = 0; i < nd; i++) {
|
||||
Printf(stdout,"array[%d] = %s\n", i, SwigType_array_getdim(ptype,i));
|
||||
}
|
||||
}
|
||||
|
||||
pdecl = SwigType_cstr(ptype,pname);
|
||||
|
||||
if ((value = Getattr(p,"value"))) {
|
||||
Printf(pdecl," = %s", value);
|
||||
numopt++;
|
||||
} else {
|
||||
if (numopt > 0) {
|
||||
printf("*** Error: Non-optional argument follows optional argument!\n");
|
||||
}
|
||||
}
|
||||
SwigWrapper_add_local(wf,pdecl,pname);
|
||||
Printf(argstr,",&%s",pname);
|
||||
|
||||
Delete(pname);
|
||||
Delete(pdecl);
|
||||
}
|
||||
|
||||
Printv(wf->code,
|
||||
"if (!PyParseArgs(\"", formatstr, "\"", argstr, ")) {\n",
|
||||
"return NULL;\n",
|
||||
"}\n",
|
||||
0);
|
||||
}
|
||||
|
||||
Printf(wf->code,"}\n");
|
||||
SwigWrapper_print(wf,wrappers);
|
||||
|
||||
function_exit:
|
||||
Delete(NewName);
|
||||
NewName = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* variable
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
emit_variable(DOH *obj, void *clientdata) {
|
||||
Printf(stdout,"variable\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* constant
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static int
|
||||
emit_constant(DOH *obj, void *clientdata) {
|
||||
Printf(stdout,"constant\n");
|
||||
|
|
@ -145,7 +262,10 @@ emit_class(DOH *obj, void *clientdata) {
|
|||
Printf(stdout,"class\n");
|
||||
c = Getattr(obj, "child");
|
||||
if (c) {
|
||||
int ic = InClass;
|
||||
InClass = 1;
|
||||
Swig_emit(c,clientdata);
|
||||
InClass = ic;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -197,7 +317,7 @@ static int
|
|||
emit_moduledirective(DOH *obj, void *clientdata) {
|
||||
if (!ModuleName) {
|
||||
ModuleName = Getattr(obj,"name");
|
||||
Incref(ModuleName);
|
||||
DohIncref(ModuleName);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -228,7 +348,7 @@ static int
|
|||
emit_namedirective(DOH *obj, void *clientdata) {
|
||||
if (NewName) Delete(NewName);
|
||||
NewName = Getattr(obj,"name");
|
||||
if (NewName) Incref(NewName);
|
||||
if (NewName) DohIncref(NewName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -287,24 +407,65 @@ emit_cleardirective(DOH *obj, void *clientdata) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
emit_map(DOH *obj, void *clientdata) {
|
||||
DOH *parms;
|
||||
DOH *rulename;
|
||||
DOH *rules;
|
||||
|
||||
rulename = Getattr(obj,"name");
|
||||
parms = Getattr(obj,"parms");
|
||||
rules = Getattr(obj,"child");
|
||||
|
||||
Swig_map_add(Rules,rulename,parms,rules);
|
||||
}
|
||||
|
||||
/* -------- Entry point -------- */
|
||||
|
||||
static char *runtime_banner = "\n\
|
||||
/* ----------------------------------------------------------------------------- \n\
|
||||
Runtime\n\
|
||||
----------------------------------------------------------------------------- */\n";
|
||||
|
||||
static char *header_banner = "\n\
|
||||
/* ----------------------------------------------------------------------------- \n\
|
||||
Headers\n\
|
||||
----------------------------------------------------------------------------- */\n";
|
||||
|
||||
static char *wrapper_banner = "\n\
|
||||
/* ----------------------------------------------------------------------------- \n\
|
||||
Wrappers\n\
|
||||
----------------------------------------------------------------------------- */\n";
|
||||
|
||||
static char *init_banner = "\n\
|
||||
/* ----------------------------------------------------------------------------- \n\
|
||||
Initialization\n\
|
||||
----------------------------------------------------------------------------- */\n";
|
||||
|
||||
void test_emit(DOH *top, void *clientdata) {
|
||||
|
||||
/* Initialization */
|
||||
|
||||
headers = NewString("\n/* --- Headers --- */\n");
|
||||
wrappers = NewString("\n/* --- Wrappers --- */\n");
|
||||
init = NewString("\n/* --- Initialization --- */\n");
|
||||
runtime = NewString(runtime_banner);
|
||||
headers = NewString(header_banner);
|
||||
wrappers = NewString(wrapper_banner);
|
||||
init = NewString(init_banner);
|
||||
|
||||
Rules = NewHash();
|
||||
RenameHash = NewHash();
|
||||
|
||||
Swig_emit(top, clientdata);
|
||||
|
||||
Swig_banner(stdout);
|
||||
|
||||
/* Get the runtime library */
|
||||
Swig_insert_file("python.swg",runtime);
|
||||
|
||||
Dump(runtime,stdout);
|
||||
Dump(headers,stdout);
|
||||
Dump(wrappers,stdout);
|
||||
Dump(init, stdout);
|
||||
Delete(runtime);
|
||||
Delete(headers);
|
||||
Delete(wrappers);
|
||||
Delete(init);
|
||||
|
|
@ -345,6 +506,7 @@ static SwigRule rules[] = {
|
|||
"typemapcopy", emit_typemapcopy,
|
||||
"applydirective", emit_applydirective,
|
||||
"cleardirective", emit_cleardirective,
|
||||
"map", emit_map,
|
||||
NULL, NULL
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@
|
|||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
SRCS = naming.c tree.c stype.c scanner.c include.c getopt.c misc.c
|
||||
OBJS = naming.o tree.o stype.o scanner.o include.o getopt.o misc.o
|
||||
SRCS = map.c wrapfunc.c naming.c tree.c stype.c scanner.c include.c getopt.c misc.c
|
||||
OBJS = map.o wrapfunc.o naming.o tree.o stype.o scanner.o include.o getopt.o misc.o
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
|
|
|||
200
Source/Swig/map.c
Normal file
200
Source/Swig/map.c
Normal file
|
|
@ -0,0 +1,200 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* map.c
|
||||
*
|
||||
* This file provides support for defining %map rules that match lists of
|
||||
* parameters to objects defining code generation rules.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
*
|
||||
* Copyright (C) 1999-2000. The University of Chicago
|
||||
* See the file LICENSE for information on usage and redistribution.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
#include "swig.h"
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Synopsis
|
||||
*
|
||||
* One of the biggest problems in wrapper generation is that of defining
|
||||
* the handling of various datatypes and function parameters. This module
|
||||
* provides support for a generic object known as a 'mapping rule' that is
|
||||
* defined using the %map directive like this:
|
||||
*
|
||||
* %map rulename(typelist) {
|
||||
* vars;
|
||||
* rule1 { ... }
|
||||
* rule2 { ... }
|
||||
* rule3 { ... }
|
||||
* rule4 { ... }
|
||||
* ...
|
||||
* }
|
||||
*
|
||||
* A mapping rule is somewhat similar to a class or structure definition. The
|
||||
* "vars" field is a list of variable declarations that will be local to the
|
||||
* mapping rule when it is used. The "rulen" fields simply define code
|
||||
* fragments and other information that language specific modules can examine
|
||||
* for their own nefarious purposes.
|
||||
*
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Swig_map_add()
|
||||
*
|
||||
* Adds a new mapping rule. The parms input to this function should be a
|
||||
* properly constructed parameter list with associated attributes. The rules
|
||||
* field can technically be any valid object.
|
||||
*
|
||||
* The structure of how data is stored is as follows:
|
||||
*
|
||||
* ruleset (hash)
|
||||
* --------------
|
||||
* rulename ------> nameset (hash)
|
||||
* --------------
|
||||
* parm1 ---------> rule (hash)
|
||||
* -------------
|
||||
* parm2 -----------> rule (hash)
|
||||
* *obj* --> obj
|
||||
*
|
||||
*
|
||||
* For multiple arguments, we end up building a large tree of hash tables.
|
||||
* The object will be stored in the *obj* attribute of the last hash table.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void
|
||||
Swig_map_add(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, DOH *obj)
|
||||
{
|
||||
|
||||
DOHHash *nameset;
|
||||
DOHHash *p, *n;
|
||||
/* Locate the appropriate nameset */
|
||||
|
||||
nameset = Getattr(ruleset,rulename);
|
||||
if (!nameset) {
|
||||
/* Hmmm. First time we've seen this. Let's add it to our mapping table */
|
||||
nameset = NewHash();
|
||||
Setattr(ruleset,rulename,nameset);
|
||||
}
|
||||
|
||||
/* Now, we walk down the parms list and create a series of hash tables */
|
||||
|
||||
p = parms;
|
||||
n = nameset;
|
||||
while (p) {
|
||||
DOHString *ty, *name, *key;
|
||||
DOHHash *nn;
|
||||
ty = Getattr(p,"type");
|
||||
name = Getattr(p,"name");
|
||||
|
||||
/* Create a hash table key */
|
||||
|
||||
key = NewStringf("%s-%s",name,ty);
|
||||
|
||||
/* See if there is already a entry with this type in the table */
|
||||
nn = Getattr(n,key);
|
||||
if (!nn) {
|
||||
/* No. Go ahead and create it */
|
||||
nn = NewHash();
|
||||
Setattr(n,key,nn);
|
||||
}
|
||||
Delete(key);
|
||||
n = nn;
|
||||
p = Swig_next(p);
|
||||
}
|
||||
|
||||
/* No more parameters. At this point, n points to the very last hash table in our search.
|
||||
We'll stick our object there */
|
||||
|
||||
Setattr(n,"*obj*",obj);
|
||||
return;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Swig_map_match()
|
||||
*
|
||||
* Perform a longest map for a list of parameters and a set of mapping rules.
|
||||
* Returns the corresponding rule object and the number of parameters that
|
||||
* were matched.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
/* Internal function used for recursively searching rulesets */
|
||||
static DOH *
|
||||
Swig_map_match_internal(DOHHash *nameset, DOHHash *parms, int *nmatch) {
|
||||
DOHHash *nn1, *nn2;
|
||||
DOHString *ty;
|
||||
DOHString *name;
|
||||
DOHString *key;
|
||||
int mlen1 = 0, mlen2 = 0, bestlen = 0;
|
||||
DOH *obj1 = 0, *obj2 = 0;
|
||||
DOH *bestobj, *bestn;
|
||||
DOHHash *nextp;
|
||||
|
||||
if (!parms) {
|
||||
bestobj = Getattr(nameset,"*obj*");
|
||||
if (bestobj) *nmatch++;
|
||||
return bestobj;
|
||||
}
|
||||
|
||||
ty = Getattr(parms,"type");
|
||||
name = Getattr(parms,"name");
|
||||
key = NewStringf("%s-%s",name,ty);
|
||||
|
||||
/* See if there is an exact name match */
|
||||
nn1 = Getattr(nameset,key);
|
||||
if (nn1) {
|
||||
mlen1++;
|
||||
obj1 = Swig_map_match_internal(nn1,Swig_next(parms), &mlen1);
|
||||
}
|
||||
|
||||
/* See if there is a generic name match */
|
||||
Clear(key);
|
||||
Printf(key,"-%s",ty);
|
||||
nn2 = Getattr(nameset,key);
|
||||
if (nn2) {
|
||||
mlen2++;
|
||||
obj2 = Swig_map_match_internal(nn2, Swig_next(parms), &mlen2);
|
||||
}
|
||||
/* Pick the best match. Note: an exact name match is preferred */
|
||||
if (obj1 && obj2) {
|
||||
if (mlen2 > mlen1) {
|
||||
bestlen = mlen2;
|
||||
bestobj = obj2;
|
||||
} else {
|
||||
bestlen = mlen1;
|
||||
bestobj = obj1;
|
||||
}
|
||||
} else if (obj1) {
|
||||
bestobj = obj1;
|
||||
bestlen = mlen1;
|
||||
} else if (obj2) {
|
||||
bestobj = obj2;
|
||||
bestlen = mlen2;
|
||||
}
|
||||
if (!bestobj) {
|
||||
bestobj = Getattr(nameset,"*obj*");
|
||||
if (bestobj) bestlen = 1;
|
||||
}
|
||||
Delete(key);
|
||||
*nmatch = *nmatch + bestlen;
|
||||
return bestobj;
|
||||
}
|
||||
|
||||
DOH *
|
||||
Swig_map_match(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, int *nmatch)
|
||||
{
|
||||
DOHHash *nameset;
|
||||
int mlen = 0;
|
||||
DOH *best;
|
||||
|
||||
/* Get the nameset */
|
||||
nameset = Getattr(ruleset,rulename);
|
||||
if (!nameset) return 0;
|
||||
|
||||
best = Swig_map_match_internal(nameset,parms,&mlen);
|
||||
*nmatch = mlen;
|
||||
return best;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -418,6 +418,40 @@ DOHString *SwigType_prefix(DOHString *t) {
|
|||
return NewString("");
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SwigType_array_ndim()
|
||||
*
|
||||
* Returns the number of dimensions of an array.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
int SwigType_array_ndim(DOHString_or_char *id) {
|
||||
int ndim = 0;
|
||||
char *c = Char(id);
|
||||
|
||||
while (c && SwigType_isarray(c)) {
|
||||
c = strchr(c,'.');
|
||||
ndim++;
|
||||
}
|
||||
return ndim;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SwigType_array_getdim()
|
||||
*
|
||||
* Get the value of the nth dimension.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
DOHString *SwigType_array_getdim(DOHString_or_char *id, int n) {
|
||||
|
||||
char *c = Char(id);
|
||||
while (c && SwigType_isarray(c) && (n > 0)) {
|
||||
c = strchr(c,'.');
|
||||
n--;
|
||||
}
|
||||
if (n == 0) return SwigType_parm(c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* SwigType_cstr(DOH *s, DOH *id)
|
||||
*
|
||||
|
|
@ -705,25 +739,3 @@ int SwigType_cmp(DOHString_or_char *tpat, DOHString_or_char *type) {
|
|||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
int main() {
|
||||
DOHString *a,*b,*c,*d;
|
||||
|
||||
a = NewString("int");
|
||||
SwigType_add_pointer(a);
|
||||
|
||||
SwigType_typedef(a,"IntPtr");
|
||||
|
||||
b = NewString("IntPtr");
|
||||
SwigType_add_array(b,"1000");
|
||||
|
||||
Printf(stdout,"b = '%s'\n", b);
|
||||
c = SwigType_typedef_resolve(b);
|
||||
Printf(stdout,"c = '%s'\n", c);
|
||||
|
||||
Printf(stdout,"cmp = %d\n", SwigType_cmp("a(1000).p.p.int",b));
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -146,6 +146,8 @@ extern DOHHash *SwigType_pop_scope();
|
|||
extern DOHString *SwigType_typedef_resolve(DOHString_or_char *t);
|
||||
extern int SwigType_istypedef(DOHString_or_char *t);
|
||||
extern int SwigType_cmp(DOHString_or_char *pat, DOHString_or_char *t);
|
||||
extern int SwigType_array_ndim(DOHString_or_char *t);
|
||||
extern DOHString *SwigType_array_getdim(DOHString_or_char *t, int n);
|
||||
|
||||
/* --- Parse tree support --- */
|
||||
|
||||
|
|
@ -159,6 +161,9 @@ extern void Swig_add_rule(DOHString_or_char *, int (*action)(DOH *, void *));
|
|||
extern void Swig_add_rules(SwigRule ruleset[]);
|
||||
extern void Swig_clear_rules();
|
||||
extern int Swig_emit(DOH *obj, void *clientdata);
|
||||
extern void Swig_cut_node(DOH *obj);
|
||||
extern DOH *Swig_next(DOH *obj);
|
||||
extern DOH *Swig_prev(DOH *obj);
|
||||
|
||||
/* -- Wrapper function Object */
|
||||
|
||||
|
|
@ -186,6 +191,11 @@ extern char *Swig_name_set(DOHString_or_char *vname);
|
|||
extern char *Swig_name_construct(DOHString_or_char *classname);
|
||||
extern char *Swig_name_destroy(DOHString_or_char *classname);
|
||||
|
||||
/* --- Mapping interface --- */
|
||||
|
||||
extern void Swig_map_add(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, DOH *obj);
|
||||
extern DOH *Swig_map_match(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, int *nmatch);
|
||||
|
||||
/* --- Misc --- */
|
||||
extern char *Swig_copy_string(const char *c);
|
||||
extern void Swig_banner(DOHFile *f);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
/* -----------------------------------------------------------------------------
|
||||
* tree.c
|
||||
*
|
||||
* This file provides some general purpose functions for walking through
|
||||
* This file provides some general purpose functions for manipulating
|
||||
* parse trees.
|
||||
*
|
||||
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
||||
|
|
@ -16,6 +16,21 @@ static char cvsroot[] = "$Header$";
|
|||
|
||||
static DOHHash *rules = 0;
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Swig_next()
|
||||
* Swig_prev()
|
||||
*
|
||||
* Return next/prev node in a parse tree
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
DOH *Swig_next(DOH *obj) {
|
||||
return Getattr(obj,"next");
|
||||
}
|
||||
|
||||
DOH *Swig_prev(DOH *obj) {
|
||||
return Getattr(obj,"prev");
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Swig_dump_tags()
|
||||
*
|
||||
|
|
@ -38,7 +53,7 @@ Swig_dump_tags(DOH *obj, DOH *root) {
|
|||
Swig_dump_tags(cobj,newroot);
|
||||
Delete(newroot);
|
||||
}
|
||||
obj = Getattr(obj,"sibling");
|
||||
obj = Swig_next(obj);
|
||||
}
|
||||
if (!root)
|
||||
Delete(croot);
|
||||
|
|
@ -115,10 +130,62 @@ Swig_emit(DOH *obj, void *clientdata) {
|
|||
} else {
|
||||
Printf(stderr,"warning: no action defined for '%s'\n", tag);
|
||||
}
|
||||
obj = Getattr(obj,"sibling");
|
||||
obj = Swig_next(obj);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* Swig_cut_node(DOH *obj)
|
||||
*
|
||||
* This function cuts an object out of a parse tree. To do this, the object
|
||||
* MUST be properly initialized with "next", "prev", and "parent" attributes.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
void Swig_cut_node(DOH *obj) {
|
||||
DOH *parent;
|
||||
DOH *next;
|
||||
DOH *prev;
|
||||
|
||||
parent = Getattr(obj,"parent");
|
||||
assert(parent);
|
||||
next = Getattr(obj,"next");
|
||||
prev = Getattr(obj,"prev");
|
||||
|
||||
DohIncref(obj); /* Make sure object doesn't go away */
|
||||
Delattr(obj,"parent"); /* Disassociate from my parent */
|
||||
|
||||
if (!next && !prev) {
|
||||
/* Well, this is a single child. Guess we'll just update the parent their child is gone */
|
||||
Delattr(parent,"child");
|
||||
return;
|
||||
}
|
||||
|
||||
/* If no next node, then this must be at the end of a list */
|
||||
if (!next) {
|
||||
Delattr(prev,"next"); /* Break the 'next' link in the previous node */
|
||||
Delattr(obj,"prev"); /* Break my link back to the previous object */
|
||||
return;
|
||||
}
|
||||
|
||||
/* No previous node. This must be the beginning of a list */
|
||||
if (!prev) {
|
||||
Delattr(next,"prev"); /* Break the 'prev' link of the next node */
|
||||
Setattr(parent,"child",next); /* Update parent to point at next node */
|
||||
Delattr(obj,"next"); /* Break my link to the next object */
|
||||
return;
|
||||
}
|
||||
|
||||
/* In the middle of a list someplace */
|
||||
Setattr(prev,"next",next); /* Update previous node to my next node */
|
||||
Setattr(next,"prev",prev); /* Update next node to my previous node */
|
||||
Delattr(obj,"next");
|
||||
Delattr(obj,"prev");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue