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