diff options
Diffstat (limited to 'Source/Swig/typemap.c')
-rw-r--r-- | Source/Swig/typemap.c | 208 |
1 files changed, 145 insertions, 63 deletions
diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c index c0f5397c1..3294bdf77 100644 --- a/Source/Swig/typemap.c +++ b/Source/Swig/typemap.c @@ -4,7 +4,7 @@ * terms also apply to certain portions of SWIG. The full details of the SWIG * license and copyrights can be found in the LICENSE and COPYRIGHT files * included with the SWIG source code as distributed by the SWIG developers - * and at http://www.swig.org/legal.html. + * and at https://www.swig.org/legal.html. * * typemap.c * @@ -102,6 +102,7 @@ static Hash *get_typemap(const SwigType *type) { dtype = Swig_symbol_type_qualify(ty, 0); type = dtype; Delete(ty); + Delete(rty); } /* remove unary scope operator (::) prefix indicating global scope for looking up in the hashmap */ @@ -151,7 +152,7 @@ static void set_typemap(const SwigType *type, Hash **tmhash) { * Initialize the typemap system * ----------------------------------------------------------------------------- */ -void Swig_typemap_init() { +void Swig_typemap_init(void) { typemaps = NewHash(); } @@ -511,7 +512,12 @@ int Swig_typemap_apply(ParmList *src, ParmList *dest) { if (sm) { /* Got a typemap. Need to only merge attributes for methods that match our signature */ Iterator ki; + Hash *deferred_add; match = 1; + + /* Since typemap_register can modify the `sm` hash, we *cannot* call typemap_register while iterating over sm. + * Create a temporary hash of typemaps to add immediately after. */ + deferred_add = NewHash(); 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))) { @@ -521,34 +527,36 @@ int Swig_typemap_apply(ParmList *src, ParmList *dest) { 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) { - String *src_str = ParmList_str_multibrackets(src); - String *dest_str = ParmList_str_multibrackets(dest); - String *source_directive = NewStringf("apply %s { %s }", src_str, dest_str); - Replace(nkey, dsig, "", DOH_REPLACE_ANY); Replace(nkey, "tmap:", "", DOH_REPLACE_ANY); - typemap_register(nkey, dest, code, locals, kwargs, source_directive); - - Delete(source_directive); - Delete(dest_str); - Delete(src_str); + Setattr(deferred_add, nkey, sm1); } } Delete(nkey); } } + + /* After assembling the key/item pairs, add the resulting typemaps */ + for (ki = First(deferred_add); ki.key; ki = Next(ki)) { + Hash *sm1 = ki.item; + String *src_str = ParmList_str_multibrackets(src); + String *dest_str = ParmList_str_multibrackets(dest); + String *source_directive = NewStringf("apply %s { %s }", src_str, dest_str); + + typemap_register(ki.key, dest, Getattr(sm1, "code"), Getattr(sm1, "locals"), Getattr(sm1, "kwargs"), source_directive); + + Delete(source_directive); + Delete(dest_str); + Delete(src_str); + } + Delete(deferred_add); } Delete(ssig); Delete(dsig); @@ -858,13 +866,6 @@ static Hash *typemap_search_multi(const_String_or_char_ptr tmap_method, ParmList } -/* ----------------------------------------------------------------------------- - * 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) { @@ -884,7 +885,23 @@ static int check_locals(ParmList *p, const char *s) { return 0; } -static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *rtype, String *pname, String *lname, int index) { +static int replace_with_override(String *src, const DOHString_or_char *token, const DOHString_or_char *rep, int flags, Hash *override_vars) { + String *override_replace = override_vars ? Getattr(override_vars, token) : NULL; + if (override_replace) + return Replace(src, token, override_replace, flags); + return Replace(src, token, rep, flags); +} + +/* ----------------------------------------------------------------------------- + * typemap_replace_vars() + * + * Replaces typemap variables in a string. index is the $n variable. + * type and pname are the type and parameter name. + * override_vars are only used to replace variable names (NOT types), so is only + * used for $n, but not the various ways of representing types: $n_ltype, $n_type etc + * ----------------------------------------------------------------------------- */ + +static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *rtype, String *pname, String *lname, int index, Hash *override_vars) { char var[512]; char *varname; SwigType *ftype; @@ -1159,7 +1176,7 @@ static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, Swi Delete(lex_type); } - /* Replace any $n. with (&n)-> */ + /* Replace variable usage $n. with (&$n)-> */ { char temp[64]; sprintf(var, "$%d.", index); @@ -1169,7 +1186,7 @@ static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, Swi /* Replace the bare $n variable */ sprintf(var, "$%d", index); - bare_substitution_count = Replace(s, var, lname, DOH_REPLACE_NUMBER_END); + bare_substitution_count = replace_with_override(s, var, lname, DOH_REPLACE_NUMBER_END, override_vars); Delete(ftype); return bare_substitution_count; } @@ -1257,6 +1274,59 @@ static String *typemap_warn(const_String_or_char_ptr tmap_method, Parm *p) { } /* ----------------------------------------------------------------------------- + * typemap_merge_fragment_kwargs() + * + * If multiple 'fragment' attributes are provided to a typemap, combine them by + * concatenating with commas. + * ----------------------------------------------------------------------------- */ + +static void typemap_merge_fragment_kwargs(Parm *kw) { + Parm *reattach_kw = NULL; + Parm *prev_kw = NULL; + Parm *next_kw = NULL; + String *fragment = NULL; + while (kw) { + next_kw = nextSibling(kw); + if (Strcmp(Getattr(kw, "name"), "fragment") == 0) { + String *thisfragment = Getattr(kw, "value"); + String *kwtype = Getattr(kw, "type"); + if (!fragment) { + /* First fragment found; it should remain in the list */ + fragment = thisfragment; + prev_kw = kw; + } else { + /* Concatenate to previously found fragment */ + Printv(fragment, ",", thisfragment, NULL); + reattach_kw = prev_kw; + } + if (kwtype) { + String *mangle = Swig_name_mangle_type(kwtype); + Append(fragment, mangle); + Delete(mangle); + /* Remove 'type' from kwargs so it's not duplicated later */ + Setattr(kw, "type", NULL); + } + } else { + /* Not a fragment */ + if (reattach_kw) { + /* Update linked list to remove duplicate fragment */ + DohIncref(kw); + set_nextSibling(reattach_kw, kw); + set_previousSibling(kw, reattach_kw); + Delete(reattach_kw); + reattach_kw = NULL; + } + prev_kw = kw; + } + kw = next_kw; + } + if (reattach_kw) { + /* Update linked list to remove duplicate fragment */ + set_nextSibling(reattach_kw, kw); + } +} + +/* ----------------------------------------------------------------------------- * Swig_typemap_lookup() * * Attach one or more typemaps to a node and optionally generate the typemap contents @@ -1390,7 +1460,6 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No * ie, not use the typemap code, otherwise both f and actioncode must be non null. */ if (actioncode) { const String *result_equals = NewStringf("%s = ", Swig_cresult_name()); - clname = Copy(actioncode); /* check that the code in the typemap can be used in this optimal way. * The code should be in the form "result = ...;\n". We need to extract * the "..." part. This may not be possible for various reasons, eg @@ -1398,22 +1467,17 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No * hack and circumvents the normal requirement for a temporary variable * to hold the result returned from a wrapped function call. */ - if (Strncmp(clname, result_equals, 9) == 0) { - int numreplacements = Replace(clname, result_equals, "", DOH_REPLACE_ID_BEGIN); - if (numreplacements == 1) { - numreplacements = Replace(clname, ";\n", "", DOH_REPLACE_ID_END); - if (numreplacements == 1) { - if (Strchr(clname, ';') == 0) { - lname = clname; - actioncode = 0; - optimal_substitution = 1; - } - } - } - } - if (!optimal_substitution) { + if (Strncmp(actioncode, result_equals, Len(result_equals)) == 0 && + Strchr(actioncode, ';') == Char(actioncode) + Len(actioncode) - 2 && + Char(actioncode)[Len(actioncode) - 1] == '\n') { + clname = NewStringWithSize(Char(actioncode) + Len(result_equals), + Len(actioncode) - Len(result_equals) - 2); + lname = clname; + actioncode = 0; + optimal_substitution = 1; + } else { Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_IGNORED, Getfile(node), Getline(node), "Method %s usage of the optimal attribute ignored\n", Swig_name_decl(node)); - Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_IGNORED, Getfile(s), Getline(s), "in the out typemap as the following cannot be used to generate optimal code: %s\n", clname); + Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_IGNORED, Getfile(s), Getline(s), "in the out typemap as the following cannot be used to generate optimal code: %s\n", actioncode); delete_optimal_attribute = 1; } } else { @@ -1444,7 +1508,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No } matchtype = mtype && SwigType_isarray(mtype) ? mtype : type; - num_substitutions = typemap_replace_vars(s, locals, matchtype, type, pname, (char *) lname, 1); + num_substitutions = typemap_replace_vars(s, locals, matchtype, type, pname, (char *) lname, 1, NULL); if (optimal_substitution && num_substitutions > 1) { Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(node), Getline(node), "Multiple calls to %s might be generated due to\n", Swig_name_decl(node)); Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(s), Getline(s), "optimal attribute usage in the out typemap.\n"); @@ -1463,6 +1527,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No /* Attach kwargs - ie the typemap attributes */ kw = Getattr(tm, "kwargs"); + typemap_merge_fragment_kwargs(kw); while (kw) { String *value = Copy(Getattr(kw, "value")); String *kwtype = Getattr(kw, "type"); @@ -1474,7 +1539,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No SwigType *mtype = Getattr(node, "tmap:match"); SwigType *matchtype = mtype ? mtype : ptype; ParmList *parm_sublist; - typemap_replace_vars(value, NULL, matchtype, ptype, pname, (char *)lname, 1); + typemap_replace_vars(value, NULL, matchtype, ptype, pname, (char *)lname, 1, NULL); /* Expand special variable macros (embedded typemaps) in typemap attributes. */ parm_sublist = NewParmWithoutFileLineInfo(ptype, pname); @@ -1483,7 +1548,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No Delete(parm_sublist); } if (kwtype) { - String *mangle = Swig_string_mangle(kwtype); + String *mangle = Swig_name_mangle_type(kwtype); Append(value, mangle); Delete(mangle); } @@ -1517,7 +1582,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No /* Print warnings, if any */ warning = typemap_warn(cmethod, node); if (warning) { - typemap_replace_vars(warning, 0, matchtype, type, pname, (char *) lname, 1); + typemap_replace_vars(warning, 0, matchtype, type, pname, (char *) lname, 1, NULL); Replace(warning, "$name", pname, DOH_REPLACE_ANY); if (symname) Replace(warning, "$symname", symname, DOH_REPLACE_ANY); @@ -1577,6 +1642,7 @@ String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *node, co static void typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr tmap_method, Parm *firstp, int nmatch) { String *temp = NewStringEmpty(); Parm *kw = Getattr(tm, "kwargs"); + typemap_merge_fragment_kwargs(kw); while (kw) { String *value = Copy(Getattr(kw, "value")); String *type = Getattr(kw, "type"); @@ -1589,7 +1655,7 @@ static void typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr tmap_method String *lname = Getattr(p, "lname"); SwigType *mtype = Getattr(p, "tmap:match"); SwigType *matchtype = mtype ? mtype : type; - typemap_replace_vars(value, NULL, matchtype, type, pname, lname, i + 1); + typemap_replace_vars(value, NULL, matchtype, type, pname, lname, i + 1, NULL); p = nextSibling(p); } @@ -1661,12 +1727,13 @@ static String *typemap_get_option(Hash *tm, const_String_or_char_ptr name) { * code can be retrieved for the first parameter with a call to Getattr(parm, "tmap:in") * and the "numinputs" attribute can be retrieved with a call to Getattr(parm, "tmap:in:numinputs"). * - * tmap_method - typemap method, eg "in", "out", "newfree" - * parms - parameter list to attach each typemap and all typemap attributes - * f - wrapper code to generate into if non null + * tmap_method - typemap method, eg "in", "out", "newfree" + * parms - parameter list to attach each typemap and all typemap attributes + * f - wrapper code to generate into if non null + * override_vars - Hash of variables from $typemap(...) that will override special variable replacements * ----------------------------------------------------------------------------- */ -void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f) { +static void typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f, Hash *override_vars) { Parm *p, *firstp; Hash *tm; int nmatch = 0; @@ -1782,7 +1849,7 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *p SwigType *mtype = Getattr(p, "tmap:match"); SwigType *matchtype = mtype ? mtype : type; - typemap_replace_vars(s, locals, matchtype, type, pname, lname, i + 1); + typemap_replace_vars(s, locals, matchtype, type, pname, lname, i + 1, override_vars); if (mtype) Delattr(p, "tmap:match"); @@ -1830,7 +1897,7 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *p String *lname = Getattr(firstp, "lname"); SwigType *mtype = Getattr(firstp, "tmap:match"); SwigType *matchtype = mtype ? mtype : type; - typemap_replace_vars(warning, 0, matchtype, type, pname, lname, 1); + typemap_replace_vars(warning, 0, matchtype, type, pname, lname, 1, override_vars); Replace(warning, "$argnum", temp, DOH_REPLACE_ANY); Swig_warning(0, Getfile(firstp), Getline(firstp), "%s\n", warning); Delete(warning); @@ -1853,6 +1920,10 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *p } +void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f) { + typemap_attach_parms(tmap_method, parms, f, NULL); +} + /* Splits the arguments of an embedded typemap */ static List *split_embedded_typemap(String *s) { List *args = 0; @@ -1897,7 +1968,7 @@ static List *split_embedded_typemap(String *s) { level--; if (*c == '<') angle_level++; - if (*c == '>') + if (*c == '>' && *(c - 1) != '-') angle_level--; if (isspace((int) *c) && leading) start++; @@ -1931,7 +2002,9 @@ void Swig_typemap_replace_embedded_typemap(String *s, Node *file_line_node) { * * $typemap(method, typelist, var1=value, var2=value, ...) * - * where varx parameters are optional and undocumented; they were used in an earlier version of $typemap. + * where varx parameters are optional and undocumented; they were initially an experiment in the first implementation of $typemap. + * They allow one to override known special variable replacements or even add in new special variables for replacement + * from the calling typemap to the called typemap. * A search is made using the typemap matching rules of form: * * %typemap(method) typelist {...} @@ -1976,7 +2049,7 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper if (!syntax_error) { List *l; String *tmap_method; - Hash *vars; + Hash *override_vars; syntax_error = 1; /* Split apart each parameter in $typemap(...) */ @@ -2005,8 +2078,8 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper Delete(empty_string); } - /* process optional extra parameters - the variable replacements (undocumented) */ - vars = NewHash(); + /* process optional extra parameters - the override variable replacements (undocumented) */ + override_vars = NewHash(); { int i, ilen; ilen = Len(l); @@ -2018,7 +2091,7 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper String *name = NewStringWithSize(c, (int)(eq - c)); String *value = NewString(eq + 1); Insert(name, 0, "$"); - Setattr(vars, name, value); + Setattr(override_vars, name, value); } else { to_match_parms = 0; /* error - variable replacement parameters must be of form varname=value */ } @@ -2035,6 +2108,7 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper Printf(stdout, "Swig_typemap_attach_parms: embedded\n"); #endif if (already_substituting < 10) { + char* found_colon; already_substituting++; if ((in_typemap_search_multi == 0) && typemap_search_debug) { String *dtypemap = NewString(dollar_typemap); @@ -2042,7 +2116,15 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper Printf(stdout, " Containing: %s\n", dtypemap); Delete(dtypemap); } - Swig_typemap_attach_parms(tmap_method, to_match_parms, f); + found_colon = Strchr(tmap_method, ':'); + if (found_colon) { + /* Substitute from a keyword argument to a typemap. Avoid emitting local variables from the attached typemap by passing NULL for the file. */ + String *temp_tmap_method = NewStringWithSize(Char(tmap_method), (int)(found_colon - Char(tmap_method))); + typemap_attach_parms(temp_tmap_method, to_match_parms, NULL, override_vars); + Delete(temp_tmap_method); + } else { + typemap_attach_parms(tmap_method, to_match_parms, f, override_vars); + } already_substituting--; /* Look for the typemap code */ @@ -2054,7 +2136,7 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper if (!Getattr(to_match_parms, attr)) { /* Replace parameter variables */ Iterator ki; - for (ki = First(vars); ki.key; ki = Next(ki)) { + for (ki = First(override_vars); ki.key; ki = Next(ki)) { Replace(tm, ki.key, ki.item, DOH_REPLACE_ANY); } /* offer the target language module the chance to make special variable substitutions */ @@ -2083,7 +2165,7 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper } syntax_error = 0; } - Delete(vars); + Delete(override_vars); } Delete(l); } @@ -2105,7 +2187,7 @@ static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper * Display all typemaps * ----------------------------------------------------------------------------- */ -void Swig_typemap_debug() { +void Swig_typemap_debug(void) { int nesting_level = 2; Printf(stdout, "---[ typemaps ]--------------------------------------------------------------\n"); Swig_print(typemaps, nesting_level); |