PageRenderTime 176ms CodeModel.GetById 71ms app.highlight 73ms RepoModel.GetById 1ms app.codeStats 0ms

/tags/rel-1-3-30rc1-b4beautify/SWIG/Source/Modules/overload.cxx

#
C++ | 796 lines | 610 code | 75 blank | 111 comment | 182 complexity | 296a4f76b5e0820d32cffce2af94fd38 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  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[] = "$Header$";
 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 *
 59Swig_overload_rank(Node *n, bool script_lang_wrapping) {
 60  Overloaded  nodes[MAX_OVERLOAD];
 61  int         nnodes = 0;
 62  Node *o = Getattr(n,"sym:overloaded");
 63  Node *c;
 64
 65  if (!o) 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 %s(%s) not supported (no type checking rule for '%s').\n", 
130			   Getattr(nodes[i].n,"name"),ParmList_str_defaultargs(Getattr(nodes[i].n,"parms")),
131			   SwigType_str(Getattr(p1,"type"),0));
132	      nodes[i].error = 1;
133	    } else if ((!t2) && (!nodes[j].error)) {
134	      Swig_warning(WARN_TYPEMAP_TYPECHECK, Getfile(nodes[j].n), Getline(nodes[j].n),
135			   "Overloaded %s(%s) not supported (no type checking rule for '%s').\n", 
136			   Getattr(nodes[j].n,"name"),ParmList_str_defaultargs(Getattr(nodes[j].n,"parms")),
137			   SwigType_str(Getattr(p2,"type"),0));
138	      nodes[j].error = 1;
139	    }
140	    if (t1 && t2) {
141	      int t1v, t2v;
142	      t1v = atoi(Char(t1));
143	      t2v = atoi(Char(t2));
144	      differ = t1v-t2v;
145	    }
146	    else if (!t1 && t2) differ = 1;
147	    else if (t2 && !t1) differ = -1;
148	    else if (!t1 && !t2) 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 %s(%s) const ignored. Non-const method at %s:%d used.\n",
227				   Getattr(nodes[j].n,"name"), ParmList_protostr(nodes[j].parms),
228				   Getfile(nodes[i].n), Getline(nodes[i].n));
229                    } else {
230                      if (!Getattr(nodes[j].n, "overload:ignore"))
231		        Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
232				     "Overloaded method %s(%s) ignored. Method %s(%s) const at %s:%d used.\n",
233				     Getattr(nodes[j].n,"name"), ParmList_protostr(nodes[j].parms),
234			             Getattr(nodes[i].n,"name"), ParmList_protostr(nodes[i].parms),
235				     Getfile(nodes[i].n), Getline(nodes[i].n));
236                    }
237		  }
238		  nodes[j].error = 1;
239		} else if (!SwigType_isconst(d1) && SwigType_isconst(d2)) {
240		  differ = 1;
241		  if (!nodes[j].error) {
242                    if (script_lang_wrapping) {
243		      Swig_warning(WARN_LANG_OVERLOAD_CONST, Getfile(nodes[j].n), Getline(nodes[j].n),
244				   "Overloaded %s(%s) const ignored. Non-const method at %s:%d used.\n",
245				   Getattr(nodes[j].n,"name"), ParmList_protostr(nodes[j].parms),
246				   Getfile(nodes[i].n), Getline(nodes[i].n));
247                    } else {
248                      if (!Getattr(nodes[j].n, "overload:ignore"))
249		        Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
250				     "Overloaded method %s(%s) const ignored. Method %s(%s) at %s:%d used.\n",
251				     Getattr(nodes[j].n,"name"), ParmList_protostr(nodes[j].parms),
252			             Getattr(nodes[i].n,"name"), ParmList_protostr(nodes[i].parms),
253				     Getfile(nodes[i].n), Getline(nodes[i].n));
254                    }
255                  }
256		  nodes[j].error = 1;
257		}
258	      }
259	      Delete(dq1);
260	      Delete(dq2);
261	    }
262	  }
263	  if (!differ) {
264	    if (!nodes[j].error) {
265              if (script_lang_wrapping) {
266	        Swig_warning(WARN_LANG_OVERLOAD_SHADOW, Getfile(nodes[j].n), Getline(nodes[j].n),
267			     "Overloaded %s(%s)%s is shadowed by %s(%s)%s at %s:%d.\n",
268			     Getattr(nodes[j].n,"name"), ParmList_protostr(nodes[j].parms),
269			     SwigType_isconst(Getattr(nodes[j].n,"decl")) ? " const" : "", 
270			     Getattr(nodes[i].n,"name"), ParmList_protostr(nodes[i].parms),
271			     SwigType_isconst(Getattr(nodes[i].n,"decl")) ? " const" : "", 
272			     Getfile(nodes[i].n),Getline(nodes[i].n));
273              } else {
274                if (!Getattr(nodes[j].n, "overload:ignore"))
275	          Swig_warning(WARN_LANG_OVERLOAD_IGNORED, Getfile(nodes[j].n), Getline(nodes[j].n),
276			       "Overloaded method %s(%s)%s ignored. Method %s(%s)%s at %s:%d used.\n",
277			       Getattr(nodes[j].n,"name"), ParmList_protostr(nodes[j].parms),
278			       SwigType_isconst(Getattr(nodes[j].n,"decl")) ? " const" : "", 
279                               Getattr(nodes[i].n,"name"), ParmList_protostr(nodes[i].parms),
280			       SwigType_isconst(Getattr(nodes[i].n,"decl")) ? " const" : "", 
281			       Getfile(nodes[i].n),Getline(nodes[i].n));
282              }
283	      nodes[j].error = 1;
284	    }
285	  }
286	}
287      }
288    }
289  }
290  List *result = NewList();
291  {
292    int i;
293    for (i = 0; i < nnodes; i++) {
294      if (nodes[i].error)
295        Setattr(nodes[i].n, "overload:ignore", "1");
296      Append(result,nodes[i].n);
297      //      Printf(stdout,"[ %d ] %s\n", i, ParmList_protostr(nodes[i].parms));
298      //      Swig_print_node(nodes[i].n);
299    }
300  }
301  return result;
302}
303
304// /* -----------------------------------------------------------------------------
305//  * print_typecheck()
306//  * ----------------------------------------------------------------------------- */
307
308static bool
309print_typecheck(String *f, int j, Parm *pj) {
310  char tmp[256];
311  sprintf(tmp,Char(argv_template_string),j);
312  String *tm = Getattr(pj,"tmap:typecheck");
313  if (tm) {
314    Replaceid(tm,Getattr(pj,"lname"),"_v");
315    String *conv = Getattr(pj,"implicitconv");
316    if (conv) {
317      Replaceall(tm,"$implicitconv", conv);
318    } else {
319      Replaceall(tm,"$implicitconv", "0");
320    }
321    Replaceall(tm,"$input", tmp);
322    Printv(f,tm,"\n",NIL);
323    return true;
324  }
325  else
326    return false;
327}
328
329/* -----------------------------------------------------------------------------
330 * ReplaceFormat()
331 * ----------------------------------------------------------------------------- */
332
333static String *
334ReplaceFormat (const String_or_char *fmt, int j) {
335  String *lfmt = NewString (fmt);
336  char buf[50];
337  sprintf (buf, "%d", j);
338  Replaceall (lfmt, "$numargs", buf);
339  int i;
340  String *commaargs = NewString ("");
341  for (i=0; i < j; i++) {
342    Printv (commaargs, ", ", NIL);
343    Printf (commaargs, Char(argv_template_string), i);
344  }
345  Replaceall (lfmt, "$commaargs", commaargs);
346  return lfmt;
347}
348
349/* -----------------------------------------------------------------------------
350 * Swig_overload_dispatch()
351 *
352 * Generate a dispatch function.  argc is assumed to hold the argument count.
353 * argv is the argument vector.
354 *
355 * Note that for C++ class member functions, Swig_overload_dispatch() assumes
356 * that argc includes the "self" argument and that the first element of argv[]
357 * is the "self" argument. So for a member function:
358 *
359 *     Foo::bar(int x, int y, int z);
360 *
361 * the argc should be 4 (not 3!) and the first element of argv[] would be
362 * the appropriate scripting language reference to "self". For regular
363 * functions (and static class functions) the argc and argv only include
364 * the regular function arguments.
365 * ----------------------------------------------------------------------------- */
366
367/*
368  Cast dispatch mechanism.
369*/
370String *
371Swig_overload_dispatch_cast(Node *n, const String_or_char *fmt, int *maxargs) {
372  int i,j;
373  
374  *maxargs = 1;
375
376  String *f = NewString("");
377  String *sw = NewString("");
378  Printf(f,"{\n");
379  Printf(f,"unsigned long _index = 0;\n");
380  Printf(f,"SWIG_TypeRank _rank = 0; \n");
381
382  /* Get a list of methods ranked by precedence values and argument count */
383  List *dispatch = Swig_overload_rank(n, true);
384  int   nfunc = Len(dispatch);
385
386  /* Loop over the functions */
387
388  bool emitcheck=1;
389  for (i = 0; i < nfunc; i++) {
390    int fn = 0;
391    Node *ni = Getitem(dispatch,i);
392    Parm *pi = Getattr(ni,"wrap:parms");
393    int num_required = emit_num_required(pi);
394    int num_arguments = emit_num_arguments(pi);
395    if (num_arguments > *maxargs) *maxargs = num_arguments;
396    int varargs = emit_isvarargs(pi);    
397    
398    if (!varargs) {
399      if (num_required == num_arguments) {
400	Printf(f,"if (%s == %d) {\n", argc_template_string, num_required);
401      } else {
402	Printf(f,"if ((%s >= %d) && (%s <= %d)) {\n", 
403	       argc_template_string, num_required, 
404	       argc_template_string, num_arguments);
405      }
406    } else {
407      Printf(f,"if (%s >= %d) {\n", argc_template_string, num_required);
408    }
409    Printf(f,"SWIG_TypeRank _ranki = 0;\n");
410    Printf(f,"SWIG_TypeRank _rankm = 0;\n");
411    if (num_arguments) Printf(f,"SWIG_TypeRank _pi = 1;\n");
412
413    /* create a list with the wrappers that collide with the
414       current one based on argument number */
415    List *coll=NewList();
416    for (int k=i+1; k<nfunc; k++) {
417      Node *nk = Getitem(dispatch,k);
418      Parm *pk = Getattr(nk,"wrap:parms");
419      int nrk = emit_num_required(pk);
420      int nak = emit_num_arguments(pk);
421      if ((nrk>=num_required && nrk<=num_arguments) ||
422	  (nak>=num_required && nak<=num_arguments) ||
423	  (nrk<=num_required && nak>=num_arguments))
424	Append(coll, nk);
425    }
426
427    // printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll));
428
429    int num_braces = 0;
430    bool test=(num_arguments > 0);
431    if (test) {
432      int need_v = 1;
433      j = 0;
434      Parm *pj = pi;
435      while (pj) {
436	if (checkAttribute(pj,"tmap:in:numinputs","0")) {
437	  pj = Getattr(pj,"tmap:in:next");
438	  continue;
439	}
440
441	String *tm = Getattr(pj,"tmap:typecheck");
442	if (tm) {
443	  /* normalise for comparison later */ 
444	  Replaceid(tm,Getattr(pj,"lname"),"_v");
445
446	  /* if all the wrappers have the same type check on this
447	     argument we can optimize it out */
448	  for (int k=0; k<Len(coll) && !emitcheck; k++) {
449	    Node *nk = Getitem(coll, k);
450	    Parm *pk = Getattr(nk,"wrap:parms");
451	    int nak=emit_num_arguments(pk);
452	    if (nak<=j)  continue;
453	    int l=0;
454	    Parm *pl=pk;
455	    /* finds arg j on the collider wrapper */
456	    while(pl && l<=j) {
457	      if (checkAttribute(pl,"tmap:in:numinputs","0")) {
458		pl = Getattr(pl,"tmap:in:next");
459		continue;
460	      }
461	      if (l==j) {
462		/* we are at arg j, so we compare the tmaps now */
463		String *tml = Getattr(pl, "tmap:typecheck");
464		/* normalise it before comparing */
465		if (tml) Replaceid(tml,Getattr(pl,"lname"),"_v");
466		if (!tml || Cmp(tm, tml)) emitcheck=1;
467		//printf("tmap: %s[%d] (%d) => %s\n\n",
468		//       Char(Getattr(nk, "sym:name")),
469		//       l, emitcheck, tml?Char(tml):0);
470	      }
471	      Parm *pl1 = Getattr(pl,"tmap:in:next");
472	      if (pl1) pl = pl1;
473	      else pl = nextSibling(pl);
474	      l++;
475	    }
476	  }
477
478	  if (emitcheck) {
479	    if (need_v) {
480	      Printf(f,"int _v = 0;\n");
481	      need_v = 0;
482	    }
483	    if (j >= num_required) {
484	      Printf(f, "if (%s > %d) {\n", argc_template_string, j);
485	      num_braces++;
486	    }
487	    String *tmp=NewStringf(argv_template_string, j);
488
489	    String *conv = Getattr(pj,"implicitconv");
490	    if (conv) {
491	      Replaceall(tm,"$implicitconv", conv);
492	    } else {
493	      Replaceall(tm,"$implicitconv", "0");
494	    }
495	    Replaceall(tm,"$input", tmp);
496	    Printv(f,"{\n",tm,"}\n",NIL);
497	    fn = i + 1;
498	    Printf(f, "if (!_v) goto check_%d;\n", fn);
499	    Printf(f, "_ranki += _v*_pi;\n", fn);
500	    Printf(f, "_rankm += _pi;\n", fn);
501	    Printf(f, "_pi *= SWIG_MAXCASTRANK;\n", fn);
502	  }
503	}
504	if (!Getattr(pj,"tmap:in:SWIGTYPE") && Getattr(pj,"tmap:typecheck:SWIGTYPE")) {
505	  /* we emit  a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */
506	  Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
507		       "Overloaded %s(%s) with no explicit typecheck typemap for arg %d of type '%s'\n", 
508		       Getattr(n,"name"),ParmList_str_defaultargs(pi),
509		       j+1, SwigType_str(Getattr(pj,"type"),0));
510	}
511	Parm *pj1 = Getattr(pj,"tmap:in:next");
512	if (pj1) pj = pj1;
513	else pj = nextSibling(pj);
514	j++;
515      }
516    }
517
518    /* close braces */
519    for (/* empty */; num_braces > 0; num_braces--) Printf(f, "}\n");
520
521    Printf(f,"if (!_index || (_ranki < _rank)) {\n",i+1);
522    Printf(f," _rank = _ranki; _index = %d;\n",i+1);
523    Printf(f," if (_rank == _rankm) goto dispatch;\n",i+1);
524    Printf(f,"}\n",i+1);
525    String *lfmt = ReplaceFormat (fmt, num_arguments);
526    Printf(sw, "case %d:\n", i+1);
527    Printf(sw, Char(lfmt),Getattr(ni,"wrap:name"));
528    Printf(sw, "\n");
529
530    Printf(f,"}\n"); /* braces closes "if" for this method */
531    if (fn) Printf(f, "check_%d:\n\n", fn);
532
533    Delete (lfmt);
534    Delete(coll);
535  }
536  Delete(dispatch);
537  Printf(f,"dispatch:\n");
538  Printf(f,"switch(_index) {\n");
539  Printf(f,"%s",sw);
540  Printf(f,"}\n");
541
542  Printf(f,"}\n");
543  return f;
544}
545
546/*
547  Fast dispatch mechanism, provided by  Salvador Fandi~no Garc'ia (#930586).
548*/
549String *
550Swig_overload_dispatch_fast(Node *n, const String_or_char *fmt, int *maxargs) {
551  int i,j;
552  
553  *maxargs = 1;
554
555  String *f = NewString("");
556
557  /* Get a list of methods ranked by precedence values and argument count */
558  List *dispatch = Swig_overload_rank(n, true);
559  int   nfunc = Len(dispatch);
560
561  /* Loop over the functions */
562
563  for (i = 0; i < nfunc; i++) {
564    int fn = 0;
565    Node *ni = Getitem(dispatch,i);
566    Parm *pi = Getattr(ni,"wrap:parms");
567    int num_required = emit_num_required(pi);
568    int num_arguments = emit_num_arguments(pi);
569    if (num_arguments > *maxargs) *maxargs = num_arguments;
570    int varargs = emit_isvarargs(pi);    
571    
572    if (!varargs) {
573      if (num_required == num_arguments) {
574	Printf(f,"if (%s == %d) {\n", argc_template_string, num_required);
575      } else {
576	Printf(f,"if ((%s >= %d) && (%s <= %d)) {\n", 
577	       argc_template_string, num_required, 
578	       argc_template_string, num_arguments);
579      }
580    } else {
581      Printf(f,"if (%s >= %d) {\n", argc_template_string, num_required);
582    }
583
584    /* create a list with the wrappers that collide with the
585       current one based on argument number */
586    List *coll=NewList();
587    for (int k=i+1; k<nfunc; k++) {
588      Node *nk = Getitem(dispatch,k);
589      Parm *pk = Getattr(nk,"wrap:parms");
590      int nrk = emit_num_required(pk);
591      int nak = emit_num_arguments(pk);
592      if ((nrk>=num_required && nrk<=num_arguments) ||
593	  (nak>=num_required && nak<=num_arguments) ||
594	  (nrk<=num_required && nak>=num_arguments))
595	Append(coll, nk);
596    }
597
598    // printf("overload: %s coll=%d\n", Char(Getattr(n, "sym:name")), Len(coll));
599
600    int num_braces = 0;
601    bool test=(Len(coll)>0 && num_arguments);
602    if (test) {
603      int need_v = 1;
604      j = 0;
605      Parm *pj = pi;
606      while (pj) {
607	if (checkAttribute(pj,"tmap:in:numinputs","0")) {
608	  pj = Getattr(pj,"tmap:in:next");
609	  continue;
610	}
611
612	String *tm = Getattr(pj,"tmap:typecheck");
613	if (tm) {
614	  /* normalise for comparison later */ 
615	  Replaceid(tm,Getattr(pj,"lname"),"_v");
616
617	  /* if all the wrappers have the same type check on this
618	     argument we can optimize it out */
619	  bool emitcheck=0;
620	  for (int k=0; k<Len(coll) && !emitcheck; k++) {
621	    Node *nk = Getitem(coll, k);
622	    Parm *pk = Getattr(nk,"wrap:parms");
623	    int nak=emit_num_arguments(pk);
624	    if (nak<=j)  continue;
625	    int l=0;
626	    Parm *pl=pk;
627	    /* finds arg j on the collider wrapper */
628	    while(pl && l<=j) {
629	      if (checkAttribute(pl,"tmap:in:numinputs","0")) {
630		pl = Getattr(pl,"tmap:in:next");
631		continue;
632	      }
633	      if (l==j) {
634		/* we are at arg j, so we compare the tmaps now */
635		String *tml = Getattr(pl, "tmap:typecheck");
636		/* normalise it before comparing */
637		if (tml) Replaceid(tml,Getattr(pl,"lname"),"_v");
638		if (!tml || Cmp(tm, tml)) emitcheck=1;
639		//printf("tmap: %s[%d] (%d) => %s\n\n",
640		//       Char(Getattr(nk, "sym:name")),
641		//       l, emitcheck, tml?Char(tml):0);
642	      }
643	      Parm *pl1 = Getattr(pl,"tmap:in:next");
644	      if (pl1) pl = pl1;
645	      else pl = nextSibling(pl);
646	      l++;
647	    }
648	  }
649
650	  if (emitcheck) {
651	    if (need_v) {
652	      Printf(f,"int _v = 0;\n");
653	      need_v = 0;
654	    }
655	    if (j >= num_required) {
656	      Printf(f, "if (%s > %d) {\n", argc_template_string, j);
657	      num_braces++;
658	    }
659	    String *tmp=NewStringf(argv_template_string, j);
660
661	    String *conv = Getattr(pj,"implicitconv");
662	    if (conv) {
663	      Replaceall(tm,"$implicitconv", conv);
664	    } else {
665	      Replaceall(tm,"$implicitconv", "0");
666	    }
667	    Replaceall(tm,"$input", tmp);
668	    Printv(f,"{\n",tm,"}\n",NIL);
669	    fn = i + 1;
670	    Printf(f, "if (!_v) goto check_%d;\n", fn);
671	  }
672	}
673	if (!Getattr(pj,"tmap:in:SWIGTYPE") && Getattr(pj,"tmap:typecheck:SWIGTYPE")) {
674	  /* we emit  a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */
675	  Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
676		       "Overloaded %s(%s) with no explicit typecheck typemap for arg %d of type '%s'\n", 
677		       Getattr(n,"name"),ParmList_str_defaultargs(pi),
678		       j+1, SwigType_str(Getattr(pj,"type"),0));
679	}
680	Parm *pj1 = Getattr(pj,"tmap:in:next");
681	if (pj1) pj = pj1;
682	else pj = nextSibling(pj);
683	j++;
684      }
685    }
686
687    /* close braces */
688    for (/* empty */; num_braces > 0; num_braces--) Printf(f, "}\n");
689
690
691    String *lfmt = ReplaceFormat (fmt, num_arguments);
692    Printf(f, Char(lfmt),Getattr(ni,"wrap:name"));
693
694    Printf(f,"}\n"); /* braces closes "if" for this method */
695    if (fn) Printf(f, "check_%d:\n\n", fn);
696
697    Delete (lfmt);
698    Delete(coll);
699  }
700  Delete(dispatch);
701  return f;
702}
703
704String *
705Swig_overload_dispatch(Node *n, const String_or_char *fmt, int *maxargs) {
706
707  if (fast_dispatch_mode  || GetFlag(n,"feature:fastdispatch")) {
708    return Swig_overload_dispatch_fast(n, fmt, maxargs);
709  }
710  
711  int i,j;
712  
713  *maxargs = 1;
714
715  String *f = NewString("");
716
717  /* Get a list of methods ranked by precedence values and argument count */
718  List *dispatch = Swig_overload_rank(n, true);
719  int   nfunc = Len(dispatch);
720
721  /* Loop over the functions */
722
723  for (i = 0; i < nfunc; i++) {
724    Node *ni = Getitem(dispatch,i);
725    Parm *pi = Getattr(ni,"wrap:parms");
726    int num_required = emit_num_required(pi);
727    int num_arguments = emit_num_arguments(pi);
728    if (num_arguments > *maxargs) *maxargs = num_arguments;
729    int varargs = emit_isvarargs(pi);    
730    
731    if (!varargs) {
732      if (num_required == num_arguments) {
733	Printf(f,"if (%s == %d) {\n", argc_template_string, num_required);
734      } else {
735	Printf(f,"if ((%s >= %d) && (%s <= %d)) {\n", 
736	       argc_template_string, num_required, 
737	       argc_template_string, num_arguments);
738      }
739    } else {
740      Printf(f,"if (%s >= %d) {\n", argc_template_string, num_required);
741    }
742
743    if (num_arguments) {
744      Printf(f,"int _v;\n");
745    }
746    
747    int num_braces = 0;
748    j = 0;
749    Parm *pj = pi;
750    while (pj) {
751      if (checkAttribute(pj,"tmap:in:numinputs","0")) {
752	pj = Getattr(pj,"tmap:in:next");
753	continue;
754      }
755      if (j >= num_required) {
756	String *lfmt = ReplaceFormat (fmt, num_arguments);
757	Printf(f, "if (%s <= %d) {\n", argc_template_string, j);
758	Printf(f, Char(lfmt),Getattr(ni,"wrap:name"));
759	Printf(f, "}\n");
760	Delete (lfmt);
761      }
762      if (print_typecheck(f, j, pj)) {
763	Printf(f, "if (_v) {\n");
764	num_braces++;
765      } 
766      if (!Getattr(pj,"tmap:in:SWIGTYPE") && Getattr(pj,"tmap:typecheck:SWIGTYPE")) {
767	/* we emit  a warning if the argument defines the 'in' typemap, but not the 'typecheck' one */
768	Swig_warning(WARN_TYPEMAP_TYPECHECK_UNDEF, Getfile(ni), Getline(ni),
769		     "Overloaded %s(%s) with no explicit typecheck typemap for arg %d of type '%s'\n", 
770		     Getattr(n,"name"),ParmList_str_defaultargs(pi),
771		     j+1, SwigType_str(Getattr(pj,"type"),0));
772      }
773      Parm *pk = Getattr(pj,"tmap:in:next");
774      if (pk) pj = pk;
775      else pj = nextSibling(pj);
776      j++;
777    }
778    String *lfmt = ReplaceFormat (fmt, num_arguments);
779    Printf(f, Char(lfmt),Getattr(ni,"wrap:name"));
780    Delete (lfmt);
781    /* close braces */
782    for (/* empty */; num_braces > 0; num_braces--)
783      Printf(f, "}\n");
784    Printf(f,"}\n"); /* braces closes "if" for this method */
785  }
786  Delete(dispatch);
787  return f;
788}
789
790/* -----------------------------------------------------------------------------
791 * Swig_overload_check()
792 * ----------------------------------------------------------------------------- */
793void Swig_overload_check(Node *n) {
794    Swig_overload_rank(n, false);
795}
796