char cvsroot_templ_c[] = "$Id: templ.c 11097 2009-01-30 10:27:37Z bhy $";
#include "swig.h"
#include "cparse.h"
static int template_debug = 0;
const char *baselists[3];
void SwigType_template_init() {
baselists[0] = "baselist";
baselists[1] = "protectedbaselist";
baselists[2] = "privatebaselist";
}
static void add_parms(ParmList *p, List *patchlist, List *typelist) {
while (p) {
SwigType *ty = Getattr(p, "type");
SwigType *val = Getattr(p, "value");
Append(typelist, ty);
Append(typelist, val);
Append(patchlist, val);
p = nextSibling(p);
}
}
void Swig_cparse_debug_templates(int x) {
template_debug = x;
}
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")) {
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 {
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")) {
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")) {
{
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);
}
}
}
}
{
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);
}
}
}
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);
}
}
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")) {
}
} else {
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
String *partial_arg(String *s, String *p) {
char *c;
char *cp = Char(p);
String *prefix;
String *newarg;
c = strchr(cp, '$');
if (!c) {
return Copy(s);
}
prefix = NewStringWithSize(cp, c - cp);
newarg = Copy(s);
Replace(newarg, prefix, "", DOH_REPLACE_ANY | DOH_REPLACE_FIRST);
Delete(prefix);
return newarg;
}
int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab *tscope) {
List *patchlist, *cpatchlist, *typelist;
String *templateargs;
String *tname;
String *iname;
String *tbase;
patchlist = NewList();
cpatchlist = NewList();
typelist = NewList();
{
String *tmp = NewStringEmpty();
if (tparms) {
SwigType_add_template(tmp, tparms);
}
templateargs = Copy(tmp);
Delete(tmp);
}
tname = Copy(Getattr(n, "name"));
tbase = Swig_scopename_last(tname);
if (Getattr(n, "partialargs")) {
Parm *p, *tp;
ParmList *ptargs = SwigType_function_parms(Getattr(n, "partialargs"));
p = ptargs;
tp = tparms;
while (p && tp) {
SwigType *ptype;
SwigType *tptype;
SwigType *partial_type;
ptype = Getattr(p, "type");
tptype = Getattr(tp, "type");
if (ptype && tptype) {
partial_type = partial_arg(tptype, ptype);
Setattr(tp, "type", partial_type);
Delete(partial_type);
}
p = nextSibling(p);
tp = nextSibling(tp);
}
assert(ParmList_len(ptargs) == ParmList_len(tparms));
Delete(ptargs);
}
cparse_template_expand(n, tname, rname, templateargs, patchlist, typelist, cpatchlist);
{
String *name = Getattr(n, "name");
if (name) {
Append(name, templateargs);
}
iname = name;
}
{
Parm *tp = Getattr(n, "templateparms");
Parm *p = tparms;
if (tp) {
Symtab *tsdecl = Getattr(n, "sym:symtab");
while (p && tp) {
String *name, *value, *valuestr, *tydef, *tmp, *tmpr;
int sz, i;
String *dvalue = 0;
String *qvalue = 0;
name = Getattr(tp, "name");
value = Getattr(p, "value");
tydef = Getattr(p, "typedef");
if (name) {
if (!value)
value = Getattr(p, "type");
qvalue = Swig_symbol_typedef_reduce(value, tsdecl);
dvalue = Swig_symbol_type_qualify(qvalue, tsdecl);
if (SwigType_istemplate(dvalue)) {
String *ty = Swig_symbol_template_deftype(dvalue, tscope);
Delete(dvalue);
dvalue = ty;
}
assert(dvalue);
valuestr = SwigType_str(dvalue, 0);
{
Parm *rp = nextSibling(p);
while (rp) {
String *rvalue = Getattr(rp, "value");
if (rvalue) {
Replace(rvalue, name, dvalue, DOH_REPLACE_ID);
}
rp = nextSibling(rp);
}
}
sz = Len(patchlist);
for (i = 0; i < sz; i++) {
String *s = Getitem(patchlist, i);
Replace(s, name, dvalue, DOH_REPLACE_ID);
}
sz = Len(typelist);
for (i = 0; i < sz; i++) {
String *s = Getitem(typelist, i);
SwigType_typename_replace(s, name, dvalue);
SwigType_typename_replace(s, tbase, iname);
}
if (!tydef) {
tydef = dvalue;
}
tmp = NewStringf("#%s", name);
tmpr = NewStringf("\"%s\"", valuestr);
sz = Len(cpatchlist);
for (i = 0; i < sz; i++) {
String *s = Getitem(cpatchlist, i);
Replace(s, tmp, tmpr, DOH_REPLACE_ID);
Replace(s, name, valuestr, DOH_REPLACE_ID);
}
Delete(tmp);
Delete(tmpr);
Delete(valuestr);
Delete(dvalue);
Delete(qvalue);
}
p = nextSibling(p);
tp = nextSibling(tp);
if (!p)
p = tp;
}
} else {
int i, sz;
sz = Len(typelist);
for (i = 0; i < sz; i++) {
String *s = Getitem(typelist, i);
SwigType_typename_replace(s, tbase, iname);
}
}
}
{
List *bases = Getattr(n, "baselist");
if (bases) {
Iterator b;
for (b = First(bases); b.item; b = Next(b)) {
String *qn = Swig_symbol_type_qualify(b.item, tscope);
Clear(b.item);
Append(b.item, qn);
Delete(qn);
}
}
}
Delete(patchlist);
Delete(cpatchlist);
Delete(typelist);
Delete(tbase);
Delete(tname);
Delete(templateargs);
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);
templ = Swig_symbol_clookup(name, 0);
if (templ) {
Symtab *tsdecl = Getattr(templ, "sym:symtab");
targs = Getattr(templ, "templateparms");
expandedparms = Swig_symbol_template_defargs(parms, targs, tscope, tsdecl);
} else {
expandedparms = parms;
}
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);
}
{
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;
}
Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n));
Delete(tname);
Delete(parms);
return 0;
}
}
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) {
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;
}
Node *Swig_cparse_template_locate(String *name, Parm *tparms, Symtab *tscope) {
Node *n = template_locate(name, tparms, tscope);
if (n) {
String *nodeType = nodeType(n);
int isclass = 0;
assert(Equal(nodeType, "template"));
isclass = (Equal(Getattr(n, "templatetype"), "class"));
if (!isclass) {
if (template_debug) {
Printf(stdout, " Not a templated class, seeking most appropriate templated function\n");
}
n = Swig_symbol_clookup_local(name, 0);
while (n) {
Parm *tparmsfound = Getattr(n, "templateparms");
if (ParmList_len(tparms) == ParmList_len(tparmsfound)) {
break;
}
n = Getattr(n, "sym:nextSibling");
}
if (!n) {
Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", name);
}
if ((template_debug) && (n)) {
Printf(stdout, "Templated function found: %p\n", n);
Swig_print_node(n);
}
}
}
return n;
}