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