diff --git a/Source/LParse/cscanner.c b/Source/LParse/cscanner.c index 2e1c01f50..ae10c041a 100644 --- a/Source/LParse/cscanner.c +++ b/Source/LParse/cscanner.c @@ -48,7 +48,7 @@ static int map[][2] = { { SWIG_TOKEN_BACKSLASH, -1 }, { SWIG_TOKEN_ENDLINE, -1}, { SWIG_TOKEN_STRING, STRING }, - { SWIG_TOKEN_POUND, POUND }, + { SWIG_TOKEN_POUND, -1 }, { SWIG_TOKEN_PERCENT, -1 }, { SWIG_TOKEN_COLON, COLON }, { SWIG_TOKEN_DCOLON, DCOLON }, @@ -384,7 +384,6 @@ yylex1(void) { } if (strcmp(yytext,"enum") == 0) return(ENUM); if (strcmp(yytext,"sizeof") == 0) return(SIZEOF); - if (strcmp(yytext,"defined") == 0) return(DEFINED); /* Ignored keywords */ if (strcmp(yytext,"volatile") == 0) return(lparse_yylex()); @@ -393,12 +392,9 @@ yylex1(void) { if (yytext[0] == '%') { if (strcmp(yytext,"%module") == 0) return(MODULE); if (strcmp(yytext,"%constant") == 0) return (CONSTANT); - if (strcmp(yytext,"%type") == 0) return (TYPE); if (strcmp(yytext,"%file") == 0) return(FILEDIRECTIVE); if (strcmp(yytext,"%insert") == 0) return (INSERT); if (strcmp(yytext,"%macro") == 0) return(MACRO); - if (strcmp(yytext,"%typedef") == 0) return(TYPEDEF); - if (strcmp(yytext,"%native") == 0) return(NATIVE); if (strcmp(yytext,"%pragma") == 0) return(PRAGMA); if (strcmp(yytext,"%addmethods") == 0) return(ADDMETHODS); if (strcmp(yytext,"%inline") == 0) return(INLINE); @@ -407,7 +403,7 @@ yylex1(void) { if (strcmp(yytext,"%echo") == 0) return(ECHO); if (strcmp(yytext,"%apply") == 0) return(APPLY); if (strcmp(yytext,"%clear") == 0) return(CLEAR); - if (strcmp(yytext,"%map") == 0) return(MAP); + if (strcmp(yytext,"%scope") == 0) return(SCOPE); } /* Have an unknown identifier, as a last step, we'll */ /* do a typedef lookup on it. */ diff --git a/Source/LParse/parser.y b/Source/LParse/parser.y index 820aa7f89..e7501d866 100644 --- a/Source/LParse/parser.y +++ b/Source/LParse/parser.y @@ -102,18 +102,18 @@ static DOH *TAG_VARIABLE = 0; DohIntern(ATTR_PARM); ATTR_STORAGE = NewString("storage"); DohIntern(ATTR_STORAGE); - TAG_ENUMVALUE = NewString("enumvalue"); + TAG_ENUMVALUE = NewString("c:enumvalue"); DohIntern(TAG_ENUMVALUE); - TAG_FUNCTION = NewString("function"); + TAG_FUNCTION = NewString("c:function"); DohIntern(TAG_FUNCTION); - TAG_VARIABLE = NewString("variable"); + TAG_VARIABLE = NewString("c:variable"); DohIntern(TAG_VARIABLE); } LParse_push(str); top = 0; tp = NewHash(); - Setattr(tp, "tag", "includefile"); + Setattr(tp, "tag", "swig:top"); Setattr(tp, ATTR_NAME, Getfile(str)); yyparse(); Setattr(tp, ATTR_CHILD, top); @@ -216,10 +216,10 @@ static int promote(int t1, int t2) { /* C Symbols */ -%token LPAREN RPAREN LBRACE RBRACE COMMA SEMI PERIOD LBRACKET RBRACKET EQUAL COLON POUND +%token LPAREN RPAREN LBRACE RBRACE COMMA SEMI PERIOD LBRACKET RBRACKET EQUAL COLON /* C keywords */ -%token CONST DEFINED ENUM EXTERN SIZEOF STATIC STRUCT TYPEDEF UNION +%token CONST ENUM EXTERN SIZEOF STATIC STRUCT TYPEDEF UNION /* C++ keywords */ %token CLASS FRIEND OPERATOR PRIVATE PROTECTED PUBLIC TEMPLATE THROW @@ -231,9 +231,9 @@ static int promote(int t1, int t2) { %token TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL /* SWIG directives */ -%token ADDMETHODS APPLY CLEAR CONSTANT ECHO EXCEPT -%token ILLEGAL FILEDIRECTIVE INLINE MACRO MODULE NAME NATIVE PRAGMA INSERT -%token TYPE TYPEMAP MAP +%token ADDMETHODS APPLY CLEAR CONSTANT ECHO EXCEPT SCOPE +%token ILLEGAL FILEDIRECTIVE INLINE MACRO MODULE NAME PRAGMA INSERT +%token TYPEMAP /* Operators */ %left LOR @@ -248,8 +248,8 @@ static int promote(int t1, int t2) { %left UMINUS NOT LNOT %left DCOLON -%type idstring template_decl cpptype expr definetype def_args storage_spec pragma_arg ename -%type parm parms ptail idlist stars +%type idstring template_decl cpptype expr definetype def_args storage_spec pragma_arg ename tm_code +%type parm parms ptail stars %type array array2 %type type strict_type opt_signed opt_unsigned %type declaration @@ -258,8 +258,8 @@ static int promote(int t1, int t2) { %type tm_name %type tm_method %type statement swig_directive c_declaration -%type file_include code_block except_directive pragma_directive native_directive typemap_directive map_directive -%type variable_decl function_decl enum_decl typedef_decl stail edecl typedeflist map_element +%type file_include code_block except_directive pragma_directive typemap_directive scope_directive +%type variable_decl function_decl enum_decl typedef_decl stail edecl typedeflist %type enumlist interface %type inherit base_list %type base_specifier access_specifier cpp_end ctor_end opt_id @@ -308,13 +308,6 @@ interface : interface statement { statement : swig_directive { $$ = $1; } | c_declaration { $$ = $1; } - | LBRACE interface RBRACE { - $$ = new_node("scope",$1.filename,$1.line); - if ($2.node) { - Setattr($$,ATTR_CHILD,$2.node); - setparent($$,$2.node); - } - } | SEMI { $$ = 0; } | error { $$ = 0; } ; @@ -323,7 +316,7 @@ statement : swig_directive { $$ = $1; } * -- SWIG DIRECTIVES -- * ============================================================================= */ swig_directive : MODULE idstring { - $$ = new_node("module",$1.filename,$1.line); + $$ = new_node("swig:module",$1.filename,$1.line); Setattr($$,ATTR_NAME,$2.text); } | MACRO ID COMMA STRING COMMA NUM_INT LBRACE { @@ -335,7 +328,7 @@ swig_directive : MODULE idstring { $$ = $9.node; } | CONSTANT ID definetype SEMI { - $$ = new_node("constant",$2.filename, $2.line); + $$ = new_node("swig:constant",$2.filename, $2.line); Setattr($$,ATTR_NAME,$2.text); Setattr($$,ATTR_VALUE,$3.text); switch($3.ivalue) { @@ -381,10 +374,25 @@ swig_directive : MODULE idstring { | code_block { $$ = $1; } | except_directive { $$ = $1; } | pragma_directive { $$ = $1; } - | native_directive { $$ = $1; } | typemap_directive { $$ = $1; } - | map_directive { $$ = $1; } - | TYPE ID idlist SEMI { $$ = 0; } + | scope_directive {$$ = $1; } + ; + +scope_directive: SCOPE LBRACE interface RBRACE { + $$ = new_node("swig:scope",$1.filename,$1.line); + if ($3.node) { + Setattr($$,ATTR_CHILD,$3.node); + setparent($$,$3.node); + } + } + | SCOPE LPAREN idstring RPAREN interface RBRACE { + $$ = new_node("swig:scope",$1.filename,$1.line); + if ($5.node) { + Setattr($$,ATTR_CHILD,$5.node); + Setattr($$,ATTR_NAME,$3.text); + setparent($$,$5.node); + } + } ; echo_directive: ECHO HBLOCK { Printf(stderr,"%s\n", $2.text); } @@ -394,39 +402,39 @@ echo_directive: ECHO HBLOCK { Printf(stderr,"%s\n", $2.text); } /* -- File inclusion directives -- */ file_include : FILEDIRECTIVE LPAREN STRING RPAREN STRING LBRACE { - $$ = new_node("file",$1.filename,$1.line); - Setattr($$,ATTR_NAME,$5.text); - Setattr($$,"type",$3.text); + $1.data = new_node("swig:file",$1.filename,$1.line); + Setattr($1.data,ATTR_NAME,$5.text); + Setattr($1.data,ATTR_TYPE,$3.text); LParse_set_location($5.text,0); } interface RBRACE { LParse_set_location($6.filename,$6.line + 1); + $$ = $1.data; if ($8.node) { Setattr($$,ATTR_CHILD,$8.node); setparent($$,$8.node); } } + ; /* -- Code inclusion directives -- */ code_block : INSERT LPAREN idstring RPAREN STRING { - $$ = new_node("insert", $1.filename, $1.line); + $$ = new_node("swig:insert", $1.filename, $1.line); Setattr($$,"filename", $5.text); Setattr($$,"section",$3.text); } | INSERT LPAREN idstring RPAREN HBLOCK { - $$ = new_node("insert",$1.filename, $1.line); + $$ = new_node("swig:insert",$1.filename, $1.line); Setattr($$,"section",$3.text); Setattr($$,"code",$5.text); } | HBLOCK { - $$ = new_node("insert",$1.filename, $1.line); - Setattr($$,"section","header"); + $$ = new_node("swig:insert",$1.filename, $1.line); Setattr($$,"code",$1.text); } | INLINE HBLOCK { DOH *pp; - $$ = new_node("insert",$2.filename,$2.line); - Setattr($$,"section","header"); + $$ = new_node("swig:insert",$2.filename,$2.line); Setattr($$,"code", $2.text); Seek($2.text,0,SEEK_SET); pp = Preprocessor_parse($2.text); @@ -445,80 +453,70 @@ idstring : ID { $$ = $1; } except_directive: EXCEPT LPAREN ID RPAREN LBRACE { DOH *t; t = LParse_skip_balanced('{','}'); - $$ = new_node("exception",$1.filename,$1.line); + $$ = new_node("swig:exception",$1.filename,$1.line); Setattr($$,"lang",$3.text); Setattr($$,"code",t); + LParse_error($1.filename,$1.line,"Warning. Language specifier in %except is now ignored.\n"); } -/* A Generic Exception (no language specified */ +/* A Generic Exception (no language specified) */ | EXCEPT LBRACE { DOH *t; t = LParse_skip_balanced('{','}'); - $$ = new_node("exception",$1.filename,$1.line); + $$ = new_node("swig:exception",$1.filename,$1.line); Setattr($$,"code",t); } /* Clear an exception */ | EXCEPT LPAREN ID RPAREN SEMI { - $$ = new_node("exception",$1.filename,$1.line); + $$ = new_node("swig:exception",$1.filename,$1.line); Setattr($$,"lang",$3.text); + LParse_error($1.filename,$1.line,"Warning. Language specifier in %except is now ignored.\n"); } /* Generic clear */ | EXCEPT SEMI { - $$ = new_node("exception",$1.filename,$1.line); + $$ = new_node("swig:exception",$1.filename,$1.line); } ; pragma_directive : PRAGMA idstring pragma_arg SEMI { - $$ = new_node("pragma",$1.filename,$1.line); + $$ = new_node("swig:pragma",$1.filename,$1.line); Setattr($$,ATTR_NAME,$2.text); Setattr($$,ATTR_VALUE,$3.text); } | PRAGMA LPAREN idstring RPAREN idstring pragma_arg SEMI { - $$ = new_node("pragma",$1.filename,$1.line); + $$ = new_node("swig:pragma",$1.filename,$1.line); Setattr($$,ATTR_NAME,$5.text); Setattr($$,"lang",$3.text); Setattr($$,ATTR_VALUE,$6.text); } ; -pragma_arg : definetype { +pragma_arg : idstring { $$.text = $1.text; } - | EQUAL definetype { + | EQUAL idstring { $$.text = $2.text; /* print warning message here */ } + | HBLOCK { + $$.text = $1.text; + } | empty { $$.text = 0; } ; - -/* A native wrapper function */ - -native_directive : NATIVE LBRACE interface RBRACE { - $$ = new_node("nativedirective",$1.filename,$1.line); - if ($3.node) { - Setattr($$,ATTR_CHILD,$3.node); - setparent($$,$3.node); - } - } - ; - - /* -- Typemap directives -- */ -typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE { +typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list tm_code { DOH *o, *prev = 0, *t, *l; - int i; - t = LParse_skip_balanced('{','}'); + t = $8.text; $$ = 0; - for (i = 0; i < Len($7); i++) { - l = Getitem($7,i); - o = new_node("typemap",$1.filename, $1.line); + for (l = $7; l; l = Getnext(l)) { + o = new_node("swig:typemap",$1.filename, $1.line); Setattr(o,"lang",$3.text); Setattr(o,"method",$5.text); Setattr(o,"code",t); @@ -534,14 +532,13 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE { } /* Create a new typemap in current language */ - | TYPEMAP LPAREN tm_method RPAREN tm_list LBRACE { + | TYPEMAP LPAREN tm_method RPAREN tm_list tm_code { DOH *o, *t, *l, *prev = 0; - int i; - t = LParse_skip_balanced('{','}'); + /* t = LParse_skip_balanced('{','}');*/ + t = $6.text; $$ = 0; - for (i = 0; i < Len($5); i++) { - l = Getitem($5,i); - o = new_node("typemap",$1.filename, $1.line); + for (l = $5; l; l = Getnext(l)) { + o = new_node("swig:typemap",$1.filename, $1.line); Setattr(o,"method",$3.text); Setattr(o,"code",t); Setattr(o,ATTR_NAME,Getattr(l,ATTR_NAME)); @@ -557,11 +554,9 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE { | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list SEMI { DOH *o, *l, *prev = 0; - int i; $$ = 0; - for (i = 0; i < Len($7); i++) { - l = Getitem($7,i); - o = new_node("typemap",$1.filename, $1.line); + for (l = $7; l; l = Getnext(l)) { + o = new_node("swig:typemap",$1.filename, $1.line); Setattr(o,"lang",$3.text); Setattr(o,"method",$5.text); Setattr(o,ATTR_NAME,Getattr(l,ATTR_NAME)); @@ -576,11 +571,9 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE { | TYPEMAP LPAREN tm_method RPAREN tm_list SEMI { DOH *o, *l, *prev = 0; - int i; $$ = 0; - for (i = 0; i < Len($5); i++) { - l = Getitem($5,i); - o = new_node("typemap",$1.filename, $1.line); + for (l = $5; l; l = Getnext(l)) { + o = new_node("swig:typemap",$1.filename, $1.line); Setattr(o,"method",$3.text); Setattr(o,ATTR_NAME,Getattr(l,ATTR_NAME)); Setattr(o,ATTR_TYPE,Getattr(l,ATTR_TYPE)); @@ -594,11 +587,9 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE { | TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list EQUAL tm_parm SEMI { DOH *o, *l, *prev = 0; - int i; $$ = 0; - for (i = 0; i < Len($7); i++) { - l = Getitem($7,i); - o = new_node("typemapcopy",$1.filename, $1.line); + for (l = $7; l ; l = Getnext(l)) { + o = new_node("swig:typemap",$1.filename, $1.line); Setattr(o,"method", $5.text); Setattr(o,"lang", $3.text); Setattr(o,ATTR_NAME, Getattr(l,ATTR_NAME)); @@ -616,11 +607,9 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE { | TYPEMAP LPAREN tm_method RPAREN tm_list EQUAL tm_parm SEMI { DOH *o, *l, *prev = 0; - int i; $$ = 0; - for (i = 0; i < Len($5); i++) { - l = Getitem($5,i); - o = new_node("typemapcopy",$1.filename, $1.line); + for (l = $5; l; l = Getnext(l)) { + o = new_node("swig:typemap",$1.filename, $1.line); Setattr(o,"method", $3.text); Setattr(o,ATTR_NAME, Getattr(l,ATTR_NAME)); Setattr(o,ATTR_TYPE, Getattr(l,ATTR_TYPE)); @@ -636,7 +625,7 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE { /* Apply directive */ | APPLY tm_parm LBRACE tm_list RBRACE { - $$ = new_node("applydirective",$1.filename, $1.line); + $$ = new_node("swig:apply",$1.filename, $1.line); Setattr($$,ATTR_NAME,Getattr($2,ATTR_NAME)); Setattr($$,ATTR_TYPE,Getattr($2,ATTR_TYPE)); Setattr($$,ATTR_PARMS,$4); @@ -645,11 +634,19 @@ typemap_directive: TYPEMAP LPAREN ID COMMA tm_method RPAREN tm_list LBRACE { /* Clear directive */ | CLEAR tm_list SEMI { - $$ = new_node("cleardirective",$1.filename, $1.line); + $$ = new_node("swig:clear",$1.filename, $1.line); Setattr($$,ATTR_PARMS,$2); } ; +tm_code : STRING { + $$.text = $1.text; + } + | LBRACE { + $$.text = LParse_skip_balanced('{','}'); + } + ; + tm_method : ID { $$ = $1; } @@ -660,16 +657,22 @@ tm_method : ID { tm_list : tm_parm tm_tail { - Insert($2,0,$1); - $$ = $2; + if ($2) { + Setattr($1,ATTR_NEXT,$2); + Setattr($2,ATTR_PREV,$1); + } + $$ = $1; } ; tm_tail : COMMA tm_parm tm_tail { - Insert($3,0,$2); - $$ = $3; + if ($3) { + Setattr($2,ATTR_NEXT,$3); + Setattr($3,ATTR_PREV,$2); + } + $$ = $2; } - | empty { $$ = NewList(); } + | empty { $$ = 0; } ; tm_parm : type tm_name { @@ -739,101 +742,6 @@ 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); - - /* Uh. Okay, this is a little nasty. We're going to take the - children and split them into rules and locals */ - - { - DOHHash *rules; - DOHHash *children = 0; - DOHHash *node, *nnode, *pnode; - rules = NewHash(); - - node = $7; - children = node; - pnode = 0; - while (node) { - nnode = Getattr(node,"next"); - if (Cmp(Getattr(node,"tag"),"maprule") == 0) { - Setattr(rules,Getattr(node,"name"),Getattr(node,"code")); - if (pnode) { - if (nnode) - Setattr(pnode,"next",nnode); - else - Delattr(pnode,"next"); - } else { - children = nnode; - } - Delete(node); - } else { - pnode = node; - } - node = nnode; - } - Setattr($$,"rules",rules); - if (children) { - Setattr($$,ATTR_CHILD,children); - setparent($$,children); - } - } - } - ; - -map_element : variable_decl map_element { - DOH *o, *o2 = 0; - $$ = $1; - o = $1; - while (o) { - o2 = o; - o = Getattr(o,ATTR_NEXT); - } - Setattr(o2,ATTR_NEXT,$2); - } - | function_decl map_element { - DOH *o, *o2 = 0; - $$ = $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('{','}'); - Delitem(text,0); - Delitem(text,DOH_END); - - $$ = new_node("maprule",$1.filename, $1.line); - Setattr($$,ATTR_NAME,$1.text); - Setattr($$,"code",text); - $1.text = $$; - } map_element { - $$ = $1.text; - if ($5) - Setattr($$,ATTR_NEXT,$5); - } - | STRING COLON STRING SEMI { - $$ = new_node("maprule",$1.filename, $1.line); - Setattr($$,ATTR_NAME,$1.text); - Setattr($$,"code",$3.text); - $1.text = $$; - } map_element { - $$ = $1.text; - if ($6) - Setattr($$,ATTR_NEXT,$6); - } - | empty { - $$ = 0; - } - ; - - /* ============================================================================= * -- C Declarations -- * ============================================================================= */ @@ -946,14 +854,14 @@ function_decl : storage_spec type declaration LPAREN parms RPAREN cpp_const sta /* A C++ destructor */ | NOT ID LPAREN parms RPAREN cpp_end { - $$ = new_node("destructor",$2.filename,$2.line); + $$ = new_node("c:destructor",$2.filename,$2.line); Setattr($$,ATTR_NAME,$2.text); if ($6.text) { Setattr($$,"code",$6.text); } } | NOT ID LPAREN parms RPAREN cpp_const SEMI { - $$ = new_node("destructor",$2.filename,$2.line); + $$ = new_node("c:destructor",$2.filename,$2.line); Setattr($$,ATTR_NAME,$2.text); } @@ -1013,7 +921,7 @@ cpp_const : CONST {} /* Enumerations */ enum_decl : storage_spec ENUM ename LBRACE enumlist RBRACE SEMI { - $$ = new_node("enum", $2.filename,$2.line); + $$ = new_node("c:enum", $2.filename,$2.line); Setattr($$,ATTR_NAME,$2.text); Setattr($$,ATTR_CHILD,$5.node); setparent($$,$5.node); @@ -1023,14 +931,14 @@ enum_decl : storage_spec ENUM ename LBRACE enumlist RBRACE SEMI { /* A typdef'd enum. Pretty common in C headers */ | TYPEDEF ENUM ename LBRACE enumlist RBRACE ID SEMI { - $$ = new_node("enum",$2.filename,$2.line); + $$ = new_node("c:enum",$2.filename,$2.line); Setattr($$,ATTR_NAME,$3.text); Setattr($$,ATTR_CHILD,$5.node); setparent($$,$5.node); /* Add typedef for enum */ { DOH *o; - o = new_node("typedef",$7.filename,$7.line); + o = new_node("c:typedef",$7.filename,$7.line); Setattr(o,ATTR_NAME,$7.text); Setattr(o,ATTR_TYPE,$3.text); Setattr($$,ATTR_NEXT,o); @@ -1070,7 +978,7 @@ edecl : ID { typedef_decl : TYPEDEF type declaration array2 typedeflist SEMI { DOH *t, *d, *o, *prev; int i; - $$ = new_node("typedef", $1.filename,$1.line); + $$ = new_node("c:typedef", $1.filename,$1.line); t = Copy($2); SwigType_push($2,$3.decl); if ($4) SwigType_push($2,$4); @@ -1081,7 +989,7 @@ typedef_decl : TYPEDEF type declaration array2 typedeflist SEMI { for (i = 0; i < Len($5); i++) { DOH *ty; d = Getitem($5,i); - o = new_node("typedef",$1.filename,$1.line); + o = new_node("c:typedef",$1.filename,$1.line); ty = Copy(t); SwigType_push(ty,Getattr(d,"decl")); SwigType_push(ty,Getattr(d,"array")); @@ -1096,7 +1004,7 @@ typedef_decl : TYPEDEF type declaration array2 typedeflist SEMI { /* A rudimentary typedef involving function pointers */ | TYPEDEF type LPAREN stars pname RPAREN LPAREN parms RPAREN SEMI { - $$ = new_node("typedef", $1.filename,$1.line); + $$ = new_node("c:typedef", $1.filename,$1.line); SwigType_push($2,parmstotype($8)); SwigType_push($2,$4); if ($5.array) @@ -1108,7 +1016,7 @@ typedef_decl : TYPEDEF type declaration array2 typedeflist SEMI { /* A typedef involving function pointers again */ | TYPEDEF type stars LPAREN stars pname RPAREN LPAREN parms RPAREN SEMI { - $$ = new_node("typedef", $1.filename,$1.line); + $$ = new_node("c:typedef", $1.filename,$1.line); SwigType_push($2,$3); SwigType_push($2,parmstotype($9)); SwigType_push($2,$5); @@ -1152,10 +1060,11 @@ cpp_decl : cpp_class { $$ = $1; } ; cpp_class : storage_spec cpptype ID inherit LBRACE interface RBRACE opt_id SEMI { - $$ = new_node("class",$3.filename,$3.line); + $$ = new_node("c:class",$3.filename,$3.line); Setattr($$,"classtype",$2.text); Setattr($$,ATTR_NAME,$3.text); Setattr($$,"bases", $4); + Setattr($$,"namespace",$3.text); if ($6.node) { Setattr($$,ATTR_CHILD,$6.node); setparent($$,$6.node); @@ -1166,7 +1075,7 @@ cpp_class : storage_spec cpptype ID inherit LBRACE interface RBRACE opt_id S } | storage_spec cpptype LBRACE interface RBRACE opt_id SEMI { - $$ = new_node("class",$3.filename,$3.line); + $$ = new_node("c:class",$3.filename,$3.line); Setattr($$,"classtype",$2.text); if ($4.node) { Setattr($$,ATTR_CHILD,$4.node); @@ -1179,10 +1088,11 @@ cpp_class : storage_spec cpptype ID inherit LBRACE interface RBRACE opt_id S /* Class with a typedef */ | TYPEDEF cpptype ID inherit LBRACE interface RBRACE declaration typedeflist { - $$ = new_node("class",$3.filename,$3.line); + $$ = new_node("c:class",$3.filename,$3.line); Setattr($$,"classtype",$2.text); Setattr($$,ATTR_NAME,$3.text); Setattr($$,"bases",$4); + Setattr($$,"namespace",$3.text); if ($6.node) { Setattr($$,ATTR_CHILD,$6.node); setparent($$,$6.node); @@ -1194,7 +1104,7 @@ cpp_class : storage_spec cpptype ID inherit LBRACE interface RBRACE opt_id S /* Go add a bunch of typedef declarations */ DOH *o, *t, *prev, *d; int i; - o = new_node("typedef",$3.filename,$3.line); + o = new_node("c:typedef",$3.filename,$3.line); Setattr(o,ATTR_NAME,$8.id); t = Copy($3.text); SwigType_push(t,$8.decl); @@ -1203,7 +1113,7 @@ cpp_class : storage_spec cpptype ID inherit LBRACE interface RBRACE opt_id S prev = o; for (i = 0; i < Len($9); i++) { d = Getitem($9,i); - o = new_node("typedef",$3.filename,$3.line); + o = new_node("c:typedef",$3.filename,$3.line); t = Copy($3.text); SwigType_push(t,Getattr(d,"decl")); SwigType_push(t,Getattr(d,"array")); @@ -1219,7 +1129,7 @@ cpp_class : storage_spec cpptype ID inherit LBRACE interface RBRACE opt_id S /* An unnamed struct with a typedef */ | TYPEDEF cpptype LBRACE interface RBRACE declaration typedeflist { - $$ = new_node("class",$3.filename,$3.line); + $$ = new_node("c:class",$3.filename,$3.line); Setattr($$,"classtype",$2.text); if ($4.node) { Setattr($$,ATTR_CHILD,$4.node); @@ -1305,13 +1215,21 @@ mem_initializer : ID LPAREN { LParse_skip_balanced('(',')'); } cpp_other :/* A dummy class name */ storage_spec cpptype ID SEMI { - DOH *o = new_node("classdecl",$4.filename,$4.line); + DOH *o = new_node("c:classdecl",$4.filename,$4.line); Setattr(o,ATTR_NAME,$3.text); } - - | PUBLIC COLON { $$ = new_node("public",$1.filename,$1.line); } - | PRIVATE COLON { $$ = new_node("private",$1.filename,$1.line); } - | PROTECTED COLON { $$ = new_node("protected",$1.filename,$1.line); } + | PUBLIC COLON { + $$ = new_node("c:access",$1.filename,$1.line); + Setattr($$,ATTR_NAME,"public"); + } + | PRIVATE COLON { + $$ = new_node("c:access",$1.filename,$1.line); + Setattr($$,ATTR_NAME,"public"); + } + | PROTECTED COLON { + $$ = new_node("c:access",$1.filename,$1.line); + Setattr($$,ATTR_NAME,"public"); + } | FRIEND { LParse_skip_decl(); @@ -1335,7 +1253,7 @@ cpp_other :/* A dummy class name */ /* %addmethods directive */ | ADDMETHODS opt_id LBRACE interface RBRACE { - $$ = new_node("addmethods",$1.filename,$1.line); + $$ = new_node("swig:addmethods",$1.filename,$1.line); if ($1.text) Setattr($$,ATTR_NAME,$1.text); if ($4.node) { @@ -1808,14 +1726,6 @@ expr : NUM_INT { } ; -idlist : idlist COMMA ID { - Append($$,$3.text); - } - | empty { - $$ = NewList(); - } - ; - empty : ; %% diff --git a/Source/LParse/tags b/Source/LParse/tags index 52cc57c12..4161a2c52 100644 --- a/Source/LParse/tags +++ b/Source/LParse/tags @@ -15,40 +15,71 @@ Attribute name Description "parent" - Parent node "child" - First child node (is the start of a linked list) -2. Parse tree nodes +2. Reserved attribute names + +Attributes starting with a "-" are used internally by the parsed and should not be +used as attributes by any extension module. + +3. General philosophy + +In SWIG1.1, all SWIG directives were defined as parser rules. This made for a rather +large and inflexible parsing module. In this version, the parser has been greatly +reduced to a few very general purpose directives. Older SWIG directives, in turn, +are then implemented as preprocessor macros. For example, in SWIG1.3 the following +directive is used to insert code into part of the output: + + %insert(section) %{ code %} + +Then, the following macros are used to emulate old behavior + +#define %wrapper %insert("wrapper") +#define %init %insert("init") +#define %runtime %insert("runtime") +... etc ... + +Similarly, most old SWIG directives such as "%readonly", "%readwrite", and so forth have +been consolidated into a single "%pragma" directive. + +By consolidating parser rules, the number of tags are reduced and language module +implementation is simplified. + +4. Namespaces + +Swig directives are tagged as "swig:tagname". +C/C++ declarations are tagged as "c:decl". + +Motivation: Maybe I'll add other stuff someday like "fortran:decl". + +5. Parse Tree nodes The following list describes all of the possible nodes that can be produced by the parser and their attributes (not including the common attributes above). +5.1 SWIG Directives -tag : "scope" -syntax : { statements } -attributes : None. "child" attribute contains nodes within the scope. +tag : "swig:scope" +syntax : %scope(name) { statements } +attributes : "name" - Scope name + "child" - attribute contains nodes within the scope. -tag : "module" +tag : "swig:module" syntax : %module idstring attributes : "name" - Module name -tag : "constant" +tag : "swig:constant" syntax : %constant name value; attributes : "name" - Constant name "value" - Constant value "type" - Constant type -tag : "includefile" +tag : "swig:file" syntax : %include filename -attributes : None + : %extern filename + : %import filename +attributes : "type" - File type ("include", "extern", "import") -tag : "externfile" -syntax : %extern filename -attributes : None - -tag : "importfile" -syntax : %import filename -attributes : None - -tag : "insert" +tag : "swig:insert" syntax : %insert(section) "filename" %insert(section) %{ code %} %{ code %} Note: same as %insert("header") %{ code %} @@ -57,11 +88,95 @@ attributes : "section" - Code section "filename" - File to include (if given) "code" - Code to include (if given) -tag : "pragma" +tag : "swig:pragma" syntax : %pragma name [ value ]; %pragma(lang) name [ value ]; +tag : "swig:exception" +syntax : %exception { code } +attributes : "code" - Exception code + +tag : "swig:typemap" +syntax : %typemap(method) type (parms) { + code + } + | %typemap(method) type (parms) "code"; + +attributes : "method" - Typemap method + "code" - Typemap code (if supplied) + "type" - Type + "name" - Typemap Name + "parms" - Parameter list + "srcname" - Source name (of another typemap) + "srctype" - Source type + +Notes : If code is not set, srcname and srctype may point to another typemap + in which a copy is performed. + If neither code nor srcname and srctype are set, then the typemap + is deleted. + + +tag : "swig:apply" +syntax : %apply type name { parms } +attributes : "name" + "type" + "parms" + +tag : "swig:clear" +syntax : %clear parms; +attributes : "parms" + +tag : "swig:addmethods" +syntax : %addmethods [(name)] { statements } +attributes : "name" - Class name (optional) + +5.2 C/C++ Declarations + +tag : "c:function" +attributes : "name" - Function name + "type" - Return type + "parms" - Parameters + "storage" - Storage class + "code" - Code + +tag : "c:variable" +attributes : "name" - Variable name + "type" - Variable type + "storage" - Storage class + "value" - Value + +tag : "c:typedef" +attributes : "name" - Typedef name + "type" - Typedef type + +tag : "c:enum" +attributes : "name" - Enum name + "child" - Enum members + +tag : "c:enumvalue" +attributes : "name" - Enum value name + "value" - Enum value + + +tag : "c:class" +attributes : "name" - Class name + "bases" - Base classes + "classtype" - { struct, class, union } + "altname" - Alternative name (from typedef) + "namespace" - Namespace attribute (used to get fully qualified names) + +tag : "c:destructor" +attributes : "name" - Destructor name + +tag : "c:classdecl" +attributes : "name" - Class name + +tag : "c:access" +attributes : "name" - { public, private, protected } + + + diff --git a/Source/Modules/Makefile.in b/Source/Modules/Makefile.in index 8eaac66b2..e898e8ac3 100644 --- a/Source/Modules/Makefile.in +++ b/Source/Modules/Makefile.in @@ -5,8 +5,8 @@ srcdir = @srcdir@ VPATH = @srcdir@ -SRCS = test.c -OBJS = test.o +SRCS = init.c test.c +OBJS = init.o test.o prefix = @prefix@ exec_prefix = @exec_prefix@ diff --git a/Source/Modules/init.c b/Source/Modules/init.c new file mode 100644 index 000000000..e08a34bd7 --- /dev/null +++ b/Source/Modules/init.c @@ -0,0 +1,37 @@ +/* ----------------------------------------------------------------------------- + * init.c + * + * Initialize built-in SWIG modules. + * + * 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" + +extern void testmodule(); + +static void (*modules[])(void) = { + testmodule, + 0 +}; + +/* ----------------------------------------------------------------------------- + * init_modules() + * + * ----------------------------------------------------------------------------- */ + +void init_modules() { + int i = 0; + while (modules[i]) { + (*modules[i])(); + i++; + } +} + +int main(int argc, char **argv) { + init_modules(); + return Swig_main(argc, argv); +} diff --git a/Source/Modules/test.c b/Source/Modules/test.c index d1707e923..713986479 100644 --- a/Source/Modules/test.c +++ b/Source/Modules/test.c @@ -1,647 +1,218 @@ /* ----------------------------------------------------------------------------- * test.c * - * This module implements a SWIG module in the new tag-based parser. - * This is work in progress. + * This module is used to test the tag-based parser. * ----------------------------------------------------------------------------- */ #include "swig.h" -#include "preprocessor.h" -#include "lparse.h" -#ifdef OLDSTUFF -/* -------- Module variables ------- */ +int test_unknown(DOH *node, void *clientdata) { + Printf(stdout,"::: Unknown tag - '%s'\n", Getattr(node,"tag")); + return 0; +} -#define CPLUS_PUBLIC 1 -#define CPLUS_PRIVATE 2 -#define CPLUS_PROTECTED 3 - -static DOHFile *runtime = 0; -static DOHFile *headers = 0; -static DOHFile *wrappers = 0; -static DOHFile *init = 0; - -static DOH *config_top = 0; - -static int ExternMode = 0; -static int ImportMode = 0; -static int ReadOnly = 0; -static int CPlusMode = CPLUS_PUBLIC; -static int NewMode = 0; -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 -------- */ - -static int -emit_includefile(DOH *obj, void *clientdata) { +int test_file(DOH *node, void *clientdata) { DOH *c; - c = Getattr(obj,"child"); - if (c) { - Swig_emit(c,clientdata); - } -} - -static int -emit_externfile(DOH *obj, void *clientdata) { - DOH *c; - int oldem = ExternMode; - ExternMode = 1; - c = Getattr(obj,"child"); - if (c) { - Swig_emit(c,clientdata); - } - ExternMode = oldem; -} - -static int -emit_importfile(DOH *obj, void *clientdata) { - DOH *c; - int oldem = ExternMode; - ExternMode = 1; - ImportMode = 1; - c = Getattr(obj,"child"); - if (c) { - Swig_emit(c,clientdata); - } - ExternMode = oldem; - ImportMode = 0; -} - -static int -emit_scope(DOH *obj, void *clientdata) { - DOH *c; - c = Getattr(obj,"child"); - if (c) { - Swig_emit(c,clientdata); - } + Printf(stdout,"::: File\n"); + Printf(stdout," name = '%s'\n", Getattr(node,"name")); + Printf(stdout," type = '%s'\n", Getattr(node,"type")); + c = Getchild(node); + Printf(stdout," # elements = %d\n", Swig_count_nodes(c)); + Swig_emit_all(c,clientdata); return 0; } - -/* -------- Code blocks -------- */ - -/* %{ ... %} directive */ -static int -emit_headerblock(DOH *obj, void *clientdata) { - Dump(Getattr(obj,"code"),headers); +int test_module(DOH *node, void *clientdata) { + Printf(stdout,"::: Module\n"); + Printf(stdout," name = '%s'\n", Getname(node)); return 0; } -/* %wrapper %{ ... %} directive */ -static int -emit_wrapperblock(DOH *obj, void *clientdata) { - Dump(Getattr(obj,"code"),wrappers); +int test_insert(DOH *node, void *clientdata) { + Printf(stdout,"::: Insert\n"); + Printf(stdout," section = '%s'\n", Getattr(node,"section")); + Printf(stdout," filename = '%s'\n", Getattr(node,"filename")); + Printf(stdout," code = '%s'\n", Getattr(node,"code")); return 0; } -/* %init %{ ... %} directive */ -static int -emit_initblock(DOH *obj, void *clientdata) { - Dump(Getattr(obj,"code"),init); +int test_pragma(DOH *node, void *clientdata) { + Printf(stdout,"::: Pragma\n"); + Printf(stdout," name = '%s'\n", Getname(node)); + Printf(stdout," value = '%s'\n", Getvalue(node)); return 0; } -/* %runtime %{ ... %} directive */ -static int -emit_runtimeblock(DOH *obj, void *clientdata) { - Dump(Getattr(obj,"code"),runtime); - return 0; -} - -/* ------ Basic C declarations ----- */ - -/* ----------------------------------------------------------------------------- - * function - * ----------------------------------------------------------------------------- */ - -static int -emit_function(DOH *obj, void *clientdata) { - DOHString *name, *scriptname, *type, *storage; - DOHList *parms; - DOHHash *p; - Wrapper *wf; - int numarg = 0, numopt = 0; - int i, pn; - - 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 = NewWrapper(); - - Printv(wf->def, - "static PyObject *", Swig_name_wrapper(scriptname), "(PyObject *self, PyObject *args) {\n", - 0); - - /* Loop over all of the function arguments and build pieces of the wrapper function */ - { - DOHString *parsestr; /* Format string for parsing arguments */ - DOHString *argstr; /* List of arguments */ - DOHString *inputstr; - DOHString *checkstr; - DOHString *initstr; - DOHString *targetstr; - - parsestr = NewString(""); - argstr = NewString(""); - inputstr = NewString(""); - checkstr = NewString(""); - initstr = NewString(""); - targetstr = NewString(""); - - p = parms; - pn = 0; - - while (p) { - int nmatch = 0; - DOHHash *map; - DOHHash *rules; - char suffix[32]; - - sprintf(suffix,"_%d", pn); - - map = Swig_map_match(Rules, "argument", p, &nmatch); - - if (!map) { - Printf(stderr,"%s:%d. No argument rule for %S\n", Getfile(p),Getline(p),SwigType_cstr(Getattr(p,"type"),Getattr(p,"name"))); - return; - } - /* Pull out the rules */ - rules = Getattr(map,"rules"); - if (rules) { - DOH *linit; - DOH *lparse; - DOH *linput; - DOH *lcheck; - DOH *largstr; - DOH *ltarget; - - linit = Copy(Getattr(rules,"init")); - lparse = Copy(Getattr(rules,"parse")); - linput = Copy(Getattr(rules,"input")); - lcheck = Copy(Getattr(rules,"check")); - ltarget = Copy(Getattr(rules,"target")); - - largstr = 0; - /* Construct the parse and argument strings */ - - if (lparse) { - DOHList *sp; - DOHString *pstr; - int i; - Seek(lparse,0,SEEK_SET); - sp = DohSplit(lparse,",",-1); - pstr = Getitem(sp,0); - if (pstr) { - char *c = Char(pstr); - while (*c && (*c != '\"')) c++; - c++; - while (*c && (*c != '\"')) { - Putc(*c, parsestr); - c++; - } - } - largstr = NewString(""); - for (i = 1; i < Len(sp); i++) { - Printf(largstr,",%s",Getitem(sp,i)); - } - Delete(sp); - } - - /* Variable substitution. We're going to walk down the map's children and perform variable name - replacements */ - - { - DOH *c = Getattr(map,"child"); - while (c) { - if (Cmp(Getattr(c,"tag"),"variable") == 0) { - DOH *vname; - DOH *rname; - DOH *vtype; - DOH *vvalue; - DOH *storage; - DOH *local; - - storage = Getattr(c,"storage"); - vname = Getattr(c,"name"); - vtype = Getattr(c,"type"); - vvalue = Getattr(c,"value"); - - rname = NewStringf("%s_%d",vname,pn); - - if (largstr) Replace(largstr,vname,rname,DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE); - if (linit) Replace(linit,vname,rname,DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE); - if (linput) Replace(linput,vname,rname,DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE); - if (lcheck) Replace(lcheck,vname,rname,DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE); - if (ltarget) Replace(ltarget,vname,rname, DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE); - - /* Declare as local to wrapper function */ - local = NewString(""); - Printf(local,"%S", SwigType_cstr(vtype,rname)); - if (vvalue) { - Printf(local," = %s", vvalue); - } - Wrapper_add_local(wf,rname,local); - Delete(local); - Delete(rname); - } - c = Swig_next(c); - } - } - if (largstr) Append(argstr, largstr); - if (linput) Append(inputstr,linput); - if (lcheck) Append(checkstr,lcheck); - if (linit) Append(initstr,linit); - if (ltarget) Printf(targetstr,"%s,", ltarget); - Delete(largstr); - Delete(linput); - Delete(lcheck); - Delete(linit); - Delete(ltarget); - } - - while (nmatch > 0) { - p = Swig_next(p); - nmatch--; - pn++; - } +int test_typemap(DOH *node, void *clientdata) { + Printf(stdout,"::: Typemap\n"); + Printf(stdout," type = '%s'\n", Gettype(node)); + Printf(stdout," name = '%s'\n", Getname(node)); + Printf(stdout," code = '%s'\n", Getattr(node,"code")); + Printf(stdout," srcname = '%s'\n", Getattr(node,"srcname")); + Printf(stdout," srctype = '%s'\n", Getattr(node,"srctype")); + { + DOH *p = Getattr(node,"parms"); + if (p) { + Printf(stdout," parms = '%s'\n", ParmList_protostr(p)); } - - /* Dump out the wrapper code */ - - if (pn > 0) - Delitem(targetstr,DOH_END); - - Printv(wf->code, - initstr, - "if (PyParse_Args(\"", parsestr, "\"", argstr, ") == NULL) return NULL;\n", - inputstr, - checkstr, - "result = ", name, "(", targetstr, ");\n", - 0); } - - Printf(wf->code,"}\n"); - Wrapper_print(wf,wrappers); - - function_exit: - Delete(NewName); - NewName = 0; return 0; } -/* ----------------------------------------------------------------------------- - * variable - * ----------------------------------------------------------------------------- */ - -static int -emit_variable(DOH *obj, void *clientdata) { - Printf(stdout,"variable\n"); +int test_apply(DOH *node, void *clientdata) { + Printf(stdout,"::: Apply\n"); + Printf(stdout," name = '%s'\n", Getname(node)); + Printf(stdout," type = '%s'\n", Gettype(node)); + Printf(stdout," parms = (%s)\n", ParmList_protostr(Getattr(node,"parms"))); return 0; } -/* ----------------------------------------------------------------------------- - * constant - * ----------------------------------------------------------------------------- */ - -static int -emit_constant(DOH *obj, void *clientdata) { - Printf(stdout,"constant\n"); +int test_exception(DOH *node, void *clientdata) { + Printf(stdout,"::: Exception\n"); + Printf(stdout," code = '%s'\n", Getattr(node,"code")); return 0; } -static int -emit_typedef(DOH *obj, void *clientdata) { - Printf(stdout,"typedef\n"); +int test_clear(DOH *node, void *clientdata) { + Printf(stdout,"::: Clear\n"); + Printf(stdout," parms = (%s)\n", ParmList_protostr(Getattr(node,"parms"))); return 0; } -static int -emit_enum(DOH *obj, void *clientdata) { +int test_constant(DOH *node, void *clientdata) { + Printf(stdout,"::: Constant\n"); + Printf(stdout," name = '%s'\n", Getname(node)); + Printf(stdout," type = '%s'\n", Gettype(node)); + Printf(stdout," value = '%s'\n", Getvalue(node)); + return 0; +} + +int test_function(DOH *node, void *clientdata) { + Printf(stdout,"::: Function\n"); + Printf(stdout," name = '%s'\n", Getname(node)); + Printf(stdout," type = '%s'\n", Gettype(node)); + Printf(stdout," parms = (%s)\n", ParmList_protostr(Getattr(node,"parms"))); + Printf(stdout," storage = '%s'\n", Getattr(node,"storage")); + Printf(stdout," code = '%s'\n", Getattr(node,"code")); + return 0; +} + +int test_variable(DOH *node, void *clientdata) { + Printf(stdout,"::: Variable\n"); + Printf(stdout," name = '%s'\n", Getname(node)); + Printf(stdout," type = '%s'\n", Gettype(node)); + Printf(stdout," storage = '%s'\n", Getattr(node,"storage")); + Printf(stdout," value = '%s'\n", Getattr(node,"value")); + return 0; +} + +int test_typedef(DOH *node, void *clientdata) { + Printf(stdout,"::: Typedef\n"); + Printf(stdout," name = '%s'\n", Getname(node)); + Printf(stdout," type = '%s'\n", Gettype(node)); + return 0; +} + +int test_enum(DOH *node, void *clientdata) { DOH *c; - Printf(stdout,"enum\n"); - c = Getattr(obj,"child"); - if (c) { - Swig_emit(c,clientdata); - } + Printf(stdout,"::: Enum\n"); + Printf(stdout," name = '%s'\n", Getname(node)); + c = Getchild(node); + Swig_emit_all(c,clientdata); return 0; } -static int -emit_enumvalue(DOH *obj, void *clientdata) { - Printf(stdout,"enumvalue\n"); +int test_enumvalue(DOH *node, void *clientdata) { + Printf(stdout,"::: Enumvalue\n"); + Printf(stdout," name = '%s'\n", Getname(node)); + Printf(stdout," value = '%s'\n", Getvalue(node)); return 0; } -/* ------ C++ stuff ------ */ - -static int -emit_class(DOH *obj, void *clientdata) { +int test_class(DOH *node, void *clientdata) { DOH *c; - Printf(stdout,"class\n"); - c = Getattr(obj, "child"); - if (c) { - int ic = InClass; - InClass = 1; - Swig_emit(c,clientdata); - InClass = ic; - } + Printf(stdout,"::: Class\n"); + Printf(stdout," name = '%s'\n", Getname(node)); + Printf(stdout," bases = %s\n", Getattr(node,"bases")); + Printf(stdout," altname = '%s'\n", Getattr(node,"altname")); + Printf(stdout," classtype = '%s'\n", Getattr(node,"classtype")); + c = Getchild(node); + Swig_emit_all(c,clientdata); return 0; } -static int -emit_destructor(DOH *obj, void *clientdata) { - Printf(stdout,"destructor\n"); +int test_classdecl(DOH *node, void *clientdata) { + Printf(stdout,"::: Classdecl\n"); + Printf(stdout," name = '%s'\n", Getname(node)); return 0; } -static int -emit_classdecl(DOH *obj, void *clientdata) { - Printf(stdout,"classdecl\n"); - return 0; -} - -static int -emit_private(DOH *obj, void *clientdata) { - CPlusMode = CPLUS_PRIVATE; - return 0; -} - -static int -emit_protected(DOH *obj, void *clientdata) { - CPlusMode = CPLUS_PROTECTED; - return 0; -} - -static int -emit_public(DOH *obj, void *clientdata) { - CPlusMode = CPLUS_PUBLIC; - return 0; -} - -static int -emit_addmethods(DOH *obj, void *clientdata) { +int test_addmethods(DOH *node, void *clientdata) { DOH *c; - Printf(stdout,"addmethods\n"); - c = Getattr(obj, "child"); - if (c) { - Swig_emit(c,clientdata); - } + Printf(stdout,"::: Addmethods\n"); + Printf(stdout," name = '%s'\n", Getname(node)); + c = Getchild(node); + Swig_emit_all(c,clientdata); return 0; } -/* ------ SWIG directives ------ */ - -static int -emit_moduledirective(DOH *obj, void *clientdata) { - if (!ModuleName) { - ModuleName = Getattr(obj,"name"); - DohIncref(ModuleName); - } +int test_destructor(DOH *node, void *clientdata) { + Printf(stdout,"::: Destructor\n"); + Printf(stdout," name = '%s'\n", Getname(node)); + Printf(stdout," code = '%s'\n", Getattr(node,"code")); return 0; } -static int -emit_renamedirective(DOH *obj, void *clientdata) { - DOHString *name, *rename; - name = Getattr(obj,"oldname"); - rename = Getattr(obj,"newname"); - if (name && rename) - Setattr(RenameHash,name,rename); +int test_access(DOH *node, void *clientdata) { + Printf(stdout,"::: AccessSpecifier\n"); + Printf(stdout," name = '%s'\n", Getname(node)); return 0; } -static int -emit_readonlydirective(DOH *obj, void *clientdata) { - ReadOnly = 1; - return 0; -} - -static int -emit_readwritedirective(DOH *obj, void *clientdata) { - ReadOnly = 0; - return 0; -} - -static int -emit_namedirective(DOH *obj, void *clientdata) { - if (NewName) Delete(NewName); - NewName = Getattr(obj,"name"); - if (NewName) DohIncref(NewName); - return 0; -} - -static int -emit_newdirective(DOH *obj, void *clientdata) { - NewMode = 1; - return 0; -} - -static int -emit_exceptiondirective(DOH *obj, void *clientdata) { - Printf(stdout,"exceptiondirective\n"); - return 0; -} - -static int -emit_pragmadirective(DOH *obj, void *clientdata) { - Printf(stdout,"pragmadirective\n"); - return 0; -} - -static int -emit_nativedirective(DOH *obj, void *clientdata) { - DOH *c; - int oldnative = NativeMode; - NativeMode = 1; - c = Getattr(obj, "child"); - if (c) { - Swig_emit(c,clientdata); - } - NativeMode = oldnative; - return 0; -} - -static int -emit_typemap(DOH *obj, void *clientdata) { - Printf(stdout,"typemap\n"); - return 0; -} - -static int -emit_typemapcopy(DOH *obj, void *clientdata) { - Printf(stdout,"typemapcopy\n"); - return 0; -} - -static int -emit_applydirective(DOH *obj, void *clientdata) { - Printf(stdout,"applydirective\n"); - return 0; -} - -static int -emit_cleardirective(DOH *obj, void *clientdata) { - Printf(stdout,"cleardirective\n"); - 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,obj); -} - -/* -------- 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 */ - - runtime = NewString(runtime_banner); - headers = NewString(header_banner); - wrappers = NewString(wrapper_banner); - init = NewString(init_banner); - - Rules = NewHash(); - RenameHash = NewHash(); - - if (config_top) - Swig_emit(config_top, clientdata); - - Swig_emit(top, clientdata); - - Swig_banner(stdout); - - Dump(runtime,stdout); - Dump(headers,stdout); - Dump(wrappers,stdout); - Dump(init, stdout); - Delete(runtime); - Delete(headers); - Delete(wrappers); - Delete(init); - Delete(RenameHash); -} - static SwigRule rules[] = { - "includefile", emit_includefile, - "externfile", emit_externfile, - "importfile", emit_importfile, - "headerblock", emit_headerblock, - "wrapperblock", emit_wrapperblock, - "initblock", emit_initblock, - "runtimeblock", emit_runtimeblock, - "scope", emit_scope, - "function", emit_function, - "variable", emit_variable, - "constant", emit_constant, - "typedef", emit_typedef, - "class", emit_class, - "destructor", emit_destructor, - "enum", emit_enum, - "enumvalue", emit_enumvalue, - "classdecl", emit_classdecl, - "private", emit_private, - "protected", emit_protected, - "public", emit_public, - "addmethods", emit_addmethods, - "moduledirective", emit_moduledirective, - "renamedirective", emit_renamedirective, - "readonlydirective", emit_readonlydirective, - "readwritedirective", emit_readwritedirective, - "namedirective", emit_namedirective, - "newdirective", emit_newdirective, - "exceptiondirective", emit_exceptiondirective, - "pragmadirective", emit_pragmadirective, - "nativedirective", emit_nativedirective, - "typemap", emit_typemap, - "typemapcopy", emit_typemapcopy, - "applydirective", emit_applydirective, - "cleardirective", emit_cleardirective, - "map", emit_map, - NULL, NULL + { "file", test_file}, + { "module", test_module}, + { "insert", test_insert}, + { "pragma", test_pragma}, + { "typemap", test_typemap}, + { "apply", test_apply}, + { "exception", test_exception}, + { "clear", test_clear}, + { "addmethods", test_addmethods}, + { "constant", test_constant}, + { "function", test_function}, + { "variable", test_variable}, + { "typedef", test_typedef}, + { "enum", test_enum}, + { "enumvalue", test_enumvalue}, + { "class", test_class}, + { "classdecl", test_classdecl}, + { "destructor", test_destructor}, + { "access", test_access}, + { "*", test_unknown}, + { 0 } }; -/* Initialize the module */ -void test_init() { - DOHString *config; - DOHString *pconfig; - - Swig_add_rules(rules); - - - /* Try to get the language specific configuration */ - - config = Swig_include("pyconf.swg"); - - if (!config) { - Printf(stderr,"*** Fatal error. Unable to find pyconf.swg\n"); - exit(0); - } - - /* Run the preprocessor on the configuration file and parse it */ - Seek(config,0,SEEK_SET); - Setline(config,1); - pconfig = Preprocessor_parse(config); - - Seek(pconfig,0,SEEK_SET); - config_top = LParse_parse(pconfig); +static +int test_init(int argc, char **argv) { + Printf(stdout,"test_init:\n"); + return 0; } -#endif +static +DOH *test_run(DOH *node) { + DOH *c; + Printf(stdout,"test_run:\n"); + Swig_add_rules(rules); + + c = Getattr(node,"child"); + Swig_emit_all(c,0); + return 0; +} + +void testmodule() { + Swig_register_module("test","swig:top", test_init, test_run); +} diff --git a/Source/Swig/Makefile.in b/Source/Swig/Makefile.in index 228714e9d..1bee11538 100644 --- a/Source/Swig/Makefile.in +++ b/Source/Swig/Makefile.in @@ -6,9 +6,9 @@ srcdir = @srcdir@ VPATH = @srcdir@ SRCS = map.c wrapfunc.c naming.c tree.c stype.c scanner.c include.c getopt.c misc.c \ - parms.c cwrap.c typemap.c + parms.c cwrap.c typemap.c module.c OBJS = map.o wrapfunc.o naming.o tree.o stype.o scanner.o include.o getopt.o misc.o \ - parms.o cwrap.o typemap.o + parms.o cwrap.o typemap.o module.o prefix = @prefix@ exec_prefix = @exec_prefix@ diff --git a/Source/Swig/getopt.c b/Source/Swig/getopt.c index 15aa94dc1..f83f18bbc 100644 --- a/Source/Swig/getopt.c +++ b/Source/Swig/getopt.c @@ -60,6 +60,18 @@ Swig_mark_arg(int n) { marked[n] = 1; } +/* ----------------------------------------------------------------------------- + * Swig_check_marked() + * + * Checks to see if argument has been picked up. + * ----------------------------------------------------------------------------- */ + +int +Swig_check_marked(int n) { + assert((n>=0) && (n < numargs)); + return marked[n]; +} + /* ----------------------------------------------------------------------------- * Swig_check_options() * diff --git a/Source/Swig/include.c b/Source/Swig/include.c index d14d2c686..93d8e16e1 100644 --- a/Source/Swig/include.c +++ b/Source/Swig/include.c @@ -21,6 +21,26 @@ static List *directories = 0; /* List of include directories */ static String *lastpath = 0; /* Last file that was included */ static int bytes_read = 0; /* Bytes read */ +static String *swiglib = 0; /* Location of SWIG library */ + +/* ----------------------------------------------------------------------------- + * Swig_swiglib_set() + * Swig_swiglib_get() + * + * Set the location of the SWIG library. This isn't really used, by the + * include mechanism, but rather as a query interface for language modules. + * ----------------------------------------------------------------------------- */ + +void +Swig_swiglib_set(const String_or_char *sl) { + swiglib = NewString(sl); +} + +String * +Swig_swiglib_get() { + return swiglib; +} + /* ----------------------------------------------------------------------------- * Swig_add_directory() * diff --git a/Source/Swig/module.c b/Source/Swig/module.c new file mode 100644 index 000000000..111b08522 --- /dev/null +++ b/Source/Swig/module.c @@ -0,0 +1,166 @@ +/* ----------------------------------------------------------------------------- + * module.c + * + * This file implements the SWIG module system. Modules are simply + * pieces of code that manipulate tree objects. Each module is defined + * by 4 quantities: + * + * - Module name (used to select the module on the command line) + * - init function (called with the SWIG command line options). + * - start function (called to launch the module) + * - start tag (starting tag expected by the module) + * + * Currently modules must be statically linked with SWIG. However, it + * is anticipated that the module system may eventually support + * dynamic loading. + * + * 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" + +static char cvsroot[] = "$Header$"; + +struct Module { + String *modname; + int (*initfunc)(int argc, char **argv); + DOH *(*startfunc)(DOH *); + String *starttag; + struct Module *next; +}; + +static Module *Modules = 0; +static Hash *LoadedModules = 0; + +/* ----------------------------------------------------------------------------- + * Swig_register_module() + * + * Register a new module with the system + * ----------------------------------------------------------------------------- */ + +void +Swig_register_module(const String_or_char *modname, const String_or_char *starttag, + int (*initfunc)(int argc, char **argv), + DOH *(*startfunc)(DOH *)) +{ + Module *m; + m = (Module *) malloc(sizeof(Module)); + m->modname = NewString(modname); + m->starttag = NewString(starttag); + m->initfunc = initfunc; + m->startfunc = startfunc; + m->next = Modules; + Modules = m; +} + +/* ----------------------------------------------------------------------------- + * Swig_load_module() + * + * Load a module. Returns the module object. + * ----------------------------------------------------------------------------- */ + +Module * +Swig_load_module(const String_or_char *modname) { + Module *m; + m = Modules; + while (m) { + if (Cmp(m->modname, modname) == 0) { + /* Create a new entry in the loaded modules table */ + List *ml; + if (!LoadedModules) LoadedModules = NewHash(); + ml = Getattr(LoadedModules,m->starttag); + if (!ml) { + ml = NewList(); + Setattr(LoadedModules,m->starttag,ml); + } + Append(ml,NewVoid(m,0)); + return m; + } + m = m->next; + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * Swig_init_module() + * + * Initialize a module + * ----------------------------------------------------------------------------- */ + +int Swig_init_module(Module *m, int argc, char **argv) { + return (*m->initfunc)(argc,argv); +} + +/* ----------------------------------------------------------------------------- + * Swig_start_module() + * + * Start a module + * ----------------------------------------------------------------------------- */ + +DOH * +Swig_start_module(Module *m, DOH *obj) { + return (*m->startfunc)(obj); +} + +/* ----------------------------------------------------------------------------- + * Swig_run_modules() + * + * Given a tree node. This function tries to run it through all of the loaded + * modules. This works by looking at the "tag" attribute of the node and + * searching for a loaded module that can handle that tag. If no module can be + * found, processing stops and an error is generated. + * + * If more than one module can work on a given tag, those modules will be + * executed one after the other. Caveat: if one of those modules outputs + * a different type of tree, processing immediately stops. + * ----------------------------------------------------------------------------- */ + +DOH *Swig_run_modules(DOH *node) { + String *tag; + List *ml; + DOH *newnode; + String *newtag; + int i; + + tag = Getattr(node,"tag"); + if (!tag) { + Printf(stderr,"Whoa. No tag attribute on node passed to Swig_module_run.\n"); + exit(EXIT_FAILURE); + } + /* Get the set of modules that can respond to this node */ + while (node) { + if (!LoadedModules) { + Printf(stderr,"No modules loaded.\n"); + return 0; + } + ml = Getattr(LoadedModules,tag); + if ((!ml) || (Len(ml) == 0)) { + Printf(stderr,"No module for object '%s'\n", tag); + return 0; + } + newnode = 0; + newtag = 0; + for (i = 0; i < Len(ml); i++) { + Module *m; + m = (Module *) Data(Getitem(ml,i)); + assert(m); + newnode = (*m->startfunc)(node); + if (!newnode) return 0; /* Done */ + newtag = Getattr(newnode,"tag"); + if (!newtag) { + Printf(stderr,"Fatal error. Module '%s' returns untagged object.\n", m->modname); + exit(EXIT_FAILURE); + } + if (Cmp(newtag,tag)) break; /* Tag is different. Oh well */ + } + if (Cmp(newtag,tag) == 0) break; /* Hmmm. The tag is the same but we already did everything */ + node = newnode; + tag = newtag; + } + return 0; +} + + diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index e9af625d7..8b9bac992 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -68,6 +68,8 @@ extern int Swig_insert_file(const String_or_char *name, File *outfile); extern int Swig_bytes_read(); extern void Swig_register_filebyname(const String_or_char *name, File *outfile); extern File *Swig_filebyname(const String_or_char *name); +extern void Swig_swiglib_set(const String_or_char *name); +extern String *Swig_swiglib_get(); #define OUTFILE(x) Swig_filebyname(x) @@ -77,6 +79,7 @@ extern File *Swig_filebyname(const String_or_char *name); extern void Swig_init_args(int argc, char **argv); extern void Swig_mark_arg(int n); +extern int Swig_check_marked(int n); extern void Swig_check_options(); extern void Swig_arg_error(); @@ -221,19 +224,39 @@ extern String *ParmList_protostr(ParmList *); /* --- Parse tree support --- */ typedef struct { - char *name; + const char *name; int (*action)(DOH *obj, void *clientdata); } SwigRule; -extern void Swig_dump_tags(DOH *obj, DOH *root); -extern void Swig_add_rule(String_or_char *, int (*action)(DOH *, void *)); + +#define SWIG_OK 1 +#define SWIG_NORULE 0 +#define SWIG_ERROR -1 + +extern void Swig_add_rule(const String_or_char *, int (*action)(DOH *, void *)); extern void Swig_add_rules(SwigRule ruleset[]); extern void Swig_clear_rules(); +extern int Swig_tag_check(DOH *obj, String_or_char *tagname); extern int Swig_emit(DOH *obj, void *clientdata); -extern void Swig_cut_node(DOH *obj); +extern int Swig_emit_all(DOH *obj, void *clientdata); +extern void Swig_set_callback(DOH *obj, void (*cb)(void *clientdata), void *clientdata); +extern void (*Swig_set_trace(DOH *obj, void (*cb)(DOH *, DOH *), DOH *arg))(DOH *, DOH *); +extern void Swig_remove_trace(DOH *obj); +extern void Swig_node_cut(DOH *obj); +extern void Swig_node_insert(DOH *node, DOH *newnode); +extern void Swig_node_temporary(DOH *node); +extern void Swig_node_ignore(DOH *node); +extern int Swig_count_nodes(DOH *node); + extern DOH *Swig_next(DOH *obj); extern DOH *Swig_prev(DOH *obj); +/* Debugging of parse trees */ +extern void Swig_debug_emit(int); +extern void Swig_dump_tags(DOH *obj, DOH *root); +extern void Swig_dump_tree(DOH *obj); +extern void Swig_dump_rules(); + /* -- Wrapper function Object */ typedef struct { @@ -349,6 +372,18 @@ extern Wrapper *Swig_cvarget_wrapper(String_or_char *varname, String_or_char *code); +/* --- Module loader and handler --- */ + +typedef struct Module Module; +extern void Swig_register_module(const String_or_char *modname, const String_or_char *starttag, + int (*initfunc)(int, char **), + DOH *(*startfunc)(DOH *)); + +extern Module *Swig_load_module(const String_or_char *modname); +extern int Swig_init_module(Module *m, int argc, char **argv); +extern DOH *Swig_start_module(Module *m, DOH *obj); +extern DOH *Swig_run_modules(DOH *node); + /* --- Legacy Typemap API (somewhat simplified) --- */ extern void Swig_typemap_init(); @@ -385,6 +420,9 @@ extern void Swig_except_clear(); #define Getnext(x) Getattr(x,"next") #define Setnext(x,n) Setattr(x,"next",n) +#define Getchild(x) Getattr(x,"child") + +extern int Swig_main(int argc, char *argv[]); #endif diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c index 1c5a19fa4..0c5c9c12b 100644 --- a/Source/Swig/tree.c +++ b/Source/Swig/tree.c @@ -14,7 +14,9 @@ static char cvsroot[] = "$Header$"; +/* Hash table mapping tag names to handler functions */ static Hash *rules = 0; +static int debug_emit = 0; /* ----------------------------------------------------------------------------- * Swig_next() @@ -31,6 +33,10 @@ DOH *Swig_prev(DOH *obj) { return Getattr(obj,"prev"); } +void Swig_debug_emit(int n) { + debug_emit = n; +} + /* ----------------------------------------------------------------------------- * Swig_dump_tags() * @@ -46,10 +52,10 @@ Swig_dump_tags(DOH *obj, DOH *root) { else croot = root; while (obj) { - Printf(stdout,"%s.%s\n", croot, Getattr(obj,"tag")); + Printf(stdout,"%s . %s\n", croot, Getattr(obj,"tag")); cobj = Getattr(obj,"child"); if (cobj) { - newroot = NewStringf("%s.%s",croot,Getattr(obj,"tag")); + newroot = NewStringf("%s . %s",croot,Getattr(obj,"tag")); Swig_dump_tags(cobj,newroot); Delete(newroot); } @@ -59,6 +65,72 @@ Swig_dump_tags(DOH *obj, DOH *root) { Delete(croot); } + +/* ----------------------------------------------------------------------------- + * Swig_dump_tree() + * + * Dump the tree structure of a parse tree to standard output + * ----------------------------------------------------------------------------- */ + +static int indent_level = 0; + +static void print_indent(int l) { + int i; + for (i = 0; i < indent_level; i++) { + fputc(' ', stdout); + } + if (l) { + fputc('|', stdout); + fputc(' ', stdout); + } +} + +void +Swig_dump_tree(DOH *obj) { + DOH *k; + DOH *cobj; + + while (obj) { + print_indent(0); + Printf(stdout,"+++ %s ----------------------------------------\n", Getattr(obj,"tag")); + + k = Firstkey(obj); + while (k) { + if ((Cmp(k,"tag") == 0) || (Cmp(k,"child") == 0) || + (Cmp(k,"parent") == 0) || (Cmp(k,"next") == 0) || + (Cmp(k,"prev") == 0)) { + /* Do nothing */ + } else if (Cmp(k,"parms") == 0) { + print_indent(2); + Printf(stdout,"%-12s - %s\n", k, ParmList_protostr(Getattr(obj,k))); + } else { + DOH *o; + char *trunc = ""; + print_indent(2); + o = Str(Getattr(obj,k)); + if (Len(o) > 40) { + trunc = "..."; + } + Printf(stdout,"%-12s - \"%(escape)-0.40s%s\"\n", k, o, trunc); + Delete(o); + } + k = Nextkey(obj); + } + cobj = Getattr(obj,"child"); + if (cobj) { + indent_level += 6; + Printf(stdout,"\n"); + Swig_dump_tree(cobj); + indent_level -= 6; + } else { + print_indent(1); + Printf(stdout,"\n"); + } + obj = Swig_next(obj); + } +} + + /* ----------------------------------------------------------------------------- * Swig_add_rule() * @@ -66,13 +138,17 @@ Swig_dump_tags(DOH *obj, DOH *root) { * ----------------------------------------------------------------------------- */ void -Swig_add_rule(String_or_char *name, int (*action)(DOH *node, void *clientdata)) +Swig_add_rule(const String_or_char *name, int (*action)(DOH *node, void *clientdata)) { if (!rules) rules = NewHash(); if (action) Setattr(rules,name,NewVoid((void *) action,0)); else Delattr(rules,name); + + if (debug_emit) { + Printf(stderr,"Swig_add_rule : '%s' -> %x\n", name, action); + } } /* ----------------------------------------------------------------------------- @@ -101,48 +177,234 @@ Swig_clear_rules() { if (rules) Delete(rules); rules = NewHash(); + if (debug_emit) { + Printf(stderr,"Swig_clear_rules :\n"); + } + +} + +/* ----------------------------------------------------------------------------- + * Swig_dump_rules() + * + * Print out debugging information for the rules + * ----------------------------------------------------------------------------- */ + +void +Swig_dump_rules() { + String *key; + Printf(stdout,"SWIG emit rules:::\n"); + if (!rules) { + Printf(stdout," No rules defined.\n"); + return; + } + key = Firstkey(rules); + while (key) { + Printf(stdout," '%-15s' -> %x\n", key, GetVoid(rules,key)); + key = Nextkey(rules); + } +} + +/* ----------------------------------------------------------------------------- + * Swig_tag_check() + * + * Checks the tag name of an object taking into account namespace issues. + * For example, a check of "function" will match any object with a tag + * of the form "xxx:function" whereas a check of "c:function" will check + * for a more exact match. Returns 1 if a match is found, 0 otherwise + * ----------------------------------------------------------------------------- */ + +int +Swig_tag_check(DOH *obj, String_or_char *tagname) { + String *tag; + char *tc; + char *tnc; + tag = Getattr(obj,"tag"); + assert(tag); + + tc = Char(tag); + tnc = Char(tagname); + + while (tnc) { + if (strcmp(tc,tnc) == 0) return 1; + tnc = strchr(tnc,':'); + if (tnc) tnc++; + } + return 0; +} + +/* ----------------------------------------------------------------------------- + * Swig_set_callback() + * + * Sets a parser callback function for a node. + * ----------------------------------------------------------------------------- */ +void +Swig_set_callback(DOH *obj, void (*cb)(void *clientdata), void *clientdata) { + SetVoid(obj,"-callback-",(void *)cb); + if (clientdata) + SetVoid(obj,"-callbackarg-", clientdata); +} + +/* ----------------------------------------------------------------------------- + * Swig_set_trace() + * + * Sets a tracing function on a parse tree node. Returns the old tracing + * function (if any). + * ----------------------------------------------------------------------------- */ + +void (*Swig_set_trace(DOH *obj, void (*cb)(DOH *, DOH *), DOH *arg))(DOH *, DOH *) { + void (*old)(DOH *,DOH *); + old = (void (*)(DOH *, DOH *)) GetVoid(obj,"-trace-"); + SetVoid(obj,"-trace-", (void *) cb); + if (arg) + Setattr(obj,"-tracearg-", arg); + return old; +} + +/* ----------------------------------------------------------------------------- + * Swig_remove_trace() + * + * Removes the tracing function from a parse tree node + * ----------------------------------------------------------------------------- */ + +void +Swig_remove_trace(DOH *obj) { + Delattr(obj,"-trace-"); + Delattr(obj,"-tracearg-"); +} + + +/* ----------------------------------------------------------------------------- + * Swig_node_temporary() + * + * Sets a node as being temporary (deleted immediately after it is emitted) + * ----------------------------------------------------------------------------- */ + +void Swig_node_temporary(DOH *obj) { + SetInt(obj,"-temp-",1); +} + +/* ----------------------------------------------------------------------------- + * Swig_node_ignore() + * + * Causes a node to be ignored + * ----------------------------------------------------------------------------- */ + +void Swig_node_ignore(DOH *obj) { + SetInt(obj,"-ignore-",1); } /* ----------------------------------------------------------------------------- * int Swig_emit() * - * Emit an action for a specific object + * This function calls the handler function (if any) for an object. * ----------------------------------------------------------------------------- */ int Swig_emit(DOH *obj, void *clientdata) { DOH *tag; DOH *actionobj; + char *tc; int (*action)(DOH *obj, void *clientdata); - + void (*callback)(void *clientdata); + void (*tracefunc)(DOH *obj, DOH *arg); int ret; assert(obj); - if (!rules) return -1; - while (obj) { + if (!rules) { + Printf(stderr,"No rules defined in Swig_emit()!\n"); + return SWIG_ERROR; + } + if (obj) { + if (Getattr(obj,"-ignore-")) return SWIG_OK; tag = Getattr(obj,"tag"); - actionobj = Getattr(rules,tag); + assert(tag); + tc = Char(tag); + while(tc) { + actionobj = Getattr(rules,tc); + if (actionobj) { + if (debug_emit) { + Printf(stderr,"Swig_emit : Matched tag '%s' -> rule '%s'\n", tag, tc); + } + /* Check for user tracing -- traces occur before any handlers are called */ + tracefunc = (void (*)(DOH *, DOH *)) GetVoid(obj,"-trace-"); + if (tracefunc) { + DOH *tobj = Getattr(obj,"-tracearg-"); + (*tracefunc)(obj,tobj); + } + action = (int (*)(DOH *, void *)) Data(actionobj); + ret = (*action)(obj,clientdata); + /* Check for a parser callback */ + callback = (void (*)(void *clientdata)) GetVoid(obj,"-callback-"); + if (callback) { + void *cbarg; + cbarg = GetVoid(obj,"-callbackarg-"); + (*callback)(cbarg); + Delattr(obj,"-callback-"); + Delattr(obj,"-callbackarg-"); + } + return ret; + } else { + tc = strchr(tc,':'); + if (tc) tc++; + } + } + actionobj = Getattr(rules,"*"); if (actionobj) { + if (debug_emit) { + Printf(stderr,"Swig_emit : Matched tag '%s' -> rule '*'\n", tag); + } + /* Check for user tracing -- traces occur before any handlers are called */ + tracefunc = (void (*)(DOH *, DOH *)) GetVoid(obj,"-trace-"); + if (tracefunc) { + DOH *tobj = Getattr(obj,"-tracearg-"); + (*tracefunc)(obj,tobj); + } action = (int (*)(DOH *, void *)) Data(actionobj); ret = (*action)(obj,clientdata); - if (ret < 0) return -1; - } else { - Printf(stderr,"warning: no action defined for '%s'\n", tag); + /* Check for a parser callback */ + callback = (void (*)(void *clientdata)) GetVoid(obj,"-callback-"); + if (callback) { + void *cbarg; + cbarg = GetVoid(obj,"-callbackarg-"); + (*callback)(cbarg); + Delattr(obj,"-callback-"); + Delattr(obj,"-callbackarg-"); + } + return ret; + } + if (debug_emit) { + Printf(stderr,"Swig_emit : No rule defined for tag '%s'\n", tag); } - obj = Swig_next(obj); } - return 0; + return SWIG_NORULE; } /* ----------------------------------------------------------------------------- - * Swig_cut_node(DOH *obj) + * Swig_emit_all() + * + * Emit all of the nodes at this level. + * ----------------------------------------------------------------------------- */ + +int +Swig_emit_all(DOH *obj, void *clientdata) { + int ret; + while (obj) { + ret = Swig_emit(obj,clientdata); + if (ret < 0) return ret; + obj = Swig_next(obj); + } + return SWIG_OK; +} + +/* ----------------------------------------------------------------------------- + * Swig_node_cut() * * 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) { +void Swig_node_cut(DOH *obj) { DOH *parent; DOH *next; DOH *prev; @@ -156,7 +418,7 @@ void Swig_cut_node(DOH *obj) { 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 */ + /* Well, this is a single child. Guess we'll just tell the parent that their child is gone */ Delattr(parent,"child"); return; } @@ -184,8 +446,43 @@ void Swig_cut_node(DOH *obj) { return; } - - +/* ----------------------------------------------------------------------------- + * Swig_node_insert() + * + * Inserts a node after a given node. The node to be inserted should be + * isolated (no parent, no siblings, etc...). + * ----------------------------------------------------------------------------- */ + +void +Swig_node_insert(DOH *node, DOH *newnode) { + DOH *next; + next = Getattr(node,"next"); + + if (next) { + Setattr(newnode,"next", next); + Setattr(next,"prev", newnode); + } + Setattr(node,"next",newnode); + Setattr(newnode,"prev", node); + Setattr(newnode,"parent", Getattr(node,"parent")); +} + +/* ----------------------------------------------------------------------------- + * Swig_count_nodes() + * + * Count number of nodes at this level + * ----------------------------------------------------------------------------- */ + +int Swig_count_nodes(DOH *node) { + int n = 0; + while (node) { + n++; + node = Getnext(node); + } + return n; +} + +