PageRenderTime 52ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Source/Swig/typeobj.c

#
C | 1212 lines | 725 code | 116 blank | 371 comment | 229 complexity | 915282a5ab291efab7de4d8817db1bd6 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  1. /* -----------------------------------------------------------------------------
  2. * This file is part of SWIG, which is licensed as a whole under version 3
  3. * (or any later version) of the GNU General Public License. Some additional
  4. * terms also apply to certain portions of SWIG. The full details of the SWIG
  5. * license and copyrights can be found in the LICENSE and COPYRIGHT files
  6. * included with the SWIG source code as distributed by the SWIG developers
  7. * and at http://www.swig.org/legal.html.
  8. *
  9. * typeobj.c
  10. *
  11. * This file provides functions for constructing, manipulating, and testing
  12. * type objects. Type objects are merely the raw low-level representation
  13. * of C++ types. They do not incorporate high-level type system features
  14. * like typedef, namespaces, etc.
  15. * ----------------------------------------------------------------------------- */
  16. char cvsroot_typeobj_c[] = "$Id: typeobj.c 12747 2011-06-20 17:46:38Z wsfulton $";
  17. #include "swig.h"
  18. #include <ctype.h>
  19. /* -----------------------------------------------------------------------------
  20. * Synopsis
  21. *
  22. * This file provides a collection of low-level functions for constructing and
  23. * manipulating C++ data types. In SWIG, C++ datatypes are encoded as simple
  24. * text strings. This representation is compact, easy to debug, and easy to read.
  25. *
  26. * General idea:
  27. *
  28. * Types are represented by a base type (e.g., "int") and a collection of
  29. * type operators applied to the base (e.g., pointers, arrays, etc...).
  30. *
  31. * Encoding:
  32. *
  33. * Types are encoded as strings of type constructors such as follows:
  34. *
  35. * String Encoding C Example
  36. * --------------- ---------
  37. * p.p.int int **
  38. * a(300).a(400).int int [300][400]
  39. * p.q(const).char char const *
  40. *
  41. * All type constructors are denoted by a trailing '.':
  42. *
  43. * 'p.' = Pointer (*)
  44. * 'r.' = Reference (&)
  45. * 'a(n).' = Array of size n [n]
  46. * 'f(..,..).' = Function with arguments (args)
  47. * 'q(str).' = Qualifier (such as const or volatile) (const, volatile)
  48. * 'm(qual).' = Pointer to member (qual::*)
  49. *
  50. * The complete type representation for varargs is:
  51. * 'v(...)'
  52. *
  53. * The encoding follows the order that you might describe a type in words.
  54. * For example "p.a(200).int" is "A pointer to array of int's" and
  55. * "p.q(const).char" is "a pointer to a const char".
  56. *
  57. * This representation of types is fairly convenient because ordinary string
  58. * operations can be used for type manipulation. For example, a type could be
  59. * formed by combining two strings such as the following:
  60. *
  61. * "p.p." + "a(400).int" = "p.p.a(400).int"
  62. *
  63. * For C++, typenames may be parameterized using <(...)>. Here are some
  64. * examples:
  65. *
  66. * String Encoding C++ Example
  67. * --------------- ------------
  68. * p.vector<(int)> vector<int> *
  69. * r.foo<(int,p.double)> foo<int,double *> &
  70. *
  71. * Contents of this file:
  72. *
  73. * Most of this functions in this file pertain to the low-level manipulation
  74. * of type objects. There are constructor functions like this:
  75. *
  76. * SwigType_add_pointer()
  77. * SwigType_add_reference()
  78. * SwigType_add_array()
  79. *
  80. * These are used to build new types. There are also functions to undo these
  81. * operations. For example:
  82. *
  83. * SwigType_del_pointer()
  84. * SwigType_del_reference()
  85. * SwigType_del_array()
  86. *
  87. * In addition, there are query functions
  88. *
  89. * SwigType_ispointer()
  90. * SwigType_isreference()
  91. * SwigType_isarray()
  92. *
  93. * Finally, there are some data extraction functions that can be used to
  94. * extract array dimensions, template arguments, and so forth.
  95. *
  96. * It is very important for developers to realize that the functions in this
  97. * module do *NOT* incorporate higher-level type system features like typedef.
  98. * For example, you could have C code like this:
  99. *
  100. * typedef int *intptr;
  101. *
  102. * In this case, a SwigType of type 'intptr' will be treated as a simple type and
  103. * functions like SwigType_ispointer() will evaluate as false. It is strongly
  104. * advised that developers use the TypeSys_* interface to check types in a more
  105. * reliable manner.
  106. * ----------------------------------------------------------------------------- */
  107. /* -----------------------------------------------------------------------------
  108. * NewSwigType()
  109. *
  110. * Constructs a new type object. Eventually, it would be nice for this function
  111. * to accept an initial value in the form a C/C++ abstract type (currently unimplemented).
  112. * ----------------------------------------------------------------------------- */
  113. #ifdef NEW
  114. SwigType *NewSwigType(const_String_or_char_ptr initial) {
  115. return NewString(initial);
  116. }
  117. #endif
  118. /* The next few functions are utility functions used in the construction and
  119. management of types */
  120. /* -----------------------------------------------------------------------------
  121. * static element_size()
  122. *
  123. * This utility function finds the size of a single type element in a type string.
  124. * Type elements are always delimited by periods, but may be nested with
  125. * parentheses. A nested element is always handled as a single item.
  126. *
  127. * Returns the integer size of the element (which can be used to extract a
  128. * substring, to chop the element off, or for other purposes).
  129. * ----------------------------------------------------------------------------- */
  130. static int element_size(char *c) {
  131. int nparen;
  132. char *s = c;
  133. while (*c) {
  134. if (*c == '.') {
  135. c++;
  136. return (int) (c - s);
  137. } else if (*c == '(') {
  138. nparen = 1;
  139. c++;
  140. while (*c) {
  141. if (*c == '(')
  142. nparen++;
  143. if (*c == ')') {
  144. nparen--;
  145. if (nparen == 0)
  146. break;
  147. }
  148. c++;
  149. }
  150. }
  151. if (*c)
  152. c++;
  153. }
  154. return (int) (c - s);
  155. }
  156. /* -----------------------------------------------------------------------------
  157. * SwigType_del_element()
  158. *
  159. * Deletes one type element from the type.
  160. * ----------------------------------------------------------------------------- */
  161. SwigType *SwigType_del_element(SwigType *t) {
  162. int sz = element_size(Char(t));
  163. Delslice(t, 0, sz);
  164. return t;
  165. }
  166. /* -----------------------------------------------------------------------------
  167. * SwigType_pop()
  168. *
  169. * Pop one type element off the type.
  170. * Example: t in: q(const).p.Integer
  171. * t out: p.Integer
  172. * result: q(const).
  173. * ----------------------------------------------------------------------------- */
  174. SwigType *SwigType_pop(SwigType *t) {
  175. SwigType *result;
  176. char *c;
  177. int sz;
  178. c = Char(t);
  179. if (!*c)
  180. return 0;
  181. sz = element_size(c);
  182. result = NewStringWithSize(c, sz);
  183. Delslice(t, 0, sz);
  184. c = Char(t);
  185. if (*c == '.') {
  186. Delitem(t, 0);
  187. }
  188. return result;
  189. }
  190. /* -----------------------------------------------------------------------------
  191. * SwigType_parm()
  192. *
  193. * Returns the parameter of an operator as a string
  194. * ----------------------------------------------------------------------------- */
  195. String *SwigType_parm(const SwigType *t) {
  196. char *start, *c;
  197. int nparens = 0;
  198. c = Char(t);
  199. while (*c && (*c != '(') && (*c != '.'))
  200. c++;
  201. if (!*c || (*c == '.'))
  202. return 0;
  203. c++;
  204. start = c;
  205. while (*c) {
  206. if (*c == ')') {
  207. if (nparens == 0)
  208. break;
  209. nparens--;
  210. } else if (*c == '(') {
  211. nparens++;
  212. }
  213. c++;
  214. }
  215. return NewStringWithSize(start, (int) (c - start));
  216. }
  217. /* -----------------------------------------------------------------------------
  218. * SwigType_split()
  219. *
  220. * Splits a type into it's component parts and returns a list of string.
  221. * ----------------------------------------------------------------------------- */
  222. List *SwigType_split(const SwigType *t) {
  223. String *item;
  224. List *list;
  225. char *c;
  226. int len;
  227. c = Char(t);
  228. list = NewList();
  229. while (*c) {
  230. len = element_size(c);
  231. item = NewStringWithSize(c, len);
  232. Append(list, item);
  233. Delete(item);
  234. c = c + len;
  235. if (*c == '.')
  236. c++;
  237. }
  238. return list;
  239. }
  240. /* -----------------------------------------------------------------------------
  241. * SwigType_parmlist()
  242. *
  243. * Splits a comma separated list of parameters into its component parts
  244. * The input is expected to contain the parameter list within () brackets
  245. * Returns 0 if no argument list in the input, ie there are no round brackets ()
  246. * Returns an empty List if there are no parameters in the () brackets
  247. * For example:
  248. *
  249. * Foo(std::string,p.f().Bar<(int,double)>)
  250. *
  251. * returns 2 elements in the list:
  252. * std::string
  253. * p.f().Bar<(int,double)>
  254. * ----------------------------------------------------------------------------- */
  255. List *SwigType_parmlist(const String *p) {
  256. String *item = 0;
  257. List *list;
  258. char *c;
  259. char *itemstart;
  260. int size;
  261. assert(p);
  262. c = Char(p);
  263. while (*c && (*c != '(') && (*c != '.'))
  264. c++;
  265. if (!*c)
  266. return 0;
  267. assert(*c != '.'); /* p is expected to contain sub elements of a type */
  268. c++;
  269. list = NewList();
  270. itemstart = c;
  271. while (*c) {
  272. if (*c == ',') {
  273. size = (int) (c - itemstart);
  274. item = NewStringWithSize(itemstart, size);
  275. Append(list, item);
  276. Delete(item);
  277. itemstart = c + 1;
  278. } else if (*c == '(') {
  279. int nparens = 1;
  280. c++;
  281. while (*c) {
  282. if (*c == '(')
  283. nparens++;
  284. if (*c == ')') {
  285. nparens--;
  286. if (nparens == 0)
  287. break;
  288. }
  289. c++;
  290. }
  291. } else if (*c == ')') {
  292. break;
  293. }
  294. if (*c)
  295. c++;
  296. }
  297. size = (int) (c - itemstart);
  298. if (size > 0) {
  299. item = NewStringWithSize(itemstart, size);
  300. Append(list, item);
  301. }
  302. Delete(item);
  303. return list;
  304. }
  305. /* -----------------------------------------------------------------------------
  306. * Pointers
  307. *
  308. * SwigType_add_pointer()
  309. * SwigType_del_pointer()
  310. * SwigType_ispointer()
  311. *
  312. * Add, remove, and test if a type is a pointer. The deletion and query
  313. * functions take into account qualifiers (if any).
  314. * ----------------------------------------------------------------------------- */
  315. SwigType *SwigType_add_pointer(SwigType *t) {
  316. Insert(t, 0, "p.");
  317. return t;
  318. }
  319. SwigType *SwigType_del_pointer(SwigType *t) {
  320. char *c, *s;
  321. c = Char(t);
  322. s = c;
  323. /* Skip qualifiers, if any */
  324. if (strncmp(c, "q(", 2) == 0) {
  325. c = strchr(c, '.');
  326. assert(c);
  327. c++;
  328. }
  329. if (strncmp(c, "p.", 2)) {
  330. printf("Fatal error. SwigType_del_pointer applied to non-pointer.\n");
  331. abort();
  332. }
  333. Delslice(t, 0, (c - s) + 2);
  334. return t;
  335. }
  336. int SwigType_ispointer(const SwigType *t) {
  337. char *c;
  338. if (!t)
  339. return 0;
  340. c = Char(t);
  341. /* Skip qualifiers, if any */
  342. if (strncmp(c, "q(", 2) == 0) {
  343. c = strchr(c, '.');
  344. if (!c)
  345. return 0;
  346. c++;
  347. }
  348. if (strncmp(c, "p.", 2) == 0) {
  349. return 1;
  350. }
  351. return 0;
  352. }
  353. /* -----------------------------------------------------------------------------
  354. * References
  355. *
  356. * SwigType_add_reference()
  357. * SwigType_del_reference()
  358. * SwigType_isreference()
  359. *
  360. * Add, remove, and test if a type is a reference. The deletion and query
  361. * functions take into account qualifiers (if any).
  362. * ----------------------------------------------------------------------------- */
  363. SwigType *SwigType_add_reference(SwigType *t) {
  364. Insert(t, 0, "r.");
  365. return t;
  366. }
  367. SwigType *SwigType_del_reference(SwigType *t) {
  368. char *c = Char(t);
  369. int check = strncmp(c, "r.", 2);
  370. assert(check == 0);
  371. Delslice(t, 0, 2);
  372. return t;
  373. }
  374. int SwigType_isreference(const SwigType *t) {
  375. char *c;
  376. if (!t)
  377. return 0;
  378. c = Char(t);
  379. if (strncmp(c, "r.", 2) == 0) {
  380. return 1;
  381. }
  382. return 0;
  383. }
  384. /* -----------------------------------------------------------------------------
  385. * Qualifiers
  386. *
  387. * SwigType_add_qualifier()
  388. * SwigType_del_qualifier()
  389. * SwigType_is_qualifier()
  390. *
  391. * Adds type qualifiers like "const" and "volatile". When multiple qualifiers
  392. * are added to a type, they are combined together into a single qualifier.
  393. * Repeated qualifications have no effect. Moreover, the order of qualifications
  394. * is alphabetical---meaning that "const volatile" and "volatile const" are
  395. * stored in exactly the same way as "q(const volatile)".
  396. * ----------------------------------------------------------------------------- */
  397. SwigType *SwigType_add_qualifier(SwigType *t, const_String_or_char_ptr qual) {
  398. char temp[256], newq[256];
  399. int sz, added = 0;
  400. char *q, *cqual;
  401. char *c = Char(t);
  402. cqual = Char(qual);
  403. if (!(strncmp(c, "q(", 2) == 0)) {
  404. sprintf(temp, "q(%s).", cqual);
  405. Insert(t, 0, temp);
  406. return t;
  407. }
  408. /* The type already has a qualifier on it. In this case, we first check to
  409. see if the qualifier is already specified. In that case do nothing.
  410. If it is a new qualifier, we add it to the qualifier list in alphabetical
  411. order */
  412. sz = element_size(c);
  413. strncpy(temp, c, (sz < 256) ? sz : 256);
  414. if (strstr(temp, cqual)) {
  415. /* Qualifier already added */
  416. return t;
  417. }
  418. /* Add the qualifier to the existing list. */
  419. strcpy(newq, "q(");
  420. q = temp + 2;
  421. q = strtok(q, " ).");
  422. while (q) {
  423. if (strcmp(cqual, q) < 0) {
  424. /* New qualifier is less that current qualifier. We need to insert it */
  425. strcat(newq, cqual);
  426. strcat(newq, " ");
  427. strcat(newq, q);
  428. added = 1;
  429. } else {
  430. strcat(newq, q);
  431. }
  432. q = strtok(NULL, " ).");
  433. if (q) {
  434. strcat(newq, " ");
  435. }
  436. }
  437. if (!added) {
  438. strcat(newq, " ");
  439. strcat(newq, cqual);
  440. }
  441. strcat(newq, ").");
  442. Delslice(t, 0, sz);
  443. Insert(t, 0, newq);
  444. return t;
  445. }
  446. SwigType *SwigType_del_qualifier(SwigType *t) {
  447. char *c = Char(t);
  448. int check = strncmp(c, "q(", 2);
  449. assert(check == 0);
  450. Delslice(t, 0, element_size(c));
  451. return t;
  452. }
  453. int SwigType_isqualifier(const SwigType *t) {
  454. char *c;
  455. if (!t)
  456. return 0;
  457. c = Char(t);
  458. if (strncmp(c, "q(", 2) == 0) {
  459. return 1;
  460. }
  461. return 0;
  462. }
  463. /* -----------------------------------------------------------------------------
  464. * Function Pointers
  465. * ----------------------------------------------------------------------------- */
  466. int SwigType_isfunctionpointer(const SwigType *t) {
  467. char *c;
  468. if (!t)
  469. return 0;
  470. c = Char(t);
  471. if (strncmp(c, "p.f(", 4) == 0) {
  472. return 1;
  473. }
  474. return 0;
  475. }
  476. /* -----------------------------------------------------------------------------
  477. * SwigType_functionpointer_decompose
  478. *
  479. * Decompose the function pointer into the parameter list and the return type
  480. * t - input and on completion contains the return type
  481. * returns the function's parameters
  482. * ----------------------------------------------------------------------------- */
  483. SwigType *SwigType_functionpointer_decompose(SwigType *t) {
  484. String *p;
  485. assert(SwigType_isfunctionpointer(t));
  486. p = SwigType_pop(t);
  487. Delete(p);
  488. p = SwigType_pop(t);
  489. return p;
  490. }
  491. /* -----------------------------------------------------------------------------
  492. * Member Pointers
  493. *
  494. * SwigType_add_memberpointer()
  495. * SwigType_del_memberpointer()
  496. * SwigType_ismemberpointer()
  497. *
  498. * Add, remove, and test for C++ pointer to members.
  499. * ----------------------------------------------------------------------------- */
  500. SwigType *SwigType_add_memberpointer(SwigType *t, const_String_or_char_ptr name) {
  501. String *temp = NewStringf("m(%s).", name);
  502. Insert(t, 0, temp);
  503. Delete(temp);
  504. return t;
  505. }
  506. SwigType *SwigType_del_memberpointer(SwigType *t) {
  507. char *c = Char(t);
  508. int check = strncmp(c, "m(", 2);
  509. assert(check == 0);
  510. Delslice(t, 0, element_size(c));
  511. return t;
  512. }
  513. int SwigType_ismemberpointer(const SwigType *t) {
  514. char *c;
  515. if (!t)
  516. return 0;
  517. c = Char(t);
  518. if (strncmp(c, "m(", 2) == 0) {
  519. return 1;
  520. }
  521. return 0;
  522. }
  523. /* -----------------------------------------------------------------------------
  524. * Arrays
  525. *
  526. * SwigType_add_array()
  527. * SwigType_del_array()
  528. * SwigType_isarray()
  529. *
  530. * Utility functions:
  531. *
  532. * SwigType_array_ndim() - Calculate number of array dimensions.
  533. * SwigType_array_getdim() - Get array dimension
  534. * SwigType_array_setdim() - Set array dimension
  535. * SwigType_array_type() - Return array type
  536. * SwigType_pop_arrays() - Remove all arrays
  537. * ----------------------------------------------------------------------------- */
  538. SwigType *SwigType_add_array(SwigType *t, const_String_or_char_ptr size) {
  539. char temp[512];
  540. strcpy(temp, "a(");
  541. strcat(temp, Char(size));
  542. strcat(temp, ").");
  543. Insert(t, 0, temp);
  544. return t;
  545. }
  546. SwigType *SwigType_del_array(SwigType *t) {
  547. char *c = Char(t);
  548. int check = strncmp(c, "a(", 2);
  549. assert(check == 0);
  550. Delslice(t, 0, element_size(c));
  551. return t;
  552. }
  553. int SwigType_isarray(const SwigType *t) {
  554. char *c;
  555. if (!t)
  556. return 0;
  557. c = Char(t);
  558. if (strncmp(c, "a(", 2) == 0) {
  559. return 1;
  560. }
  561. return 0;
  562. }
  563. /*
  564. * SwigType_prefix_is_simple_1D_array
  565. *
  566. * Determine if the type is a 1D array type that is treated as a pointer within SWIG
  567. * eg Foo[], Foo[3] return true, but Foo[3][3], Foo*[], Foo*[3], Foo**[] return false
  568. */
  569. int SwigType_prefix_is_simple_1D_array(const SwigType *t) {
  570. char *c = Char(t);
  571. if (c && (strncmp(c, "a(", 2) == 0)) {
  572. c = strchr(c, '.');
  573. c++;
  574. return (*c == 0);
  575. }
  576. return 0;
  577. }
  578. /* Remove all arrays */
  579. SwigType *SwigType_pop_arrays(SwigType *t) {
  580. String *ta;
  581. assert(SwigType_isarray(t));
  582. ta = NewStringEmpty();
  583. while (SwigType_isarray(t)) {
  584. SwigType *td = SwigType_pop(t);
  585. Append(ta, td);
  586. Delete(td);
  587. }
  588. return ta;
  589. }
  590. /* Return number of array dimensions */
  591. int SwigType_array_ndim(const SwigType *t) {
  592. int ndim = 0;
  593. char *c = Char(t);
  594. while (c && (strncmp(c, "a(", 2) == 0)) {
  595. c = strchr(c, '.');
  596. c++;
  597. ndim++;
  598. }
  599. return ndim;
  600. }
  601. /* Get nth array dimension */
  602. String *SwigType_array_getdim(const SwigType *t, int n) {
  603. char *c = Char(t);
  604. while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
  605. c = strchr(c, '.');
  606. c++;
  607. n--;
  608. }
  609. if (n == 0) {
  610. String *dim = SwigType_parm(c);
  611. if (SwigType_istemplate(dim)) {
  612. String *ndim = SwigType_namestr(dim);
  613. Delete(dim);
  614. dim = ndim;
  615. }
  616. return dim;
  617. }
  618. return 0;
  619. }
  620. /* Replace nth array dimension */
  621. void SwigType_array_setdim(SwigType *t, int n, const_String_or_char_ptr rep) {
  622. String *result = 0;
  623. char temp;
  624. char *start;
  625. char *c = Char(t);
  626. start = c;
  627. if (strncmp(c, "a(", 2))
  628. abort();
  629. while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
  630. c = strchr(c, '.');
  631. c++;
  632. n--;
  633. }
  634. if (n == 0) {
  635. temp = *c;
  636. *c = 0;
  637. result = NewString(start);
  638. Printf(result, "a(%s)", rep);
  639. *c = temp;
  640. c = strchr(c, '.');
  641. Append(result, c);
  642. }
  643. Clear(t);
  644. Append(t, result);
  645. Delete(result);
  646. }
  647. /* Return base type of an array */
  648. SwigType *SwigType_array_type(const SwigType *ty) {
  649. SwigType *t;
  650. t = Copy(ty);
  651. while (SwigType_isarray(t)) {
  652. Delete(SwigType_pop(t));
  653. }
  654. return t;
  655. }
  656. /* -----------------------------------------------------------------------------
  657. * Functions
  658. *
  659. * SwigType_add_function()
  660. * SwigType_del_function()
  661. * SwigType_isfunction()
  662. * SwigType_pop_function()
  663. *
  664. * Add, remove, and test for function types.
  665. * ----------------------------------------------------------------------------- */
  666. /* Returns the function type, t, constructed from the parameters, parms */
  667. SwigType *SwigType_add_function(SwigType *t, ParmList *parms) {
  668. String *pstr;
  669. Parm *p;
  670. Insert(t, 0, ").");
  671. pstr = NewString("f(");
  672. p = parms;
  673. for (p = parms; p; p = nextSibling(p)) {
  674. if (p != parms)
  675. Putc(',', pstr);
  676. Append(pstr, Getattr(p, "type"));
  677. }
  678. Insert(t, 0, pstr);
  679. Delete(pstr);
  680. return t;
  681. }
  682. SwigType *SwigType_pop_function(SwigType *t) {
  683. SwigType *f = 0;
  684. SwigType *g = 0;
  685. char *c = Char(t);
  686. if (strncmp(c, "q(", 2) == 0) {
  687. f = SwigType_pop(t);
  688. c = Char(t);
  689. }
  690. if (strncmp(c, "f(", 2)) {
  691. printf("Fatal error. SwigType_pop_function applied to non-function.\n");
  692. abort();
  693. }
  694. g = SwigType_pop(t);
  695. if (f)
  696. SwigType_push(g, f);
  697. Delete(f);
  698. return g;
  699. }
  700. int SwigType_isfunction(const SwigType *t) {
  701. char *c;
  702. if (!t) {
  703. return 0;
  704. }
  705. c = Char(t);
  706. if (strncmp(c, "q(", 2) == 0) {
  707. /* Might be a 'const' function. Try to skip over the 'const' */
  708. c = strchr(c, '.');
  709. if (c)
  710. c++;
  711. else
  712. return 0;
  713. }
  714. if (strncmp(c, "f(", 2) == 0) {
  715. return 1;
  716. }
  717. return 0;
  718. }
  719. /* Create a list of parameters from the type t, using the file_line_node Node for
  720. * file and line numbering for the parameters */
  721. ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node) {
  722. List *l = SwigType_parmlist(t);
  723. Hash *p, *pp = 0, *firstp = 0;
  724. Iterator o;
  725. for (o = First(l); o.item; o = Next(o)) {
  726. p = file_line_node ? NewParm(o.item, 0, file_line_node) : NewParmWithoutFileLineInfo(o.item, 0);
  727. if (!firstp)
  728. firstp = p;
  729. if (pp) {
  730. set_nextSibling(pp, p);
  731. Delete(p);
  732. }
  733. pp = p;
  734. }
  735. Delete(l);
  736. return firstp;
  737. }
  738. int SwigType_isvarargs(const SwigType *t) {
  739. if (Strcmp(t, "v(...)") == 0)
  740. return 1;
  741. return 0;
  742. }
  743. /* -----------------------------------------------------------------------------
  744. * Templates
  745. *
  746. * SwigType_add_template()
  747. *
  748. * Template handling.
  749. * ----------------------------------------------------------------------------- */
  750. /* -----------------------------------------------------------------------------
  751. * SwigType_add_template()
  752. *
  753. * Adds a template to a type. This template is encoded in the SWIG type
  754. * mechanism and produces a string like this:
  755. *
  756. * vector<int *> ----> "vector<(p.int)>"
  757. * ----------------------------------------------------------------------------- */
  758. SwigType *SwigType_add_template(SwigType *t, ParmList *parms) {
  759. Parm *p;
  760. Append(t, "<(");
  761. p = parms;
  762. for (p = parms; p; p = nextSibling(p)) {
  763. String *v;
  764. if (Getattr(p, "default"))
  765. continue;
  766. if (p != parms)
  767. Append(t, ",");
  768. v = Getattr(p, "value");
  769. if (v) {
  770. Append(t, v);
  771. } else {
  772. Append(t, Getattr(p, "type"));
  773. }
  774. }
  775. Append(t, ")>");
  776. return t;
  777. }
  778. /* -----------------------------------------------------------------------------
  779. * SwigType_templateprefix()
  780. *
  781. * Returns the prefix before the first template definition.
  782. * Returns the type unmodified if not a template.
  783. * For example:
  784. *
  785. * Foo<(p.int)>::bar => Foo
  786. * r.q(const).Foo<(p.int)>::bar => r.q(const).Foo
  787. * Foo => Foo
  788. * ----------------------------------------------------------------------------- */
  789. String *SwigType_templateprefix(const SwigType *t) {
  790. const char *s = Char(t);
  791. const char *c = strstr(s, "<(");
  792. return c ? NewStringWithSize(s, c - s) : NewString(s);
  793. }
  794. /* -----------------------------------------------------------------------------
  795. * SwigType_templatesuffix()
  796. *
  797. * Returns text after a template substitution. Used to handle scope names
  798. * for example:
  799. *
  800. * Foo<(p.int)>::bar
  801. *
  802. * returns "::bar"
  803. * ----------------------------------------------------------------------------- */
  804. String *SwigType_templatesuffix(const SwigType *t) {
  805. const char *c;
  806. c = Char(t);
  807. while (*c) {
  808. if ((*c == '<') && (*(c + 1) == '(')) {
  809. int nest = 1;
  810. c++;
  811. while (*c && nest) {
  812. if (*c == '<')
  813. nest++;
  814. if (*c == '>')
  815. nest--;
  816. c++;
  817. }
  818. return NewString(c);
  819. }
  820. c++;
  821. }
  822. return NewStringEmpty();
  823. }
  824. /* -----------------------------------------------------------------------------
  825. * SwigType_istemplate_templateprefix()
  826. *
  827. * Combines SwigType_istemplate and SwigType_templateprefix efficiently into one function.
  828. * Returns the prefix before the first template definition.
  829. * Returns NULL if not a template.
  830. * For example:
  831. *
  832. * Foo<(p.int)>::bar => Foo
  833. * r.q(const).Foo<(p.int)>::bar => r.q(const).Foo
  834. * Foo => NULL
  835. * ----------------------------------------------------------------------------- */
  836. String *SwigType_istemplate_templateprefix(const SwigType *t) {
  837. const char *s = Char(t);
  838. const char *c = strstr(s, "<(");
  839. return c ? NewStringWithSize(s, c - s) : 0;
  840. }
  841. /* -----------------------------------------------------------------------------
  842. * SwigType_istemplate_only_templateprefix()
  843. *
  844. * Similar to SwigType_istemplate_templateprefix() but only returns the template
  845. * prefix if the type is just the template and not a subtype/symbol within the template.
  846. * Returns NULL if not a template or is a template with a symbol within the template.
  847. * For example:
  848. *
  849. * Foo<(p.int)> => Foo
  850. * Foo<(p.int)>::bar => NULL
  851. * r.q(const).Foo<(p.int)> => r.q(const).Foo
  852. * r.q(const).Foo<(p.int)>::bar => NULL
  853. * Foo => NULL
  854. * ----------------------------------------------------------------------------- */
  855. String *SwigType_istemplate_only_templateprefix(const SwigType *t) {
  856. int len = Len(t);
  857. const char *s = Char(t);
  858. if (len >= 4 && strcmp(s + len - 2, ")>") == 0) {
  859. const char *c = strstr(s, "<(");
  860. return c ? NewStringWithSize(s, c - s) : 0;
  861. } else {
  862. return 0;
  863. }
  864. }
  865. /* -----------------------------------------------------------------------------
  866. * SwigType_templateargs()
  867. *
  868. * Returns the template arguments
  869. * For example:
  870. *
  871. * Foo<(p.int)>::bar
  872. *
  873. * returns "<(p.int)>"
  874. * ----------------------------------------------------------------------------- */
  875. String *SwigType_templateargs(const SwigType *t) {
  876. const char *c;
  877. const char *start;
  878. c = Char(t);
  879. while (*c) {
  880. if ((*c == '<') && (*(c + 1) == '(')) {
  881. int nest = 1;
  882. start = c;
  883. c++;
  884. while (*c && nest) {
  885. if (*c == '<')
  886. nest++;
  887. if (*c == '>')
  888. nest--;
  889. c++;
  890. }
  891. return NewStringWithSize(start, c - start);
  892. }
  893. c++;
  894. }
  895. return 0;
  896. }
  897. /* -----------------------------------------------------------------------------
  898. * SwigType_istemplate()
  899. *
  900. * Tests a type to see if it includes template parameters
  901. * ----------------------------------------------------------------------------- */
  902. int SwigType_istemplate(const SwigType *t) {
  903. char *ct = Char(t);
  904. ct = strstr(ct, "<(");
  905. if (ct && (strstr(ct + 2, ")>")))
  906. return 1;
  907. return 0;
  908. }
  909. /* -----------------------------------------------------------------------------
  910. * SwigType_base()
  911. *
  912. * This function returns the base of a type. For example, if you have a
  913. * type "p.p.int", the function would return "int".
  914. * ----------------------------------------------------------------------------- */
  915. SwigType *SwigType_base(const SwigType *t) {
  916. char *c;
  917. char *lastop = 0;
  918. c = Char(t);
  919. lastop = c;
  920. /* Search for the last type constructor separator '.' */
  921. while (*c) {
  922. if (*c == '.') {
  923. if (*(c + 1)) {
  924. lastop = c + 1;
  925. }
  926. c++;
  927. continue;
  928. }
  929. if (*c == '<') {
  930. /* Skip over template---it's part of the base name */
  931. int ntemp = 1;
  932. c++;
  933. while ((*c) && (ntemp > 0)) {
  934. if (*c == '>')
  935. ntemp--;
  936. else if (*c == '<')
  937. ntemp++;
  938. c++;
  939. }
  940. if (ntemp)
  941. break;
  942. continue;
  943. }
  944. if (*c == '(') {
  945. /* Skip over params */
  946. int nparen = 1;
  947. c++;
  948. while ((*c) && (nparen > 0)) {
  949. if (*c == '(')
  950. nparen++;
  951. else if (*c == ')')
  952. nparen--;
  953. c++;
  954. }
  955. if (nparen)
  956. break;
  957. continue;
  958. }
  959. c++;
  960. }
  961. return NewString(lastop);
  962. }
  963. /* -----------------------------------------------------------------------------
  964. * SwigType_prefix()
  965. *
  966. * Returns the prefix of a datatype. For example, the prefix of the
  967. * type "p.p.int" is "p.p.".
  968. * ----------------------------------------------------------------------------- */
  969. String *SwigType_prefix(const SwigType *t) {
  970. char *c, *d;
  971. String *r = 0;
  972. c = Char(t);
  973. d = c + strlen(c);
  974. /* Check for a type constructor */
  975. if ((d > c) && (*(d - 1) == '.'))
  976. d--;
  977. while (d > c) {
  978. d--;
  979. if (*d == '>') {
  980. int nest = 1;
  981. d--;
  982. while ((d > c) && (nest)) {
  983. if (*d == '>')
  984. nest++;
  985. if (*d == '<')
  986. nest--;
  987. d--;
  988. }
  989. }
  990. if (*d == ')') {
  991. /* Skip over params */
  992. int nparen = 1;
  993. d--;
  994. while ((d > c) && (nparen)) {
  995. if (*d == ')')
  996. nparen++;
  997. if (*d == '(')
  998. nparen--;
  999. d--;
  1000. }
  1001. }
  1002. if (*d == '.') {
  1003. char t = *(d + 1);
  1004. *(d + 1) = 0;
  1005. r = NewString(c);
  1006. *(d + 1) = t;
  1007. return r;
  1008. }
  1009. }
  1010. return NewStringEmpty();
  1011. }
  1012. /* -----------------------------------------------------------------------------
  1013. * SwigType_strip_qualifiers()
  1014. *
  1015. * Strip all qualifiers from a type and return a new type
  1016. * ----------------------------------------------------------------------------- */
  1017. SwigType *SwigType_strip_qualifiers(const SwigType *t) {
  1018. static Hash *memoize_stripped = 0;
  1019. SwigType *r;
  1020. List *l;
  1021. Iterator ei;
  1022. if (!memoize_stripped)
  1023. memoize_stripped = NewHash();
  1024. r = Getattr(memoize_stripped, t);
  1025. if (r)
  1026. return Copy(r);
  1027. l = SwigType_split(t);
  1028. r = NewStringEmpty();
  1029. for (ei = First(l); ei.item; ei = Next(ei)) {
  1030. if (SwigType_isqualifier(ei.item))
  1031. continue;
  1032. Append(r, ei.item);
  1033. }
  1034. Delete(l);
  1035. {
  1036. String *key, *value;
  1037. key = Copy(t);
  1038. value = Copy(r);
  1039. Setattr(memoize_stripped, key, value);
  1040. Delete(key);
  1041. Delete(value);
  1042. }
  1043. return r;
  1044. }
  1045. /* -----------------------------------------------------------------------------
  1046. * SwigType_strip_single_qualifier()
  1047. *
  1048. * If the type contains a qualifier, strip one qualifier and return a new type.
  1049. * The left most qualifier is stripped first (when viewed as C source code) but
  1050. * this is the equivalent to the right most qualifier using SwigType notation.
  1051. * Example:
  1052. * r.q(const).p.q(const).int => r.q(const).p.int
  1053. * r.q(const).p.int => r.p.int
  1054. * r.p.int => r.p.int
  1055. * ----------------------------------------------------------------------------- */
  1056. SwigType *SwigType_strip_single_qualifier(const SwigType *t) {
  1057. static Hash *memoize_stripped = 0;
  1058. SwigType *r = 0;
  1059. List *l;
  1060. int numitems;
  1061. if (!memoize_stripped)
  1062. memoize_stripped = NewHash();
  1063. r = Getattr(memoize_stripped, t);
  1064. if (r)
  1065. return Copy(r);
  1066. l = SwigType_split(t);
  1067. numitems = Len(l);
  1068. if (numitems >= 2) {
  1069. int item;
  1070. /* iterate backwards from last but one item */
  1071. for (item = numitems - 2; item >= 0; --item) {
  1072. String *subtype = Getitem(l, item);
  1073. if (SwigType_isqualifier(subtype)) {
  1074. Iterator it;
  1075. Delitem(l, item);
  1076. r = NewStringEmpty();
  1077. for (it = First(l); it.item; it = Next(it)) {
  1078. Append(r, it.item);
  1079. }
  1080. break;
  1081. }
  1082. }
  1083. }
  1084. if (!r)
  1085. r = Copy(t);
  1086. Delete(l);
  1087. {
  1088. String *key, *value;
  1089. key = Copy(t);
  1090. value = Copy(r);
  1091. Setattr(memoize_stripped, key, value);
  1092. Delete(key);
  1093. Delete(value);
  1094. }
  1095. return r;
  1096. }