import source from 1.3.40
[external/swig.git] / Source / Modules / overload.cxx
1 /* ----------------------------------------------------------------------------- 
2  * See the LICENSE file for information on copyright, usage and redistribution
3  * of SWIG, and the README file for authors - http://www.swig.org/release.html.
4  *
5  * overload.cxx
6  *
7  * This file is used to analyze overloaded functions and methods.
8  * It looks at signatures and tries to gather information for
9  * building a dispatch function.
10  * ----------------------------------------------------------------------------- */
11
12 char cvsroot_overload_cxx[] = "$Id: overload.cxx 11455 2009-07-26 21:29:55Z wsfulton $";
13
14 #include "swigmod.h"
15
16 #define MAX_OVERLOAD 4096
17
18 /* Overload "argc" and "argv" */
19 String *argv_template_string;
20 String *argc_template_string;
21
22 struct Overloaded {
23   Node *n;                      /* Node                               */
24   int argc;                     /* Argument count                     */
25   ParmList *parms;              /* Parameters used for overload check */
26   int error;                    /* Ambiguity error                    */
27 };
28
29 static int fast_dispatch_mode = 0;
30 static int cast_dispatch_mode = 0;
31
32 /* Set fast_dispatch_mode */
33 void Wrapper_fast_dispatch_mode_set(int flag) {
34   fast_dispatch_mode = flag;
35 }
36
37 void Wrapper_cast_dispatch_mode_set(int flag) {
38   cast_dispatch_mode = flag;
39 }
40
41 /* -----------------------------------------------------------------------------
42  * Swig_overload_rank()
43  *
44  * This function takes an overloaded declaration and creates a list that ranks
45  * all overloaded methods in an order that can be used to generate a dispatch 
46  * function.
47  * Slight difference in the way this function is used by scripting languages and
48  * statically typed languages. The script languages call this method via 
49  * Swig_overload_dispatch() - where wrappers for all overloaded methods are generated,
50  * however sometimes the code can never be executed. The non-scripting languages
51  * call this method via Swig_overload_check() for each overloaded method in order
52  * to determine whether or not the method should be wrapped. Note the slight
53  * difference when overloading methods that differ by const only. The
54  * scripting languages will ignore the const method, whereas the non-scripting
55  * languages ignore the first method parsed.
56  * ----------------------------------------------------------------------------- */
57
58 static List *Swig_overload_rank(Node *n, bool script_lang_wrapping) {
59   Overloaded nodes[MAX_OVERLOAD];
60   int nnodes = 0;
61   Node *o = Getattr(n, "sym:overloaded");
62   Node *c;
63
64   if (!o)
65     return 0;
66
67   c = o;
68   while (c) {
69     if (Getattr(c, "error")) {
70       c = Getattr(c, "sym:nextSibling");
71       continue;
72     }
73     /*    if (SmartPointer && Getattr(c,"cplus:staticbase")) {
74        c = Getattr(c,"sym:nextSibling");
75        continue;
76        } */
77
78     /* Make a list of all the declarations (methods) that are overloaded with
79      * this one particular method name */
80     if (Getattr(c, "wrap:name")) {
81       assert(nnodes < MAX_OVERLOAD);
82       nodes[nnodes].n = c;
83       nodes[nnodes].parms = Getattr(c, "wrap:parms");
84       nodes[nnodes].argc = emit_num_required(nodes[nnodes].parms);
85       nodes[nnodes].error = 0;
86       nnodes++;
87     }
88     c = Getattr(c, "sym:nextSibling");
89   }
90
91   /* Sort the declarations by required argument count */
92   {
93     int i, j;
94     for (i = 0; i < nnodes; i++) {
95       for (j = i + 1; j < nnodes; j++) {
96         if (nodes[i].argc > nodes[j].argc) {
97           Overloaded t = nodes[i];
98           nodes[i] = nodes[j];
99           nodes[j] = t;
100         }
101       }
102     }
103   }
104
105   /* Sort the declarations by argument types */
106   {
107     int i, j;
108     for (i = 0; i < nnodes - 1; i++) {
109       if (nodes[i].argc == nodes[i + 1].argc) {
110         for (j = i + 1; (j < nnodes) && (nodes[j].argc == nodes[i].argc); j++) {
111           Parm *p1 = nodes[i].parms;
112           Parm *p2 = nodes[j].parms;
113           int differ = 0;
114           int num_checked = 0;
115           while (p1 && p2 && (num_checked < nodes[i].argc)) {
116             //    Printf(stdout,"p1 = '%s', p2 = '%s'\n", Getattr(p1,"type"), Getattr(p2,"type"));
117             if (checkAttribute(p1, "tmap:in:numinputs", "0")) {
118               p1 = Getattr(p1, "tmap:in:next");
119               continue;
120             }
121             if (checkAttribute(p2, "tmap:in:numinputs", "0")) {
122               p2 = Getattr(p2, "tmap:in:next");
123               continue;
124             }
125             String *t1 = Getattr(p1, "tmap:typecheck:precedence");
126             String *t2 = Getattr(p2, "tmap:typecheck:precedence");
127             if ((!t1) && (!nodes[i].error)) {
128               Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[i].n), Getline(nodes[i].n),
129                            "Overloaded method %s not supported (no type checking rule for '%s').\n",
130                            Swig_name_decl(nodes[i].n), SwigType_str(Getattr(p1, "type"), 0));
131               nodes[i].error = 1;
132             } else if ((!t2) && (!nodes[j].error)) {
133               Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
134                            "Overloaded method %s not supported (no type checking rule for '%s').\n",
135                            Swig_name_decl(nodes[j].n), SwigType_str(Getattr(p2, "type"), 0));
136               nodes[j].error = 1;
137             }
138             if (t1 && t2) {
139               int t1v, t2v;
140               t1v = atoi(Char(t1));
141               t2v = atoi(Char(t2));
142               differ = t1v - t2v;
143             } else if (!t1 && t2)
144               differ = 1;
145             else if (t1 && !t2)
146               differ = -1;
147             else if (!t1 && !t2)
148               differ = -1;
149             num_checked++;
150             if (differ > 0) {
151               Overloaded t = nodes[i];
152               nodes[i] = nodes[j];
153               nodes[j] = t;
154               break;
155             } else if ((differ == 0) && (Strcmp(t1, "0") == 0)) {
156               t1 = Getattr(p1, "ltype");
157               if (!t1) {
158                 t1 = SwigType_ltype(Getattr(p1, "type"));
159                 if (Getattr(p1, "tmap:typecheck:SWIGTYPE")) {
160                   SwigType_add_pointer(t1);
161                 }
162                 Setattr(p1, "ltype", t1);
163               }
164               t2 = Getattr(p2, "ltype");
165               if (!t2) {
166                 t2 = SwigType_ltype(Getattr(p2, "type"));
167                 if (Getattr(p2, "tmap:typecheck:SWIGTYPE")) {
168                   SwigType_add_pointer(t2);
169                 }
170                 Setattr(p2, "ltype", t2);
171               }
172
173               /* Need subtype check here.  If t2 is a subtype of t1, then we need to change the
174                  order */
175
176               if (SwigType_issubtype(t2, t1)) {
177                 Overloaded t = nodes[i];
178                 nodes[i] = nodes[j];
179                 nodes[j] = t;
180               }
181
182               if (Strcmp(t1, t2) != 0) {
183                 differ = 1;
184                 break;
185               }
186             } else if (differ) {
187               break;
188             }
189             if (Getattr(p1, "tmap:in:next")) {
190               p1 = Getattr(p1, "tmap:in:next");
191             } else {
192               p1 = nextSibling(p1);
193             }
194             if (Getattr(p2, "tmap:in:next")) {
195               p2 = Getattr(p2, "tmap:in:next");
196             } else {
197               p2 = nextSibling(p2);
198             }
199           }
200           if (!differ) {
201             /* See if declarations differ by const only */
202             String *d1 = Getattr(nodes[i].n, "decl");
203             String *d2 = Getattr(nodes[j].n, "decl");
204             if (d1 && d2) {
205               String *dq1 = Copy(d1);
206               String *dq2 = Copy(d2);
207               if (SwigType_isconst(d1)) {
208                 Delete(SwigType_pop(dq1));
209               }
210               if (SwigType_isconst(d2)) {
211                 Delete(SwigType_pop(dq2));
212               }
213               if (Strcmp(dq1, dq2) == 0) {
214
215                 if (SwigType_isconst(d1) && !SwigType_isconst(d2)) {
216                   if (script_lang_wrapping) {
217                     // Swap nodes so that the const method gets ignored (shadowed by the non-const method)
218                     Overloaded t = nodes[i];
219                     nodes[i] = nodes[j];
220                     nodes[j] = t;
221                   }
222                   differ = 1;
223                   if (!nodes[j].error) {
224                     if (script_lang_wrapping) {
225                       Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
226                                    "Overloaded method %s ignored. Non-const method %s at %s:%d used.\n",
227                                    Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(nodes[i].n));
228                     } else {
229                       if (!Getattr(nodes[j].n, "overload:ignore"))
230                         Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
231                                      "Overloaded method %s ignored. Method %s at %s:%d used.\n",
232                                      Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(nodes[i].n));
233                     }
234                   }
235                   nodes[j].error = 1;
236                 } else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) {
237                   differ = 1;
238                   if (!nodes[j].error) {
239                     if (script_lang_wrapping) {
240                       Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
241                                    "Overloaded method %s ignored. Non-const method %s at %s:%d used.\n",
242                                    Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(nodes[i].n));
243                     } else {
244                       if (!Getattr(nodes[j].n, "overload:ignore"))
245                         Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
246                                      "Overloaded method %s ignored. Method %s at %s:%d used.\n",
247                                      Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n), Getfile(nodes[i].n), Getline(nodes[i].n));
248                     }
249                   }
250                   nodes[j].error = 1;
251                 }
252               }
253               Delete(dq1);
254               Delete(dq2);
255             }
256           }
257           if (!differ) {
258             if (!nodes[j].error) {
259               if (script_lang_wrapping) {
260                 Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
261                              "Overloaded method %s is shadowed by %s at %s:%d.\n",
262                              Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
263                              Getfile(nodes[i].n), Getline(nodes[i].n));
264               } else {
265                 if (!Getattr(nodes[j].n, "overload:ignore"))
266                   Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
267                                "Overloaded method %s ignored. Method %s at %s:%d used.\n",
268                                Swig_name_decl(nodes[j].n), Swig_name_decl(nodes[i].n),
269                                Getfile(nodes[i].n), Getline(nodes[i].n));
270               }
271               nodes[j].error = 1;
272             }
273           }
274         }
275       }
276     }
277   }
278   List *result = NewList();
279   {
280     int i;
281     for (i = 0; i < nnodes; i++) {
282       if (nodes[i].error)
283         Setattr(nodes[i].n, "overload:ignore", "1");
284       Append(result, nodes[i].n);
285       //      Printf(stdout,"[ %d ] %s\n", i, ParmList_errorstr(nodes[i].parms));
286       //      Swig_print_node(nodes[i].n);
287     }
288   }
289   return result;
290 }
291
292 // /* -----------------------------------------------------------------------------
293 //  * print_typecheck()
294 //  * ----------------------------------------------------------------------------- */
295
296 static bool print_typecheck(String *f, int j, Parm *pj) {
297   char tmp[256];
298   sprintf(tmp, Char(argv_template_string), j);
299   String *tm = Getattr(pj, "tmap:typecheck");
300   if (tm) {
301     Replaceid(tm, Getattr(pj, "lname"), "_v");
302     String *conv = Getattr(pj, "implicitconv");
303     if (conv) {
304       Replaceall(tm, "$implicitconv", conv);
305     } else {
306       Replaceall(tm, "$implicitconv", "0");
307     }
308     Replaceall(tm, "$input", tmp);
309     Printv(f, tm, "\n", NIL);
310     return true;
311   } else
312     return false;
313 }
314
315 /* -----------------------------------------------------------------------------
316  * ReplaceFormat()
317  * ----------------------------------------------------------------------------- */
318
319 static String *ReplaceFormat(const_String_or_char_ptr fmt, int j) {
320   String *lfmt = NewString(fmt);
321   char buf[50];
322   sprintf(buf, "%d", j);
323   Replaceall(lfmt, "$numargs", buf);
324   int i;
325   String *commaargs = NewString("");
326   for (i = 0; i < j; i++) {
327     Printv(commaargs, ", ", NIL);
328     Printf(commaargs, Char(argv_template_string), i);
329   }
330   Replaceall(lfmt, "$commaargs", commaargs);
331   return lfmt;
332 }
333
334 /* -----------------------------------------------------------------------------
335  * Swig_overload_dispatch()
336  *
337  * Generate a dispatch function.  argc is assumed to hold the argument count.
338  * argv is the argument vector.
339  *
340  * Note that for C++ class member functions, Swig_overload_dispatch() assumes
341  * that argc includes the "self" argument and that the first element of argv[]
342  * is the "self" argument. So for a member function:
343  *
344  *     Foo::bar(int x, int y, int z);
345  *
346  * the argc should be 4 (not 3!) and the first element of argv[] would be
347  * the appropriate scripting language reference to "self". For regular
348  * functions (and static class functions) the argc and argv only include
349  * the regular function arguments.
350  * ----------------------------------------------------------------------------- */
351
352 /*
353   Cast dispatch mechanism.
354 */
355 String *Swig_overload_dispatch_cast(Node *n, const_String_or_char_ptr fmt, int *maxargs) {
356   int i, j;
357
358   *maxargs = 1;
359
360   String *f = NewString("");
361   String *sw = NewString("");
362   Printf(f, "{\n");
363   Printf(f, "unsigned long _index = 0;\n");
364   Printf(f, "SWIG_TypeRank _rank = 0; \n");
365
366   /* Get a list of methods ranked by precedence values and argument count */
367   List *dispatch = Swig_overload_rank(n, true);
368   int nfunc = Len(dispatch);
369
370   /* Loop over the functions */
371
372   bool emitcheck = 1;
373   for (i = 0; i < nfunc; i++) {
374     int fn = 0;
375     Node *ni = Getitem(dispatch, i);
376     Parm *pi = Getattr(ni, "wrap:parms");
377     int num_required = emit_num_required(pi);
378     int num_arguments = emit_num_arguments(pi);
379     if (num_arguments > *maxargs)
380       *maxargs = num_arguments;
381     int varargs = emit_isvarargs(pi);
382
383     if (!varargs) {
384       if (num_required == num_arguments) {
385         Printf(f, "if (%s == %d) {\n", argc_template_string, num_required);
386       } else {
387         Printf(f, "if ((%s >= %d) && (%s <= %d)) {\n", argc_template_string, num_required, argc_template_string, num_arguments);
388       }
389     } else {
390       Printf(f, "if (%s >= %d) {\n", argc_template_string, num_required);
391     }
392     Printf(f, "SWIG_TypeRank _ranki = 0;\n");
393     Printf(f, "SWIG_TypeRank _rankm = 0;\n");
394     if (num_arguments)
395       Printf(f, "SWIG_TypeRank _pi = 1;\n");
396
397     /* create a list with the wrappers that collide with the
398        current one based on argument number */
399     List *coll = NewList();
400     for (int k = i + 1; k < nfunc; k++) {
401       Node *nk = Getitem(dispatch, k);
402       Parm *pk = Getattr(nk, "wrap:parms");
403       int nrk = emit_num_required(pk);
404       int nak = emit_num_arguments(pk);
405       if ((nrk >= num_required && nrk <= num_arguments) || (nak >= num_required && nak <= num_arguments) || (nrk <= num_required && nak >= num_arguments))
406         Append(coll, nk);
407     }
408
409     // printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll));
410
411     int num_braces = 0;
412     bool test = (num_arguments > 0);
413     if (test) {
414       int need_v = 1;
415       j = 0;
416       Parm *pj = pi;
417       while (pj) {
418         if (checkAttribute(pj, "tmap:in:numinputs", "0")) {
419           pj = Getattr(pj, "tmap:in:next");
420           continue;
421         }
422
423         String *tm = Getattr(pj, "tmap:typecheck");
424         if (tm) {
425           /* normalise for comparison later */
426           Replaceid(tm, Getattr(pj, "lname"), "_v");
427
428           /* if all the wrappers have the same type check on this
429              argument we can optimize it out */
430           for (int k = 0; k < Len(coll) && !emitcheck; k++) {
431             Node *nk = Getitem(coll, k);
432             Parm *pk = Getattr(nk, "wrap:parms");
433             int nak = emit_num_arguments(pk);
434             if (nak <= j)
435               continue;
436             int l = 0;
437             Parm *pl = pk;
438             /* finds arg j on the collider wrapper */
439             while (pl && l <= j) {
440               if (checkAttribute(pl, "tmap:in:numinputs", "0")) {
441                 pl = Getattr(pl, "tmap:in:next");
442                 continue;
443               }
444               if (l == j) {
445                 /* we are at arg j, so we compare the tmaps now */
446                 String *tml = Getattr(pl, "tmap:typecheck");
447                 /* normalise it before comparing */
448                 if (tml)
449                   Replaceid(tml, Getattr(pl, "lname"), "_v");
450                 if (!tml || Cmp(tm, tml))
451                   emitcheck = 1;
452                 //printf("tmap: %s[%d] (%d) => %s\n\n",
453                 //       Char(Getattr(nk, "sym:name")),
454                 //       l, emitcheck, tml?Char(tml):0);
455               }
456               Parm *pl1 = Getattr(pl, "tmap:in:next");
457               if (pl1)
458                 pl = pl1;
459               else
460                 pl = nextSibling(pl);
461               l++;
462             }
463           }
464
465           if (emitcheck) {
466             if (need_v) {
467               Printf(f, "int _v = 0;\n");
468               need_v = 0;
469             }
470             if (j >= num_required) {
471               Printf(f, "if (%s > %d) {\n", argc_template_string, j);
472               num_braces++;
473             }
474             String *tmp = NewStringf(argv_template_string, j);
475
476             String *conv = Getattr(pj, "implicitconv");
477             if (conv) {
478               Replaceall(tm, "$implicitconv", conv);
479             } else {
480               Replaceall(tm, "$implicitconv", "0");
481             }
482             Replaceall(tm, "$input", tmp);
483             Printv(f, "{\n", tm, "}\n", NIL);
484             fn = i + 1;
485             Printf(f, "if (!_v) goto check_%d;\n", fn);
486             Printf(f, "_ranki += _v*_pi;\n");
487             Printf(f, "_rankm += _pi;\n");
488             Printf(f, "_pi *= SWIG_MAXCASTRANK;\n");
489           }
490         }
491         if (!Getattr(pj, "tmap:in:SWIGTYPE") && Getattr(pj, "tmap:typecheck:SWIGTYPE")) {
492           /* we emit  a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */
493           Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
494                        "Overloaded method %s with no explicit typecheck typemap for arg %d of type '%s'\n",
495                        Swig_name_decl(n), j, SwigType_str(Getattr(pj, "type"), 0));
496         }
497         Parm *pj1 = Getattr(pj, "tmap:in:next");
498         if (pj1)
499           pj = pj1;
500         else
501           pj = nextSibling(pj);
502         j++;
503       }
504     }
505
506     /* close braces */
507     for ( /* empty */ ; num_braces > 0; num_braces--)
508       Printf(f, "}\n");
509
510     Printf(f, "if (!_index || (_ranki < _rank)) {\n");
511     Printf(f, " _rank = _ranki; _index = %d;\n", i + 1);
512     Printf(f, " if (_rank == _rankm) goto dispatch;\n");
513     Printf(f, "}\n");
514     String *lfmt = ReplaceFormat(fmt, num_arguments);
515     Printf(sw, "case %d:\n", i + 1);
516     Printf(sw, Char(lfmt), Getattr(ni, "wrap:name"));
517     Printf(sw, "\n");
518
519     Printf(f, "}\n");           /* braces closes "if" for this method */
520     if (fn)
521       Printf(f, "check_%d:\n\n", fn);
522
523     Delete(lfmt);
524     Delete(coll);
525   }
526   Delete(dispatch);
527   Printf(f, "dispatch:\n");
528   Printf(f, "switch(_index) {\n");
529   Printf(f, "%s", sw);
530   Printf(f, "}\n");
531
532   Printf(f, "}\n");
533   return f;
534 }
535
536 /*
537   Fast dispatch mechanism, provided by  Salvador Fandi~no Garc'ia (#930586).
538 */
539 String *Swig_overload_dispatch_fast(Node *n, const_String_or_char_ptr fmt, int *maxargs) {
540   int i, j;
541
542   *maxargs = 1;
543
544   String *f = NewString("");
545
546   /* Get a list of methods ranked by precedence values and argument count */
547   List *dispatch = Swig_overload_rank(n, true);
548   int nfunc = Len(dispatch);
549
550   /* Loop over the functions */
551
552   for (i = 0; i < nfunc; i++) {
553     int fn = 0;
554     Node *ni = Getitem(dispatch, i);
555     Parm *pi = Getattr(ni, "wrap:parms");
556     int num_required = emit_num_required(pi);
557     int num_arguments = emit_num_arguments(pi);
558     if (num_arguments > *maxargs)
559       *maxargs = num_arguments;
560     int varargs = emit_isvarargs(pi);
561
562     if (!varargs) {
563       if (num_required == num_arguments) {
564         Printf(f, "if (%s == %d) {\n", argc_template_string, num_required);
565       } else {
566         Printf(f, "if ((%s >= %d) && (%s <= %d)) {\n", argc_template_string, num_required, argc_template_string, num_arguments);
567       }
568     } else {
569       Printf(f, "if (%s >= %d) {\n", argc_template_string, num_required);
570     }
571
572     /* create a list with the wrappers that collide with the
573        current one based on argument number */
574     List *coll = NewList();
575     for (int k = i + 1; k < nfunc; k++) {
576       Node *nk = Getitem(dispatch, k);
577       Parm *pk = Getattr(nk, "wrap:parms");
578       int nrk = emit_num_required(pk);
579       int nak = emit_num_arguments(pk);
580       if ((nrk >= num_required && nrk <= num_arguments) || (nak >= num_required && nak <= num_arguments) || (nrk <= num_required && nak >= num_arguments))
581         Append(coll, nk);
582     }
583
584     // printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll));
585
586     int num_braces = 0;
587     bool test = (Len(coll) > 0 && num_arguments);
588     if (test) {
589       int need_v = 1;
590       j = 0;
591       Parm *pj = pi;
592       while (pj) {
593         if (checkAttribute(pj, "tmap:in:numinputs", "0")) {
594           pj = Getattr(pj, "tmap:in:next");
595           continue;
596         }
597
598         String *tm = Getattr(pj, "tmap:typecheck");
599         if (tm) {
600           /* normalise for comparison later */
601           Replaceid(tm, Getattr(pj, "lname"), "_v");
602
603           /* if all the wrappers have the same type check on this
604              argument we can optimize it out */
605           bool emitcheck = 0;
606           for (int k = 0; k < Len(coll) && !emitcheck; k++) {
607             Node *nk = Getitem(coll, k);
608             Parm *pk = Getattr(nk, "wrap:parms");
609             int nak = emit_num_arguments(pk);
610             if (nak <= j)
611               continue;
612             int l = 0;
613             Parm *pl = pk;
614             /* finds arg j on the collider wrapper */
615             while (pl && l <= j) {
616               if (checkAttribute(pl, "tmap:in:numinputs", "0")) {
617                 pl = Getattr(pl, "tmap:in:next");
618                 continue;
619               }
620               if (l == j) {
621                 /* we are at arg j, so we compare the tmaps now */
622                 String *tml = Getattr(pl, "tmap:typecheck");
623                 /* normalise it before comparing */
624                 if (tml)
625                   Replaceid(tml, Getattr(pl, "lname"), "_v");
626                 if (!tml || Cmp(tm, tml))
627                   emitcheck = 1;
628                 //printf("tmap: %s[%d] (%d) => %s\n\n",
629                 //       Char(Getattr(nk, "sym:name")),
630                 //       l, emitcheck, tml?Char(tml):0);
631               }
632               Parm *pl1 = Getattr(pl, "tmap:in:next");
633               if (pl1)
634                 pl = pl1;
635               else
636                 pl = nextSibling(pl);
637               l++;
638             }
639           }
640
641           if (emitcheck) {
642             if (need_v) {
643               Printf(f, "int _v = 0;\n");
644               need_v = 0;
645             }
646             if (j >= num_required) {
647               Printf(f, "if (%s > %d) {\n", argc_template_string, j);
648               num_braces++;
649             }
650             String *tmp = NewStringf(argv_template_string, j);
651
652             String *conv = Getattr(pj, "implicitconv");
653             if (conv) {
654               Replaceall(tm, "$implicitconv", conv);
655             } else {
656               Replaceall(tm, "$implicitconv", "0");
657             }
658             Replaceall(tm, "$input", tmp);
659             Printv(f, "{\n", tm, "}\n", NIL);
660             fn = i + 1;
661             Printf(f, "if (!_v) goto check_%d;\n", fn);
662           }
663         }
664         if (!Getattr(pj, "tmap:in:SWIGTYPE") && Getattr(pj, "tmap:typecheck:SWIGTYPE")) {
665           /* we emit  a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */
666           Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
667                        "Overloaded method %s with no explicit typecheck typemap for arg %d of type '%s'\n",
668                        Swig_name_decl(n), j, SwigType_str(Getattr(pj, "type"), 0));
669         }
670         Parm *pj1 = Getattr(pj, "tmap:in:next");
671         if (pj1)
672           pj = pj1;
673         else
674           pj = nextSibling(pj);
675         j++;
676       }
677     }
678
679     /* close braces */
680     for ( /* empty */ ; num_braces > 0; num_braces--)
681       Printf(f, "}\n");
682
683
684     String *lfmt = ReplaceFormat(fmt, num_arguments);
685     Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
686
687     Printf(f, "}\n");           /* braces closes "if" for this method */
688     if (fn)
689       Printf(f, "check_%d:\n\n", fn);
690
691     Delete(lfmt);
692     Delete(coll);
693   }
694   Delete(dispatch);
695   return f;
696 }
697
698 String *Swig_overload_dispatch(Node *n, const_String_or_char_ptr fmt, int *maxargs) {
699
700   if (fast_dispatch_mode || GetFlag(n, "feature:fastdispatch")) {
701     return Swig_overload_dispatch_fast(n, fmt, maxargs);
702   }
703
704   int i, j;
705
706   *maxargs = 1;
707
708   String *f = NewString("");
709
710   /* Get a list of methods ranked by precedence values and argument count */
711   List *dispatch = Swig_overload_rank(n, true);
712   int nfunc = Len(dispatch);
713
714   /* Loop over the functions */
715
716   for (i = 0; i < nfunc; i++) {
717     Node *ni = Getitem(dispatch, i);
718     Parm *pi = Getattr(ni, "wrap:parms");
719     int num_required = emit_num_required(pi);
720     int num_arguments = emit_num_arguments(pi);
721     if (GetFlag(n, "wrap:this")) {
722       num_required++;
723       num_arguments++;
724     }
725     if (num_arguments > *maxargs)
726       *maxargs = num_arguments;
727     int varargs = emit_isvarargs(pi);
728
729     if (!varargs) {
730       if (num_required == num_arguments) {
731         Printf(f, "if (%s == %d) {\n", argc_template_string, num_required);
732       } else {
733         Printf(f, "if ((%s >= %d) && (%s <= %d)) {\n", argc_template_string, num_required, argc_template_string, num_arguments);
734       }
735     } else {
736       Printf(f, "if (%s >= %d) {\n", argc_template_string, num_required);
737     }
738
739     if (num_arguments) {
740       Printf(f, "int _v;\n");
741     }
742
743     int num_braces = 0;
744     j = 0;
745     Parm *pj = pi;
746     while (pj) {
747       if (checkAttribute(pj, "tmap:in:numinputs", "0")) {
748         pj = Getattr(pj, "tmap:in:next");
749         continue;
750       }
751       if (j >= num_required) {
752         String *lfmt = ReplaceFormat(fmt, num_arguments);
753         Printf(f, "if (%s <= %d) {\n", argc_template_string, j);
754         Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
755         Printf(f, "}\n");
756         Delete(lfmt);
757       }
758       if (print_typecheck(f, (GetFlag(n, "wrap:this") ? j + 1 : j), pj)) {
759         Printf(f, "if (_v) {\n");
760         num_braces++;
761       }
762       if (!Getattr(pj, "tmap:in:SWIGTYPE") && Getattr(pj, "tmap:typecheck:SWIGTYPE")) {
763         /* we emit  a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */
764         Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
765                      "Overloaded method %s with no explicit typecheck typemap for arg %d of type '%s'\n",
766                      Swig_name_decl(n), j, SwigType_str(Getattr(pj, "type"), 0));
767       }
768       Parm *pk = Getattr(pj, "tmap:in:next");
769       if (pk)
770         pj = pk;
771       else
772         pj = nextSibling(pj);
773       j++;
774     }
775     String *lfmt = ReplaceFormat(fmt, num_arguments);
776     Printf(f, Char(lfmt), Getattr(ni, "wrap:name"));
777     Delete(lfmt);
778     /* close braces */
779     for ( /* empty */ ; num_braces > 0; num_braces--)
780       Printf(f, "}\n");
781     Printf(f, "}\n");           /* braces closes "if" for this method */
782   }
783   Delete(dispatch);
784   return f;
785 }
786
787 /* -----------------------------------------------------------------------------
788  * Swig_overload_check()
789  * ----------------------------------------------------------------------------- */
790 void Swig_overload_check(Node *n) {
791   Swig_overload_rank(n, false);
792 }