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
11char 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
88SwigType *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
156void 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
176int 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
189int 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
202int 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
228int 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
239int 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
249int 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
292static Hash *default_cache = 0;
293#endif
294
295#define SWIG_NEW_TYPE_DEFAULT
296/* The new default type resolution method:
297
2981.- 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
326static
327void 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
358SwigType *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
497String *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
540String *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
637SwigType *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
735String *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
752String *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
895String *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 */
923String *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
993String *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
1003void 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
1094int 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}
1106