/* ----------------------------------------------------------------------------- * typemap.c * * A somewhat generalized implementation of SWIG1.1 typemaps. * * 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. * ----------------------------------------------------------------------------- */ char cvsroot_typemap_c[] = "$Header$"; #include "swig.h" /* ----------------------------------------------------------------------------- * 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; /* ----------------------------------------------------------------------------- * 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; if (!names) names = NewHash(); s = Getattr(names,op); if (s) return s; s = NewStringf("tmap:%s",op); Setattr(names,op,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 = Getattr(typemaps[tm_scope],type); if (!tm) { tm = NewHash(); Setattr(typemaps[tm_scope],Copy(type),tm); Delete(tm); } if (pname) { /* See if parameter has been seen before */ tm1 = Getattr(tm,pname); if (!tm1) { tm1 = NewHash(); Setattr(tm,NewString(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 { Setattr(tm2,"code",NewString(code)); Setattr(tm2,"type",Copy(type)); Setattr(tm2,"typemap",NewStringf("typemap(%s) %s", op, SwigType_str(type,pname))); if (pname) { Setattr(tm2,"pname", NewString(pname)); } Setattr(tm2,"locals", CopyParmList(locals)); Setattr(tm2,"kwargs", CopyParmList(kwargs)); } } /* ----------------------------------------------------------------------------- * 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 = Getattr(typemaps[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 = NewString(""); dsig = NewString(""); 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 */ tm = Getattr(typemaps[tm_scope],Getattr(lastdp,"type")); if (!tm) { tm = NewHash(); Setattr(typemaps[tm_scope],Getattr(lastdp,"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 (sm) { /* Got a typemap. Need to only merge attributes for methods that match our signature */ String *key; match = 1; for (key = Firstkey(sm); key; key = Nextkey(sm)) { /* Check for a signature match with the source signature */ if ((count_args(key) == narg) && (Strstr(key,ssig))) { String *oldm; /* A typemap we have to copy */ String *nkey = Copy(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 = Getattr(sm,key); 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--; } 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 = NewString(""); 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 = Getattr(typemaps[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 */ String *key, *key2; for (key = Firstkey(tm); key; key = Nextkey(tm)) { if (Strncmp(key,"tmap:",5) == 0) { int na = count_args(key); if ((na == narg) && Strstr(key,tsig)) { Hash *h = Getattr(tm,key); for (key2 = Firstkey(h); key2; key2 = Nextkey(h)) { Delattr(h,key2); } } } } } 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, 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; 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 = Getattr(typemaps[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 = Getattr(typemaps[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 (Strcmp(ctype,unstripped) != 0) 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 = Getattr(typemaps[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, String *name, 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, String *pname, String *lname, int index) { char var[512]; char *varname; SwigType *ftype; 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 it's array dimensions */ if (SwigType_isarray(type)) { String *size; int ndim = SwigType_array_ndim(type); int i; size = NewString(""); 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; SwigType *ltype, *star_ltype, *amp_ltype; String *mangle, *star_mangle, *amp_mangle, *base_mangle; 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); } if (index == 1) { Replace(s,"$basetype", base_type, DOH_REPLACE_ANY); replace_local_types(locals,"$basetype", base_type); } strcpy(varname,"basetype"); Replace(s,var,base_type,DOH_REPLACE_ANY); replace_local_types(locals,var,base_type); 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); } /* 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"); String *pn = Getattr(p,"name"); String *value = Getattr(p,"value"); if (pn) { if (Len(pn) > 0) { String *str; int isglobal = 0; str = NewString(""); if (Strncmp(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 { Printf(str,"%s",pn); } if (isglobal && Wrapper_check_local(f,str)) { p = nextSibling(p); continue; } if (value) { new_name = Wrapper_new_localv(f,str, SwigType_str(pt,str), "=", value, NIL); } else { new_name = Wrapper_new_localv(f,str, SwigType_str(pt,str), NIL); } if (!isglobal) { /* Substitute */ Replace(s,pn,new_name,DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE); } } } p = nextSibling(p); } } /* ----------------------------------------------------------------------------- * 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) return 0; /* Blocked */ if (Cmp(s,"pass") == 0) 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,pname,lname,1); } else { typemap_replace_vars(s,locals,type,pname,lname,1); } if (locals && f) { typemap_locals(s,locals,f,-1); } /* 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 * ----------------------------------------------------------------------------- */ 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; String *s = 0; ParmList *locals; ParmList *kw; char temp[256]; String *symname; String *cname = 0; String *clname = 0; type = Getattr(node,"type"); if (!type) return 0; pname = Getattr(node,"name"); tm = Swig_typemap_search(op,type,pname,&mtype); if (!tm) return 0; s = Getattr(tm,"code"); if (!s) return 0; /* Empty typemap. No match */ if (Cmp(s,"pass") == 0) return 0; 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,pname,(char *) lname,1); } else { typemap_replace_vars(s,locals,type,pname,(char *) lname,1); } if (locals && f) { typemap_locals(s,locals,f,-1); } { 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", Char(op)); Setattr(node,tmop_name(temp), locals); Delete(locals); } if (checkAttribute(tm,"type","SWIGTYPE")) { sprintf(temp,"%s:SWIGTYPE", Char(op)); Setattr(node,tmop_name(temp),"1"); } /* Attach kwargs */ kw = Getattr(tm,"kwargs"); while (kw) { sprintf(temp,"%s:%s",Char(op),Char(Getattr(kw,"name"))); Setattr(node,tmop_name(temp), Copy(Getattr(kw,"value"))); kw = nextSibling(kw); } /* Look for warnings */ { String *w; sprintf(temp,"%s:warning", Char(op)); 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", Char(op)); f = Getattr(node,tmop_name(temp)); if (f) { char *c, *tok; String *t = Copy(f); c = Char(t); tok = strtok(c,","); while (tok) { Swig_fragment_emit(tok); tok = strtok(NULL,","); } Delete(t); } } if (cname) Delete(cname); if (clname) Delete(clname); if (mtype) Delete(mtype); return s; } /* ----------------------------------------------------------------------------- * Swig_typemap_attach_parms() * * Given a parmeter list, this function attaches all of the typemaps for a * given typemap type * ----------------------------------------------------------------------------- */ 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]; Parm *kw; p = parms; while (p) { argnum++; nmatch = 0; tm = Swig_typemap_search_multi(op,p,&nmatch); if (!tm) { p = nextSibling(p); continue; } s = Getattr(tm,"code"); if (!s) { p = nextSibling(p); continue; } /* 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; 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,pname,lname,i+1); Delattr(p,"tmap:match"); } else { typemap_replace_vars(s,locals, type,pname,lname,i+1); } if (checkAttribute(tm,"type","SWIGTYPE")) { sprintf(temp,"%s:SWIGTYPE", Char(op)); Setattr(p,tmop_name(temp),"1"); } p = nextSibling(p); } if (locals && f) { typemap_locals(s,locals,f,argnum); } /* Replace the argument number */ sprintf(temp,"%d",argnum); Replace(s,"$argnum",temp, DOH_REPLACE_ANY); /* Attach attributes to object */ Setattr(firstp,tmop_name(op),s); /* Code object */ if (locals) { sprintf(temp,"%s:locals", Char(op)); Setattr(firstp,tmop_name(temp), locals); Delete(locals); } /* Attach a link to the next parameter. Needed for multimaps */ sprintf(temp,"%s:next",Char(op)); Setattr(firstp,tmop_name(temp),p); /* Attach kwargs */ kw = Getattr(tm,"kwargs"); while (kw) { sprintf(temp,"%s:%s",Char(op),Char(Getattr(kw,"name"))); Setattr(firstp,tmop_name(temp), Copy(Getattr(kw,"value"))); kw = nextSibling(kw); } { String *w; sprintf(temp,"%s:warning", Char(op)); w = Getattr(firstp,tmop_name(temp)); if (w) { Swig_warning(0,Getfile(firstp), Getline(firstp), "%s\n", w); } } /* Look for code fragments */ { String *f; sprintf(temp,"%s:fragment", Char(op)); f = Getattr(firstp,tmop_name(temp)); if (f) { char *c, *tok; String *t = Copy(f); c = Char(t); tok = strtok(c,","); while (tok) { Swig_fragment_emit(tok); tok = strtok(NULL,","); } Delete(t); } } } } /* ----------------------------------------------------------------------------- * 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"); }