diff --git a/Source/LParse/cscanner.c b/Source/LParse/cscanner.c index be6f94286..036c259f8 100644 --- a/Source/LParse/cscanner.c +++ b/Source/LParse/cscanner.c @@ -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); diff --git a/Source/LParse/parser.y b/Source/LParse/parser.y index 836045f5b..b7aa9cf89 100644 --- a/Source/LParse/parser.y +++ b/Source/LParse/parser.y @@ -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 ADDMETHODS ALPHA_MODE APPLY CHECKOUT CLEAR CONSTANT DOCONLY DOC_DISABLE DOC_ENABLE ECHO EXCEPT %token ILLEGAL IMPORT INCLUDE INIT INLINE LOCALSTYLE MACRO MODULE NAME NATIVE NEW PRAGMA %token RAW_MODE READONLY READWRITE RENAME SECTION STYLE SUBSECTION SUBSUBSECTION TEXT TITLE -%token TYPE TYPEMAP USERDIRECTIVE WEXTERN WRAPPER +%token TYPE TYPEMAP USERDIRECTIVE WEXTERN WRAPPER MAP /* Operators */ %left LOR @@ -237,8 +260,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 doc_directive except_directive pragma_directive modifier_directive native_directive typemap_directive -%type variable_decl function_decl enum_decl typedef_decl stail edecl typedeflist +%type file_include code_block doc_directive except_directive pragma_directive modifier_directive native_directive typemap_directive map_directive +%type variable_decl function_decl enum_decl typedef_decl stail edecl typedeflist map_element %type enumlist interface %type inherit base_list %type 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; } ; diff --git a/Source/Modules/test.c b/Source/Modules/test.c index 9f2129143..2f9823c52 100644 --- a/Source/Modules/test.c +++ b/Source/Modules/test.c @@ -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 }; diff --git a/Source/Swig/Makefile.in b/Source/Swig/Makefile.in index 527af4d4e..1db076f5b 100644 --- a/Source/Swig/Makefile.in +++ b/Source/Swig/Makefile.in @@ -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@ diff --git a/Source/Swig/map.c b/Source/Swig/map.c new file mode 100644 index 000000000..0971da08e --- /dev/null +++ b/Source/Swig/map.c @@ -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; +} + + + + + diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c index 048fd8f31..9a3417e0e 100644 --- a/Source/Swig/stype.c +++ b/Source/Swig/stype.c @@ -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 diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 7be953786..31670ae96 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -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); diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c index 09832e1e5..6bcbde549 100644 --- a/Source/Swig/tree.c +++ b/Source/Swig/tree.c @@ -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; +} + + + + + -