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
12char 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" */
19String *argv_template_string;
20String *argc_template_string;
21
22struct 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
29static int fast_dispatch_mode = 0;
30static int cast_dispatch_mode = 0;
31
32/* Set fast_dispatch_mode */
33void Wrapper_fast_dispatch_mode_set(int flag) {
34  fast_dispatch_mode = flag;
35}
36
37void 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
58static 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
296static 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
319static 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*/
355String *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*/
539String *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
698String *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 * ----------------------------------------------------------------------------- */
790void Swig_overload_check(Node *n) {
791  Swig_overload_rank(n, false);
792}
793