PageRenderTime 73ms CodeModel.GetById 31ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/Swig/typeobj.c

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