PageRenderTime 68ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/rel-1.3.35/Source/Swig/typemap.c

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