/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