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