char cvsroot_overload_cxx[] = "$Id: overload.cxx 11455 2009-07-26 21:29:55Z wsfulton $";
#include "swigmod.h"
#define MAX_OVERLOAD 4096
String *argv_template_string;
String *argc_template_string;
struct Overloaded {
Node *n;
int argc;
ParmList *parms;
int error;
};
static int fast_dispatch_mode = 0;
static int cast_dispatch_mode = 0;
void Wrapper_fast_dispatch_mode_set(int flag) {
fast_dispatch_mode = flag;
}
void Wrapper_cast_dispatch_mode_set(int flag) {
cast_dispatch_mode = flag;
}
static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
Overloaded nodes[MAX_OVERLOAD];
int nnodes = 0;
Node *o = Getattr(n, "sym:overloaded");
Node *c;
if (!o)
return 0;
c = o;
while (c) {
if (Getattr(c, "error")) {
c = Getattr(c, "sym:nextSibling");
continue;
}
if (Getattr(c, "wrap:name")) {
assert(nnodes < MAX_OVERLOAD);
nodes[nnodes].n = c;
nodes[nnodes].parms = Getattr(c, "wrap:parms");
nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms);
nodes[nnodes].error = 0;
nnodes++;
}
c = Getattr(c, "sym:nextSibling");
}
{
int i, j;
for (i = 0; i < nnodes; i++) {
for (j = i + 1; j < nnodes; j++) {
if (nodes[i].argc > nodes[j].argc) {
Overloaded t = nodes[i];
nodes[i] = nodes[j];
nodes[j] = t;
}
}
}
}
{
int i, j;
for (i = 0; i < nnodes - 1; i++) {
if (nodes[i].argc == nodes[i + 1].argc) {
for (j = i + 1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) {
Parm *p1 = nodes[i].parms;
Parm *p2 = nodes[j].parms;
int differ = 0;
int num_checked = 0;
while (p1 && p2 && (num_checked < nodes[i].argc)) {
if (checkAttribute(p1, "tmap:in:numinputs", "0")) {
p1 = Getattr(p1, "tmap:in:next");
continue;
}
if (checkAttribute(p2, "tmap:in:numinputs", "0")) {
p2 = Getattr(p2, "tmap:in:next");
continue;
}
String *t1 = Getattr(p1, "tmap:typecheck:precedence");
String *t2 = Getattr(p2, "tmap:typecheck:precedence");
if ((!t1) && (!nodes[i].error)) {
Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n),
"Overloaded method %s not supported (no type checking rule for '%s').\n",
Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0));
nodes[i].error = 1;
} else if ((!t2) && (!nodes[j].error)) {
Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s not supported (no type checking rule for '%s').\n",
Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0));
nodes[j].error = 1;
}
if (t1 && t2) {
int t1v, t2v;
t1v = atoi(Char(t1));
t2v = atoi(Char(t2));
differ = t1v - t2v;
} else if (!t1 && t2)
differ = 1;
else if (t1 && !t2)
differ = -1;
else if (!t1 && !t2)
differ = -1;
num_checked++;
if (differ > 0) {
Overloaded t = nodes[i];
nodes[i] = nodes[j];
nodes[j] = t;
break;
} else if ((differ == 0) && (Strcmp(t1, "0") == 0)) {
t1 = Getattr(p1, "ltype");
if (!t1) {
t1 = SwigType_ltype(Getattr(p1, "type"));
if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) {
SwigType_add_pointer(t1);
}
Setattr(p1, "ltype", t1);
}
t2 = Getattr(p2, "ltype");
if (!t2) {
t2 = SwigType_ltype(Getattr(p2, "type"));
if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) {
SwigType_add_pointer(t2);
}
Setattr(p2, "ltype", t2);
}
if (SwigType_issubtype(t2, t1)) {
Overloaded t = nodes[i];
nodes[i] = nodes[j];
nodes[j] = t;
}
if (Strcmp(t1, t2) != 0) {
differ = 1;
break;
}
} else if (differ) {
break;
}
if (Getattr(p1, "tmap:in:next")) {
p1 = Getattr(p1, "tmap:in:next");
} else {
p1 = nextSibling(p1);
}
if (Getattr(p2, "tmap:in:next")) {
p2 = Getattr(p2, "tmap:in:next");
} else {
p2 = nextSibling(p2);
}
}
if (!differ) {
String *d1 = Getattr(nodes[i].n, "decl");
String *d2 = Getattr(nodes[j].n, "decl");
if (d1 && d2) {
String *dq1 = Copy(d1);
String *dq2 = Copy(d2);
if (SwigType_isconst(d1)) {
Delete(SwigType_pop(dq1));
}
if (SwigType_isconst(d2)) {
Delete(SwigType_pop(dq2));
}
if (Strcmp(dq1, dq2) == 0) {
if (SwigType_isconst(d1) && !SwigType_isconst(d2)) {
if (script_lang_wrapping) {
Overloaded t = nodes[i];
nodes[i] = nodes[j];
nodes[j] = t;
}
differ = 1;
if (!nodes[j].error) {
if (script_lang_wrapping) {
Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s ignored. Non-const method %s at %s:%d used.\n",
Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(nodes[i].n));
} else {
if (!Getattr(nodes[j].n, "overload:ignore"))
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s ignored. Method %s at %s:%d used.\n",
Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(nodes[i].n));
}
}
nodes[j].error = 1;
} else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) {
differ = 1;
if (!nodes[j].error) {
if (script_lang_wrapping) {
Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s ignored. Non-const method %s at %s:%d used.\n",
Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(nodes[i].n));
} else {
if (!Getattr(nodes[j].n, "overload:ignore"))
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s ignored. Method %s at %s:%d used.\n",
Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(nodes[i].n));
}
}
nodes[j].error = 1;
}
}
Delete(dq1);
Delete(dq2);
}
}
if (!differ) {
if (!nodes[j].error) {
if (script_lang_wrapping) {
Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s is shadowed by %s at %s:%d.\n",
Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
Getfile(nodes[i].n), Getline(nodes[i].n));
} else {
if (!Getattr(nodes[j].n, "overload:ignore"))
Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
"Overloaded method %s ignored. Method %s at %s:%d used.\n",
Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
Getfile(nodes[i].n), Getline(nodes[i].n));
}
nodes[j].error = 1;
}
}
}
}
}
}
List *result = NewList();
{
int i;
for (i = 0; i < nnodes; i++) {
if (nodes[i].error)
Setattr(nodes[i].n, "overload:ignore", "1");
Append(result, nodes[i].n);
}
}
return result;
}
static bool print_typecheck(String *f, int j, Parm *pj) {
char tmp[256];
sprintf(tmp, Char(argv_template_string), j);
String *tm = Getattr(pj, "tmap:typecheck");
if (tm) {
Replaceid(tm, Getattr(pj, "lname"), "_v");
String *conv = Getattr(pj, "implicitconv");
if (conv) {
Replaceall(tm, "$implicitconv", conv);
} else {
Replaceall(tm, "$implicitconv", "0");
}
Replaceall(tm, "$input", tmp);
Printv(f, tm, "\n", NIL);
return true;
} else
return false;
}
static String *ReplaceFormat(const_String_or_char_ptr fmt, int j) {
String *lfmt = NewString(fmt);
char buf[50];
sprintf(buf, "%d", j);
Replaceall(lfmt, "$numargs", buf);
int i;
String *commaargs = NewString("");
for (i = 0; i < j; i++) {
Printv(commaargs, ", ", NIL);
Printf(commaargs, Char(argv_template_string), i);
}
Replaceall(lfmt, "$commaargs", commaargs);
return lfmt;
}
String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *maxargs) {
int i, j;
*maxargs = 1;
String *f = NewString("");
String *sw = NewString("");
Printf(f, "{\n");
Printf(f, "unsigned long _index = 0;\n");
Printf(f, "SWIG_TypeRank _rank = 0; \n");
List *dispatch = Swig_overload_rank(n, true);
int nfunc = Len(dispatch);
bool emitcheck = 1;
for (i = 0; i < nfunc; i++) {
int fn = 0;
Node *ni = Getitem(dispatch, i);
Parm *pi = Getattr(ni, "wrap:parms");
int num_required = emit_num_required(pi);
int num_arguments = emit_num_arguments(pi);
if (num_arguments > *maxargs)
*maxargs = num_arguments;
int varargs = emit_isvarargs(pi);
if (!varargs) {
if (num_required == num_arguments) {
Printf(f, "if (%s == %d) {\n", argc_template_string, num_required);
} else {
Printf(f, "if ((%s >= %d) && (%s <= %d)) {\n", argc_template_string, num_required, argc_template_string, num_arguments);
}
} else {
Printf(f, "if (%s >= %d) {\n", argc_template_string, num_required);
}
Printf(f, "SWIG_TypeRank _ranki = 0;\n");
Printf(f, "SWIG_TypeRank _rankm = 0;\n");
if (num_arguments)
Printf(f, "SWIG_TypeRank _pi = 1;\n");
List *coll = NewList();
for (int k = i + 1; k < nfunc; k++) {
Node *nk = Getitem(dispatch, k);
Parm *pk = Getattr(nk, "wrap:parms");
int nrk = emit_num_required(pk);
int nak = emit_num_arguments(pk);
if ((nrk >= num_required && nrk <= num_arguments) || (nak >= num_required && nak <= num_arguments) || (nrk <= num_required && nak >= num_arguments))
Append(coll, nk);
}
int num_braces = 0;
bool test = (num_arguments > 0);
if (test) {
int need_v = 1;
j = 0;
Parm *pj = pi;
while (pj) {
if (checkAttribute(pj, "tmap:in:numinputs", "0")) {
pj = Getattr(pj, "tmap:in:next");
continue;
}
String *tm = Getattr(pj, "tmap:typecheck");
if (tm) {
Replaceid(tm, Getattr(pj, "lname"), "_v");
for (int k = 0; k < Len(coll) && !emitcheck; k++) {
Node *nk = Getitem(coll, k);
Parm *pk = Getattr(nk, "wrap:parms");
int nak = emit_num_arguments(pk);
if (nak <= j)
continue;
int l = 0;
Parm *pl = pk;
while (pl && l <= j) {
if (checkAttribute(pl, "tmap:in:numinputs", "0")) {
pl = Getattr(pl, "tmap:in:next");
continue;
}
if (l == j) {
String *tml = Getattr(pl, "tmap:typecheck");
if (tml)
Replaceid(tml, Getattr(pl, "lname"), "_v");
if (!tml || Cmp(tm, tml))
emitcheck = 1;
}
Parm *pl1 = Getattr(pl, "tmap:in:next");
if (pl1)
pl = pl1;
else
pl = nextSibling(pl);
l++;
}
}
if (emitcheck) {
if (need_v) {
Printf(f, "int _v = 0;\n");
need_v = 0;
}
if (j >= num_required) {
Printf(f, "if (%s > %d) {\n", argc_template_string, j);
num_braces++;
}
String *tmp = NewStringf(argv_template_string, j);
String *conv = Getattr(pj, "implicitconv");
if (conv) {
Replaceall(tm, "$implicitconv", conv);
} else {
Replaceall(tm, "$implicitconv", "0");
}
Replaceall(tm, "$input", tmp);
Printv(f, "{\n", tm, "}\n", NIL);
fn = i + 1;
Printf(f, "if (!_v) goto check_%d;\n", fn);
Printf(f, "_ranki += _v*_pi;\n");
Printf(f, "_rankm += _pi;\n");
Printf(f, "_pi *= SWIG_MAXCASTRANK;\n");
}
}
if (!Getattr(pj, "tmap:in:SWIGTYPE") && Getattr(pj, "tmap:typecheck:SWIGTYPE")) {
Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
"Overloaded method %s with no explicit typecheck typemap for arg %d of type '%s'\n",
Swig_name_decl(n), j, SwigType_str(Getattr(pj, "type"), 0));
}
Parm *pj1 = Getattr(pj, "tmap:in:next");
if (pj1)
pj = pj1;
else
pj = nextSibling(pj);
j++;
}
}
for ( ; num_braces > 0; num_braces--)
Printf(f, "}\n");
Printf(f, "if (!_index || (_ranki < _rank)) {\n");
Printf(f, " _rank = _ranki; _index = %d;\n", i + 1);
Printf(f, " if (_rank == _rankm) goto dispatch;\n");
Printf(f, "}\n");
String *lfmt = ReplaceFormat(fmt, num_arguments);
Printf(sw, "case %d:\n", i + 1);
Printf(sw, Char(lfmt), Getattr(ni, "wrap:name"));
Printf(sw, "\n");
Printf(f, "}\n");
if (fn)
Printf(f, "check_%d:\n\n", fn);
Delete(lfmt);
Delete(coll);
}
Delete(dispatch);
Printf(f, "dispatch:\n");
Printf(f, "switch(_index) {\n");
Printf(f, "%s", sw);
Printf(f, "}\n");
Printf(f, "}\n");
return f;
}
String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *maxargs) {
int i, j;
*maxargs = 1;
String *f = NewString("");
List *dispatch = Swig_overload_rank(n, true);
int nfunc = Len(dispatch);
for (i = 0; i < nfunc; i++) {
int fn = 0;
Node *ni = Getitem(dispatch, i);
Parm *pi = Getattr(ni, "wrap:parms");
int num_required = emit_num_required(pi);
int num_arguments = emit_num_arguments(pi);
if (num_arguments > *maxargs)
*maxargs = num_arguments;
int varargs = emit_isvarargs(pi);
if (!varargs) {
if (num_required == num_arguments) {
Printf(f, "if (%s == %d) {\n", argc_template_string, num_required);
} else {
Printf(f, "if ((%s >= %d) && (%s <= %d)) {\n", argc_template_string, num_required, argc_template_string, num_arguments);
}
} else {
Printf(f, "if (%s >= %d) {\n", argc_template_string, num_required);
}
List *coll = NewList();
for (int k = i + 1; k < nfunc; k++) {
Node *nk = Getitem(dispatch, k);
Parm *pk = Getattr(nk, "wrap:parms");
int nrk = emit_num_required(pk);
int nak = emit_num_arguments(pk);
if ((nrk >= num_required && nrk <= num_arguments) || (nak >= num_required && nak <= num_arguments) || (nrk <= num_required && nak >= num_arguments))
Append(coll, nk);
}
int num_braces = 0;
bool test = (Len(coll) > 0 && num_arguments);
if (test) {
int need_v = 1;
j = 0;
Parm *pj = pi;
while (pj) {
if (checkAttribute(pj, "tmap:in:numinputs", "0")) {
pj = Getattr(pj, "tmap:in:next");
continue;
}
String *tm = Getattr(pj, "tmap:typecheck");
if (tm) {
Replaceid(tm, Getattr(pj, "lname"), "_v");
bool emitcheck = 0;
for (int k = 0; k < Len(coll) && !emitcheck; k++) {
Node *nk = Getitem(coll, k);
Parm *pk = Getattr(nk, "wrap:parms");
int nak = emit_num_arguments(pk);
if (nak <= j)
continue;
int l = 0;
Parm *pl = pk;
while (pl && l <= j) {
if (checkAttribute(pl, "tmap:in:numinputs", "0")) {
pl = Getattr(pl, "tmap:in:next");
continue;
}
if (l == j) {
String *tml = Getattr(pl, "tmap:typecheck");
if (tml)
Replaceid(tml, Getattr(pl, "lname"), "_v");
if (!tml || Cmp(tm, tml))
emitcheck = 1;
}
Parm *pl1 = Getattr(pl, "tmap:in:next");
if (pl1)
pl = pl1;
else
pl = nextSibling(pl);
l++;
}
}
if (emitcheck) {
if (need_v) {
Printf(f, "int _v = 0;\n");
need_v = 0;
}
if (j >= num_required) {
Printf(f, "if (%s > %d) {\n", argc_template_string, j);
num_braces++;
}
String *tmp = NewStringf(argv_template_string, j);
String *conv = Getattr(pj, "implicitconv");
if (conv) {
Replaceall(tm, "$implicitconv", conv);
} else {
Replaceall(tm, "$implicitconv", "0");
}
Replaceall(tm, "$input", tmp);
Printv(f, "{\n", tm, "}\n", NIL);
fn = i + 1;
Printf(f, "if (!_v) goto check_%d;\n", fn);
}
}
if (!Getattr(pj, "tmap:in:SWIGTYPE") && Getattr(pj, "tmap:typecheck:SWIGTYPE")) {
Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
"Overloaded method %s with no explicit typecheck typemap for arg %d of type '%s'\n",
Swig_name_decl(n), j, SwigType_str(Getattr(pj, "type"), 0));
}
Parm *pj1 = Getattr(pj, "tmap:in:next");
if (pj1)
pj = pj1;
else
pj = nextSibling(pj);
j++;
}
}
for ( ; num_braces > 0; num_braces--)
Printf(f, "}\n");
String *lfmt = ReplaceFormat(fmt, num_arguments);
Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
Printf(f, "}\n");
if (fn)
Printf(f, "check_%d:\n\n", fn);
Delete(lfmt);
Delete(coll);
}
Delete(dispatch);
return f;
}
String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxargs) {
if (fast_dispatch_mode || GetFlag(n, "feature:fastdispatch")) {
return Swig_overload_dispatch_fast(n, fmt, maxargs);
}
int i, j;
*maxargs = 1;
String *f = NewString("");
List *dispatch = Swig_overload_rank(n, true);
int nfunc = Len(dispatch);
for (i = 0; i < nfunc; i++) {
Node *ni = Getitem(dispatch, i);
Parm *pi = Getattr(ni, "wrap:parms");
int num_required = emit_num_required(pi);
int num_arguments = emit_num_arguments(pi);
if (GetFlag(n, "wrap:this")) {
num_required++;
num_arguments++;
}
if (num_arguments > *maxargs)
*maxargs = num_arguments;
int varargs = emit_isvarargs(pi);
if (!varargs) {
if (num_required == num_arguments) {
Printf(f, "if (%s == %d) {\n", argc_template_string, num_required);
} else {
Printf(f, "if ((%s >= %d) && (%s <= %d)) {\n", argc_template_string, num_required, argc_template_string, num_arguments);
}
} else {
Printf(f, "if (%s >= %d) {\n", argc_template_string, num_required);
}
if (num_arguments) {
Printf(f, "int _v;\n");
}
int num_braces = 0;
j = 0;
Parm *pj = pi;
while (pj) {
if (checkAttribute(pj, "tmap:in:numinputs", "0")) {
pj = Getattr(pj, "tmap:in:next");
continue;
}
if (j >= num_required) {
String *lfmt = ReplaceFormat(fmt, num_arguments);
Printf(f, "if (%s <= %d) {\n", argc_template_string, j);
Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
Printf(f, "}\n");
Delete(lfmt);
}
if (print_typecheck(f, (GetFlag(n, "wrap:this") ? j + 1 : j), pj)) {
Printf(f, "if (_v) {\n");
num_braces++;
}
if (!Getattr(pj, "tmap:in:SWIGTYPE") && Getattr(pj, "tmap:typecheck:SWIGTYPE")) {
Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
"Overloaded method %s with no explicit typecheck typemap for arg %d of type '%s'\n",
Swig_name_decl(n), j, SwigType_str(Getattr(pj, "type"), 0));
}
Parm *pk = Getattr(pj, "tmap:in:next");
if (pk)
pj = pk;
else
pj = nextSibling(pj);
j++;
}
String *lfmt = ReplaceFormat(fmt, num_arguments);
Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
Delete(lfmt);
for ( ; num_braces > 0; num_braces--)
Printf(f, "}\n");
Printf(f, "}\n");
}
Delete(dispatch);
return f;
}
void Swig_overload_check(Node *n) {
Swig_overload_rank(n, false);
}