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