PageRenderTime 65ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 1ms

/Source/Swig/typemap.c

https://github.com/sunaku/swig-ruby-ffi
C | 1936 lines | 1396 code | 198 blank | 342 comment | 361 complexity | 7fabb35cd4d611b0d420b650544cf23f MD5 | raw file
Possible License(s): 0BSD, GPL-2.0, LGPL-2.1

Large files files are truncated, but you can click here to view the full file

  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. * typemap.c
  6. *
  7. * A somewhat generalized implementation of SWIG1.1 typemaps.
  8. * ----------------------------------------------------------------------------- */
  9. char cvsroot_typemap_c[] = "$Id$";
  10. #include "swig.h"
  11. #include "cparse.h"
  12. #include <ctype.h>
  13. #if 0
  14. #define SWIG_DEBUG
  15. #endif
  16. static void replace_embedded_typemap(String *s, ParmList *parm_sublist, Wrapper *f);
  17. /* -----------------------------------------------------------------------------
  18. * Typemaps are stored in a collection of nested hash tables. Something like
  19. * this:
  20. *
  21. * [ type ]
  22. * +-------- [ name ]
  23. * +-------- [ name ]
  24. *
  25. * Each hash table [ type ] or [ name ] then contains references to the
  26. * different typemap methods. These are referenced by names such as
  27. * "tmap:in", "tmap:out", "tmap:argout", and so forth.
  28. *
  29. * The object corresponding to a specific typemap method has the following attributes:
  30. *
  31. * "type" - Typemap type
  32. * "pname" - Parameter name
  33. * "code" - Typemap code
  34. * "typemap" - Descriptive text describing the actual map
  35. * "locals" - Local variables (if any)
  36. * "kwargs" - Typemap attributes
  37. *
  38. * Example for a typemap method named "in":
  39. * %typemap(in, warning="987:my warning", noblock=1) int &my_int (int tmp) "$1 = $input;"
  40. *
  41. * "type" - r.int
  42. * "pname" - my_int
  43. * "code" - $1 = $input;
  44. * "typemap" - typemap(in) int &my_int
  45. * "locals" - int tmp
  46. * "kwargs" - warning="987:my typemap warning", foo=123
  47. *
  48. * ----------------------------------------------------------------------------- */
  49. #define MAX_SCOPE 32
  50. static Hash *typemaps[MAX_SCOPE];
  51. static int tm_scope = 0;
  52. static Hash *get_typemap(int tm_scope, SwigType *type) {
  53. Hash *tm = 0;
  54. SwigType *dtype = 0;
  55. if (SwigType_istemplate(type)) {
  56. String *ty = Swig_symbol_template_deftype(type, 0);
  57. dtype = Swig_symbol_type_qualify(ty, 0);
  58. /* Printf(stderr,"gettm %s %s\n", type, dtype); */
  59. type = dtype;
  60. Delete(ty);
  61. }
  62. tm = Getattr(typemaps[tm_scope], type);
  63. if (dtype) {
  64. if (!tm) {
  65. String *t_name = SwigType_templateprefix(type);
  66. if (!Equal(t_name, type)) {
  67. tm = Getattr(typemaps[tm_scope], t_name);
  68. }
  69. Delete(t_name);
  70. }
  71. Delete(dtype);
  72. }
  73. return tm;
  74. }
  75. static void set_typemap(int tm_scope, SwigType *type, Hash *tm) {
  76. SwigType *dtype = 0;
  77. if (SwigType_istemplate(type)) {
  78. String *ty = Swig_symbol_template_deftype(type, 0);
  79. dtype = Swig_symbol_type_qualify(ty, 0);
  80. /* Printf(stderr,"settm %s %s\n", type, dtype); */
  81. type = dtype;
  82. Delete(ty);
  83. } else {
  84. dtype = Copy(type);
  85. type = dtype;
  86. }
  87. Setattr(typemaps[tm_scope], type, tm);
  88. Delete(dtype);
  89. }
  90. /* -----------------------------------------------------------------------------
  91. * Swig_typemap_init()
  92. *
  93. * Initialize the typemap system
  94. * ----------------------------------------------------------------------------- */
  95. void Swig_typemap_init() {
  96. int i;
  97. for (i = 0; i < MAX_SCOPE; i++) {
  98. typemaps[i] = 0;
  99. }
  100. typemaps[0] = NewHash();
  101. tm_scope = 0;
  102. }
  103. static String *typemap_method_name(const_String_or_char_ptr tmap_method) {
  104. static Hash *names = 0;
  105. String *s;
  106. /* Due to "interesting" object-identity semantics of DOH,
  107. we have to make sure that we only intern strings without object
  108. identity into the hash table.
  109. (typemap_attach_kwargs calls typemap_method_name several times with
  110. the "same" String *tmap_method (i.e., same object identity) but differing
  111. string values.)
  112. Most other callers work around this by using char* rather than
  113. String *.
  114. -- mkoeppe, Jun 17, 2003
  115. */
  116. const char *method_without_object_identity = Char(tmap_method);
  117. if (!names)
  118. names = NewHash();
  119. s = Getattr(names, method_without_object_identity);
  120. if (s)
  121. return s;
  122. s = NewStringf("tmap:%s", tmap_method);
  123. Setattr(names, method_without_object_identity, s);
  124. Delete(s);
  125. return s;
  126. }
  127. #if 0
  128. /* -----------------------------------------------------------------------------
  129. * Swig_typemap_new_scope()
  130. *
  131. * Create a new typemap scope
  132. * ----------------------------------------------------------------------------- */
  133. void Swig_typemap_new_scope() {
  134. tm_scope++;
  135. typemaps[tm_scope] = NewHash();
  136. }
  137. /* -----------------------------------------------------------------------------
  138. * Swig_typemap_pop_scope()
  139. *
  140. * Pop the last typemap scope off
  141. * ----------------------------------------------------------------------------- */
  142. Hash *Swig_typemap_pop_scope() {
  143. if (tm_scope > 0) {
  144. return typemaps[tm_scope--];
  145. }
  146. return 0;
  147. }
  148. #endif
  149. /* -----------------------------------------------------------------------------
  150. * Swig_typemap_register()
  151. *
  152. * Add a new multi-argument typemap
  153. * ----------------------------------------------------------------------------- */
  154. void Swig_typemap_register(const_String_or_char_ptr tmap_method, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs) {
  155. Hash *tm;
  156. Hash *tm1;
  157. Hash *tm2;
  158. Parm *np;
  159. String *tm_method;
  160. SwigType *type;
  161. String *pname;
  162. if (!parms)
  163. return;
  164. tm_method = typemap_method_name(tmap_method);
  165. /* Register the first type in the parameter list */
  166. type = Getattr(parms, "type");
  167. pname = Getattr(parms, "name");
  168. /* See if this type has been seen before */
  169. tm = get_typemap(tm_scope, type);
  170. if (!tm) {
  171. tm = NewHash();
  172. set_typemap(tm_scope, type, tm);
  173. Delete(tm);
  174. }
  175. if (pname) {
  176. /* See if parameter has been seen before */
  177. tm1 = Getattr(tm, pname);
  178. if (!tm1) {
  179. tm1 = NewHash();
  180. Setattr(tm, pname, tm1);
  181. Delete(tm1);
  182. }
  183. tm = tm1;
  184. }
  185. /* Now see if this typemap method has been seen before */
  186. tm2 = Getattr(tm, tm_method);
  187. if (!tm2) {
  188. tm2 = NewHash();
  189. Setattr(tm, tm_method, tm2);
  190. Delete(tm2);
  191. }
  192. /* For a multi-argument typemap, the typemap code and information
  193. is really only stored in the last argument. However, to
  194. make this work, we perform a really neat trick using
  195. the typemap operator name.
  196. For example, consider this typemap
  197. %typemap(in) (int foo, int *bar, char *blah[]) {
  198. ...
  199. }
  200. To store it, we look at typemaps for the following:
  201. operator type-name
  202. ----------------------------------------------
  203. "in" int foo
  204. "in-int+foo:" int *bar
  205. "in-int+foo:-p.int+bar: char *blah[]
  206. Notice how the operator expands to encode information about
  207. previous arguments.
  208. */
  209. np = nextSibling(parms);
  210. if (np) {
  211. /* Make an entirely new operator key */
  212. String *newop = NewStringf("%s-%s+%s:", tmap_method, type, pname);
  213. /* Now reregister on the remaining arguments */
  214. Swig_typemap_register(newop, np, code, locals, kwargs);
  215. /* Setattr(tm2,newop,newop); */
  216. Delete(newop);
  217. } else {
  218. String *str = SwigType_str(type, pname);
  219. String *typemap = NewStringf("typemap(%s) %s", tmap_method, str);
  220. ParmList *clocals = CopyParmList(locals);
  221. ParmList *ckwargs = CopyParmList(kwargs);
  222. Setattr(tm2, "code", code);
  223. Setattr(tm2, "type", type);
  224. Setattr(tm2, "typemap", typemap);
  225. if (pname) {
  226. Setattr(tm2, "pname", pname);
  227. }
  228. Setattr(tm2, "locals", clocals);
  229. Setattr(tm2, "kwargs", ckwargs);
  230. Delete(clocals);
  231. Delete(ckwargs);
  232. Delete(str);
  233. Delete(typemap);
  234. }
  235. }
  236. /* -----------------------------------------------------------------------------
  237. * typemap_get()
  238. *
  239. * Retrieve typemap information from current scope.
  240. * ----------------------------------------------------------------------------- */
  241. static Hash *typemap_get(SwigType *type, const_String_or_char_ptr name, int scope) {
  242. Hash *tm, *tm1;
  243. /* See if this type has been seen before */
  244. if ((scope < 0) || (scope > tm_scope))
  245. return 0;
  246. tm = get_typemap(scope, type);
  247. if (!tm) {
  248. return 0;
  249. }
  250. if ((name) && Len(name)) {
  251. tm1 = Getattr(tm, name);
  252. return tm1;
  253. }
  254. return tm;
  255. }
  256. /* -----------------------------------------------------------------------------
  257. * Swig_typemap_copy()
  258. *
  259. * Copy a typemap
  260. * ----------------------------------------------------------------------------- */
  261. int Swig_typemap_copy(const_String_or_char_ptr tmap_method, ParmList *srcparms, ParmList *parms) {
  262. Hash *tm = 0;
  263. String *tm_method;
  264. Parm *p;
  265. String *pname;
  266. SwigType *ptype;
  267. int ts = tm_scope;
  268. String *tm_methods, *newop;
  269. if (ParmList_len(parms) != ParmList_len(srcparms))
  270. return -1;
  271. tm_method = typemap_method_name(tmap_method);
  272. while (ts >= 0) {
  273. p = srcparms;
  274. tm_methods = NewString(tm_method);
  275. while (p) {
  276. ptype = Getattr(p, "type");
  277. pname = Getattr(p, "name");
  278. /* Lookup the type */
  279. tm = typemap_get(ptype, pname, ts);
  280. if (!tm)
  281. break;
  282. tm = Getattr(tm, tm_methods);
  283. if (!tm)
  284. break;
  285. /* Got a match. Look for next typemap */
  286. newop = NewStringf("%s-%s+%s:", tm_methods, ptype, pname);
  287. Delete(tm_methods);
  288. tm_methods = newop;
  289. p = nextSibling(p);
  290. }
  291. Delete(tm_methods);
  292. if (!p && tm) {
  293. /* Got some kind of match */
  294. Swig_typemap_register(tmap_method, parms, Getattr(tm, "code"), Getattr(tm, "locals"), Getattr(tm, "kwargs"));
  295. return 0;
  296. }
  297. ts--;
  298. }
  299. /* Not found */
  300. return -1;
  301. }
  302. /* -----------------------------------------------------------------------------
  303. * Swig_typemap_clear()
  304. *
  305. * Delete a multi-argument typemap
  306. * ----------------------------------------------------------------------------- */
  307. void Swig_typemap_clear(const_String_or_char_ptr tmap_method, ParmList *parms) {
  308. SwigType *type;
  309. String *name;
  310. Parm *p;
  311. String *newop;
  312. Hash *tm = 0;
  313. /* This might not work */
  314. newop = NewString(tmap_method);
  315. p = parms;
  316. while (p) {
  317. type = Getattr(p, "type");
  318. name = Getattr(p, "name");
  319. tm = typemap_get(type, name, tm_scope);
  320. if (!tm)
  321. return;
  322. p = nextSibling(p);
  323. if (p)
  324. Printf(newop, "-%s+%s:", type, name);
  325. }
  326. if (tm) {
  327. tm = Getattr(tm, typemap_method_name(newop));
  328. if (tm) {
  329. Delattr(tm, "code");
  330. Delattr(tm, "locals");
  331. Delattr(tm, "kwargs");
  332. }
  333. }
  334. Delete(newop);
  335. }
  336. /* -----------------------------------------------------------------------------
  337. * Swig_typemap_apply()
  338. *
  339. * Multi-argument %apply directive. This is pretty horrible so I sure hope
  340. * it works.
  341. * ----------------------------------------------------------------------------- */
  342. static int count_args(String *s) {
  343. /* Count up number of arguments */
  344. int na = 0;
  345. char *c = Char(s);
  346. while (*c) {
  347. if (*c == '+')
  348. na++;
  349. c++;
  350. }
  351. return na;
  352. }
  353. int Swig_typemap_apply(ParmList *src, ParmList *dest) {
  354. String *ssig, *dsig;
  355. Parm *p, *np, *lastp, *dp, *lastdp = 0;
  356. int narg = 0;
  357. int ts = tm_scope;
  358. SwigType *type = 0, *name;
  359. Hash *tm, *sm;
  360. int match = 0;
  361. /* Printf(stdout,"apply : %s --> %s\n", ParmList_str(src), ParmList_str(dest)); */
  362. /* Create type signature of source */
  363. ssig = NewStringEmpty();
  364. dsig = NewStringEmpty();
  365. p = src;
  366. dp = dest;
  367. lastp = 0;
  368. while (p) {
  369. lastp = p;
  370. lastdp = dp;
  371. np = nextSibling(p);
  372. if (np) {
  373. Printf(ssig, "-%s+%s:", Getattr(p, "type"), Getattr(p, "name"));
  374. Printf(dsig, "-%s+%s:", Getattr(dp, "type"), Getattr(dp, "name"));
  375. narg++;
  376. }
  377. p = np;
  378. dp = nextSibling(dp);
  379. }
  380. /* make sure a typemap node exists for the last destination node */
  381. type = Getattr(lastdp, "type");
  382. tm = get_typemap(tm_scope, type);
  383. if (!tm) {
  384. tm = NewHash();
  385. set_typemap(tm_scope, type, tm);
  386. Delete(tm);
  387. }
  388. name = Getattr(lastdp, "name");
  389. if (name) {
  390. Hash *tm1 = Getattr(tm, name);
  391. if (!tm1) {
  392. tm1 = NewHash();
  393. Setattr(tm, NewString(name), tm1);
  394. Delete(tm1);
  395. }
  396. tm = tm1;
  397. }
  398. /* This is a little nasty. We need to go searching for all possible typemaps in the
  399. source and apply them to the target */
  400. type = Getattr(lastp, "type");
  401. name = Getattr(lastp, "name");
  402. while (ts >= 0) {
  403. /* See if there is a matching typemap in this scope */
  404. sm = typemap_get(type, name, ts);
  405. /* if there is not matching, look for a typemap in the
  406. original typedef, if any, like in:
  407. typedef unsigned long size_t;
  408. ...
  409. %apply(size_t) {my_size}; ==> %apply(unsigned long) {my_size};
  410. */
  411. if (!sm) {
  412. SwigType *ntype = SwigType_typedef_resolve(type);
  413. if (ntype && (Cmp(ntype, type) != 0)) {
  414. sm = typemap_get(ntype, name, ts);
  415. }
  416. Delete(ntype);
  417. }
  418. if (sm) {
  419. /* Got a typemap. Need to only merge attributes for methods that match our signature */
  420. Iterator ki;
  421. match = 1;
  422. for (ki = First(sm); ki.key; ki = Next(ki)) {
  423. /* Check for a signature match with the source signature */
  424. if ((count_args(ki.key) == narg) && (Strstr(ki.key, ssig))) {
  425. String *oldm;
  426. /* A typemap we have to copy */
  427. String *nkey = Copy(ki.key);
  428. Replace(nkey, ssig, dsig, DOH_REPLACE_ANY);
  429. /* Make sure the typemap doesn't already exist in the target map */
  430. oldm = Getattr(tm, nkey);
  431. if (!oldm || (!Getattr(tm, "code"))) {
  432. String *code;
  433. ParmList *locals;
  434. ParmList *kwargs;
  435. Hash *sm1 = ki.item;
  436. code = Getattr(sm1, "code");
  437. locals = Getattr(sm1, "locals");
  438. kwargs = Getattr(sm1, "kwargs");
  439. if (code) {
  440. Replace(nkey, dsig, "", DOH_REPLACE_ANY);
  441. Replace(nkey, "tmap:", "", DOH_REPLACE_ANY);
  442. Swig_typemap_register(nkey, dest, code, locals, kwargs);
  443. }
  444. }
  445. Delete(nkey);
  446. }
  447. }
  448. }
  449. ts--;
  450. }
  451. Delete(ssig);
  452. Delete(dsig);
  453. return match;
  454. }
  455. /* -----------------------------------------------------------------------------
  456. * Swig_typemap_clear_apply()
  457. *
  458. * %clear directive. Clears all typemaps for a type (in the current scope only).
  459. * ----------------------------------------------------------------------------- */
  460. /* Multi-argument %clear directive */
  461. void Swig_typemap_clear_apply(Parm *parms) {
  462. String *tsig;
  463. Parm *p, *np, *lastp;
  464. int narg = 0;
  465. Hash *tm;
  466. String *name;
  467. /* Create a type signature of the parameters */
  468. tsig = NewStringEmpty();
  469. p = parms;
  470. lastp = 0;
  471. while (p) {
  472. lastp = p;
  473. np = nextSibling(p);
  474. if (np) {
  475. Printf(tsig, "-%s+%s:", Getattr(p, "type"), Getattr(p, "name"));
  476. narg++;
  477. }
  478. p = np;
  479. }
  480. tm = get_typemap(tm_scope, Getattr(lastp, "type"));
  481. if (!tm) {
  482. Delete(tsig);
  483. return;
  484. }
  485. name = Getattr(lastp, "name");
  486. if (name) {
  487. tm = Getattr(tm, name);
  488. }
  489. if (tm) {
  490. /* Clear typemaps that match our signature */
  491. Iterator ki, ki2;
  492. char *ctsig = Char(tsig);
  493. for (ki = First(tm); ki.key; ki = Next(ki)) {
  494. char *ckey = Char(ki.key);
  495. if (strncmp(ckey, "tmap:", 5) == 0) {
  496. int na = count_args(ki.key);
  497. if ((na == narg) && strstr(ckey, ctsig)) {
  498. Hash *h = ki.item;
  499. for (ki2 = First(h); ki2.key; ki2 = Next(ki2)) {
  500. Delattr(h, ki2.key);
  501. }
  502. }
  503. }
  504. }
  505. }
  506. Delete(tsig);
  507. }
  508. /* Internal function to strip array dimensions. */
  509. static SwigType *strip_arrays(SwigType *type) {
  510. SwigType *t;
  511. int ndim;
  512. int i;
  513. t = Copy(type);
  514. ndim = SwigType_array_ndim(t);
  515. for (i = 0; i < ndim; i++) {
  516. SwigType_array_setdim(t, i, "ANY");
  517. }
  518. return t;
  519. }
  520. /* -----------------------------------------------------------------------------
  521. * typemap_search()
  522. *
  523. * Search for a typemap match. Tries to find the most specific typemap
  524. * that includes a 'code' attribute.
  525. * ----------------------------------------------------------------------------- */
  526. static Hash *typemap_search(const_String_or_char_ptr tmap_method, SwigType *type, const_String_or_char_ptr name, SwigType **matchtype) {
  527. Hash *result = 0, *tm, *tm1, *tma;
  528. Hash *backup = 0;
  529. SwigType *noarrays = 0;
  530. SwigType *primitive = 0;
  531. SwigType *ctype = 0;
  532. int ts;
  533. int isarray;
  534. const String *cname = 0;
  535. SwigType *unstripped = 0;
  536. String *tm_method = typemap_method_name(tmap_method);
  537. if ((name) && Len(name))
  538. cname = name;
  539. ts = tm_scope;
  540. while (ts >= 0) {
  541. ctype = type;
  542. while (ctype) {
  543. /* Try to get an exact type-match */
  544. tm = get_typemap(ts, ctype);
  545. if (tm && cname) {
  546. tm1 = Getattr(tm, cname);
  547. if (tm1) {
  548. result = Getattr(tm1, tm_method); /* See if there is a type-name match */
  549. if (result && Getattr(result, "code"))
  550. goto ret_result;
  551. if (result)
  552. backup = result;
  553. }
  554. }
  555. if (tm) {
  556. result = Getattr(tm, tm_method); /* See if there is simply a type match */
  557. if (result && Getattr(result, "code"))
  558. goto ret_result;
  559. if (result)
  560. backup = result;
  561. }
  562. isarray = SwigType_isarray(ctype);
  563. if (isarray) {
  564. /* If working with arrays, strip away all of the dimensions and replace with "ANY".
  565. See if that generates a match */
  566. if (!noarrays) {
  567. noarrays = strip_arrays(ctype);
  568. }
  569. tma = get_typemap(ts, noarrays);
  570. if (tma && cname) {
  571. tm1 = Getattr(tma, cname);
  572. if (tm1) {
  573. result = Getattr(tm1, tm_method); /* type-name match */
  574. if (result && Getattr(result, "code"))
  575. goto ret_result;
  576. if (result)
  577. backup = result;
  578. }
  579. }
  580. if (tma) {
  581. result = Getattr(tma, tm_method); /* type match */
  582. if (result && Getattr(result, "code"))
  583. goto ret_result;
  584. if (result)
  585. backup = result;
  586. }
  587. Delete(noarrays);
  588. noarrays = 0;
  589. }
  590. /* No match so far. If the type is unstripped, we'll strip its
  591. qualifiers and check. Otherwise, we'll try to resolve a typedef */
  592. if (!unstripped) {
  593. unstripped = ctype;
  594. ctype = SwigType_strip_qualifiers(ctype);
  595. if (!Equal(ctype, unstripped))
  596. continue; /* Types are different */
  597. Delete(ctype);
  598. ctype = unstripped;
  599. unstripped = 0;
  600. }
  601. {
  602. String *octype;
  603. if (unstripped) {
  604. Delete(ctype);
  605. ctype = unstripped;
  606. unstripped = 0;
  607. }
  608. octype = ctype;
  609. ctype = SwigType_typedef_resolve(ctype);
  610. if (octype != type)
  611. Delete(octype);
  612. }
  613. }
  614. /* Hmmm. Well, no match seems to be found at all. See if there is some kind of default mapping */
  615. primitive = SwigType_default(type);
  616. while (primitive) {
  617. tm = get_typemap(ts, primitive);
  618. if (tm && cname) {
  619. tm1 = Getattr(tm, cname);
  620. if (tm1) {
  621. result = Getattr(tm1, tm_method); /* See if there is a type-name match */
  622. if (result)
  623. goto ret_result;
  624. }
  625. }
  626. if (tm) { /* See if there is simply a type match */
  627. result = Getattr(tm, tm_method);
  628. if (result)
  629. goto ret_result;
  630. }
  631. {
  632. SwigType *nprim = SwigType_default(primitive);
  633. Delete(primitive);
  634. primitive = nprim;
  635. }
  636. }
  637. if (ctype != type) {
  638. Delete(ctype);
  639. ctype = 0;
  640. }
  641. ts--; /* Hmmm. Nothing found in this scope. Guess we'll go try another scope */
  642. }
  643. result = backup;
  644. ret_result:
  645. if (noarrays)
  646. Delete(noarrays);
  647. if (primitive)
  648. Delete(primitive);
  649. if ((unstripped) && (unstripped != type))
  650. Delete(unstripped);
  651. if (matchtype) {
  652. *matchtype = Copy(ctype);
  653. }
  654. if (type != ctype)
  655. Delete(ctype);
  656. return result;
  657. }
  658. /* -----------------------------------------------------------------------------
  659. * typemap_search_multi()
  660. *
  661. * Search for a multi-argument typemap.
  662. * ----------------------------------------------------------------------------- */
  663. static Hash *typemap_search_multi(const_String_or_char_ptr tmap_method, ParmList *parms, int *nmatch) {
  664. SwigType *type;
  665. SwigType *mtype = 0;
  666. String *name;
  667. String *newop;
  668. Hash *tm, *tm1;
  669. if (!parms) {
  670. *nmatch = 0;
  671. return 0;
  672. }
  673. type = Getattr(parms, "type");
  674. name = Getattr(parms, "name");
  675. /* Try to find a match on the first type */
  676. tm = typemap_search(tmap_method, type, name, &mtype);
  677. if (tm) {
  678. if (mtype && SwigType_isarray(mtype)) {
  679. Setattr(parms, "tmap:match", mtype);
  680. }
  681. Delete(mtype);
  682. newop = NewStringf("%s-%s+%s:", tmap_method, type, name);
  683. tm1 = typemap_search_multi(newop, nextSibling(parms), nmatch);
  684. if (tm1)
  685. tm = tm1;
  686. if (Getattr(tm, "code")) {
  687. *(nmatch) = *nmatch + 1;
  688. } else {
  689. tm = 0;
  690. }
  691. Delete(newop);
  692. }
  693. return tm;
  694. }
  695. /* -----------------------------------------------------------------------------
  696. * typemap_replace_vars()
  697. *
  698. * Replaces typemap variables on a string. index is the $n variable.
  699. * type and pname are the type and parameter name.
  700. * ----------------------------------------------------------------------------- */
  701. static void replace_local_types(ParmList *p, const String *name, const String *rep) {
  702. SwigType *t;
  703. while (p) {
  704. t = Getattr(p, "type");
  705. Replace(t, name, rep, DOH_REPLACE_ANY);
  706. p = nextSibling(p);
  707. }
  708. }
  709. static int check_locals(ParmList *p, const char *s) {
  710. while (p) {
  711. char *c = GetChar(p, "type");
  712. if (strstr(c, s))
  713. return 1;
  714. p = nextSibling(p);
  715. }
  716. return 0;
  717. }
  718. static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, SwigType *rtype, String *pname, String *lname, int index) {
  719. char var[512];
  720. char *varname;
  721. SwigType *ftype;
  722. int bare_substitution_count = 0;
  723. Replaceall(s, "$typemap", "$TYPEMAP"); /* workaround for $type substitution below */
  724. ftype = SwigType_typedef_resolve_all(type);
  725. if (!pname)
  726. pname = lname;
  727. {
  728. Parm *p;
  729. int rep = 0;
  730. p = locals;
  731. while (p) {
  732. if (Strchr(Getattr(p, "type"), '$'))
  733. rep = 1;
  734. p = nextSibling(p);
  735. }
  736. if (!rep)
  737. locals = 0;
  738. }
  739. sprintf(var, "$%d_", index);
  740. varname = &var[strlen(var)];
  741. /* If the original datatype was an array. We're going to go through and substitute
  742. its array dimensions */
  743. if (SwigType_isarray(type) || SwigType_isarray(ftype)) {
  744. String *size;
  745. int ndim;
  746. int i;
  747. if (SwigType_array_ndim(type) != SwigType_array_ndim(ftype))
  748. type = ftype;
  749. ndim = SwigType_array_ndim(type);
  750. size = NewStringEmpty();
  751. for (i = 0; i < ndim; i++) {
  752. String *dim = SwigType_array_getdim(type, i);
  753. if (index == 1) {
  754. char t[32];
  755. sprintf(t, "$dim%d", i);
  756. Replace(s, t, dim, DOH_REPLACE_ANY);
  757. replace_local_types(locals, t, dim);
  758. }
  759. sprintf(varname, "dim%d", i);
  760. Replace(s, var, dim, DOH_REPLACE_ANY);
  761. replace_local_types(locals, var, dim);
  762. if (Len(size))
  763. Putc('*', size);
  764. Append(size, dim);
  765. Delete(dim);
  766. }
  767. sprintf(varname, "size");
  768. Replace(s, var, size, DOH_REPLACE_ANY);
  769. replace_local_types(locals, var, size);
  770. Delete(size);
  771. }
  772. /* Parameter name substitution */
  773. if (index == 1) {
  774. Replace(s, "$parmname", pname, DOH_REPLACE_ANY);
  775. }
  776. strcpy(varname, "name");
  777. Replace(s, var, pname, DOH_REPLACE_ANY);
  778. /* Type-related stuff */
  779. {
  780. SwigType *star_type, *amp_type, *base_type, *lex_type;
  781. SwigType *ltype, *star_ltype, *amp_ltype;
  782. String *mangle, *star_mangle, *amp_mangle, *base_mangle, *base_name;
  783. String *descriptor, *star_descriptor, *amp_descriptor;
  784. String *ts;
  785. char *sc;
  786. sc = Char(s);
  787. if (strstr(sc, "type") || check_locals(locals, "type")) {
  788. /* Given type : $type */
  789. ts = SwigType_str(type, 0);
  790. if (index == 1) {
  791. Replace(s, "$type", ts, DOH_REPLACE_ANY);
  792. replace_local_types(locals, "$type", type);
  793. }
  794. strcpy(varname, "type");
  795. Replace(s, var, ts, DOH_REPLACE_ANY);
  796. replace_local_types(locals, var, type);
  797. Delete(ts);
  798. sc = Char(s);
  799. }
  800. if (strstr(sc, "ltype") || check_locals(locals, "ltype")) {
  801. /* Local type: $ltype */
  802. ltype = SwigType_ltype(type);
  803. ts = SwigType_str(ltype, 0);
  804. if (index == 1) {
  805. Replace(s, "$ltype", ts, DOH_REPLACE_ANY);
  806. replace_local_types(locals, "$ltype", ltype);
  807. }
  808. strcpy(varname, "ltype");
  809. Replace(s, var, ts, DOH_REPLACE_ANY);
  810. replace_local_types(locals, var, ltype);
  811. Delete(ts);
  812. Delete(ltype);
  813. sc = Char(s);
  814. }
  815. if (strstr(sc, "mangle") || strstr(sc, "descriptor")) {
  816. /* Mangled type */
  817. mangle = SwigType_manglestr(type);
  818. if (index == 1)
  819. Replace(s, "$mangle", mangle, DOH_REPLACE_ANY);
  820. strcpy(varname, "mangle");
  821. Replace(s, var, mangle, DOH_REPLACE_ANY);
  822. descriptor = NewStringf("SWIGTYPE%s", mangle);
  823. if (index == 1)
  824. if (Replace(s, "$descriptor", descriptor, DOH_REPLACE_ANY))
  825. SwigType_remember(type);
  826. strcpy(varname, "descriptor");
  827. if (Replace(s, var, descriptor, DOH_REPLACE_ANY))
  828. SwigType_remember(type);
  829. Delete(descriptor);
  830. Delete(mangle);
  831. }
  832. /* One pointer level removed */
  833. /* This creates variables of the form
  834. $*n_type
  835. $*n_ltype
  836. */
  837. if (SwigType_ispointer(ftype) || (SwigType_isarray(ftype)) || (SwigType_isreference(ftype))) {
  838. if (!(SwigType_isarray(type) || SwigType_ispointer(type) || SwigType_isreference(type))) {
  839. star_type = Copy(ftype);
  840. } else {
  841. star_type = Copy(type);
  842. }
  843. if (!SwigType_isreference(star_type)) {
  844. if (SwigType_isarray(star_type)) {
  845. SwigType_del_element(star_type);
  846. } else {
  847. SwigType_del_pointer(star_type);
  848. }
  849. ts = SwigType_str(star_type, 0);
  850. if (index == 1) {
  851. Replace(s, "$*type", ts, DOH_REPLACE_ANY);
  852. replace_local_types(locals, "$*type", star_type);
  853. }
  854. sprintf(varname, "$*%d_type", index);
  855. Replace(s, varname, ts, DOH_REPLACE_ANY);
  856. replace_local_types(locals, varname, star_type);
  857. Delete(ts);
  858. } else {
  859. SwigType_del_element(star_type);
  860. }
  861. star_ltype = SwigType_ltype(star_type);
  862. ts = SwigType_str(star_ltype, 0);
  863. if (index == 1) {
  864. Replace(s, "$*ltype", ts, DOH_REPLACE_ANY);
  865. replace_local_types(locals, "$*ltype", star_ltype);
  866. }
  867. sprintf(varname, "$*%d_ltype", index);
  868. Replace(s, varname, ts, DOH_REPLACE_ANY);
  869. replace_local_types(locals, varname, star_ltype);
  870. Delete(ts);
  871. Delete(star_ltype);
  872. star_mangle = SwigType_manglestr(star_type);
  873. if (index == 1)
  874. Replace(s, "$*mangle", star_mangle, DOH_REPLACE_ANY);
  875. sprintf(varname, "$*%d_mangle", index);
  876. Replace(s, varname, star_mangle, DOH_REPLACE_ANY);
  877. star_descriptor = NewStringf("SWIGTYPE%s", star_mangle);
  878. if (index == 1)
  879. if (Replace(s, "$*descriptor", star_descriptor, DOH_REPLACE_ANY))
  880. SwigType_remember(star_type);
  881. sprintf(varname, "$*%d_descriptor", index);
  882. if (Replace(s, varname, star_descriptor, DOH_REPLACE_ANY))
  883. SwigType_remember(star_type);
  884. Delete(star_descriptor);
  885. Delete(star_mangle);
  886. Delete(star_type);
  887. } else {
  888. /* TODO: Signal error if one of the $* substitutions is
  889. requested */
  890. }
  891. /* One pointer level added */
  892. amp_type = Copy(type);
  893. SwigType_add_pointer(amp_type);
  894. ts = SwigType_str(amp_type, 0);
  895. if (index == 1) {
  896. Replace(s, "$&type", ts, DOH_REPLACE_ANY);
  897. replace_local_types(locals, "$&type", amp_type);
  898. }
  899. sprintf(varname, "$&%d_type", index);
  900. Replace(s, varname, ts, DOH_REPLACE_ANY);
  901. replace_local_types(locals, varname, amp_type);
  902. Delete(ts);
  903. amp_ltype = SwigType_ltype(type);
  904. SwigType_add_pointer(amp_ltype);
  905. ts = SwigType_str(amp_ltype, 0);
  906. if (index == 1) {
  907. Replace(s, "$&ltype", ts, DOH_REPLACE_ANY);
  908. replace_local_types(locals, "$&ltype", amp_ltype);
  909. }
  910. sprintf(varname, "$&%d_ltype", index);
  911. Replace(s, varname, ts, DOH_REPLACE_ANY);
  912. replace_local_types(locals, varname, amp_ltype);
  913. Delete(ts);
  914. Delete(amp_ltype);
  915. amp_mangle = SwigType_manglestr(amp_type);
  916. if (index == 1)
  917. Replace(s, "$&mangle", amp_mangle, DOH_REPLACE_ANY);
  918. sprintf(varname, "$&%d_mangle", index);
  919. Replace(s, varname, amp_mangle, DOH_REPLACE_ANY);
  920. amp_descriptor = NewStringf("SWIGTYPE%s", amp_mangle);
  921. if (index == 1)
  922. if (Replace(s, "$&descriptor", amp_descriptor, DOH_REPLACE_ANY))
  923. SwigType_remember(amp_type);
  924. sprintf(varname, "$&%d_descriptor", index);
  925. if (Replace(s, varname, amp_descriptor, DOH_REPLACE_ANY))
  926. SwigType_remember(amp_type);
  927. Delete(amp_descriptor);
  928. Delete(amp_mangle);
  929. Delete(amp_type);
  930. /* Base type */
  931. if (SwigType_isarray(type)) {
  932. SwigType *bt = Copy(type);
  933. Delete(SwigType_pop_arrays(bt));
  934. base_type = SwigType_str(bt, 0);
  935. Delete(bt);
  936. } else {
  937. base_type = SwigType_base(type);
  938. }
  939. base_name = SwigType_namestr(base_type);
  940. if (index == 1) {
  941. Replace(s, "$basetype", base_name, DOH_REPLACE_ANY);
  942. replace_local_types(locals, "$basetype", base_name);
  943. }
  944. strcpy(varname, "basetype");
  945. Replace(s, var, base_type, DOH_REPLACE_ANY);
  946. replace_local_types(locals, var, base_name);
  947. base_mangle = SwigType_manglestr(base_type);
  948. if (index == 1)
  949. Replace(s, "$basemangle", base_mangle, DOH_REPLACE_ANY);
  950. strcpy(varname, "basemangle");
  951. Replace(s, var, base_mangle, DOH_REPLACE_ANY);
  952. Delete(base_mangle);
  953. Delete(base_type);
  954. Delete(base_name);
  955. lex_type = SwigType_base(rtype);
  956. if (index == 1)
  957. Replace(s, "$lextype", lex_type, DOH_REPLACE_ANY);
  958. strcpy(varname, "lextype");
  959. Replace(s, var, lex_type, DOH_REPLACE_ANY);
  960. Delete(lex_type);
  961. }
  962. /* Replace any $n. with (&n)-> */
  963. {
  964. char temp[64];
  965. sprintf(var, "$%d.", index);
  966. sprintf(temp, "(&$%d)->", index);
  967. Replace(s, var, temp, DOH_REPLACE_ANY);
  968. }
  969. /* Replace the bare $n variable */
  970. sprintf(var, "$%d", index);
  971. bare_substitution_count = Replace(s, var, lname, DOH_REPLACE_ANY);
  972. Delete(ftype);
  973. return bare_substitution_count;
  974. }
  975. /* ------------------------------------------------------------------------
  976. * static typemap_locals()
  977. *
  978. * Takes a string, a parameter list and a wrapper function argument and
  979. * creates the local variables.
  980. * ------------------------------------------------------------------------ */
  981. static void typemap_locals(DOHString * s, ParmList *l, Wrapper *f, int argnum) {
  982. Parm *p;
  983. char *new_name;
  984. p = l;
  985. while (p) {
  986. SwigType *pt = Getattr(p, "type");
  987. SwigType *at = SwigType_alttype(pt, 1);
  988. String *pn = Getattr(p, "name");
  989. String *value = Getattr(p, "value");
  990. if (at)
  991. pt = at;
  992. if (pn) {
  993. if (Len(pn) > 0) {
  994. String *str;
  995. int isglobal = 0;
  996. str = NewStringEmpty();
  997. if (strncmp(Char(pn), "_global_", 8) == 0) {
  998. isglobal = 1;
  999. }
  1000. /* If the user gave us $type as the name of the local variable, we'll use
  1001. the passed datatype instead */
  1002. if ((argnum >= 0) && (!isglobal)) {
  1003. Printf(str, "%s%d", pn, argnum);
  1004. } else {
  1005. Append(str, pn);
  1006. }
  1007. if (isglobal && Wrapper_check_local(f, str)) {
  1008. p = nextSibling(p);
  1009. Delete(str);
  1010. if (at)
  1011. Delete(at);
  1012. continue;
  1013. }
  1014. if (value) {
  1015. String *pstr = SwigType_str(pt, str);
  1016. new_name = Wrapper_new_localv(f, str, pstr, "=", value, NIL);
  1017. Delete(pstr);
  1018. } else {
  1019. String *pstr = SwigType_str(pt, str);
  1020. new_name = Wrapper_new_localv(f, str, pstr, NIL);
  1021. Delete(pstr);
  1022. }
  1023. if (!isglobal) {
  1024. /* Substitute */
  1025. Replace(s, pn, new_name, DOH_REPLACE_ID | DOH_REPLACE_NOQUOTE);
  1026. }
  1027. Delete(str);
  1028. }
  1029. }
  1030. p = nextSibling(p);
  1031. if (at)
  1032. Delete(at);
  1033. }
  1034. }
  1035. /* -----------------------------------------------------------------------------
  1036. * Swig_typemap_lookup()
  1037. *
  1038. * Attach one or more typemaps to a node and optionally generate the typemap contents
  1039. * into the wrapper.
  1040. *
  1041. * Looks for a typemap matching the given type and name and attaches the typemap code
  1042. * and any typemap attributes to the provided node.
  1043. *
  1044. * The node should contain the "type" and "name" attributes for the typemap match on.
  1045. * input. The typemap code and typemap attribute values are attached onto the node
  1046. * prefixed with "tmap:". For example with tmap_method="in", the typemap code can be retrieved
  1047. * with a call to Getattr(node, "tmap:in") (this is also the string returned) and the
  1048. * "noblock" attribute can be retrieved with a call to Getattr(node, "tmap:in:noblock").
  1049. *
  1050. * tmap_method - typemap method, eg "in", "out", "newfree"
  1051. * node - the node to attach the typemap and typemap attributes to
  1052. * lname - name of variable to substitute $1, $2 etc for
  1053. * f - wrapper code to generate into if non null
  1054. * actioncode - code to generate into f before the out typemap code, unless
  1055. * the optimal attribute is set in the out typemap in which case
  1056. * $1 in the out typemap will be replaced by the code in actioncode.
  1057. * ----------------------------------------------------------------------------- */
  1058. static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) {
  1059. SwigType *type;
  1060. SwigType *mtype = 0;
  1061. String *pname;
  1062. Hash *tm = 0;
  1063. String *s = 0;
  1064. String *sdef = 0;
  1065. ParmList *locals;
  1066. ParmList *kw;
  1067. char temp[256];
  1068. String *symname;
  1069. String *cname = 0;
  1070. String *clname = 0;
  1071. char *cop = Char(tmap_method);
  1072. int optimal_attribute = 0;
  1073. int optimal_substitution = 0;
  1074. int num_substitutions = 0;
  1075. /* special case, we need to check for 'ref' call
  1076. and set the default code 'sdef' */
  1077. if (node && Cmp(tmap_method, "newfree") == 0) {
  1078. sdef = Swig_ref_call(node, lname);
  1079. }
  1080. type = Getattr(node, "type");
  1081. if (!type)
  1082. return sdef;
  1083. pname = Getattr(node, "name");
  1084. #if 1
  1085. if (pname && node && checkAttribute(node, "kind", "function")) {
  1086. /*
  1087. For functions, look qualified names first, such as
  1088. struct Foo {
  1089. int *foo(int bar) -> Foo::foo
  1090. };
  1091. */
  1092. Symtab *st = Getattr(node, "sym:symtab");
  1093. String *qsn = st ? Swig_symbol_string_qualify(pname, st) : 0;
  1094. if (qsn) {
  1095. if (Len(qsn) && !Equal(qsn, pname)) {
  1096. tm = typemap_search(tmap_method, type, qsn, &mtype);
  1097. if (tm && (!Getattr(tm, "pname") || strstr(Char(Getattr(tm, "type")), "SWIGTYPE"))) {
  1098. tm = 0;
  1099. }
  1100. }
  1101. Delete(qsn);
  1102. }
  1103. }
  1104. if (!tm)
  1105. #endif
  1106. tm = typemap_search(tmap_method, type, pname, &mtype);
  1107. if (!tm)
  1108. return sdef;
  1109. s = Getattr(tm, "code");
  1110. if (!s)
  1111. return sdef;
  1112. /* Empty typemap. No match */
  1113. if (Cmp(s, "pass") == 0)
  1114. return sdef;
  1115. s = Copy(s); /* Make a local copy of the typemap code */
  1116. /* Attach kwargs - ie the typemap attributes */
  1117. kw = Getattr(tm, "kwargs");
  1118. while (kw) {
  1119. String *value = Copy(Getattr(kw, "value"));
  1120. String *kwtype = Getattr(kw, "type");
  1121. char *ckwname = Char(Getattr(kw, "name"));
  1122. if (kwtype) {
  1123. String *mangle = Swig_string_mangle(kwtype);
  1124. Append(value, mangle);
  1125. Delete(mangle);
  1126. }
  1127. sprintf(temp, "%s:%s", cop, ckwname);
  1128. Setattr(node, typemap_method_name(temp), value);
  1129. if (Cmp(temp, "out:optimal") == 0)
  1130. optimal_attribute = (Cmp(value, "0") != 0) ? 1 : 0;
  1131. Delete(value);
  1132. kw = nextSibling(kw);
  1133. }
  1134. if (optimal_attribute) {
  1135. /* Note: "out" typemap is the only typemap that will have the "optimal" attribute set.
  1136. * If f and actioncode are NULL, then the caller is just looking to attach the "out" attributes
  1137. * ie, not use the typemap code, otherwise both f and actioncode must be non null. */
  1138. if (actioncode) {
  1139. clname = Copy(actioncode);
  1140. /* check that the code in the typemap can be used in this optimal way.
  1141. * The code should be in the form "result = ...;\n". We need to extract
  1142. * the "..." part. This may not be possible for various reasons, eg
  1143. * code added by %exception. This optimal code generation is bit of a
  1144. * hack and circumvents the normal requirement for a temporary variable
  1145. * to hold the result returned from a wrapped function call.
  1146. */
  1147. if (Strncmp(clname, "result = ", 9) == 0) {
  1148. int numreplacements = Replace(clname, "result = ", "", DOH_REPLACE_ID_BEGIN);
  1149. if (numreplacements == 1) {
  1150. numreplacements = Replace(clname, ";\n", "", DOH_REPLACE_ID_END);
  1151. if (numreplacements == 1) {
  1152. if (Strchr(clname, ';') == 0) {
  1153. lname = clname;
  1154. actioncode = 0;
  1155. optimal_substitution = 1;
  1156. }
  1157. }
  1158. }
  1159. }
  1160. if (!optimal_substitution) {
  1161. Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_IGNORED, Getfile(node), Getline(node), "Method %s usage of the optimal attribute in the out typemap at %s:%d ignored as the following cannot be used to generate optimal code: %s\n", Swig_name_decl(node), Getfile(s), Getline(s), clname);
  1162. Delattr(node, "tmap:out:optimal");
  1163. }
  1164. } else {
  1165. assert(!f);
  1166. }
  1167. }
  1168. if (actioncode) {
  1169. assert(f);
  1170. Append(f->code, actioncode);
  1171. }
  1172. /* emit local variables declared in typemap, eg emit declarations for aa and bb in:
  1173. * %typemap(in) foo (int aa, int bb) "..." */
  1174. locals = Getattr(tm, "locals");
  1175. if (locals)
  1176. locals = CopyParmList(locals);
  1177. if (pname) {
  1178. if (SwigType_istemplate(pname)) {
  1179. cname = SwigType_namestr(pname);
  1180. pname = cname;
  1181. }
  1182. }
  1183. if (SwigType_istemplate((char *) lname)) {
  1184. clname = SwigType_namestr((char *) lname);
  1185. lname = clname;
  1186. }
  1187. if (mtype && SwigType_isarray(mtype)) {
  1188. num_substitutions = typemap_replace_vars(s, locals, mtype, type, pname, (char *) lname, 1);
  1189. } else {
  1190. num_substitutions = typemap_replace_vars(s, locals, type, type, pname, (char *) lname, 1);
  1191. }
  1192. if (optimal_substitution && num_substitutions > 1)
  1193. Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(node), Getline(node), "Multiple calls to %s might be generated due to optimal attribute usage in the out typemap at %s:%d.\n", Swig_name_decl(node), Getfile(s), Getline(s));
  1194. if (locals && f) {
  1195. typemap_locals(s, locals, f, -1);
  1196. }
  1197. {
  1198. ParmList *parm_sublist = NewParm(type, pname);
  1199. Setattr(parm_sublist, "lname", lname);
  1200. replace_embedded_typemap(s, parm_sublist, f);
  1201. Delete(parm_sublist);
  1202. }
  1203. Replace(s, "$name", pname, DOH_REPLACE_ANY);
  1204. symname = Getattr(node, "sym:name");
  1205. if (symname) {
  1206. Replace(s, "$symname", symname, DOH_REPLACE_ANY);
  1207. }
  1208. Setattr(node, typemap_method_name(tmap_method), s);
  1209. if (locals) {
  1210. sprintf(temp, "%s:locals", cop);
  1211. Setattr(node, typemap_method_name(temp), locals);
  1212. Delete(locals);
  1213. }
  1214. if (Checkattr(tm, "type", "SWIGTYPE")) {
  1215. sprintf(temp, "%s:SWIGTYPE", cop);
  1216. Setattr(node, typemap_method_name(temp), "1");
  1217. }
  1218. /* Look for warnings */
  1219. {
  1220. String *w;
  1221. sprintf(temp, "%s:warning", cop);
  1222. w = Getattr(node, typemap_method_name(temp));
  1223. if (w) {
  1224. Swig_warning(0, Getfile(node), Getline(node), "%s\n", w);
  1225. }
  1226. }
  1227. /* Look for code fragments */
  1228. {
  1229. String *fragment;
  1230. sprintf(temp, "%s:fragment", cop);
  1231. fragment = Getattr(node, typemap_method_name(temp));
  1232. if (fragment) {
  1233. String *fname = Copy(fragment);
  1234. Setfile(fname, Getfile(node));
  1235. Setline(fname, Getline(node));
  1236. Swig_fragment_emit(fname);
  1237. Delete(fname);
  1238. }
  1239. }
  1240. Delete(cname);
  1241. Delete(clname);
  1242. Delete(mtype);
  1243. if (sdef) { /* put 'ref' and 'newfree' codes together */
  1244. String *p = NewStringf("%s\n%s", sdef, s);
  1245. Delete(s);
  1246. Delete(sdef);
  1247. s = p;
  1248. }
  1249. Delete(actioncode);
  1250. return s;
  1251. }
  1252. String *Swig_typemap_lookup_out(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f, String *actioncode) {
  1253. assert(actioncode);
  1254. assert(Cmp(tmap_method, "out") == 0);
  1255. return Swig_typemap_lookup_impl(tmap_method, node, lname, f, actioncode);
  1256. }
  1257. String *Swig_typemap_lookup(const_String_or_char_ptr tmap_method, Node *node, const_String_or_char_ptr lname, Wrapper *f) {
  1258. return Swig_typemap_lookup_impl(tmap_method, node, lname, f, 0);
  1259. }
  1260. /* -----------------------------------------------------------------------------
  1261. * typemap_attach_kwargs()
  1262. *
  1263. * If this hash (tm) contains a linked list of parameters under its "kwargs"
  1264. * attribute, add keys for each of those named keyword arguments to this
  1265. * parameter for later use.
  1266. * For example, attach the typemap attributes to p:
  1267. * %typemap(in, foo="xyz") ...
  1268. * A new attribute called "tmap:in:foo" with value "xyz" is attached to p.
  1269. * ----------------------------------------------------------------------------- */
  1270. static void typemap_attach_kwargs(Hash *tm, const_String_or_char_ptr tmap_method, Parm *p) {
  1271. String *temp = NewStringEmpty();
  1272. Parm *kw = Getattr(tm, "kwargs");
  1273. while (kw) {
  1274. String *value = Copy(Getattr(kw, "value"));
  1275. String *type = Getattr(kw, "type");
  1276. if (type) {
  1277. Hash *v = NewHash();
  1278. Setattr(v, "type", type);
  1279. Setattr(v, "value", value);
  1280. Delete(value);
  1281. value = v;
  1282. }
  1283. Clear(temp);
  1284. Printf(temp, "%s:%s", tmap_method, Getattr(kw, "name"));
  1285. Setattr(p, typemap_method_name(temp), value);
  1286. Delete(value);
  1287. kw = nextSibling(kw);
  1288. }
  1289. Clear(temp);
  1290. Printf(temp, "%s:match_type", tmap_method);
  1291. Setattr(p, typemap_method_name(temp), Getattr(tm, "type"));
  1292. Delete(temp);
  1293. }
  1294. /* -----------------------------------------------------------------------------
  1295. * typemap_warn()
  1296. *
  1297. * If any warning message is attached to this parameter's "tmap:<method>:warning"
  1298. * attribute, print that warning message.
  1299. * ----------------------------------------------------------------------------- */
  1300. static void typemap_warn(const_String_or_char_ptr tmap_method, Parm *p) {
  1301. String *temp = NewStringf("%s:warning", tmap_method);
  1302. String *w = Getattr(p, typemap_method_name(temp));
  1303. Delete(temp);
  1304. if (w) {
  1305. Swig_warning(0, Getfile(p), Getline(p), "%s\n", w);
  1306. }
  1307. }
  1308. static void typemap_emit_code_fragments(const_String_or_char_ptr tmap_method, Parm *p) {
  1309. String *temp = NewStringf("%s:fragment", tmap_method);
  1310. String *f = Getattr(p, typemap_method_name(temp));
  1311. if (f) {
  1312. String *fname = Copy(f);
  1313. Setfile(fname, Getfile(p));
  1314. Setline(fname, Getline(p));
  1315. Swig_fragment_emit(fname);
  1316. Delete(fname);
  1317. }
  1318. Delete(temp);
  1319. }
  1320. static String *typemap_get_option(Hash *tm, const_String_or_char_ptr name) {
  1321. Parm *kw = Getattr(tm, "kwargs");
  1322. while (kw) {
  1323. String *kname = Getattr(kw, "name");
  1324. if (Equal(kname, name)) {
  1325. return Getattr(kw, "value");
  1326. }
  1327. kw = nextSibling(kw);
  1328. }
  1329. return 0;
  1330. }
  1331. /* -----------------------------------------------------------------------------
  1332. * Swig_typemap_attach_parms()
  1333. *
  1334. * Given a parameter list, this function attaches all of the typemaps and typemap
  1335. * attributes to the parameter for each type in the parameter list.
  1336. *
  1337. * This function basically provides the typemap code and typemap attribute values as
  1338. * attributes on each parameter prefixed with "tmap:". For example with tmap_method="in", the typemap
  1339. * code can be retrieved for the first parameter with a call to Getattr(parm, "tmap:in")
  1340. * and the "numinputs" attribute can be retrieved with a call to Getattr(parm, "tmap:in:numinputs").
  1341. *
  1342. * tmap_method - typemap method, eg "in", "out", "newfree"
  1343. * parms - parameter list to attach each typemap and all typemap attributes
  1344. * f - wrapper code to generate into if non null
  1345. * ----------------------------------------------------------------------------- */
  1346. void Swig_typemap_attach_parms(const_String_or_char_ptr tmap_method, ParmList *parms, Wrapper *f) {
  1347. Parm *p, *firstp;
  1348. Hash *tm;
  1349. int nmatch = 0;
  1350. int i;
  1351. String *s;
  1352. ParmList *locals;
  1353. int argnum = 0;
  1354. char temp[256];
  1355. char *cop = Char(tmap_method);
  1356. String *kwmatch = 0;
  1357. p = parms;
  1358. #ifdef SWIG_DEBUG
  1359. Printf(stdout, "Swig_typemap_attach_parms: %s\n", tmap_method);
  1360. #endif
  1361. while (p) {
  1362. argnum++;
  1363. nmatch = 0;
  1364. #ifdef SWIG_DEBUG
  1365. Printf(stdout, "parms: %s %s %s\n", tmap_method, Getattr(p, "name"), Getattr(p, "type"));
  1366. #endif
  1367. tm = typemap_search_multi(tmap_method, p, &nmatch);
  1368. #ifdef SWIG_DEBUG
  1369. if (tm)
  1370. Printf(stdout, "found: %s\n", tm);
  1371. #endif
  1372. if (!tm) {
  1373. p = nextSibling(p);
  1374. continue;
  1375. }
  1376. /*
  1377. Check if the typemap requires to match the type of another
  1378. typemap, for example:
  1379. %typemap(in) SWIGTYPE * (int var) {...}
  1380. %typemap(freearg,match="in") SWIGTYPE * {if (var$argnum) ...}
  1381. here, the freearg typemap requires the "in" typemap to match,
  1382. or the 'var$argnum' variable will not exist.
  1383. */
  1384. kwmatch = typemap_get_option(tm, "match");
  1385. if (kwmatch) {
  1386. String *tmname = NewStringf("tmap:%s", kwmatch);
  1387. String *tmin = Getattr(p, tmname);
  1388. Delete(tmname);
  1389. #ifdef SWIG_DEBUG
  1390. if (tm)
  1391. Printf(stdout, "matching: %s\n", kwmatch);
  1392. #endif
  1393. if (tmin) {
  1394. String *tmninp = NewStringf("tmap:%s:numinputs", kwmatch);
  1395. String *ninp = Getattr(p, tmninp);
  1396. Delete(tmninp);
  1397. if (ninp && Equal(ninp, "0")) {
  1398. p = nextSibling(p);
  1399. continue;
  1400. } else {
  1401. SwigType *typetm = Getattr(tm, "type");
  1402. String *temp = NewStringf("tmap:%s:match_type", kwmatch);
  1403. SwigType *typein = Getattr(p, temp);
  1404. Delete(temp);
  1405. if (!Equal(typein, typetm)) {
  1406. p = nextSibling(p);
  1407. continue;
  1408. } else {
  1409. int nnmatch;
  1410. Hash *tmapin = typemap_search_multi(kwmatch, p, &nnmatch);
  1411. String *tmname = Getattr(tm, "pname");
  1412. String *tnname = Getattr(tmapin, "pname");
  1413. if (!(tmname && tnname && Equal(tmname, tnname)) && !(!tmname && !tnname)) {
  1414. p = nextSibling(p);
  1415. continue;
  1416. }
  1417. }
  1418. }
  1419. } else {
  1420. p = nextSibling(p);
  1421. continue;
  1422. }
  1423. }
  1424. s = Getattr(tm, "code");
  1425. if (!s) {
  1426. p = nextSibling(p);
  1427. continue;
  1428. }
  1429. #ifdef SWIG_DEBUG
  1430. if (s)
  1431. Printf(stdout, "code: %s\n", s);
  1432. #endif
  1433. /* Empty typemap. No match */
  1434. if (Cmp(s, "pass") == 0) {
  1435. p = nextSibling(p);
  1436. continue;
  1437. }
  1438. s = Copy(s);
  1439. locals = Getattr(tm, "locals");
  1440. if (locals)
  1441. locals = CopyParmList(locals);
  1442. firstp = p;
  1443. #ifdef SWIG_DEBUG
  1444. Printf(stdout, "nmatch: %d\n", nmatch);
  1445. #endif
  1446. for (i = 0; i < nmatch; i++) {
  1447. SwigType *type;
  1448. String *pname;
  1449. String *lname;
  1450. SwigType *mtype;
  1451. type = Getattr(p, "type");
  1452. pname = Getattr(p, "name");
  1453. lname = Getattr(p, "lname");
  1454. mtype = Getattr(p, "tmap:match");
  1455. if (mtype) {
  1456. typemap_replace_vars(s, locals, mtype, type, pname, lname, i + 1);
  1457. Delattr(p, "tmap:match");
  1458. } else {
  1459. typemap_replace_vars(s, locals, type, type, pname, lname, i + 1);
  1460. }
  1461. if (Checkattr(tm, "type", "SWIGTYPE")) {
  1462. sprintf(temp, "%s:SWIGTYPE", cop);
  1463. Setattr(p, typemap_method_name(temp), "1");
  1464. }
  1465. p = nextSibling(p);
  1466. }
  1467. if (locals && f) {
  1468. typemap_locals(s, locals, f, argnum);
  1469. }
  1470. replace_embedded_typemap(s, firstp, f);
  1471. /* Replace the argument number */
  1472. sprintf(temp, "%d", argnum);
  1473. Replace(s, "$argnum", temp, DOH_REPLACE_ANY);
  1474. /* Attach attributes to object */
  1475. #ifdef SWIG_DEBUG
  1476. Printf(stdout, "attach: %s %s %s\n", Getattr(firstp, "name"), typemap_method_name(tmap_method), s);
  1477. #endif
  1478. Setattr(firstp, typemap_method_name(tmap_method), s); /* Code object */
  1479. if (locals) {
  1480. sprintf(temp, "%s:locals", cop);
  1481. Setattr(firstp, typemap_method_name(temp), locals);
  1482. Delete(locals);
  1483. }
  1484. /* Attach a link to the next parameter. Needed for multimaps */
  1485. sprintf(temp, "%s:next", cop);
  1486. Setattr(firstp, typemap_method_name(temp), p);
  1487. /* Attach kwargs */
  1488. typemap_attach_kwargs(tm, tmap_method, firstp);
  1489. /* Print warnings, if any */
  1490. typemap_warn(tmap_method, firstp);
  1491. /* Look for code fragments */
  1492. typemap_emit_code_fragments(tmap_method, firstp);
  1493. /* increase argnum to consider numinputs */
  1494. argnum += nmatch - 1;
  1495. Delete(s);
  1496. #ifdef SWIG_DEBUG
  1497. Printf(stdout, "res: %s %s %s\n", Getattr(firstp, "name"), typemap_method_name(tmap_method), Getattr(firstp, typemap_method_name(tmap_method)));
  1498. #endif
  1499. }
  1500. #ifdef SWIG_DEBUG
  1501. Printf(stdout, "Swig_typemap_attach_parms: end\n");
  1502. #endif
  1503. }
  1504. /* Splits the arguments of an embedded typemap */
  1505. static List *split_embedded_typemap(String *s) {
  1506. List *args = 0;
  1507. char *c, *start;
  1508. int level = 0;
  1509. int angle_level = 0;
  1510. int leading = 1;
  1511. args = NewList();
  1512. c = strchr(Char(s), '(');
  1513. assert(c);
  1514. c++;
  1515. start = c;
  1516. while (*c) {
  1517. if (*c == '\"') {
  1518. c++;
  1519. while (*c) {
  1520. if (*c == '\\') {
  1521. c++;
  1522. } else {
  1523. if (*c == '\"')
  1524. break;
  1525. }
  1526. c++;
  1527. }
  1528. }
  1529. if ((level == 0) && angle_level == 0 && ((*c == ',') || (*c == ')'))) {
  1530. String *tmp = NewStringWithSize(start, c - start);
  1531. Append(args, tmp);
  1532. Delete(tmp);
  1533. start = c + 1;
  1534. leading = 1;
  1535. if (*c == ')')
  1536. break;
  1537. c++;
  1538. continue;
  1539. }
  1540. if (*c == '(')
  1541. level++;
  1542. if (*c == ')')
  1543. level--;
  1544. if (*c == '<')
  1545. angle_level++;
  1546. if (*c == '>')
  1547. angle_level--;
  1548. if (isspace((int) *c) && leading)
  1549. start++;
  1550. if (!isspace((int) *c))
  1551. leading = 0;
  1552. c++;
  1553. }
  1554. return args;
  1555. }
  1556. /* -----------------------------------------------------------------------------
  1557. * replace_embedded_typemap()
  1558. *
  1559. * This function replaces the special variable macro $typemap(...) with typemap
  1560. * code. The general form of $typemap is as follows:
  1561. *
  1562. * $typemap(method, typelist, var1=value, var2=value, ...)
  1563. *
  1564. * where varx parameters are optional and undocumented; they were used in an earlier version of $typemap.
  1565. * A search is made using the typemap matching rules of form:
  1566. *
  1567. * %typemap(method) typelist {...}
  1568. *
  1569. * and if found will substitute in the typemap contents, making appropriate variable replacements.
  1570. *
  1571. * For example:
  1572. * $typemap(in, int) # simple usage matching %typemap(in) int { ... }
  1573. * $typemap(in, int b) # simple usage matching %typemap(in) int b { ... } or above %typemap
  1574. * $typemap(in, (Foo<int, bool> a, int b)) # multi-argument typemap matching %typemap(in) (Foo<int, bool> a, int b) {...}
  1575. * --------------------------------------------------------------------…

Large files files are truncated, but you can click here to view the full file