static EMatch does_parm_match(SwigType *type, SwigType *partial_parm_type, const char *partial_parm_type_base, Symtab *tscope, int *specialization_priority) { static const int EXACT_MATCH_PRIORITY = 99999; /* a number bigger than the length of any conceivable type */ int matches; int substitutions; EMatch match; SwigType *ty = Swig_symbol_typedef_reduce(type, tscope); String *base = SwigType_base(ty); SwigType *t = Copy(partial_parm_type); substitutions = Replaceid(t, partial_parm_type_base, base); /* eg: Replaceid("p.$1", "$1", "int") returns t="p.int" */ matches = Equal(ty, t); *specialization_priority = -1; if (substitutions == 1) { /* we have a non-explicit specialized parameter (in partial_parm_type) because a substitution for $1, $2... etc has taken place */ SwigType *tt = Copy(partial_parm_type); int len; /* check for match to partial specialization type, for example, all of the following could match the type in the %template: template <typename T> struct XX {}; template <typename T> struct XX<T &> {}; // r.$1 template <typename T> struct XX<T const&> {}; // r.q(const).$1 template <typename T> struct XX<T *const&> {}; // r.q(const).p.$1 %template(XXX) XX<int *const&>; // r.q(const).p.int where type="r.q(const).p.int" will match either of tt="r.", tt="r.q(const)" tt="r.q(const).p" */ Replaceid(tt, partial_parm_type_base, ""); /* remove the $1, $2 etc, eg tt="p.$1" => "p." */ len = Len(tt); if (Strncmp(tt, ty, len) == 0) { match = PartiallySpecializedMatch; *specialization_priority = len; } else { match = PartiallySpecializedNoMatch; } Delete(tt); } else { match = matches ? ExactMatch : ExactNoMatch; if (matches) *specialization_priority = EXACT_MATCH_PRIORITY; /* exact matches always take precedence */ } /* Printf(stdout, " does_parm_match %2d %5d [%s] [%s]\n", match, *specialization_priority, type, partial_parm_type); */ Delete(t); Delete(base); Delete(ty); return match; }
static int cparse_template_expand(Node *n, String *tname, String *rname, String *templateargs, List *patchlist, List *typelist, List *cpatchlist) { static int expanded = 0; int ret; String *nodeType; if (!n) return 0; nodeType = nodeType(n); if (Getattr(n, "error")) return 0; if (Equal(nodeType, "template")) { /* Change the node type back to normal */ if (!expanded) { expanded = 1; set_nodeType(n, Getattr(n, "templatetype")); ret = cparse_template_expand(n, tname, rname, templateargs, patchlist, typelist, cpatchlist); expanded = 0; return ret; } else { /* Called when template appears inside another template */ /* Member templates */ set_nodeType(n, Getattr(n, "templatetype")); ret = cparse_template_expand(n, tname, rname, templateargs, patchlist, typelist, cpatchlist); set_nodeType(n, "template"); return ret; } } else if (Equal(nodeType, "cdecl")) { /* A simple C declaration */ SwigType *t, *v, *d; String *code; t = Getattr(n, "type"); v = Getattr(n, "value"); d = Getattr(n, "decl"); code = Getattr(n, "code"); Append(typelist, t); Append(typelist, d); Append(patchlist, v); Append(cpatchlist, code); if (Getattr(n, "conversion_operator")) { Append(cpatchlist, Getattr(n, "name")); if (Getattr(n, "sym:name")) { Append(cpatchlist, Getattr(n, "sym:name")); } } add_parms(Getattr(n, "parms"), cpatchlist, typelist); add_parms(Getattr(n, "throws"), cpatchlist, typelist); } else if (Equal(nodeType, "class")) { /* Patch base classes */ { int b = 0; for (b = 0; b < 3; ++b) { List *bases = Getattr(n, baselists[b]); if (bases) { int i; int ilen = Len(bases); for (i = 0; i < ilen; i++) { String *name = Copy(Getitem(bases, i)); Setitem(bases, i, name); Append(typelist, name); } } } } /* Patch children */ { Node *cn = firstChild(n); while (cn) { cparse_template_expand(cn, tname, rname, templateargs, patchlist, typelist, cpatchlist); cn = nextSibling(cn); } } } else if (Equal(nodeType, "constructor")) { String *name = Getattr(n, "name"); if (!(Getattr(n, "templatetype"))) { String *symname; String *stripped_name = SwigType_templateprefix(name); if (Strstr(tname, stripped_name)) { Replaceid(name, stripped_name, tname); } Delete(stripped_name); symname = Getattr(n, "sym:name"); if (symname) { stripped_name = SwigType_templateprefix(symname); if (Strstr(tname, stripped_name)) { Replaceid(symname, stripped_name, tname); } Delete(stripped_name); } if (strchr(Char(name), '<')) { Append(patchlist, Getattr(n, "name")); } else { Append(name, templateargs); } name = Getattr(n, "sym:name"); if (name) { if (strchr(Char(name), '<')) { Clear(name); Append(name, rname); } else { String *tmp = Copy(name); Replace(tmp, tname, rname, DOH_REPLACE_ANY); Clear(name); Append(name, tmp); Delete(tmp); } } /* Setattr(n,"sym:name",name); */ } Append(cpatchlist, Getattr(n, "code")); Append(typelist, Getattr(n, "decl")); add_parms(Getattr(n, "parms"), cpatchlist, typelist); add_parms(Getattr(n, "throws"), cpatchlist, typelist); } else if (Equal(nodeType, "destructor")) { String *name = Getattr(n, "name"); if (name) { if (strchr(Char(name), '<')) Append(patchlist, Getattr(n, "name")); else Append(name, templateargs); } name = Getattr(n, "sym:name"); if (name) { if (strchr(Char(name), '<')) { String *sn = Copy(tname); Setattr(n, "sym:name", sn); Delete(sn); } else { Replace(name, tname, rname, DOH_REPLACE_ANY); } } /* Setattr(n,"sym:name",name); */ Append(cpatchlist, Getattr(n, "code")); } else if (Equal(nodeType, "using")) { String *uname = Getattr(n, "uname"); if (uname && strchr(Char(uname), '<')) { Append(patchlist, uname); } if (Getattr(n, "namespace")) { /* Namespace link. This is nasty. Is other namespace defined? */ } } else { /* Look for obvious parameters */ Node *cn; Append(cpatchlist, Getattr(n, "code")); Append(typelist, Getattr(n, "type")); Append(typelist, Getattr(n, "decl")); add_parms(Getattr(n, "parms"), cpatchlist, typelist); add_parms(Getattr(n, "kwargs"), cpatchlist, typelist); add_parms(Getattr(n, "pattern"), cpatchlist, typelist); add_parms(Getattr(n, "throws"), cpatchlist, typelist); cn = firstChild(n); while (cn) { cparse_template_expand(cn, tname, rname, templateargs, patchlist, typelist, cpatchlist); cn = nextSibling(cn); } } return 0; }
static Node *template_locate(String *name, Parm *tparms, Symtab *tscope) { Node *n; String *tname, *rname = 0; Node *templ; List *mpartials = 0; Parm *p; Parm *parms; Parm *targs; ParmList *expandedparms; tname = Copy(name); parms = CopyParmList(tparms); /* Search for generic template */ templ = Swig_symbol_clookup(name, 0); /* Add default values from generic template */ if (templ) { Symtab *tsdecl = Getattr(templ, "sym:symtab"); targs = Getattr(templ, "templateparms"); expandedparms = Swig_symbol_template_defargs(parms, targs, tscope, tsdecl); } else { expandedparms = parms; } /* reduce the typedef */ p = expandedparms; while (p) { SwigType *ty = Getattr(p, "type"); if (ty) { SwigType *nt = Swig_symbol_type_qualify(ty, tscope); Setattr(p, "type", nt); Delete(nt); } p = nextSibling(p); } SwigType_add_template(tname, expandedparms); if (template_debug) { Printf(stdout, "\n%s:%d: template_debug: Searching for %s\n", cparse_file, cparse_line, tname); } /* Search for an exact specialization. Example: template<> class name<int> { ... } */ { if (template_debug) { Printf(stdout, " searching: '%s' (exact specialization)\n", tname); } n = Swig_symbol_clookup_local(tname, 0); if (!n) { SwigType *rname = Swig_symbol_typedef_reduce(tname, tscope); if (!Equal(rname, tname)) { if (template_debug) { Printf(stdout, " searching: '%s' (exact specialization)\n", rname); } n = Swig_symbol_clookup_local(rname, 0); } Delete(rname); } if (n) { Node *tn; String *nodeType = nodeType(n); if (Equal(nodeType, "template")) goto success; tn = Getattr(n, "template"); if (tn) { n = tn; goto success; /* Previously wrapped by a template return that */ } Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n)); Delete(tname); Delete(parms); return 0; /* Found a match, but it's not a template of any kind. */ } } /* Search for partial specialization. Example: template<typename T> class name<T *> { ... } */ /* Generate reduced template name (stripped of extraneous pointers, etc.) */ rname = NewStringf("%s<(", name); p = parms; while (p) { String *t; t = Getattr(p, "type"); if (!t) t = Getattr(p, "value"); if (t) { String *ty = Swig_symbol_typedef_reduce(t, tscope); String *tb = SwigType_base(ty); String *td = SwigType_default(ty); Replaceid(td, "enum SWIGTYPE", tb); Replaceid(td, "SWIGTYPE", tb); Append(rname, td); Delete(tb); Delete(ty); Delete(td); } p = nextSibling(p); if (p) { Append(rname, ","); } } Append(rname, ")>"); mpartials = NewList(); if (templ) { /* First, we search using an exact type prototype */ Parm *p; char tmp[32]; int i; List *partials; String *ss; Iterator pi; partials = Getattr(templ, "partials"); if (partials) { for (pi = First(partials); pi.item; pi = Next(pi)) { ss = Copy(pi.item); p = parms; i = 1; while (p) { String *t, *tn; sprintf(tmp, "$%d", i); t = Getattr(p, "type"); if (!t) t = Getattr(p, "value"); if (t) { String *ty = Swig_symbol_typedef_reduce(t, tscope); tn = SwigType_base(ty); Replaceid(ss, tmp, tn); Delete(tn); Delete(ty); } i++; p = nextSibling(p); } if (template_debug) { Printf(stdout, " searching: '%s' (partial specialization - %s)\n", ss, pi.item); } if ((Equal(ss, tname)) || (Equal(ss, rname))) { Append(mpartials, pi.item); } Delete(ss); } } } if (template_debug) { Printf(stdout, " Matched partials: %s\n", mpartials); } if (Len(mpartials)) { String *s = Getitem(mpartials, 0); n = Swig_symbol_clookup_local(s, 0); if (Len(mpartials) > 1) { if (n) { Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, cparse_file, cparse_line, "Instantiation of template '%s' is ambiguous,\n", SwigType_namestr(tname)); Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, Getfile(n), Getline(n), " instantiation '%s' is used.\n", SwigType_namestr(Getattr(n, "name"))); } } } if (!n) { n = templ; } if (!n) { Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", name); } else if (n) { String *nodeType = nodeType(n); if (!Equal(nodeType, "template")) { Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType); n = 0; } } success: Delete(tname); Delete(rname); Delete(mpartials); if ((template_debug) && (n)) { Printf(stdout, "Node: %p\n", n); Swig_print_node(n); } Delete(parms); return n; }
static void cparse_template_expand(Node *templnode, Node *n, String *tname, String *rname, String *templateargs, List *patchlist, List *typelist, List *cpatchlist) { static int expanded = 0; String *nodeType; if (!n) return; nodeType = nodeType(n); if (Getattr(n, "error")) return; if (Equal(nodeType, "template")) { /* Change the node type back to normal */ if (!expanded) { expanded = 1; set_nodeType(n, Getattr(n, "templatetype")); cparse_template_expand(templnode, n, tname, rname, templateargs, patchlist, typelist, cpatchlist); expanded = 0; return; } else { /* Called when template appears inside another template */ /* Member templates */ set_nodeType(n, Getattr(n, "templatetype")); cparse_template_expand(templnode, n, tname, rname, templateargs, patchlist, typelist, cpatchlist); set_nodeType(n, "template"); return; } } else if (Equal(nodeType, "cdecl")) { /* A simple C declaration */ SwigType *t, *v, *d; String *code; t = Getattr(n, "type"); v = Getattr(n, "value"); d = Getattr(n, "decl"); code = Getattr(n, "code"); Append(typelist, t); Append(typelist, d); Append(patchlist, v); Append(cpatchlist, code); if (Getattr(n, "conversion_operator")) { Append(cpatchlist, Getattr(n, "name")); if (Getattr(n, "sym:name")) { Append(cpatchlist, Getattr(n, "sym:name")); } } if (checkAttribute(n, "storage", "friend")) { String *symname = Getattr(n, "sym:name"); if (symname) { String *stripped_name = SwigType_templateprefix(symname); Setattr(n, "sym:name", stripped_name); Delete(stripped_name); } Append(typelist, Getattr(n, "name")); } add_parms(Getattr(n, "parms"), cpatchlist, typelist); add_parms(Getattr(n, "throws"), cpatchlist, typelist); } else if (Equal(nodeType, "class")) { /* Patch base classes */ { int b = 0; for (b = 0; b < 3; ++b) { List *bases = Getattr(n, baselists[b]); if (bases) { int i; int ilen = Len(bases); for (i = 0; i < ilen; i++) { String *name = Copy(Getitem(bases, i)); Setitem(bases, i, name); Append(typelist, name); } } } } /* Patch children */ { Node *cn = firstChild(n); while (cn) { cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist); cn = nextSibling(cn); } } } else if (Equal(nodeType, "constructor")) { String *name = Getattr(n, "name"); if (!(Getattr(n, "templatetype"))) { String *symname; String *stripped_name = SwigType_templateprefix(name); if (Strstr(tname, stripped_name)) { Replaceid(name, stripped_name, tname); } Delete(stripped_name); symname = Getattr(n, "sym:name"); if (symname) { stripped_name = SwigType_templateprefix(symname); if (Strstr(tname, stripped_name)) { Replaceid(symname, stripped_name, tname); } Delete(stripped_name); } if (strchr(Char(name), '<')) { Append(patchlist, Getattr(n, "name")); } else { Append(name, templateargs); } name = Getattr(n, "sym:name"); if (name) { if (strchr(Char(name), '<')) { Clear(name); Append(name, rname); } else { String *tmp = Copy(name); Replace(tmp, tname, rname, DOH_REPLACE_ANY); Clear(name); Append(name, tmp); Delete(tmp); } } /* Setattr(n,"sym:name",name); */ } Append(cpatchlist, Getattr(n, "code")); Append(typelist, Getattr(n, "decl")); add_parms(Getattr(n, "parms"), cpatchlist, typelist); add_parms(Getattr(n, "throws"), cpatchlist, typelist); } else if (Equal(nodeType, "destructor")) { /* We only need to patch the dtor of the template itself, not the destructors of any nested classes, so check that the parent of this node is the root * template node, with the special exception for %extend which adds its methods under an intermediate node. */ Node* parent = parentNode(n); if (parent == templnode || (parentNode(parent) == templnode && Equal(nodeType(parent), "extend"))) { String *name = Getattr(n, "name"); if (name) { if (strchr(Char(name), '<')) Append(patchlist, Getattr(n, "name")); else Append(name, templateargs); } name = Getattr(n, "sym:name"); if (name) { if (strchr(Char(name), '<')) { String *sn = Copy(tname); Setattr(n, "sym:name", sn); Delete(sn); } else { Replace(name, tname, rname, DOH_REPLACE_ANY); } } /* Setattr(n,"sym:name",name); */ Append(cpatchlist, Getattr(n, "code")); } } else if (Equal(nodeType, "using")) { String *uname = Getattr(n, "uname"); if (uname && strchr(Char(uname), '<')) { Append(patchlist, uname); } if (Getattr(n, "namespace")) { /* Namespace link. This is nasty. Is other namespace defined? */ } } else { /* Look for obvious parameters */ Node *cn; Append(cpatchlist, Getattr(n, "code")); Append(typelist, Getattr(n, "type")); Append(typelist, Getattr(n, "decl")); add_parms(Getattr(n, "parms"), cpatchlist, typelist); add_parms(Getattr(n, "kwargs"), cpatchlist, typelist); add_parms(Getattr(n, "pattern"), cpatchlist, typelist); add_parms(Getattr(n, "throws"), cpatchlist, typelist); cn = firstChild(n); while (cn) { cparse_template_expand(templnode, cn, tname, rname, templateargs, patchlist, typelist, cpatchlist); cn = nextSibling(cn); } } }