diff options
Diffstat (limited to 'Source/Modules/overload.cxx')
| -rw-r--r-- | Source/Modules/overload.cxx | 792 |
1 files changed, 792 insertions, 0 deletions
diff --git a/Source/Modules/overload.cxx b/Source/Modules/overload.cxx new file mode 100644 index 0000000..38cb729 --- /dev/null +++ b/Source/Modules/overload.cxx @@ -0,0 +1,792 @@ +/* ----------------------------------------------------------------------------- + * See the LICENSE file for information on copyright, usage and redistribution + * of SWIG, and the README file for authors - http://www.swig.org/release.html. + * + * overload.cxx + * + * This file is used to analyze overloaded functions and methods. + * It looks at signatures and tries to gather information for + * building a dispatch function. + * ----------------------------------------------------------------------------- */ + +char cvsroot_overload_cxx[] = "$Id: overload.cxx 11455 2009-07-26 21:29:55Z wsfulton $"; + +#include "swigmod.h" + +#define MAX_OVERLOAD 4096 + +/* Overload "argc" and "argv" */ +String *argv_template_string; +String *argc_template_string; + +struct Overloaded { + Node *n; /* Node */ + int argc; /* Argument count */ + ParmList *parms; /* Parameters used for overload check */ + int error; /* Ambiguity error */ +}; + +static int fast_dispatch_mode = 0; +static int cast_dispatch_mode = 0; + +/* Set fast_dispatch_mode */ +void Wrapper_fast_dispatch_mode_set(int flag) { + fast_dispatch_mode = flag; +} + +void Wrapper_cast_dispatch_mode_set(int flag) { + cast_dispatch_mode = flag; +} + +/* ----------------------------------------------------------------------------- + * Swig_overload_rank() + * + * This function takes an overloaded declaration and creates a list that ranks + * all overloaded methods in an order that can be used to generate a dispatch + * function. + * Slight difference in the way this function is used by scripting languages and + * statically typed languages. The script languages call this method via + * Swig_overload_dispatch() - where wrappers for all overloaded methods are generated, + * however sometimes the code can never be executed. The non-scripting languages + * call this method via Swig_overload_check() for each overloaded method in order + * to determine whether or not the method should be wrapped. Note the slight + * difference when overloading methods that differ by const only. The + * scripting languages will ignore the const method, whereas the non-scripting + * languages ignore the first method parsed. + * ----------------------------------------------------------------------------- */ + +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 (SmartPointer && Getattr(c,"cplus:staticbase")) { + c = Getattr(c,"sym:nextSibling"); + continue; + } */ + + /* Make a list of all the declarations (methods) that are overloaded with + * this one particular method name */ + 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"); + } + + /* Sort the declarations by required argument count */ + { + 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; + } + } + } + } + + /* Sort the declarations by argument types */ + { + 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)) { + // Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type")); + 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); + } + + /* Need subtype check here. If t2 is a subtype of t1, then we need to change the + order */ + + 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) { + /* See if declarations differ by const only */ + 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) { + // Swap nodes so that the const method gets ignored (shadowed by the non-const method) + 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); + // Printf(stdout,"[ %d ] %s\n", i, ParmList_errorstr(nodes[i].parms)); + // Swig_print_node(nodes[i].n); + } + } + return result; +} + +// /* ----------------------------------------------------------------------------- +// * print_typecheck() +// * ----------------------------------------------------------------------------- */ + +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; +} + +/* ----------------------------------------------------------------------------- + * ReplaceFormat() + * ----------------------------------------------------------------------------- */ + +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; +} + +/* ----------------------------------------------------------------------------- + * Swig_overload_dispatch() + * + * Generate a dispatch function. argc is assumed to hold the argument count. + * argv is the argument vector. + * + * Note that for C++ class member functions, Swig_overload_dispatch() assumes + * that argc includes the "self" argument and that the first element of argv[] + * is the "self" argument. So for a member function: + * + * Foo::bar(int x, int y, int z); + * + * the argc should be 4 (not 3!) and the first element of argv[] would be + * the appropriate scripting language reference to "self". For regular + * functions (and static class functions) the argc and argv only include + * the regular function arguments. + * ----------------------------------------------------------------------------- */ + +/* + Cast dispatch mechanism. +*/ +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"); + + /* Get a list of methods ranked by precedence values and argument count */ + List *dispatch = Swig_overload_rank(n, true); + int nfunc = Len(dispatch); + + /* Loop over the functions */ + + 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"); + + /* create a list with the wrappers that collide with the + current one based on argument number */ + 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); + } + + // printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll)); + + 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) { + /* normalise for comparison later */ + Replaceid(tm, Getattr(pj, "lname"), "_v"); + + /* if all the wrappers have the same type check on this + argument we can optimize it out */ + 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; + /* finds arg j on the collider wrapper */ + while (pl && l <= j) { + if (checkAttribute(pl, "tmap:in:numinputs", "0")) { + pl = Getattr(pl, "tmap:in:next"); + continue; + } + if (l == j) { + /* we are at arg j, so we compare the tmaps now */ + String *tml = Getattr(pl, "tmap:typecheck"); + /* normalise it before comparing */ + if (tml) + Replaceid(tml, Getattr(pl, "lname"), "_v"); + if (!tml || Cmp(tm, tml)) + emitcheck = 1; + //printf("tmap: %s[%d] (%d) => %s\n\n", + // Char(Getattr(nk, "sym:name")), + // l, emitcheck, tml?Char(tml):0); + } + 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")) { + /* we emit a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */ + 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++; + } + } + + /* close braces */ + for ( /* empty */ ; 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"); /* braces closes "if" for this method */ + 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; +} + +/* + Fast dispatch mechanism, provided by Salvador Fandi~no Garc'ia (#930586). +*/ +String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *maxargs) { + int i, j; + + *maxargs = 1; + + String *f = NewString(""); + + /* Get a list of methods ranked by precedence values and argument count */ + List *dispatch = Swig_overload_rank(n, true); + int nfunc = Len(dispatch); + + /* Loop over the functions */ + + 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); + } + + /* create a list with the wrappers that collide with the + current one based on argument number */ + 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); + } + + // printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll)); + + 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) { + /* normalise for comparison later */ + Replaceid(tm, Getattr(pj, "lname"), "_v"); + + /* if all the wrappers have the same type check on this + argument we can optimize it out */ + 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; + /* finds arg j on the collider wrapper */ + while (pl && l <= j) { + if (checkAttribute(pl, "tmap:in:numinputs", "0")) { + pl = Getattr(pl, "tmap:in:next"); + continue; + } + if (l == j) { + /* we are at arg j, so we compare the tmaps now */ + String *tml = Getattr(pl, "tmap:typecheck"); + /* normalise it before comparing */ + if (tml) + Replaceid(tml, Getattr(pl, "lname"), "_v"); + if (!tml || Cmp(tm, tml)) + emitcheck = 1; + //printf("tmap: %s[%d] (%d) => %s\n\n", + // Char(Getattr(nk, "sym:name")), + // l, emitcheck, tml?Char(tml):0); + } + 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")) { + /* we emit a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */ + 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++; + } + } + + /* close braces */ + for ( /* empty */ ; 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"); /* braces closes "if" for this method */ + 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(""); + + /* Get a list of methods ranked by precedence values and argument count */ + List *dispatch = Swig_overload_rank(n, true); + int nfunc = Len(dispatch); + + /* Loop over the functions */ + + 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")) { + /* we emit a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */ + 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); + /* close braces */ + for ( /* empty */ ; num_braces > 0; num_braces--) + Printf(f, "}\n"); + Printf(f, "}\n"); /* braces closes "if" for this method */ + } + Delete(dispatch); + return f; +} + +/* ----------------------------------------------------------------------------- + * Swig_overload_check() + * ----------------------------------------------------------------------------- */ +void Swig_overload_check(Node *n) { + Swig_overload_rank(n, false); +} |
