From 2cc9dbe7fd58a55cf6d41ed2f8bbf4b286be63c8 Mon Sep 17 00:00:00 2001 From: Dave Beazley Date: Thu, 6 Jul 2000 04:20:33 +0000 Subject: [PATCH] More improvements to types and related code git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@521 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- Source/LParse/parser.y | 53 ++++++++++- Source/Modules/test.c | 4 +- Source/Swig/map.c | 202 ++++++++++++++++++++++++++++++++++++++++- Source/Swig/stype.c | 48 ++++++++-- Source/Swig/swig.h | 1 + 5 files changed, 294 insertions(+), 14 deletions(-) diff --git a/Source/LParse/parser.y b/Source/LParse/parser.y index b7aa9cf89..2505a1eb6 100644 --- a/Source/LParse/parser.y +++ b/Source/LParse/parser.y @@ -810,9 +810,42 @@ 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); + + /* 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); + } } } ; @@ -827,7 +860,7 @@ map_element : variable_decl map_element { } Setattr(o2,ATTR_NEXT,$2); } - | function_decl map_element { + | function_decl map_element { DOH *o, *o2; $$ = $1; o = $1; @@ -839,7 +872,7 @@ map_element : variable_decl map_element { } | STRING COLON LBRACE { DOH *text = LParse_skip_balanced('{','}'); - $$ = new_node("mapelement",$1.filename, $1.line); + $$ = new_node("maprule",$1.filename, $1.line); Setattr($$,ATTR_NAME,$1.text); Setattr($$,"code",text); $1.text = $$; @@ -848,6 +881,16 @@ map_element : variable_decl map_element { 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; } diff --git a/Source/Modules/test.c b/Source/Modules/test.c index 2f9823c52..afe967fd6 100644 --- a/Source/Modules/test.c +++ b/Source/Modules/test.c @@ -174,7 +174,7 @@ emit_function(DOH *obj, void *clientdata) { 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)); + Printf(stdout,"array[%d] = %S\n", i, SwigType_array_getdim(ptype,i)); } } @@ -417,7 +417,7 @@ emit_map(DOH *obj, void *clientdata) { parms = Getattr(obj,"parms"); rules = Getattr(obj,"child"); - Swig_map_add(Rules,rulename,parms,rules); + Swig_map_add(Rules,rulename,parms,obj); } /* -------- Entry point -------- */ diff --git a/Source/Swig/map.c b/Source/Swig/map.c index 0971da08e..2c5ffa512 100644 --- a/Source/Swig/map.c +++ b/Source/Swig/map.c @@ -67,7 +67,7 @@ Swig_map_add(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, DOH 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 */ @@ -108,6 +108,205 @@ Swig_map_add(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, DOH return; } + +typedef struct MatchObject { + DOH *ruleset; /* Hash table of rules */ + DOHHash *p; /* Parameter on which checking starts */ + int depth; /* Depth of the match */ + struct MatchObject *next; /* Next match object */ +} MatchObject; + + +static MatchObject *matchstack = 0; + +/* ----------------------------------------------------------------------------- + * Swig_map_match() + * + * Perform a longest map match for a list of parameters and a set of mapping rules. + * Returns the corresponding rule object and the number of parameters that were + * matched. + * ----------------------------------------------------------------------------- */ + +DOH * +Swig_map_match(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, int *nmatch) +{ + DOHHash *nameset; + MatchObject *mo; + + DOH *bestobj = 0; + int bestdepth = -1; + + /* Get the nameset */ + nameset = Getattr(ruleset,rulename); + if (!nameset) return 0; + + mo = (MatchObject *) malloc(sizeof(MatchObject)); + mo->ruleset = nameset; + mo->depth = 0; + mo->p = parms; + mo->next = 0; + + matchstack = mo; + + /* Loop over all candidates until we find the best one */ + + while (matchstack) { + DOHHash *rs; + DOHHash *p; + int depth = 0; + DOH *obj; + DOHString *key; + DOHString *ty; + DOHString *name; + DOHString *nm; + int matched = 0; + + mo = matchstack; + /* See if there is a match at this level */ + rs = mo->ruleset; + obj = Getattr(rs,"*obj*"); + if (obj) { + if (mo->depth > bestdepth) { + bestdepth = mo->depth; + bestobj = obj; + } + } + p = mo->p; + + /* No more parameters. Oh well */ + if (!p) { + matchstack = mo->next; + free(mo); + continue; + } + + /* Generate some keys for checking the next parameter */ + + depth = mo->depth; + name = Getattr(p,"name"); + ty = Getattr(p,"type"); + + + if (!SwigType_isarray(ty)) { + key = NewStringf("-%s",ty); + /* See if there is a generic name match for this type */ + nm = Getattr(rs,key); + if (nm) { + /* Yes! Add to our stack. Just reuse mo for this */ + mo->ruleset = nm; + mo->p = Swig_next(p); + mo->depth++; + mo = 0; + matched++; + } + + /* See if there is a specific name match for this type */ + Clear(key); + Printf(key,"%s-%s",name,ty); + nm = Getattr(rs,key); + if (nm) { + if (!mo) { + mo = (MatchObject *) malloc(sizeof(MatchObject)); + mo->next = matchstack; + matchstack = mo; + } + mo->ruleset = nm; + mo->p = Swig_next(p); + mo->depth = depth+1; + matched++; + } + Delete(key); + } else { + /* The next parameter is an array. This is pretty nasty because we have to do a bunch of checks + related to array indices */ + + int ndim; + int i, j, k, n; + int ncheck; + DOHString *ntype; + + key = NewString(""); + + /* Drop the mo record. This is too complicated */ + matchstack = mo->next; + free(mo); + mo = 0; + + /* Get the number of array dimensions */ + ndim = SwigType_array_ndim(ty); + + /* First, we test all of the generic-unnamed parameters */ + ncheck = 1 << ndim; + + j = ncheck-1; + for (i = 0; i < ncheck; i++, j--) { + int k = j; + ntype = Copy(ty); + for (n = 0; n < ndim; n++, k = k >> 1) { + if (k & 1) { + SwigType_array_setdim(ntype,n,""); + } + } + Clear(key); + Printf(key,"-%s",ntype); + Printf(stdout,"matcharray : %s\n", key); + nm = Getattr(rs,key); + if (nm) { + mo = (MatchObject *) malloc(sizeof(MatchObject)); + mo->ruleset = nm; + mo->p = Swig_next(p); + mo->depth = depth+1; + mo->next = matchstack; + matchstack = mo; + matched++; + mo = 0; + } + Delete(ntype); + } + + /* Next check all of the named parameters */ + ncheck = 1 << ndim; + + j = ncheck-1; + for (i = 0; i < ncheck; i++, j--) { + int k = j; + ntype = Copy(ty); + for (n = 0; n < ndim; n++, k = k >> 1) { + if (k & 1) { + SwigType_array_setdim(ntype,n,""); + } + } + Clear(key); + Printf(key,"%s-%s",name,ntype); + Printf(stdout,"matcharray : %s\n", key); + nm = Getattr(rs,key); + if (nm) { + mo = (MatchObject *) malloc(sizeof(MatchObject)); + mo->ruleset = nm; + mo->p = Swig_next(p); + mo->depth = depth+1; + mo->next = matchstack; + matchstack = mo; + matched++; + mo = 0; + } + Delete(ntype); + } + Delete(key); + } + if ((!matched) && mo) { + matchstack = mo->next; + free(mo); + } + } + if (bestobj) { + *nmatch = bestdepth; + } + return bestobj; +} + +#ifdef OLD + /* ----------------------------------------------------------------------------- * Swig_map_match() * @@ -194,6 +393,7 @@ Swig_map_match(DOHHash *ruleset, DOHString_or_char *rulename, DOHHash *parms, in return best; } +#endif diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c index 9a3417e0e..cab8408c9 100644 --- a/Source/Swig/stype.c +++ b/Source/Swig/stype.c @@ -424,12 +424,13 @@ DOHString *SwigType_prefix(DOHString *t) { * Returns the number of dimensions of an array. * ----------------------------------------------------------------------------- */ -int SwigType_array_ndim(DOHString_or_char *id) { +int SwigType_array_ndim(DOHString_or_char *t) { int ndim = 0; - char *c = Char(id); + char *c = Char(t); - while (c && SwigType_isarray(c)) { + while (c && (strncmp(c,"a(",2) == 0)) { c = strchr(c,'.'); + c++; ndim++; } return ndim; @@ -441,17 +442,52 @@ int SwigType_array_ndim(DOHString_or_char *id) { * Get the value of the nth dimension. * ----------------------------------------------------------------------------- */ -DOHString *SwigType_array_getdim(DOHString_or_char *id, int n) { +DOHString *SwigType_array_getdim(DOHString_or_char *t, int n) { - char *c = Char(id); - while (c && SwigType_isarray(c) && (n > 0)) { + char *c = Char(t); + while (c && (strncmp(c,"a(",2) == 0) && (n > 0)) { c = strchr(c,'.'); + c++; n--; } if (n == 0) return SwigType_parm(c); return 0; } +/* ----------------------------------------------------------------------------- + * SwigType_array_setdim() + * + * Replace the nth dimension of an array to a new value. + * ----------------------------------------------------------------------------- */ + +void SwigType_array_setdim(DOHString_or_char *t, int n, DOHString_or_char *rep) { + DOHString *result = 0; + char temp; + char *start; + char *c = Char(t); + + start = c; + if (strncmp(c,"a(",2)) abort; + + while (c && (strncmp(c,"a(",2) == 0) && (n > 0)) { + c = strchr(c,'.'); + c++; + n--; + } + if (n == 0) { + temp = *c; + *c = 0; + result = NewString(start); + Printf(result,"a(%s)",rep); + *c = temp; + c = strchr(c,'.'); + Append(result,c); + } + Clear(t); + Append(t,result); + Delete(result); +} + /* ----------------------------------------------------------------------------- * SwigType_cstr(DOH *s, DOH *id) * diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index 31670ae96..646e6e725 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -148,6 +148,7 @@ 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); +extern void SwigType_array_setdim(DOHString_or_char *t, int n, DOHString_or_char *rep); /* --- Parse tree support --- */