import source from 1.3.40
[external/swig.git] / Source / Swig / stype.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  * stype.c
6  *
7  * This file provides general support for datatypes that are encoded in
8  * the form of simple strings.
9  * ----------------------------------------------------------------------------- */
10
11 char cvsroot_stype_c[] = "$Id: stype.c 11080 2009-01-24 13:15:51Z bhy $";
12
13 #include "swig.h"
14 #include "cparse.h"
15 #include <ctype.h>
16
17 /* -----------------------------------------------------------------------------
18  * Synopsis
19  *
20  * The purpose of this module is to provide a general purpose type representation
21  * based on simple text strings. 
22  *
23  * General idea:
24  *
25  * Types are represented by a base type (e.g., "int") and a collection of
26  * type operators applied to the base (e.g., pointers, arrays, etc...).
27  *
28  * Encoding:
29  *
30  * Types are encoded as strings of type constructors such as follows:
31  *
32  *        String Encoding                 C Example
33  *        ---------------                 ---------
34  *        p.p.int                         int **
35  *        a(300).a(400).int               int [300][400]
36  *        p.q(const).char                 char const *
37  *
38  * All type constructors are denoted by a trailing '.':
39  * 
40  *  'p.'                = Pointer (*)
41  *  'r.'                = Reference (&)
42  *  'a(n).'             = Array of size n  [n]
43  *  'f(..,..).'         = Function with arguments  (args)
44  *  'q(str).'           = Qualifier (such as const or volatile) (const, volatile)
45  *  'm(qual).'          = Pointer to member (qual::*)
46  *
47  * The encoding follows the order that you might describe a type in words.
48  * For example "p.a(200).int" is "A pointer to array of int's" and
49  * "p.q(const).char" is "a pointer to a const char".
50  *
51  * This representation of types is fairly convenient because ordinary string
52  * operations can be used for type manipulation. For example, a type could be
53  * formed by combining two strings such as the following:
54  *
55  *        "p.p." + "a(400).int" = "p.p.a(400).int"
56  *
57  * Similarly, one could strip a 'const' declaration from a type doing something
58  * like this:
59  *
60  *        Replace(t,"q(const).","",DOH_REPLACE_ANY)
61  *
62  * For the most part, this module tries to minimize the use of special
63  * characters (*, [, <, etc...) in its type encoding.  One reason for this
64  * is that SWIG might be extended to encode data in formats such as XML
65  * where you might want to do this:
66  * 
67  *      <function>
68  *         <type>p.p.int</type>
69  *         ...
70  *      </function>
71  *
72  * Or alternatively,
73  *
74  *      <function type="p.p.int" ...>blah</function>
75  *
76  * In either case, it's probably best to avoid characters such as '&', '*', or '<'.
77  *
78  * Why not use C syntax?  Well, C syntax is fairly complicated to parse
79  * and not particularly easy to manipulate---especially for adding, deleting and
80  * composing type constructors.  The string representation presented here makes
81  * this pretty easy.
82  *
83  * Why not use a bunch of nested data structures?  Are you kidding? How
84  * would that be easier to use than a few simple string operations? 
85  * ----------------------------------------------------------------------------- */
86
87
88 SwigType *NewSwigType(int t) {
89   switch (t) {
90   case T_BOOL:
91     return NewString("bool");
92     break;
93   case T_INT:
94     return NewString("int");
95     break;
96   case T_UINT:
97     return NewString("unsigned int");
98     break;
99   case T_SHORT:
100     return NewString("short");
101     break;
102   case T_USHORT:
103     return NewString("unsigned short");
104     break;
105   case T_LONG:
106     return NewString("long");
107     break;
108   case T_ULONG:
109     return NewString("unsigned long");
110     break;
111   case T_FLOAT:
112     return NewString("float");
113     break;
114   case T_DOUBLE:
115     return NewString("double");
116     break;
117   case T_COMPLEX:
118     return NewString("complex");
119     break;
120   case T_CHAR:
121     return NewString("char");
122     break;
123   case T_SCHAR:
124     return NewString("signed char");
125     break;
126   case T_UCHAR:
127     return NewString("unsigned char");
128     break;
129   case T_STRING:{
130       SwigType *t = NewString("char");
131       SwigType_add_pointer(t);
132       return t;
133       break;
134     }
135   case T_LONGLONG:
136     return NewString("long long");
137     break;
138   case T_ULONGLONG:
139     return NewString("unsigned long long");
140     break;
141   case T_VOID:
142     return NewString("void");
143     break;
144   default:
145     break;
146   }
147   return NewStringEmpty();
148 }
149
150 /* -----------------------------------------------------------------------------
151  * SwigType_push()
152  *
153  * Push a type constructor onto the type
154  * ----------------------------------------------------------------------------- */
155
156 void SwigType_push(SwigType *t, String *cons) {
157   if (!cons)
158     return;
159   if (!Len(cons))
160     return;
161
162   if (Len(t)) {
163     char *c = Char(cons);
164     if (c[strlen(c) - 1] != '.')
165       Insert(t, 0, ".");
166   }
167   Insert(t, 0, cons);
168 }
169
170 /* -----------------------------------------------------------------------------
171  * SwigType_ispointer_return()
172  *
173  * Testing functions for querying a raw datatype
174  * ----------------------------------------------------------------------------- */
175
176 int SwigType_ispointer_return(SwigType *t) {
177   char *c;
178   int idx;
179   if (!t)
180     return 0;
181   c = Char(t);
182   idx = strlen(c) - 4;
183   if (idx >= 0) {
184     return (strcmp(c + idx, ").p.") == 0);
185   }
186   return 0;
187 }
188
189 int SwigType_isreference_return(SwigType *t) {
190   char *c;
191   int idx;
192   if (!t)
193     return 0;
194   c = Char(t);
195   idx = strlen(c) - 4;
196   if (idx >= 0) {
197     return (strcmp(c + idx, ").r.") == 0);
198   }
199   return 0;
200 }
201
202 int SwigType_isconst(SwigType *t) {
203   char *c;
204   if (!t)
205     return 0;
206   c = Char(t);
207   if (strncmp(c, "q(", 2) == 0) {
208     String *q = SwigType_parm(t);
209     if (strstr(Char(q), "const")) {
210       Delete(q);
211       return 1;
212     }
213     Delete(q);
214   }
215   /* Hmmm. Might be const through a typedef */
216   if (SwigType_issimple(t)) {
217     int ret;
218     SwigType *td = SwigType_typedef_resolve(t);
219     if (td) {
220       ret = SwigType_isconst(td);
221       Delete(td);
222       return ret;
223     }
224   }
225   return 0;
226 }
227
228 int SwigType_ismutable(SwigType *t) {
229   int r;
230   SwigType *qt = SwigType_typedef_resolve_all(t);
231   if (SwigType_isreference(qt) || SwigType_isarray(qt)) {
232     Delete(SwigType_pop(qt));
233   }
234   r = SwigType_isconst(qt);
235   Delete(qt);
236   return r ? 0 : 1;
237 }
238
239 int SwigType_isenum(SwigType *t) {
240   char *c = Char(t);
241   if (!t)
242     return 0;
243   if (strncmp(c, "enum ", 5) == 0) {
244     return 1;
245   }
246   return 0;
247 }
248
249 int SwigType_issimple(SwigType *t) {
250   char *c = Char(t);
251   if (!t)
252     return 0;
253   while (*c) {
254     if (*c == '<') {
255       int nest = 1;
256       c++;
257       while (*c && nest) {
258         if (*c == '<')
259           nest++;
260         if (*c == '>')
261           nest--;
262         c++;
263       }
264       c--;
265     }
266     if (*c == '.')
267       return 0;
268     c++;
269   }
270   return 1;
271 }
272
273 /* -----------------------------------------------------------------------------
274  * SwigType_default()
275  *
276  * Create the default string for this datatype.   This takes a type and strips it
277  * down to its most primitive form--resolving all typedefs and removing operators.
278  *
279  * Rules:
280  *     Pointers:      p.SWIGTYPE
281  *     References:    r.SWIGTYPE
282  *     Arrays:        a().SWIGTYPE
283  *     Types:         SWIGTYPE
284  *     MemberPointer: m(CLASS).SWIGTYPE
285  *     Enums:         enum SWIGTYPE
286  *
287  * Note: if this function is applied to a primitive type, it returns NULL.  This
288  * allows recursive application for special types like arrays.
289  * ----------------------------------------------------------------------------- */
290
291 #ifdef SWIG_DEFAULT_CACHE
292 static Hash *default_cache = 0;
293 #endif
294
295 #define SWIG_NEW_TYPE_DEFAULT
296 /* The new default type resolution method:
297
298 1.- It preserves the original mixed types, then it goes 'backward'
299     first deleting the qualifier, then the inner types
300     
301     typedef A *Aptr;
302     const Aptr&;
303     r.q(const).Aptr       -> r.q(const).p.SWIGTYPE
304     r.q(const).p.SWIGTYPE -> r.p.SWIGTYPE
305     r.p.SWIGTYPE          -> r.SWIGTYPE
306     r.SWIGTYPE            -> SWIGTYPE
307
308
309     enum Hello {};
310     const Hello& hi;
311     r.q(const).Hello          -> r.q(const).enum SWIGTYPE
312     r.q(const).enum SWIGTYPE  -> r.enum SWIGTYPE
313     r.enum SWIGTYPE           -> r.SWIGTYPE
314     r.SWIGTYPE                -> SWIGTYPE
315
316     int a[2][4];
317     a(2).a(4).int           -> a(ANY).a(ANY).SWIGTYPE
318     a(ANY).a(ANY).SWIGTYPE  -> a(ANY).a().SWIGTYPE
319     a(ANY).a().SWIGTYPE     -> a(ANY).p.SWIGTYPE
320     a(ANY).p.SWIGTYPE       -> a(ANY).SWIGTYPE
321     a(ANY).SWIGTYPE         -> a().SWIGTYPE
322     a().SWIGTYPE            -> p.SWIGTYPE
323     p.SWIGTYPE              -> SWIGTYPE
324 */
325
326 static
327 void SwigType_add_default(String *def, SwigType *nr) {
328   if (Strcmp(nr, "SWIGTYPE") == 0) {
329     Append(def, "SWIGTYPE");
330   } else {
331     String *q = SwigType_isqualifier(nr) ? SwigType_pop(nr) : 0;
332     if (q && strstr(Char(nr), "SWIGTYPE")) {
333       Append(def, nr);
334     } else {
335       String *nd = SwigType_default(nr);
336       if (nd) {
337         String *bdef = nd;
338         if (q) {
339           bdef = NewStringf("%s%s", q, nd);
340           if ((Strcmp(nr, bdef) == 0)) {
341             Delete(bdef);
342             bdef = nd;
343           } else {
344             Delete(nd);
345           }
346         }
347         Append(def, bdef);
348         Delete(bdef);
349       } else {
350         Append(def, nr);
351       }
352     }
353     Delete(q);
354   }
355 }
356
357
358 SwigType *SwigType_default(SwigType *t) {
359   String *r1, *def;
360   String *r = 0;
361   char *cr;
362
363 #ifdef SWIG_DEFAULT_CACHE
364   if (!default_cache)
365     default_cache = NewHash();
366
367   r = Getattr(default_cache, t);
368   if (r) {
369     return Copy(r);
370   }
371 #endif
372
373   if (SwigType_isvarargs(t)) {
374     return 0;
375   }
376
377   r = t;
378   while ((r1 = SwigType_typedef_resolve(r))) {
379     if (r != t)
380       Delete(r);
381     r = r1;
382   }
383   if (SwigType_isqualifier(r)) {
384     String *q;
385     if (r == t)
386       r = Copy(t);
387     q = SwigType_pop(r);
388     if (strstr(Char(r), "SWIGTYPE")) {
389       Delete(q);
390       def = r;
391       return def;
392     }
393     Delete(q);
394   }
395   cr = Char(r);
396   if (strcmp(cr, "p.SWIGTYPE") == 0) {
397     def = NewString("SWIGTYPE");
398   } else if (SwigType_ispointer(r)) {
399 #ifdef SWIG_NEW_TYPE_DEFAULT
400     SwigType *nr = Copy(r);
401     SwigType_del_pointer(nr);
402     def = SwigType_isfunction(nr) ? NewStringEmpty() : NewString("p.");
403     SwigType_add_default(def, nr);
404     Delete(nr);
405 #else
406     def = NewString("p.SWIGTYPE");
407 #endif
408   } else if (strcmp(cr, "r.SWIGTYPE") == 0) {
409     def = NewString("SWIGTYPE");
410   } else if (SwigType_isreference(r)) {
411 #ifdef SWIG_NEW_TYPE_DEFAULT
412     SwigType *nr = Copy(r);
413     SwigType_del_reference(nr);
414     def = NewString("r.");
415     SwigType_add_default(def, nr);
416     Delete(nr);
417 #else
418     def = NewString("r.SWIGTYPE");
419 #endif
420   } else if (SwigType_isarray(r)) {
421     if (strcmp(cr, "a().SWIGTYPE") == 0) {
422       def = NewString("p.SWIGTYPE");
423     } else if (strcmp(cr, "a(ANY).SWIGTYPE") == 0) {
424       def = NewString("a().SWIGTYPE");
425     } else {
426       int i, empty = 0;
427       int ndim = SwigType_array_ndim(r);
428       SwigType *nr = Copy(r);
429       for (i = 0; i < ndim; i++) {
430         String *dim = SwigType_array_getdim(r, i);
431         if (!Len(dim)) {
432           char *c = Char(nr);
433           empty = strstr(c, "a(ANY).") != c;
434         }
435         Delete(dim);
436       }
437       if (empty) {
438         def = NewString("a().");
439       } else {
440         def = NewString("a(ANY).");
441       }
442 #ifdef SWIG_NEW_TYPE_DEFAULT
443       SwigType_del_array(nr);
444       SwigType_add_default(def, nr);
445 #else
446       Append(def, "SWIGTYPE");
447 #endif
448       Delete(nr);
449     }
450   } else if (SwigType_ismemberpointer(r)) {
451     if (strcmp(cr, "m(CLASS).SWIGTYPE") == 0) {
452       def = NewString("p.SWIGTYPE");
453     } else {
454       def = NewString("m(CLASS).SWIGTYPE");
455     }
456   } else if (SwigType_isenum(r)) {
457     if (strcmp(cr, "enum SWIGTYPE") == 0) {
458       def = NewString("SWIGTYPE");
459     } else {
460       def = NewString("enum SWIGTYPE");
461     }
462   } else if (SwigType_isfunction(r)) {
463     if (strcmp(cr, "f(ANY).SWIGTYPE") == 0) {
464       def = NewString("p.SWIGTYPE");
465     } else {
466       def = NewString("p.f(ANY).SWIGTYPE");
467     }
468   } else {
469     def = NewString("SWIGTYPE");
470   }
471   if (r != t)
472     Delete(r);
473   if (Equal(def, t)) {
474     Delete(def);
475     def = 0;
476   }
477 #ifdef SWIG_DEFAULT_CACHE
478   /* The cache produces strange results, see enum_template.i case */
479   if (def) {
480     String *cdef = Copy(def);
481     Setattr(default_cache, t, cdef);
482     Delete(cdef);
483   }
484 #endif
485
486   /* Printf(stderr,"type : def %s : %s\n", t, def);  */
487
488   return def;
489 }
490
491 /* -----------------------------------------------------------------------------
492  * SwigType_namestr()
493  *
494  * Returns a string of the base type.  Takes care of template expansions
495  * ----------------------------------------------------------------------------- */
496
497 String *SwigType_namestr(const SwigType *t) {
498   String *r;
499   String *suffix;
500   List *p;
501   int i, sz;
502   char *d = Char(t);
503   char *c = strstr(d, "<(");
504
505   if (!c || !strstr(c + 2, ")>"))
506     return NewString(t);
507
508   r = NewStringWithSize(d, c - d);
509   if (*(c - 1) == '<')
510     Putc(' ', r);
511   Putc('<', r);
512
513   p = SwigType_parmlist(c + 1);
514   sz = Len(p);
515   for (i = 0; i < sz; i++) {
516     String *str = SwigType_str(Getitem(p, i), 0);
517     /* Avoid creating a <: token, which is the same as [ in C++ - put a space after '<'. */
518     if (i == 0 && Len(str))
519       Putc(' ', r);
520     Append(r, str);
521     if ((i + 1) < sz)
522       Putc(',', r);
523     Delete(str);
524   }
525   Putc(' ', r);
526   Putc('>', r);
527   suffix = SwigType_templatesuffix(t);
528   Append(r, suffix);
529   Delete(suffix);
530   Delete(p);
531   return r;
532 }
533
534 /* -----------------------------------------------------------------------------
535  * SwigType_str()
536  *
537  * Create a C string representation of a datatype.
538  * ----------------------------------------------------------------------------- */
539
540 String *SwigType_str(SwigType *s, const_String_or_char_ptr id) {
541   String *result;
542   String *element = 0, *nextelement;
543   List *elements;
544   int nelements, i;
545
546   if (id) {
547     result = NewString(id);
548   } else {
549     result = NewStringEmpty();
550   }
551
552   elements = SwigType_split(s);
553   nelements = Len(elements);
554
555   if (nelements > 0) {
556     element = Getitem(elements, 0);
557   }
558   /* Now, walk the type list and start emitting */
559   for (i = 0; i < nelements; i++) {
560     if (i < (nelements - 1)) {
561       nextelement = Getitem(elements, i + 1);
562     } else {
563       nextelement = 0;
564     }
565     if (SwigType_isqualifier(element)) {
566       DOH *q = 0;
567       q = SwigType_parm(element);
568       Insert(result, 0, " ");
569       Insert(result, 0, q);
570       Delete(q);
571     } else if (SwigType_ispointer(element)) {
572       Insert(result, 0, "*");
573       if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
574         Insert(result, 0, "(");
575         Append(result, ")");
576       }
577     } else if (SwigType_ismemberpointer(element)) {
578       String *q;
579       q = SwigType_parm(element);
580       Insert(result, 0, "::*");
581       Insert(result, 0, q);
582       if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
583         Insert(result, 0, "(");
584         Append(result, ")");
585       }
586       Delete(q);
587     } else if (SwigType_isreference(element)) {
588       Insert(result, 0, "&");
589       if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
590         Insert(result, 0, "(");
591         Append(result, ")");
592       }
593     } else if (SwigType_isarray(element)) {
594       DOH *size;
595       Append(result, "[");
596       size = SwigType_parm(element);
597       Append(result, size);
598       Append(result, "]");
599       Delete(size);
600     } else if (SwigType_isfunction(element)) {
601       DOH *parms, *p;
602       int j, plen;
603       Append(result, "(");
604       parms = SwigType_parmlist(element);
605       plen = Len(parms);
606       for (j = 0; j < plen; j++) {
607         p = SwigType_str(Getitem(parms, j), 0);
608         Append(result, p);
609         if (j < (plen - 1))
610           Append(result, ",");
611       }
612       Append(result, ")");
613       Delete(parms);
614     } else {
615       if (strcmp(Char(element), "v(...)") == 0) {
616         Insert(result, 0, "...");
617       } else {
618         String *bs = SwigType_namestr(element);
619         Insert(result, 0, " ");
620         Insert(result, 0, bs);
621         Delete(bs);
622       }
623     }
624     element = nextelement;
625   }
626   Delete(elements);
627   Chop(result);
628   return result;
629 }
630
631 /* -----------------------------------------------------------------------------
632  * SwigType_ltype(SwigType *ty)
633  *
634  * Create a locally assignable type
635  * ----------------------------------------------------------------------------- */
636
637 SwigType *SwigType_ltype(SwigType *s) {
638   String *result;
639   String *element;
640   SwigType *td, *tc = 0;
641   List *elements;
642   int nelements, i;
643   int firstarray = 1;
644   int notypeconv = 0;
645
646   result = NewStringEmpty();
647   tc = Copy(s);
648   /* Nuke all leading qualifiers */
649   while (SwigType_isqualifier(tc)) {
650     Delete(SwigType_pop(tc));
651   }
652   if (SwigType_issimple(tc)) {
653     /* Resolve any typedef definitions */
654     SwigType *tt = Copy(tc);
655     td = 0;
656     while ((td = SwigType_typedef_resolve(tt))) {
657       if (td && (SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td))) {
658         /* We need to use the typedef type */
659         Delete(tt);
660         tt = td;
661         break;
662       } else if (td) {
663         Delete(tt);
664         tt = td;
665       }
666     }
667     if (td) {
668       Delete(tc);
669       tc = td;
670     }
671   }
672   elements = SwigType_split(tc);
673   nelements = Len(elements);
674
675   /* Now, walk the type list and start emitting */
676   for (i = 0; i < nelements; i++) {
677     element = Getitem(elements, i);
678     /* when we see a function, we need to preserve the following types */
679     if (SwigType_isfunction(element)) {
680       notypeconv = 1;
681     }
682     if (SwigType_isqualifier(element)) {
683       /* Do nothing. Ignore */
684     } else if (SwigType_ispointer(element)) {
685       Append(result, element);
686       firstarray = 0;
687     } else if (SwigType_ismemberpointer(element)) {
688       Append(result, element);
689       firstarray = 0;
690     } else if (SwigType_isreference(element)) {
691       if (notypeconv) {
692         Append(result, element);
693       } else {
694         Append(result, "p.");
695       }
696       firstarray = 0;
697     } else if (SwigType_isarray(element) && firstarray) {
698       if (notypeconv) {
699         Append(result, element);
700       } else {
701         Append(result, "p.");
702       }
703       firstarray = 0;
704     } else if (SwigType_isenum(element)) {
705       int anonymous_enum = (Cmp(element, "enum ") == 0);
706       if (notypeconv || !anonymous_enum) {
707         Append(result, element);
708       } else {
709         Append(result, "int");
710       }
711     } else {
712       Append(result, element);
713     }
714   }
715   Delete(elements);
716   Delete(tc);
717   return result;
718 }
719
720 /* -----------------------------------------------------------------------------
721  * SwigType_lstr(DOH *s, DOH *id)
722  *
723  * Produces a type-string that is suitable as a lvalue in an expression.
724  * That is, a type that can be freely assigned a value without violating
725  * any C assignment rules.
726  *
727  *      -   Qualifiers such as 'const' and 'volatile' are stripped.
728  *      -   Arrays are converted into a *single* pointer (i.e.,
729  *          double [][] becomes double *).
730  *      -   References are converted into a pointer.
731  *      -   Typedef names that refer to read-only types will be replaced
732  *          with an equivalent assignable version.
733  * -------------------------------------------------------------------- */
734
735 String *SwigType_lstr(SwigType *s, const_String_or_char_ptr id) {
736   String *result;
737   SwigType *tc;
738
739   tc = SwigType_ltype(s);
740   result = SwigType_str(tc, id);
741   Delete(tc);
742   return result;
743 }
744
745 /* -----------------------------------------------------------------------------
746  * SwigType_rcaststr()
747  *
748  * Produces a casting string that maps the type returned by lstr() to the real 
749  * datatype printed by str().
750  * ----------------------------------------------------------------------------- */
751
752 String *SwigType_rcaststr(SwigType *s, const_String_or_char_ptr name) {
753   String *result, *cast;
754   String *element = 0, *nextelement;
755   SwigType *td, *rs, *tc = 0;
756   List *elements;
757   int nelements, i;
758   int clear = 1;
759   int firstarray = 1;
760   int isreference = 0;
761   int isarray = 0;
762
763   result = NewStringEmpty();
764
765   if (SwigType_isconst(s)) {
766     tc = Copy(s);
767     Delete(SwigType_pop(tc));
768     rs = tc;
769   } else {
770     rs = s;
771   }
772
773   if ((SwigType_isconst(rs) || SwigType_isarray(rs) || SwigType_isreference(rs))) {
774     td = 0;
775   } else {
776     td = SwigType_typedef_resolve(rs);
777   }
778
779   if (td) {
780     if ((SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td))) {
781       elements = SwigType_split(td);
782     } else {
783       elements = SwigType_split(rs);
784     }
785     Delete(td);
786   } else {
787     elements = SwigType_split(rs);
788   }
789   nelements = Len(elements);
790   if (nelements > 0) {
791     element = Getitem(elements, 0);
792   }
793   /* Now, walk the type list and start emitting */
794   for (i = 0; i < nelements; i++) {
795     if (i < (nelements - 1)) {
796       nextelement = Getitem(elements, i + 1);
797     } else {
798       nextelement = 0;
799     }
800     if (SwigType_isqualifier(element)) {
801       DOH *q = 0;
802       q = SwigType_parm(element);
803       Insert(result, 0, " ");
804       Insert(result, 0, q);
805       Delete(q);
806       clear = 0;
807     } else if (SwigType_ispointer(element)) {
808       Insert(result, 0, "*");
809       if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
810         Insert(result, 0, "(");
811         Append(result, ")");
812       }
813       firstarray = 0;
814     } else if (SwigType_ismemberpointer(element)) {
815       String *q;
816       Insert(result, 0, "::*");
817       q = SwigType_parm(element);
818       Insert(result, 0, q);
819       Delete(q);
820       if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
821         Insert(result, 0, "(");
822         Append(result, ")");
823       }
824       firstarray = 0;
825     } else if (SwigType_isreference(element)) {
826       Insert(result, 0, "&");
827       if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
828         Insert(result, 0, "(");
829         Append(result, ")");
830       }
831       isreference = 1;
832     } else if (SwigType_isarray(element)) {
833       DOH *size;
834       if (firstarray && !isreference) {
835         Append(result, "(*)");
836         firstarray = 0;
837       } else {
838         Append(result, "[");
839         size = SwigType_parm(element);
840         Append(result, size);
841         Append(result, "]");
842         Delete(size);
843         clear = 0;
844       }
845       isarray = 1;
846     } else if (SwigType_isfunction(element)) {
847       DOH *parms, *p;
848       int j, plen;
849       Append(result, "(");
850       parms = SwigType_parmlist(element);
851       plen = Len(parms);
852       for (j = 0; j < plen; j++) {
853         p = SwigType_str(Getitem(parms, j), 0);
854         Append(result, p);
855         Delete(p);
856         if (j < (plen - 1))
857           Append(result, ",");
858       }
859       Append(result, ")");
860       Delete(parms);
861     } else {
862       String *bs = SwigType_namestr(element);
863       Insert(result, 0, " ");
864       Insert(result, 0, bs);
865       Delete(bs);
866     }
867     element = nextelement;
868   }
869   Delete(elements);
870   if (clear) {
871     cast = NewStringEmpty();
872   } else {
873     cast = NewStringf("(%s)", result);
874   }
875   if (name) {
876     if (isreference) {
877       if (isarray)
878         Clear(cast);
879       Append(cast, "*");
880     }
881     Append(cast, name);
882   }
883   Delete(result);
884   Delete(tc);
885   return cast;
886 }
887
888
889 /* -----------------------------------------------------------------------------
890  * SwigType_lcaststr()
891  *
892  * Casts a variable from the real type to the local datatype.
893  * ----------------------------------------------------------------------------- */
894
895 String *SwigType_lcaststr(SwigType *s, const_String_or_char_ptr name) {
896   String *result;
897
898   result = NewStringEmpty();
899
900   if (SwigType_isarray(s)) {
901     String *lstr = SwigType_lstr(s, 0);
902     Printf(result, "(%s)%s", lstr, name);
903     Delete(lstr);
904   } else if (SwigType_isreference(s)) {
905     String *str = SwigType_str(s, 0);
906     Printf(result, "(%s)", str);
907     Delete(str);
908     if (name)
909       Append(result, name);
910   } else if (SwigType_isqualifier(s)) {
911     String *lstr = SwigType_lstr(s, 0);
912     Printf(result, "(%s)%s", lstr, name);
913     Delete(lstr);
914   } else {
915     if (name)
916       Append(result, name);
917   }
918   return result;
919 }
920
921
922 /* keep old mangling since Java codes need it */
923 String *SwigType_manglestr_default(SwigType *s) {
924   char *c;
925   String *result = 0;
926   String *base = 0;
927   SwigType *lt;
928   SwigType *sr = SwigType_typedef_qualified(s);
929   SwigType *ss = SwigType_typedef_resolve_all(sr);
930
931   s = ss;
932
933   if (SwigType_istemplate(ss)) {
934     SwigType *ty = Swig_symbol_template_deftype(ss, 0);
935     Delete(ss);
936     ss = ty;
937     s = ss;
938   }
939   Delete(sr);
940
941   lt = SwigType_ltype(s);
942   result = SwigType_prefix(lt);
943   base = SwigType_base(lt);
944
945   c = Char(result);
946   while (*c) {
947     if (!isalnum((int) *c))
948       *c = '_';
949     c++;
950   }
951   if (SwigType_istemplate(base)) {
952     String *b = SwigType_namestr(base);
953     Delete(base);
954     base = b;
955   }
956
957   Replace(base, "struct ", "", DOH_REPLACE_ANY);        /* This might be problematic */
958   Replace(base, "class ", "", DOH_REPLACE_ANY);
959   Replace(base, "union ", "", DOH_REPLACE_ANY);
960   Replace(base, "enum ", "", DOH_REPLACE_ANY);
961
962   c = Char(base);
963   while (*c) {
964     if (*c == '<')
965       *c = 'T';
966     else if (*c == '>')
967       *c = 't';
968     else if (*c == '*')
969       *c = 'p';
970     else if (*c == '[')
971       *c = 'a';
972     else if (*c == ']')
973       *c = 'A';
974     else if (*c == '&')
975       *c = 'R';
976     else if (*c == '(')
977       *c = 'f';
978     else if (*c == ')')
979       *c = 'F';
980     else if (!isalnum((int) *c))
981       *c = '_';
982     c++;
983   }
984   Append(result, base);
985   Insert(result, 0, "_");
986   Delete(lt);
987   Delete(base);
988   if (ss)
989     Delete(ss);
990   return result;
991 }
992
993 String *SwigType_manglestr(SwigType *s) {
994   return SwigType_manglestr_default(s);
995 }
996
997 /* -----------------------------------------------------------------------------
998  * SwigType_typename_replace()
999  *
1000  * Replaces a typename in a type with something else.  Needed for templates.
1001  * ----------------------------------------------------------------------------- */
1002
1003 void SwigType_typename_replace(SwigType *t, String *pat, String *rep) {
1004   String *nt;
1005   int i, ilen;
1006   List *elem;
1007
1008   if (!Strstr(t, pat))
1009     return;
1010
1011   if (Equal(t, pat)) {
1012     Replace(t, pat, rep, DOH_REPLACE_ANY);
1013     return;
1014   }
1015   nt = NewStringEmpty();
1016   elem = SwigType_split(t);
1017   ilen = Len(elem);
1018   for (i = 0; i < ilen; i++) {
1019     String *e = Getitem(elem, i);
1020     if (SwigType_issimple(e)) {
1021       if (Equal(e, pat)) {
1022         /* Replaces a type of the form 'pat' with 'rep<args>' */
1023         Replace(e, pat, rep, DOH_REPLACE_ANY);
1024       } else if (SwigType_istemplate(e)) {
1025         /* Replaces a type of the form 'pat<args>' with 'rep' */
1026         if (Equal(e, pat)) {
1027           String *repbase = SwigType_templateprefix(rep);
1028           Replace(e, pat, repbase, DOH_REPLACE_ID | DOH_REPLACE_FIRST);
1029           Delete(repbase);
1030         }
1031         {
1032           String *tsuffix;
1033           List *tparms = SwigType_parmlist(e);
1034           int j, jlen;
1035           String *nt = SwigType_templateprefix(e);
1036           Append(nt, "<(");
1037           jlen = Len(tparms);
1038           for (j = 0; j < jlen; j++) {
1039             SwigType_typename_replace(Getitem(tparms, j), pat, rep);
1040             Append(nt, Getitem(tparms, j));
1041             if (j < (jlen - 1))
1042               Putc(',', nt);
1043           }
1044           tsuffix = SwigType_templatesuffix(e);
1045           Printf(nt, ")>%s", tsuffix);
1046           Delete(tsuffix);
1047           Clear(e);
1048           Append(e, nt);
1049           Delete(nt);
1050           Delete(tparms);
1051         }
1052       } else if (Swig_scopename_check(e)) {
1053         String *first, *rest;
1054         first = Swig_scopename_first(e);
1055         rest = Swig_scopename_suffix(e);
1056         SwigType_typename_replace(rest, pat, rep);
1057         SwigType_typename_replace(first, pat, rep);
1058         Clear(e);
1059         Printv(e, first, "::", rest, NIL);
1060         Delete(first);
1061         Delete(rest);
1062       }
1063     } else if (SwigType_isfunction(e)) {
1064       int j, jlen;
1065       List *fparms = SwigType_parmlist(e);
1066       Clear(e);
1067       Append(e, "f(");
1068       jlen = Len(fparms);
1069       for (j = 0; j < jlen; j++) {
1070         SwigType_typename_replace(Getitem(fparms, j), pat, rep);
1071         Append(e, Getitem(fparms, j));
1072         if (j < (jlen - 1))
1073           Putc(',', e);
1074       }
1075       Append(e, ").");
1076       Delete(fparms);
1077     } else if (SwigType_isarray(e)) {
1078       Replace(e, pat, rep, DOH_REPLACE_ID);
1079     }
1080     Append(nt, e);
1081   }
1082   Clear(t);
1083   Append(t, nt);
1084   Delete(nt);
1085   Delete(elem);
1086 }
1087
1088 /* -----------------------------------------------------------------------------
1089  * SwigType_check_decl()
1090  *
1091  * Checks type declarators for a match
1092  * ----------------------------------------------------------------------------- */
1093
1094 int SwigType_check_decl(SwigType *ty, const SwigType *decl) {
1095   SwigType *t, *t1, *t2;
1096   int r;
1097   t = SwigType_typedef_resolve_all(ty);
1098   t1 = SwigType_strip_qualifiers(t);
1099   t2 = SwigType_prefix(t1);
1100   r = Equal(t2, decl);
1101   Delete(t);
1102   Delete(t1);
1103   Delete(t2);
1104   return r == 1;
1105 }