| /* ----------------------------------------------------------------------------- |
| * See the LICENSE file for information on copyright, usage and redistribution |
| * of SWIG, and the README file for authors - http://www.swig.org/release.html. |
| * |
| * typemap.c |
| * |
| * A somewhat generalized implementation of SWIG1.1 typemaps. |
| * ----------------------------------------------------------------------------- */ |
| |
| char cvsroot_typemap_c[] = "$Id$"; |
| |
| #include "swig.h" |
| #include "cparse.h" |
| #include <ctype.h> |
| |
| #if 0 |
| #define SWIG_DEBUG |
| #endif |
| |
| static void replace_embedded_typemap(String *s); |
| |
| /* ----------------------------------------------------------------------------- |
| * Typemaps are stored in a collection of nested hash tables. Something like |
| * this: |
| * |
| * [ type ] |
| * +-------- [ name ] |
| * +-------- [ name ] |
| * |
| * Each hash table [ type ] or [ name ] then contains references to the |
| * different typemap methods. These are referenced by names such as |
| * "tmap:in", "tmap:out", "tmap:argout", and so forth. |
| * |
| * The object corresponding to a specific method has the following |
| * attributes: |
| * |
| * "type" - Typemap type |
| * "pname" - Parameter name |
| * "code" - Typemap code |
| * "typemap" - Descriptive text describing the actual map |
| * "locals" - Local variables (if any) |
| * |
| * ----------------------------------------------------------------------------- */ |
| |
| #define MAX_SCOPE 32 |
| |
| |
| static Hash *typemaps[MAX_SCOPE]; |
| static int tm_scope = 0; |
| |
| static Hash *get_typemap(int tm_scope, SwigType *type) { |
| Hash *tm = 0; |
| SwigType *dtype = 0; |
| if (SwigType_istemplate(type)) { |
| String *ty = Swig_symbol_template_deftype(type, 0); |
| dtype = Swig_symbol_type_qualify(ty, 0); |
| /* Printf(stderr,"gettm %s %s\n", type, dtype); */ |
| type = dtype; |
| Delete(ty); |
| } |
| tm = Getattr(typemaps[tm_scope], type); |
| |
| |
| if (dtype) { |
| if (!tm) { |
| String *t_name = SwigType_templateprefix(type); |
| if (!Equal(t_name, type)) { |
| tm = Getattr(typemaps[tm_scope], t_name); |
| } |
| Delete(t_name); |
| } |
| Delete(dtype); |
| } |
| |
| return tm; |
| } |
| |
| static void set_typemap(int tm_scope, SwigType *type, Hash *tm) { |
| SwigType *dtype = 0; |
| if (SwigType_istemplate(type)) { |
| String *ty = Swig_symbol_template_deftype(type, 0); |
| dtype = Swig_symbol_type_qualify(ty, 0); |
| /* Printf(stderr,"settm %s %s\n", type, dtype); */ |
| type = dtype; |
| Delete(ty); |
| } else { |
| dtype = Copy(type); |
| type = dtype; |
| } |
| Setattr(typemaps[tm_scope], type, tm); |
| Delete(dtype); |
| } |
| |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_init() |
| * |
| * Initialize the typemap system |
| * ----------------------------------------------------------------------------- */ |
| |
| void Swig_typemap_init() { |
| int i; |
| for (i = 0; i < MAX_SCOPE; i++) { |
| typemaps[i] = 0; |
| } |
| typemaps[0] = NewHash(); |
| tm_scope = 0; |
| } |
| |
| static String *tmop_name(const String_or_char *op) { |
| static Hash *names = 0; |
| String *s; |
| /* Due to "interesting" object-identity semantics of DOH, |
| we have to make sure that we only intern strings without object |
| identity into the hash table. |
| |
| (Swig_typemap_attach_kwargs calls tmop_name several times with |
| the "same" String *op (i.e., same object identity) but differing |
| string values.) |
| |
| Most other callers work around this by using char* rather than |
| String *. |
| -- mkoeppe, Jun 17, 2003 |
| */ |
| const char *op_without_object_identity = Char(op); |
| if (!names) |
| names = NewHash(); |
| s = Getattr(names, op_without_object_identity); |
| if (s) |
| return s; |
| s = NewStringf("tmap:%s", op); |
| Setattr(names, op_without_object_identity, s); |
| Delete(s); |
| return s; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_new_scope() |
| * |
| * Create a new typemap scope |
| * ----------------------------------------------------------------------------- */ |
| |
| void Swig_typemap_new_scope() { |
| tm_scope++; |
| typemaps[tm_scope] = NewHash(); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_pop_scope() |
| * |
| * Pop the last typemap scope off |
| * ----------------------------------------------------------------------------- */ |
| |
| Hash *Swig_typemap_pop_scope() { |
| if (tm_scope > 0) { |
| return typemaps[tm_scope--]; |
| } |
| return 0; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_register() |
| * |
| * Add a new multi-valued typemap |
| * ----------------------------------------------------------------------------- */ |
| |
| void Swig_typemap_register(const String_or_char *op, ParmList *parms, String_or_char *code, ParmList *locals, ParmList *kwargs) { |
| Hash *tm; |
| Hash *tm1; |
| Hash *tm2; |
| Parm *np; |
| String *tmop; |
| SwigType *type; |
| String *pname; |
| |
| if (!parms) |
| return; |
| tmop = tmop_name(op); |
| |
| /* Register the first type in the parameter list */ |
| |
| type = Getattr(parms, "type"); |
| pname = Getattr(parms, "name"); |
| |
| /* See if this type has been seen before */ |
| tm = get_typemap(tm_scope, type); |
| if (!tm) { |
| tm = NewHash(); |
| set_typemap(tm_scope, type, tm); |
| Delete(tm); |
| } |
| if (pname) { |
| /* See if parameter has been seen before */ |
| tm1 = Getattr(tm, pname); |
| if (!tm1) { |
| tm1 = NewHash(); |
| Setattr(tm, pname, tm1); |
| Delete(tm1); |
| } |
| tm = tm1; |
| } |
| |
| /* Now see if this typemap op has been seen before */ |
| tm2 = Getattr(tm, tmop); |
| if (!tm2) { |
| tm2 = NewHash(); |
| Setattr(tm, tmop, tm2); |
| Delete(tm2); |
| } |
| |
| /* For a multi-valued typemap, the typemap code and information |
| is really only stored in the last argument. However, to |
| make this work, we perform a really neat trick using |
| the typemap operator name. |
| |
| For example, consider this typemap |
| |
| %typemap(in) (int foo, int *bar, char *blah[]) { |
| ... |
| } |
| |
| To store it, we look at typemaps for the following: |
| |
| operator type-name |
| ---------------------------------------------- |
| "in" int foo |
| "in-int+foo:" int *bar |
| "in-int+foo:-p.int+bar: char *blah[] |
| |
| Notice how the operator expands to encode information about |
| previous arguments. |
| |
| */ |
| |
| np = nextSibling(parms); |
| if (np) { |
| /* Make an entirely new operator key */ |
| String *newop = NewStringf("%s-%s+%s:", op, type, pname); |
| /* Now reregister on the remaining arguments */ |
| Swig_typemap_register(newop, np, code, locals, kwargs); |
| |
| /* Setattr(tm2,newop,newop); */ |
| Delete(newop); |
| } else { |
| String *str = SwigType_str(type, pname); |
| String *typemap = NewStringf("typemap(%s) %s", op, str); |
| ParmList *clocals = CopyParmList(locals); |
| ParmList *ckwargs = CopyParmList(kwargs); |
| |
| Setattr(tm2, "code", code); |
| Setattr(tm2, "type", type); |
| Setattr(tm2, "typemap", typemap); |
| if (pname) { |
| Setattr(tm2, "pname", pname); |
| } |
| Setattr(tm2, "locals", clocals); |
| Setattr(tm2, "kwargs", ckwargs); |
| |
| Delete(clocals); |
| Delete(ckwargs); |
| |
| Delete(str); |
| Delete(typemap); |
| } |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_get() |
| * |
| * Retrieve typemap information from current scope. |
| * ----------------------------------------------------------------------------- */ |
| |
| static Hash *Swig_typemap_get(SwigType *type, String_or_char *name, int scope) { |
| Hash *tm, *tm1; |
| /* See if this type has been seen before */ |
| if ((scope < 0) || (scope > tm_scope)) |
| return 0; |
| tm = get_typemap(scope, type); |
| if (!tm) { |
| return 0; |
| } |
| if ((name) && Len(name)) { |
| tm1 = Getattr(tm, name); |
| return tm1; |
| } |
| return tm; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_copy() |
| * |
| * Copy a typemap |
| * ----------------------------------------------------------------------------- */ |
| |
| int Swig_typemap_copy(const String_or_char *op, ParmList *srcparms, ParmList *parms) { |
| Hash *tm = 0; |
| String *tmop; |
| Parm *p; |
| String *pname; |
| SwigType *ptype; |
| int ts = tm_scope; |
| String *tmops, *newop; |
| if (ParmList_len(parms) != ParmList_len(srcparms)) |
| return -1; |
| |
| tmop = tmop_name(op); |
| while (ts >= 0) { |
| p = srcparms; |
| tmops = NewString(tmop); |
| while (p) { |
| ptype = Getattr(p, "type"); |
| pname = Getattr(p, "name"); |
| |
| /* Lookup the type */ |
| tm = Swig_typemap_get(ptype, pname, ts); |
| if (!tm) |
| break; |
| |
| tm = Getattr(tm, tmops); |
| if (!tm) |
| break; |
| |
| /* Got a match. Look for next typemap */ |
| newop = NewStringf("%s-%s+%s:", tmops, ptype, pname); |
| Delete(tmops); |
| tmops = newop; |
| p = nextSibling(p); |
| } |
| Delete(tmops); |
| |
| if (!p && tm) { |
| |
| /* Got some kind of match */ |
| Swig_typemap_register(op, parms, Getattr(tm, "code"), Getattr(tm, "locals"), Getattr(tm, "kwargs")); |
| return 0; |
| } |
| ts--; |
| } |
| /* Not found */ |
| return -1; |
| |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_clear() |
| * |
| * Delete a multi-valued typemap |
| * ----------------------------------------------------------------------------- */ |
| |
| void Swig_typemap_clear(const String_or_char *op, ParmList *parms) { |
| SwigType *type; |
| String *name; |
| Parm *p; |
| String *newop; |
| Hash *tm = 0; |
| |
| /* This might not work */ |
| newop = NewString(op); |
| p = parms; |
| while (p) { |
| type = Getattr(p, "type"); |
| name = Getattr(p, "name"); |
| tm = Swig_typemap_get(type, name, tm_scope); |
| if (!tm) |
| return; |
| p = nextSibling(p); |
| if (p) |
| Printf(newop, "-%s+%s:", type, name); |
| } |
| if (tm) { |
| tm = Getattr(tm, tmop_name(newop)); |
| if (tm) { |
| Delattr(tm, "code"); |
| Delattr(tm, "locals"); |
| Delattr(tm, "kwargs"); |
| } |
| } |
| Delete(newop); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_apply() |
| * |
| * Multi-argument %apply directive. This is pretty horrible so I sure hope |
| * it works. |
| * ----------------------------------------------------------------------------- */ |
| |
| static |
| int count_args(String *s) { |
| /* Count up number of arguments */ |
| int na = 0; |
| char *c = Char(s); |
| while (*c) { |
| if (*c == '+') |
| na++; |
| c++; |
| } |
| return na; |
| } |
| |
| int Swig_typemap_apply(ParmList *src, ParmList *dest) { |
| String *ssig, *dsig; |
| Parm *p, *np, *lastp, *dp, *lastdp = 0; |
| int narg = 0; |
| int ts = tm_scope; |
| SwigType *type = 0, *name; |
| Hash *tm, *sm; |
| int match = 0; |
| |
| /* Printf(stdout,"apply : %s --> %s\n", ParmList_str(src), ParmList_str(dest)); */ |
| |
| /* Create type signature of source */ |
| ssig = NewStringEmpty(); |
| dsig = NewStringEmpty(); |
| p = src; |
| dp = dest; |
| lastp = 0; |
| while (p) { |
| lastp = p; |
| lastdp = dp; |
| np = nextSibling(p); |
| if (np) { |
| Printf(ssig, "-%s+%s:", Getattr(p, "type"), Getattr(p, "name")); |
| Printf(dsig, "-%s+%s:", Getattr(dp, "type"), Getattr(dp, "name")); |
| narg++; |
| } |
| p = np; |
| dp = nextSibling(dp); |
| } |
| |
| /* make sure a typemap node exists for the last destination node */ |
| type = Getattr(lastdp, "type"); |
| tm = get_typemap(tm_scope, type); |
| if (!tm) { |
| tm = NewHash(); |
| set_typemap(tm_scope, type, tm); |
| Delete(tm); |
| } |
| name = Getattr(lastdp, "name"); |
| if (name) { |
| Hash *tm1 = Getattr(tm, name); |
| if (!tm1) { |
| tm1 = NewHash(); |
| Setattr(tm, NewString(name), tm1); |
| Delete(tm1); |
| } |
| tm = tm1; |
| } |
| |
| /* This is a little nasty. We need to go searching for all possible typemaps in the |
| source and apply them to the target */ |
| |
| type = Getattr(lastp, "type"); |
| name = Getattr(lastp, "name"); |
| |
| while (ts >= 0) { |
| |
| /* See if there is a matching typemap in this scope */ |
| sm = Swig_typemap_get(type, name, ts); |
| |
| /* if there is not matching, look for a typemap in the |
| original typedef, if any, like in: |
| |
| typedef unsigned long size_t; |
| ... |
| %apply(size_t) {my_size}; ==> %apply(unsigned long) {my_size}; |
| */ |
| if (!sm) { |
| SwigType *ntype = SwigType_typedef_resolve(type); |
| if (ntype && (Cmp(ntype, type) != 0)) { |
| sm = Swig_typemap_get(ntype, name, ts); |
| } |
| Delete(ntype); |
| } |
| |
| if (sm) { |
| /* Got a typemap. Need to only merge attributes for methods that match our signature */ |
| Iterator ki; |
| match = 1; |
| for (ki = First(sm); ki.key; ki = Next(ki)) { |
| /* Check for a signature match with the source signature */ |
| if ((count_args(ki.key) == narg) && (Strstr(ki.key, ssig))) { |
| String *oldm; |
| /* A typemap we have to copy */ |
| String *nkey = Copy(ki.key); |
| Replace(nkey, ssig, dsig, DOH_REPLACE_ANY); |
| |
| /* Make sure the typemap doesn't already exist in the target map */ |
| |
| oldm = Getattr(tm, nkey); |
| if (!oldm || (!Getattr(tm, "code"))) { |
| String *code; |
| ParmList *locals; |
| ParmList *kwargs; |
| Hash *sm1 = ki.item; |
| |
| code = Getattr(sm1, "code"); |
| locals = Getattr(sm1, "locals"); |
| kwargs = Getattr(sm1, "kwargs"); |
| if (code) { |
| Replace(nkey, dsig, "", DOH_REPLACE_ANY); |
| Replace(nkey, "tmap:", "", DOH_REPLACE_ANY); |
| Swig_typemap_register(nkey, dest, code, locals, kwargs); |
| } |
| } |
| Delete(nkey); |
| } |
| } |
| } |
| ts--; |
| } |
| Delete(ssig); |
| Delete(dsig); |
| return match; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_clear_apply() |
| * |
| * %clear directive. Clears all typemaps for a type (in the current scope only). |
| * ----------------------------------------------------------------------------- */ |
| |
| /* Multi-argument %clear directive */ |
| void Swig_typemap_clear_apply(Parm *parms) { |
| String *tsig; |
| Parm *p, *np, *lastp; |
| int narg = 0; |
| Hash *tm; |
| String *name; |
| |
| /* Create a type signature of the parameters */ |
| tsig = NewStringEmpty(); |
| p = parms; |
| lastp = 0; |
| while (p) { |
| lastp = p; |
| np = nextSibling(p); |
| if (np) { |
| Printf(tsig, "-%s+%s:", Getattr(p, "type"), Getattr(p, "name")); |
| narg++; |
| } |
| p = np; |
| } |
| tm = get_typemap(tm_scope, Getattr(lastp, "type")); |
| if (!tm) { |
| Delete(tsig); |
| return; |
| } |
| name = Getattr(lastp, "name"); |
| if (name) { |
| tm = Getattr(tm, name); |
| } |
| if (tm) { |
| /* Clear typemaps that match our signature */ |
| Iterator ki, ki2; |
| char *ctsig = Char(tsig); |
| for (ki = First(tm); ki.key; ki = Next(ki)) { |
| char *ckey = Char(ki.key); |
| if (strncmp(ckey, "tmap:", 5) == 0) { |
| int na = count_args(ki.key); |
| if ((na == narg) && strstr(ckey, ctsig)) { |
| Hash *h = ki.item; |
| for (ki2 = First(h); ki2.key; ki2 = Next(ki2)) { |
| Delattr(h, ki2.key); |
| } |
| } |
| } |
| } |
| } |
| Delete(tsig); |
| } |
| |
| /* Internal function to strip array dimensions. */ |
| static SwigType *strip_arrays(SwigType *type) { |
| SwigType *t; |
| int ndim; |
| int i; |
| t = Copy(type); |
| ndim = SwigType_array_ndim(t); |
| for (i = 0; i < ndim; i++) { |
| SwigType_array_setdim(t, i, "ANY"); |
| } |
| return t; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_search() |
| * |
| * Search for a typemap match. Tries to find the most specific typemap |
| * that includes a 'code' attribute. |
| * ----------------------------------------------------------------------------- */ |
| |
| Hash *Swig_typemap_search(const String_or_char *op, SwigType *type, const String_or_char *name, SwigType **matchtype) { |
| Hash *result = 0, *tm, *tm1, *tma; |
| Hash *backup = 0; |
| SwigType *noarrays = 0; |
| SwigType *primitive = 0; |
| SwigType *ctype = 0; |
| int ts; |
| int isarray; |
| const String *cname = 0; |
| SwigType *unstripped = 0; |
| String *tmop = tmop_name(op); |
| |
| if ((name) && Len(name)) |
| cname = name; |
| ts = tm_scope; |
| |
| while (ts >= 0) { |
| ctype = type; |
| while (ctype) { |
| /* Try to get an exact type-match */ |
| tm = get_typemap(ts, ctype); |
| if (tm && cname) { |
| tm1 = Getattr(tm, cname); |
| if (tm1) { |
| result = Getattr(tm1, tmop); /* See if there is a type-name match */ |
| if (result && Getattr(result, "code")) |
| goto ret_result; |
| if (result) |
| backup = result; |
| } |
| } |
| if (tm) { |
| result = Getattr(tm, tmop); /* See if there is simply a type match */ |
| if (result && Getattr(result, "code")) |
| goto ret_result; |
| if (result) |
| backup = result; |
| } |
| isarray = SwigType_isarray(ctype); |
| if (isarray) { |
| /* If working with arrays, strip away all of the dimensions and replace with "ANY". |
| See if that generates a match */ |
| if (!noarrays) { |
| noarrays = strip_arrays(ctype); |
| } |
| tma = get_typemap(ts, noarrays); |
| if (tma && cname) { |
| tm1 = Getattr(tma, cname); |
| if (tm1) { |
| result = Getattr(tm1, tmop); /* type-name match */ |
| if (result && Getattr(result, "code")) |
| goto ret_result; |
| if (result) |
| backup = result; |
| } |
| } |
| if (tma) { |
| result = Getattr(tma, tmop); /* type match */ |
| if (result && Getattr(result, "code")) |
| goto ret_result; |
| if (result) |
| backup = result; |
| } |
| Delete(noarrays); |
| noarrays = 0; |
| } |
| |
| /* No match so far. If the type is unstripped, we'll strip its |
| qualifiers and check. Otherwise, we'll try to resolve a typedef */ |
| |
| if (!unstripped) { |
| unstripped = ctype; |
| ctype = SwigType_strip_qualifiers(ctype); |
| if (!Equal(ctype, unstripped)) |
| continue; /* Types are different */ |
| Delete(ctype); |
| ctype = unstripped; |
| unstripped = 0; |
| } |
| { |
| String *octype; |
| if (unstripped) { |
| Delete(ctype); |
| ctype = unstripped; |
| unstripped = 0; |
| } |
| octype = ctype; |
| ctype = SwigType_typedef_resolve(ctype); |
| if (octype != type) |
| Delete(octype); |
| } |
| } |
| |
| /* Hmmm. Well, no match seems to be found at all. See if there is some kind of default mapping */ |
| |
| primitive = SwigType_default(type); |
| while (primitive) { |
| tm = get_typemap(ts, primitive); |
| if (tm && cname) { |
| tm1 = Getattr(tm, cname); |
| if (tm1) { |
| result = Getattr(tm1, tmop); /* See if there is a type-name match */ |
| if (result) |
| goto ret_result; |
| } |
| } |
| if (tm) { /* See if there is simply a type match */ |
| result = Getattr(tm, tmop); |
| if (result) |
| goto ret_result; |
| } |
| { |
| SwigType *nprim = SwigType_default(primitive); |
| Delete(primitive); |
| primitive = nprim; |
| } |
| } |
| if (ctype != type) { |
| Delete(ctype); |
| ctype = 0; |
| } |
| ts--; /* Hmmm. Nothing found in this scope. Guess we'll go try another scope */ |
| } |
| result = backup; |
| |
| ret_result: |
| if (noarrays) |
| Delete(noarrays); |
| if (primitive) |
| Delete(primitive); |
| if ((unstripped) && (unstripped != type)) |
| Delete(unstripped); |
| if (matchtype) { |
| *matchtype = Copy(ctype); |
| } |
| if (type != ctype) |
| Delete(ctype); |
| return result; |
| } |
| |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_search_multi() |
| * |
| * Search for a multi-valued typemap. |
| * ----------------------------------------------------------------------------- */ |
| |
| Hash *Swig_typemap_search_multi(const String_or_char *op, ParmList *parms, int *nmatch) { |
| SwigType *type; |
| SwigType *mtype = 0; |
| String *name; |
| String *newop; |
| Hash *tm, *tm1; |
| |
| if (!parms) { |
| *nmatch = 0; |
| return 0; |
| } |
| type = Getattr(parms, "type"); |
| name = Getattr(parms, "name"); |
| |
| /* Try to find a match on the first type */ |
| tm = Swig_typemap_search(op, type, name, &mtype); |
| if (tm) { |
| if (mtype && SwigType_isarray(mtype)) { |
| Setattr(parms, "tmap:match", mtype); |
| } |
| Delete(mtype); |
| newop = NewStringf("%s-%s+%s:", op, type, name); |
| tm1 = Swig_typemap_search_multi(newop, nextSibling(parms), nmatch); |
| if (tm1) |
| tm = tm1; |
| if (Getattr(tm, "code")) { |
| *(nmatch) = *nmatch + 1; |
| } else { |
| tm = 0; |
| } |
| Delete(newop); |
| } |
| return tm; |
| } |
| |
| |
| /* ----------------------------------------------------------------------------- |
| * typemap_replace_vars() |
| * |
| * Replaces typemap variables on a string. index is the $n variable. |
| * type and pname are the type and parameter name. |
| * ----------------------------------------------------------------------------- */ |
| |
| static |
| void replace_local_types(ParmList *p, const String *name, const String *rep) { |
| SwigType *t; |
| while (p) { |
| t = Getattr(p, "type"); |
| Replace(t, name, rep, DOH_REPLACE_ANY); |
| p = nextSibling(p); |
| } |
| } |
| |
| static |
| int check_locals(ParmList *p, const char *s) { |
| while (p) { |
| char *c = GetChar(p, "type"); |
| if (strstr(c, s)) |
| return 1; |
| p = nextSibling(p); |
| } |
| return 0; |
| } |
| |
| static |
| void typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *rtype, String *pname, String *lname, int index) { |
| char var[512]; |
| char *varname; |
| SwigType *ftype; |
| |
| Replaceall(s, "$typemap", "$TYPEMAP"); |
| |
| ftype = SwigType_typedef_resolve_all(type); |
| |
| if (!pname) |
| pname = lname; |
| { |
| Parm *p; |
| int rep = 0; |
| p = locals; |
| while (p) { |
| if (Strchr(Getattr(p, "type"), '$')) |
| rep = 1; |
| p = nextSibling(p); |
| } |
| if (!rep) |
| locals = 0; |
| } |
| |
| sprintf(var, "$%d_", index); |
| varname = &var[strlen(var)]; |
| |
| /* If the original datatype was an array. We're going to go through and substitute |
| its array dimensions */ |
| |
| if (SwigType_isarray(type) || SwigType_isarray(ftype)) { |
| String *size; |
| int ndim; |
| int i; |
| if (SwigType_array_ndim(type) != SwigType_array_ndim(ftype)) |
| type = ftype; |
| ndim = SwigType_array_ndim(type); |
| size = NewStringEmpty(); |
| for (i = 0; i < ndim; i++) { |
| String *dim = SwigType_array_getdim(type, i); |
| if (index == 1) { |
| char t[32]; |
| sprintf(t, "$dim%d", i); |
| Replace(s, t, dim, DOH_REPLACE_ANY); |
| replace_local_types(locals, t, dim); |
| } |
| sprintf(varname, "dim%d", i); |
| Replace(s, var, dim, DOH_REPLACE_ANY); |
| replace_local_types(locals, var, dim); |
| if (Len(size)) |
| Putc('*', size); |
| Append(size, dim); |
| Delete(dim); |
| } |
| sprintf(varname, "size"); |
| Replace(s, var, size, DOH_REPLACE_ANY); |
| replace_local_types(locals, var, size); |
| Delete(size); |
| } |
| |
| /* Parameter name substitution */ |
| if (index == 1) { |
| Replace(s, "$parmname", pname, DOH_REPLACE_ANY); |
| } |
| strcpy(varname, "name"); |
| Replace(s, var, pname, DOH_REPLACE_ANY); |
| |
| /* Type-related stuff */ |
| { |
| SwigType *star_type, *amp_type, *base_type, *lex_type; |
| SwigType *ltype, *star_ltype, *amp_ltype; |
| String *mangle, *star_mangle, *amp_mangle, *base_mangle, *base_name; |
| String *descriptor, *star_descriptor, *amp_descriptor; |
| String *ts; |
| char *sc; |
| |
| sc = Char(s); |
| |
| if (strstr(sc, "type") || check_locals(locals, "type")) { |
| /* Given type : $type */ |
| ts = SwigType_str(type, 0); |
| if (index == 1) { |
| Replace(s, "$type", ts, DOH_REPLACE_ANY); |
| replace_local_types(locals, "$type", type); |
| } |
| strcpy(varname, "type"); |
| Replace(s, var, ts, DOH_REPLACE_ANY); |
| replace_local_types(locals, var, type); |
| Delete(ts); |
| sc = Char(s); |
| } |
| if (strstr(sc, "ltype") || check_locals(locals, "ltype")) { |
| /* Local type: $ltype */ |
| ltype = SwigType_ltype(type); |
| ts = SwigType_str(ltype, 0); |
| if (index == 1) { |
| Replace(s, "$ltype", ts, DOH_REPLACE_ANY); |
| replace_local_types(locals, "$ltype", ltype); |
| } |
| strcpy(varname, "ltype"); |
| Replace(s, var, ts, DOH_REPLACE_ANY); |
| replace_local_types(locals, var, ltype); |
| Delete(ts); |
| Delete(ltype); |
| sc = Char(s); |
| } |
| if (strstr(sc, "mangle") || strstr(sc, "descriptor")) { |
| /* Mangled type */ |
| |
| mangle = SwigType_manglestr(type); |
| if (index == 1) |
| Replace(s, "$mangle", mangle, DOH_REPLACE_ANY); |
| strcpy(varname, "mangle"); |
| Replace(s, var, mangle, DOH_REPLACE_ANY); |
| |
| descriptor = NewStringf("SWIGTYPE%s", mangle); |
| |
| if (index == 1) |
| if (Replace(s, "$descriptor", descriptor, DOH_REPLACE_ANY)) |
| SwigType_remember(type); |
| |
| strcpy(varname, "descriptor"); |
| if (Replace(s, var, descriptor, DOH_REPLACE_ANY)) |
| SwigType_remember(type); |
| |
| Delete(descriptor); |
| Delete(mangle); |
| } |
| |
| /* One pointer level removed */ |
| /* This creates variables of the form |
| $*n_type |
| $*n_ltype |
| */ |
| |
| if (SwigType_ispointer(ftype) || (SwigType_isarray(ftype)) || (SwigType_isreference(ftype))) { |
| if (!(SwigType_isarray(type) || SwigType_ispointer(type) || SwigType_isreference(type))) { |
| star_type = Copy(ftype); |
| } else { |
| star_type = Copy(type); |
| } |
| if (!SwigType_isreference(star_type)) { |
| if (SwigType_isarray(star_type)) { |
| SwigType_del_element(star_type); |
| } else { |
| SwigType_del_pointer(star_type); |
| } |
| ts = SwigType_str(star_type, 0); |
| if (index == 1) { |
| Replace(s, "$*type", ts, DOH_REPLACE_ANY); |
| replace_local_types(locals, "$*type", star_type); |
| } |
| sprintf(varname, "$*%d_type", index); |
| Replace(s, varname, ts, DOH_REPLACE_ANY); |
| replace_local_types(locals, varname, star_type); |
| Delete(ts); |
| } else { |
| SwigType_del_element(star_type); |
| } |
| star_ltype = SwigType_ltype(star_type); |
| ts = SwigType_str(star_ltype, 0); |
| if (index == 1) { |
| Replace(s, "$*ltype", ts, DOH_REPLACE_ANY); |
| replace_local_types(locals, "$*ltype", star_ltype); |
| } |
| sprintf(varname, "$*%d_ltype", index); |
| Replace(s, varname, ts, DOH_REPLACE_ANY); |
| replace_local_types(locals, varname, star_ltype); |
| Delete(ts); |
| Delete(star_ltype); |
| |
| star_mangle = SwigType_manglestr(star_type); |
| if (index == 1) |
| Replace(s, "$*mangle", star_mangle, DOH_REPLACE_ANY); |
| |
| sprintf(varname, "$*%d_mangle", index); |
| Replace(s, varname, star_mangle, DOH_REPLACE_ANY); |
| |
| star_descriptor = NewStringf("SWIGTYPE%s", star_mangle); |
| if (index == 1) |
| if (Replace(s, "$*descriptor", star_descriptor, DOH_REPLACE_ANY)) |
| SwigType_remember(star_type); |
| sprintf(varname, "$*%d_descriptor", index); |
| if (Replace(s, varname, star_descriptor, DOH_REPLACE_ANY)) |
| SwigType_remember(star_type); |
| |
| Delete(star_descriptor); |
| Delete(star_mangle); |
| Delete(star_type); |
| } else { |
| /* TODO: Signal error if one of the $* substitutions is |
| requested */ |
| } |
| /* One pointer level added */ |
| amp_type = Copy(type); |
| SwigType_add_pointer(amp_type); |
| ts = SwigType_str(amp_type, 0); |
| if (index == 1) { |
| Replace(s, "$&type", ts, DOH_REPLACE_ANY); |
| replace_local_types(locals, "$&type", amp_type); |
| } |
| sprintf(varname, "$&%d_type", index); |
| Replace(s, varname, ts, DOH_REPLACE_ANY); |
| replace_local_types(locals, varname, amp_type); |
| Delete(ts); |
| |
| amp_ltype = SwigType_ltype(type); |
| SwigType_add_pointer(amp_ltype); |
| ts = SwigType_str(amp_ltype, 0); |
| |
| if (index == 1) { |
| Replace(s, "$<ype", ts, DOH_REPLACE_ANY); |
| replace_local_types(locals, "$<ype", amp_ltype); |
| } |
| sprintf(varname, "$&%d_ltype", index); |
| Replace(s, varname, ts, DOH_REPLACE_ANY); |
| replace_local_types(locals, varname, amp_ltype); |
| Delete(ts); |
| Delete(amp_ltype); |
| |
| amp_mangle = SwigType_manglestr(amp_type); |
| if (index == 1) |
| Replace(s, "$&mangle", amp_mangle, DOH_REPLACE_ANY); |
| sprintf(varname, "$&%d_mangle", index); |
| Replace(s, varname, amp_mangle, DOH_REPLACE_ANY); |
| |
| amp_descriptor = NewStringf("SWIGTYPE%s", amp_mangle); |
| if (index == 1) |
| if (Replace(s, "$&descriptor", amp_descriptor, DOH_REPLACE_ANY)) |
| SwigType_remember(amp_type); |
| sprintf(varname, "$&%d_descriptor", index); |
| if (Replace(s, varname, amp_descriptor, DOH_REPLACE_ANY)) |
| SwigType_remember(amp_type); |
| |
| Delete(amp_descriptor); |
| Delete(amp_mangle); |
| Delete(amp_type); |
| |
| /* Base type */ |
| if (SwigType_isarray(type)) { |
| SwigType *bt = Copy(type); |
| Delete(SwigType_pop_arrays(bt)); |
| base_type = SwigType_str(bt, 0); |
| Delete(bt); |
| } else { |
| base_type = SwigType_base(type); |
| } |
| |
| base_name = SwigType_namestr(base_type); |
| if (index == 1) { |
| Replace(s, "$basetype", base_name, DOH_REPLACE_ANY); |
| replace_local_types(locals, "$basetype", base_name); |
| } |
| strcpy(varname, "basetype"); |
| Replace(s, var, base_type, DOH_REPLACE_ANY); |
| replace_local_types(locals, var, base_name); |
| |
| base_mangle = SwigType_manglestr(base_type); |
| if (index == 1) |
| Replace(s, "$basemangle", base_mangle, DOH_REPLACE_ANY); |
| strcpy(varname, "basemangle"); |
| Replace(s, var, base_mangle, DOH_REPLACE_ANY); |
| Delete(base_mangle); |
| Delete(base_type); |
| Delete(base_name); |
| |
| lex_type = SwigType_base(rtype); |
| if (index == 1) |
| Replace(s, "$lextype", lex_type, DOH_REPLACE_ANY); |
| strcpy(varname, "lextype"); |
| Replace(s, var, lex_type, DOH_REPLACE_ANY); |
| Delete(lex_type); |
| } |
| |
| /* Replace any $n. with (&n)-> */ |
| { |
| char temp[64]; |
| sprintf(var, "$%d.", index); |
| sprintf(temp, "(&$%d)->", index); |
| Replace(s, var, temp, DOH_REPLACE_ANY); |
| } |
| |
| /* Replace the bare $n variable */ |
| sprintf(var, "$%d", index); |
| Replace(s, var, lname, DOH_REPLACE_ANY); |
| Delete(ftype); |
| } |
| |
| /* ------------------------------------------------------------------------ |
| * static typemap_locals() |
| * |
| * Takes a string, a parameter list and a wrapper function argument and |
| * creates the local variables. |
| * ------------------------------------------------------------------------ */ |
| |
| static void typemap_locals(DOHString * s, ParmList *l, Wrapper *f, int argnum) { |
| Parm *p; |
| char *new_name; |
| |
| p = l; |
| while (p) { |
| SwigType *pt = Getattr(p, "type"); |
| SwigType *at = SwigType_alttype(pt, 1); |
| String *pn = Getattr(p, "name"); |
| String *value = Getattr(p, "value"); |
| if (at) |
| pt = at; |
| if (pn) { |
| if (Len(pn) > 0) { |
| String *str; |
| int isglobal = 0; |
| |
| str = NewStringEmpty(); |
| |
| if (strncmp(Char(pn), "_global_", 8) == 0) { |
| isglobal = 1; |
| } |
| |
| /* If the user gave us $type as the name of the local variable, we'll use |
| the passed datatype instead */ |
| |
| if ((argnum >= 0) && (!isglobal)) { |
| Printf(str, "%s%d", pn, argnum); |
| } else { |
| Append(str, pn); |
| } |
| if (isglobal && Wrapper_check_local(f, str)) { |
| p = nextSibling(p); |
| Delete(str); |
| if (at) |
| Delete(at); |
| continue; |
| } |
| if (value) { |
| String *pstr = SwigType_str(pt, str); |
| new_name = Wrapper_new_localv(f, str, pstr, "=", value, NIL); |
| Delete(pstr); |
| } else { |
| String *pstr = SwigType_str(pt, str); |
| new_name = Wrapper_new_localv(f, str, pstr, NIL); |
| Delete(pstr); |
| } |
| if (!isglobal) { |
| /* Substitute */ |
| Replace(s, pn, new_name, DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE); |
| } |
| Delete(str); |
| } |
| } |
| p = nextSibling(p); |
| if (at) |
| Delete(at); |
| } |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_lookup() |
| * |
| * Perform a typemap lookup (ala SWIG1.1) |
| * ----------------------------------------------------------------------------- */ |
| |
| String *Swig_typemap_lookup(const String_or_char *op, SwigType *type, String_or_char *pname, |
| String_or_char *lname, String_or_char *source, String_or_char *target, Wrapper *f) { |
| Hash *tm; |
| String *s = 0; |
| SwigType *mtype = 0; |
| ParmList *locals; |
| tm = Swig_typemap_search(op, type, pname, &mtype); |
| if (!tm) |
| return 0; |
| |
| s = Getattr(tm, "code"); |
| if (!s) { |
| if (mtype) |
| Delete(mtype); |
| return 0; |
| } |
| |
| |
| /* Blocked */ |
| if (Cmp(s, "pass") == 0) { |
| Delete(mtype); |
| return 0; |
| } |
| |
| s = Copy(s); /* Make a local copy of the typemap code */ |
| |
| locals = Getattr(tm, "locals"); |
| if (locals) |
| locals = CopyParmList(locals); |
| |
| /* This is wrong. It replaces locals in place. Need to fix this */ |
| if (mtype && SwigType_isarray(mtype)) { |
| typemap_replace_vars(s, locals, mtype, type, pname, lname, 1); |
| } else { |
| typemap_replace_vars(s, locals, type, type, pname, lname, 1); |
| } |
| |
| if (locals && f) { |
| typemap_locals(s, locals, f, -1); |
| } |
| |
| replace_embedded_typemap(s); |
| |
| /* Now perform character replacements */ |
| Replace(s, "$source", source, DOH_REPLACE_ANY); |
| Replace(s, "$target", target, DOH_REPLACE_ANY); |
| |
| /* { |
| String *tmname = Getattr(tm,"typemap"); |
| if (tmname) Replace(s,"$typemap",tmname, DOH_REPLACE_ANY); |
| } |
| */ |
| |
| Replace(s, "$parmname", pname, DOH_REPLACE_ANY); |
| /* Replace(s,"$name",pname,DOH_REPLACE_ANY); */ |
| |
| Delete(locals); |
| Delete(mtype); |
| return s; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_lookup_new() |
| * |
| * Attach one or more typemaps to a node |
| * op - typemap name, eg "out", "newfree" |
| * node - the node to attach the typemaps to |
| * lname - |
| * f - |
| * ----------------------------------------------------------------------------- */ |
| |
| String *Swig_typemap_lookup_new(const String_or_char *op, Node *node, const String_or_char *lname, Wrapper *f) { |
| SwigType *type; |
| SwigType *mtype = 0; |
| String *pname; |
| Hash *tm = 0; |
| String *s = 0; |
| String *sdef = 0; |
| ParmList *locals; |
| ParmList *kw; |
| char temp[256]; |
| String *symname; |
| String *cname = 0; |
| String *clname = 0; |
| char *cop = Char(op); |
| /* special case, we need to check for 'ref' call |
| and set the default code 'sdef' */ |
| if (node && Cmp(op, "newfree") == 0) { |
| sdef = Swig_ref_call(node, lname); |
| } |
| |
| type = Getattr(node, "type"); |
| if (!type) |
| return sdef; |
| |
| pname = Getattr(node, "name"); |
| |
| #if 1 |
| if (pname && node && checkAttribute(node, "kind", "function")) { |
| /* |
| For functions, look qualified names first, such as |
| |
| struct Foo { |
| int *foo(int bar) -> Foo::foo |
| }; |
| */ |
| Symtab *st = Getattr(node, "sym:symtab"); |
| String *qsn = st ? Swig_symbol_string_qualify(pname, st) : 0; |
| if (qsn) { |
| if (Len(qsn) && !Equal(qsn, pname)) { |
| tm = Swig_typemap_search(op, type, qsn, &mtype); |
| if (tm && (!Getattr(tm, "pname") || strstr(Char(Getattr(tm, "type")), "SWIGTYPE"))) { |
| tm = 0; |
| } |
| } |
| Delete(qsn); |
| } |
| } |
| if (!tm) |
| #endif |
| tm = Swig_typemap_search(op, type, pname, &mtype); |
| if (!tm) |
| return sdef; |
| |
| s = Getattr(tm, "code"); |
| if (!s) |
| return sdef; |
| |
| /* Empty typemap. No match */ |
| if (Cmp(s, "pass") == 0) |
| return sdef; |
| |
| s = Copy(s); /* Make a local copy of the typemap code */ |
| |
| locals = Getattr(tm, "locals"); |
| if (locals) |
| locals = CopyParmList(locals); |
| |
| if (pname) { |
| if (SwigType_istemplate(pname)) { |
| cname = SwigType_namestr(pname); |
| pname = cname; |
| } |
| } |
| if (SwigType_istemplate((char *) lname)) { |
| clname = SwigType_namestr((char *) lname); |
| lname = clname; |
| } |
| |
| if (mtype && SwigType_isarray(mtype)) { |
| typemap_replace_vars(s, locals, mtype, type, pname, (char *) lname, 1); |
| } else { |
| typemap_replace_vars(s, locals, type, type, pname, (char *) lname, 1); |
| } |
| |
| if (locals && f) { |
| typemap_locals(s, locals, f, -1); |
| } |
| replace_embedded_typemap(s); |
| /* { |
| String *tmname = Getattr(tm,"typemap"); |
| if (tmname) Replace(s,"$typemap",tmname, DOH_REPLACE_ANY); |
| } */ |
| |
| Replace(s, "$name", pname, DOH_REPLACE_ANY); |
| |
| symname = Getattr(node, "sym:name"); |
| if (symname) { |
| Replace(s, "$symname", symname, DOH_REPLACE_ANY); |
| } |
| |
| Setattr(node, tmop_name(op), s); |
| if (locals) { |
| sprintf(temp, "%s:locals", cop); |
| Setattr(node, tmop_name(temp), locals); |
| Delete(locals); |
| } |
| |
| if (Checkattr(tm, "type", "SWIGTYPE")) { |
| sprintf(temp, "%s:SWIGTYPE", cop); |
| Setattr(node, tmop_name(temp), "1"); |
| } |
| |
| /* Attach kwargs */ |
| kw = Getattr(tm, "kwargs"); |
| while (kw) { |
| String *value = Copy(Getattr(kw, "value")); |
| String *type = Getattr(kw, "type"); |
| char *ckwname = Char(Getattr(kw, "name")); |
| if (type) { |
| String *mangle = Swig_string_mangle(type); |
| Append(value, mangle); |
| Delete(mangle); |
| } |
| sprintf(temp, "%s:%s", cop, ckwname); |
| Setattr(node, tmop_name(temp), value); |
| Delete(value); |
| kw = nextSibling(kw); |
| } |
| |
| /* Look for warnings */ |
| { |
| String *w; |
| sprintf(temp, "%s:warning", cop); |
| w = Getattr(node, tmop_name(temp)); |
| if (w) { |
| Swig_warning(0, Getfile(node), Getline(node), "%s\n", w); |
| } |
| } |
| |
| /* Look for code fragments */ |
| { |
| String *f; |
| sprintf(temp, "%s:fragment", cop); |
| f = Getattr(node, tmop_name(temp)); |
| if (f) { |
| String *fname = Copy(f); |
| Setfile(fname, Getfile(node)); |
| Setline(fname, Getline(node)); |
| Swig_fragment_emit(fname); |
| Delete(fname); |
| } |
| } |
| |
| if (cname) |
| Delete(cname); |
| if (clname) |
| Delete(clname); |
| if (mtype) |
| Delete(mtype); |
| if (sdef) { /* put 'ref' and 'newfree' codes together */ |
| String *p = NewStringf("%s\n%s", sdef, s); |
| Delete(s); |
| Delete(sdef); |
| s = p; |
| } |
| return s; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_attach_kwargs() |
| * |
| * If this hash (tm) contains a linked list of parameters under its "kwargs" |
| * attribute, add keys for each of those named keyword arguments to this |
| * parameter for later use. |
| * For example, attach the typemap attributes to p: |
| * %typemap(in, foo="xyz") ... |
| * A new attribute called "tmap:in:foo" with value "xyz" is attached to p. |
| * ----------------------------------------------------------------------------- */ |
| |
| void Swig_typemap_attach_kwargs(Hash *tm, const String_or_char *op, Parm *p) { |
| String *temp = NewStringEmpty(); |
| Parm *kw = Getattr(tm, "kwargs"); |
| while (kw) { |
| String *value = Copy(Getattr(kw, "value")); |
| String *type = Getattr(kw, "type"); |
| if (type) { |
| Hash *v = NewHash(); |
| Setattr(v, "type", type); |
| Setattr(v, "value", value); |
| Delete(value); |
| value = v; |
| } |
| Clear(temp); |
| Printf(temp, "%s:%s", op, Getattr(kw, "name")); |
| Setattr(p, tmop_name(temp), value); |
| Delete(value); |
| kw = nextSibling(kw); |
| } |
| Clear(temp); |
| Printf(temp, "%s:match_type", op); |
| Setattr(p, tmop_name(temp), Getattr(tm, "type")); |
| Delete(temp); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_warn() |
| * |
| * If any warning message is attached to this parameter's "tmap:op:warning" |
| * attribute, print that warning message. |
| * ----------------------------------------------------------------------------- */ |
| |
| static void Swig_typemap_warn(const String_or_char *op, Parm *p) { |
| String *temp = NewStringf("%s:warning", op); |
| String *w = Getattr(p, tmop_name(temp)); |
| Delete(temp); |
| if (w) { |
| Swig_warning(0, Getfile(p), Getline(p), "%s\n", w); |
| } |
| } |
| |
| static void Swig_typemap_emit_code_fragments(const String_or_char *op, Parm *p) { |
| String *temp = NewStringf("%s:fragment", op); |
| String *f = Getattr(p, tmop_name(temp)); |
| if (f) { |
| String *fname = Copy(f); |
| Setfile(fname, Getfile(p)); |
| Setline(fname, Getline(p)); |
| Swig_fragment_emit(fname); |
| Delete(fname); |
| } |
| Delete(temp); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_attach_parms() |
| * |
| * Given a parameter list, this function attaches all of the typemaps for a |
| * given typemap type |
| * ----------------------------------------------------------------------------- */ |
| |
| String *Swig_typemap_get_option(Hash *tm, String *name) { |
| Parm *kw = Getattr(tm, "kwargs"); |
| while (kw) { |
| String *kname = Getattr(kw, "name"); |
| if (Equal(kname, name)) { |
| return Getattr(kw, "value"); |
| } |
| kw = nextSibling(kw); |
| } |
| return 0; |
| } |
| |
| void Swig_typemap_attach_parms(const String_or_char *op, ParmList *parms, Wrapper *f) { |
| Parm *p, *firstp; |
| Hash *tm; |
| int nmatch = 0; |
| int i; |
| String *s; |
| ParmList *locals; |
| int argnum = 0; |
| char temp[256]; |
| char *cop = Char(op); |
| String *kwmatch = 0; |
| p = parms; |
| |
| #ifdef SWIG_DEBUG |
| Printf(stdout, "Swig_typemap_attach_parms: %s\n", op); |
| #endif |
| |
| while (p) { |
| argnum++; |
| nmatch = 0; |
| #ifdef SWIG_DEBUG |
| Printf(stdout, "parms: %s %s %s\n", op, Getattr(p, "name"), Getattr(p, "type")); |
| #endif |
| tm = Swig_typemap_search_multi(op, p, &nmatch); |
| #ifdef SWIG_DEBUG |
| if (tm) |
| Printf(stdout, "found: %s\n", tm); |
| #endif |
| if (!tm) { |
| p = nextSibling(p); |
| continue; |
| } |
| /* |
| Check if the typemap requires to match the type of another |
| typemap, for example: |
| |
| %typemap(in) SWIGTYPE * (int var) {...} |
| %typemap(freearg,match="in") SWIGTYPE * {if (var$argnum) ...} |
| |
| here, the freearg typemap requires the "in" typemap to match, |
| or the 'var$argnum' variable will not exist. |
| */ |
| kwmatch = Swig_typemap_get_option(tm, "match"); |
| if (kwmatch) { |
| String *tmname = NewStringf("tmap:%s", kwmatch); |
| String *tmin = Getattr(p, tmname); |
| Delete(tmname); |
| #ifdef SWIG_DEBUG |
| if (tm) |
| Printf(stdout, "matching: %s\n", kwmatch); |
| #endif |
| if (tmin) { |
| String *tmninp = NewStringf("tmap:%s:numinputs", kwmatch); |
| String *ninp = Getattr(p, tmninp); |
| Delete(tmninp); |
| if (ninp && Equal(ninp, "0")) { |
| p = nextSibling(p); |
| continue; |
| } else { |
| SwigType *typetm = Getattr(tm, "type"); |
| String *temp = NewStringf("tmap:%s:match_type", kwmatch); |
| SwigType *typein = Getattr(p, temp); |
| Delete(temp); |
| if (!Equal(typein, typetm)) { |
| p = nextSibling(p); |
| continue; |
| } else { |
| int nnmatch; |
| Hash *tmapin = Swig_typemap_search_multi(kwmatch, p, &nnmatch); |
| String *tmname = Getattr(tm, "pname"); |
| String *tnname = Getattr(tmapin, "pname"); |
| if (!(tmname && tnname && Equal(tmname, tnname)) && !(!tmname && !tnname)) { |
| p = nextSibling(p); |
| continue; |
| } |
| } |
| |
| } |
| } else { |
| p = nextSibling(p); |
| continue; |
| } |
| } |
| |
| s = Getattr(tm, "code"); |
| if (!s) { |
| p = nextSibling(p); |
| continue; |
| } |
| #ifdef SWIG_DEBUG |
| if (s) |
| Printf(stdout, "code: %s\n", s); |
| #endif |
| |
| /* Empty typemap. No match */ |
| if (Cmp(s, "pass") == 0) { |
| p = nextSibling(p); |
| continue; |
| } |
| |
| s = Copy(s); |
| locals = Getattr(tm, "locals"); |
| if (locals) |
| locals = CopyParmList(locals); |
| firstp = p; |
| #ifdef SWIG_DEBUG |
| Printf(stdout, "nmatch: %d\n", nmatch); |
| #endif |
| for (i = 0; i < nmatch; i++) { |
| SwigType *type; |
| String *pname; |
| String *lname; |
| SwigType *mtype; |
| |
| |
| type = Getattr(p, "type"); |
| pname = Getattr(p, "name"); |
| lname = Getattr(p, "lname"); |
| mtype = Getattr(p, "tmap:match"); |
| |
| if (mtype) { |
| typemap_replace_vars(s, locals, mtype, type, pname, lname, i + 1); |
| Delattr(p, "tmap:match"); |
| } else { |
| typemap_replace_vars(s, locals, type, type, pname, lname, i + 1); |
| } |
| |
| if (Checkattr(tm, "type", "SWIGTYPE")) { |
| sprintf(temp, "%s:SWIGTYPE", cop); |
| Setattr(p, tmop_name(temp), "1"); |
| } |
| p = nextSibling(p); |
| } |
| |
| if (locals && f) { |
| typemap_locals(s, locals, f, argnum); |
| } |
| |
| replace_embedded_typemap(s); |
| |
| /* Replace the argument number */ |
| sprintf(temp, "%d", argnum); |
| Replace(s, "$argnum", temp, DOH_REPLACE_ANY); |
| |
| /* Attach attributes to object */ |
| #ifdef SWIG_DEBUG |
| Printf(stdout, "attach: %s %s %s\n", Getattr(firstp, "name"), tmop_name(op), s); |
| #endif |
| Setattr(firstp, tmop_name(op), s); /* Code object */ |
| |
| if (locals) { |
| sprintf(temp, "%s:locals", cop); |
| Setattr(firstp, tmop_name(temp), locals); |
| Delete(locals); |
| } |
| |
| /* Attach a link to the next parameter. Needed for multimaps */ |
| sprintf(temp, "%s:next", cop); |
| Setattr(firstp, tmop_name(temp), p); |
| |
| /* Attach kwargs */ |
| Swig_typemap_attach_kwargs(tm, op, firstp); |
| |
| /* Print warnings, if any */ |
| Swig_typemap_warn(op, firstp); |
| |
| /* Look for code fragments */ |
| Swig_typemap_emit_code_fragments(op, firstp); |
| |
| /* increase argnum to consider numinputs */ |
| argnum += nmatch - 1; |
| Delete(s); |
| #ifdef SWIG_DEBUG |
| Printf(stdout, "res: %s %s %s\n", Getattr(firstp, "name"), tmop_name(op), Getattr(firstp, tmop_name(op))); |
| #endif |
| |
| } |
| #ifdef SWIG_DEBUG |
| Printf(stdout, "Swig_typemap_attach_parms: end\n"); |
| #endif |
| |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * split_embedded() |
| * |
| * This function replaces the special variable $typemap(....) with typemap |
| * code. The general form of $typemap is as follows: |
| * |
| * $TYPEMAP(method, $var1=value, $var2=value, $var3=value,...) |
| * |
| * For example: |
| * |
| * $TYPEMAP(in, $1=int x, $input=y, ...) |
| * |
| * Note: this was added as an experiment and could be removed |
| * ----------------------------------------------------------------------------- */ |
| |
| /* Splits the arguments of an embedded typemap */ |
| static List *split_embedded(String *s) { |
| List *args = 0; |
| char *c, *start; |
| int level = 0; |
| int leading = 1; |
| args = NewList(); |
| |
| c = strchr(Char(s), '('); |
| c++; |
| |
| start = c; |
| while (*c) { |
| if (*c == '\"') { |
| c++; |
| while (*c) { |
| if (*c == '\\') { |
| c++; |
| } else { |
| if (*c == '\"') |
| break; |
| } |
| c++; |
| } |
| } |
| if ((level == 0) && ((*c == ',') || (*c == ')'))) { |
| String *tmp = NewStringWithSize(start, c - start); |
| Append(args, tmp); |
| Delete(tmp); |
| start = c + 1; |
| leading = 1; |
| if (*c == ')') |
| break; |
| c++; |
| continue; |
| } |
| if (*c == '(') |
| level++; |
| if (*c == ')') |
| level--; |
| if (isspace((int) *c) && leading) |
| start++; |
| if (!isspace((int) *c)) |
| leading = 0; |
| c++; |
| } |
| return args; |
| } |
| |
| static void split_var(String *s, String **name, String **value) { |
| char *eq; |
| char *c; |
| |
| eq = strchr(Char(s), '='); |
| if (!eq) { |
| *name = 0; |
| *value = 0; |
| return; |
| } |
| c = Char(s); |
| *name = NewStringWithSize(c, eq - c); |
| |
| /* Look for $n variables */ |
| if (isdigit((int) *(c))) { |
| /* Parse the value as a type */ |
| String *v; |
| Parm *p; |
| v = NewString(eq + 1); |
| p = Swig_cparse_parm(v); |
| Delete(v); |
| *value = p; |
| } else { |
| *value = NewString(eq + 1); |
| } |
| } |
| |
| static void replace_embedded_typemap(String *s) { |
| char *start = 0; |
| while ((start = strstr(Char(s), "$TYPEMAP("))) { |
| |
| /* Gather the argument */ |
| char *end = 0, *c; |
| int level = 0; |
| String *tmp; |
| c = start; |
| while (*c) { |
| if (*c == '(') |
| level++; |
| if (*c == ')') { |
| level--; |
| if (level == 0) { |
| end = c + 1; |
| break; |
| } |
| } |
| c++; |
| } |
| if (end) { |
| tmp = NewStringWithSize(start, (end - start)); |
| } else { |
| tmp = 0; |
| } |
| |
| /* Got a substitution. Split it apart into pieces */ |
| if (tmp) { |
| List *l; |
| Hash *vars; |
| String *method; |
| int i, ilen; |
| |
| l = split_embedded(tmp); |
| vars = NewHash(); |
| ilen = Len(l); |
| for (i = 1; i < ilen; i++) { |
| String *n, *v; |
| split_var(Getitem(l, i), &n, &v); |
| if (n && v) { |
| Insert(n, 0, "$"); |
| Setattr(vars, n, v); |
| } |
| Delete(n); |
| Delete(v); |
| } |
| |
| method = Getitem(l, 0); |
| /* Generate the parameter list for matching typemaps */ |
| |
| { |
| Parm *p = 0; |
| Parm *first = 0; |
| char temp[32]; |
| int n = 1; |
| while (1) { |
| Hash *v; |
| sprintf(temp, "$%d", n); |
| v = Getattr(vars, temp); |
| if (v) { |
| if (p) { |
| set_nextSibling(p, v); |
| set_previousSibling(v, p); |
| } |
| p = v; |
| Setattr(p, "lname", Getattr(p, "name")); |
| if (Getattr(p, "value")) { |
| Setattr(p, "name", Getattr(p, "value")); |
| } |
| if (!first) |
| first = p; |
| DohIncref(p); |
| Delattr(vars, temp); |
| } else { |
| break; |
| } |
| n++; |
| } |
| /* Perform a typemap search */ |
| if (first) { |
| #ifdef SWIG_DEBUG |
| Printf(stdout, "Swig_typemap_attach_parms: embedded\n"); |
| #endif |
| Swig_typemap_attach_parms(method, first, 0); |
| { |
| String *tm; |
| int match = 0; |
| char attr[64]; |
| sprintf(attr, "tmap:%s", Char(method)); |
| |
| /* Look for the typemap code */ |
| tm = Getattr(first, attr); |
| if (tm) { |
| sprintf(attr, "tmap:%s:next", Char(method)); |
| if (!Getattr(first, attr)) { |
| /* Should be no more matches. Hack??? */ |
| /* Replace all of the remaining variables */ |
| Iterator ki; |
| for (ki = First(vars); ki.key; ki = Next(ki)) { |
| Replace(tm, ki.key, ki.item, DOH_REPLACE_ANY); |
| } |
| /* Do the replacement */ |
| Replace(s, tmp, tm, DOH_REPLACE_ANY); |
| Delete(tm); |
| match = 1; |
| } |
| } |
| if (!match) { |
| Swig_error(Getfile(s), Getline(s), "No typemap found for %s\n", tmp); |
| } |
| } |
| } |
| } |
| Replace(s, tmp, "<embedded typemap>", DOH_REPLACE_ANY); |
| Delete(vars); |
| Delete(tmp); |
| Delete(l); |
| } |
| } |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Swig_typemap_debug() |
| * ----------------------------------------------------------------------------- */ |
| |
| void Swig_typemap_debug() { |
| int ts; |
| Printf(stdout, "---[ typemaps ]--------------------------------------------------------------\n"); |
| |
| ts = tm_scope; |
| while (ts >= 0) { |
| Printf(stdout, "::: scope %d\n\n", ts); |
| Printf(stdout, "%s\n", typemaps[ts]); |
| ts--; |
| } |
| Printf(stdout, "-----------------------------------------------------------------------------\n"); |
| } |