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

/tags/rel-1-3-25/SWIG/Source/Swig/typemap.c

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