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