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.
7 * This file provides general support for datatypes that are encoded in
8 * the form of simple strings.
9 * ----------------------------------------------------------------------------- */
11 char cvsroot_stype_c[] = "$Id: stype.c 11080 2009-01-24 13:15:51Z bhy $";
17 /* -----------------------------------------------------------------------------
20 * The purpose of this module is to provide a general purpose type representation
21 * based on simple text strings.
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...).
30 * Types are encoded as strings of type constructors such as follows:
32 * String Encoding C Example
33 * --------------- ---------
35 * a(300).a(400).int int [300][400]
36 * p.q(const).char char const *
38 * All type constructors are denoted by a trailing '.':
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::*)
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".
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:
55 * "p.p." + "a(400).int" = "p.p.a(400).int"
57 * Similarly, one could strip a 'const' declaration from a type doing something
60 * Replace(t,"q(const).","",DOH_REPLACE_ANY)
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:
68 * <type>p.p.int</type>
74 * <function type="p.p.int" ...>blah</function>
76 * In either case, it's probably best to avoid characters such as '&', '*', or '<'.
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
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 * ----------------------------------------------------------------------------- */
88 SwigType *NewSwigType(int t) {
91 return NewString("bool");
94 return NewString("int");
97 return NewString("unsigned int");
100 return NewString("short");
103 return NewString("unsigned short");
106 return NewString("long");
109 return NewString("unsigned long");
112 return NewString("float");
115 return NewString("double");
118 return NewString("complex");
121 return NewString("char");
124 return NewString("signed char");
127 return NewString("unsigned char");
130 SwigType *t = NewString("char");
131 SwigType_add_pointer(t);
136 return NewString("long long");
139 return NewString("unsigned long long");
142 return NewString("void");
147 return NewStringEmpty();
150 /* -----------------------------------------------------------------------------
153 * Push a type constructor onto the type
154 * ----------------------------------------------------------------------------- */
156 void SwigType_push(SwigType *t, String *cons) {
163 char *c = Char(cons);
164 if (c[strlen(c) - 1] != '.')
170 /* -----------------------------------------------------------------------------
171 * SwigType_ispointer_return()
173 * Testing functions for querying a raw datatype
174 * ----------------------------------------------------------------------------- */
176 int SwigType_ispointer_return(SwigType *t) {
184 return (strcmp(c + idx, ").p.") == 0);
189 int SwigType_isreference_return(SwigType *t) {
197 return (strcmp(c + idx, ").r.") == 0);
202 int SwigType_isconst(SwigType *t) {
207 if (strncmp(c, "q(", 2) == 0) {
208 String *q = SwigType_parm(t);
209 if (strstr(Char(q), "const")) {
215 /* Hmmm. Might be const through a typedef */
216 if (SwigType_issimple(t)) {
218 SwigType *td = SwigType_typedef_resolve(t);
220 ret = SwigType_isconst(td);
228 int SwigType_ismutable(SwigType *t) {
230 SwigType *qt = SwigType_typedef_resolve_all(t);
231 if (SwigType_isreference(qt) || SwigType_isarray(qt)) {
232 Delete(SwigType_pop(qt));
234 r = SwigType_isconst(qt);
239 int SwigType_isenum(SwigType *t) {
243 if (strncmp(c, "enum ", 5) == 0) {
249 int SwigType_issimple(SwigType *t) {
273 /* -----------------------------------------------------------------------------
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.
280 * Pointers: p.SWIGTYPE
281 * References: r.SWIGTYPE
282 * Arrays: a().SWIGTYPE
284 * MemberPointer: m(CLASS).SWIGTYPE
285 * Enums: enum SWIGTYPE
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 * ----------------------------------------------------------------------------- */
291 #ifdef SWIG_DEFAULT_CACHE
292 static Hash *default_cache = 0;
295 #define SWIG_NEW_TYPE_DEFAULT
296 /* The new default type resolution method:
298 1.- It preserves the original mixed types, then it goes 'backward'
299 first deleting the qualifier, then the inner types
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
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
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
327 void SwigType_add_default(String *def, SwigType *nr) {
328 if (Strcmp(nr, "SWIGTYPE") == 0) {
329 Append(def, "SWIGTYPE");
331 String *q = SwigType_isqualifier(nr) ? SwigType_pop(nr) : 0;
332 if (q && strstr(Char(nr), "SWIGTYPE")) {
335 String *nd = SwigType_default(nr);
339 bdef = NewStringf("%s%s", q, nd);
340 if ((Strcmp(nr, bdef) == 0)) {
358 SwigType *SwigType_default(SwigType *t) {
363 #ifdef SWIG_DEFAULT_CACHE
365 default_cache = NewHash();
367 r = Getattr(default_cache, t);
373 if (SwigType_isvarargs(t)) {
378 while ((r1 = SwigType_typedef_resolve(r))) {
383 if (SwigType_isqualifier(r)) {
388 if (strstr(Char(r), "SWIGTYPE")) {
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);
406 def = NewString("p.SWIGTYPE");
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);
418 def = NewString("r.SWIGTYPE");
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");
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);
433 empty = strstr(c, "a(ANY).") != c;
438 def = NewString("a().");
440 def = NewString("a(ANY).");
442 #ifdef SWIG_NEW_TYPE_DEFAULT
443 SwigType_del_array(nr);
444 SwigType_add_default(def, nr);
446 Append(def, "SWIGTYPE");
450 } else if (SwigType_ismemberpointer(r)) {
451 if (strcmp(cr, "m(CLASS).SWIGTYPE") == 0) {
452 def = NewString("p.SWIGTYPE");
454 def = NewString("m(CLASS).SWIGTYPE");
456 } else if (SwigType_isenum(r)) {
457 if (strcmp(cr, "enum SWIGTYPE") == 0) {
458 def = NewString("SWIGTYPE");
460 def = NewString("enum SWIGTYPE");
462 } else if (SwigType_isfunction(r)) {
463 if (strcmp(cr, "f(ANY).SWIGTYPE") == 0) {
464 def = NewString("p.SWIGTYPE");
466 def = NewString("p.f(ANY).SWIGTYPE");
469 def = NewString("SWIGTYPE");
477 #ifdef SWIG_DEFAULT_CACHE
478 /* The cache produces strange results, see enum_template.i case */
480 String *cdef = Copy(def);
481 Setattr(default_cache, t, cdef);
486 /* Printf(stderr,"type : def %s : %s\n", t, def); */
491 /* -----------------------------------------------------------------------------
494 * Returns a string of the base type. Takes care of template expansions
495 * ----------------------------------------------------------------------------- */
497 String *SwigType_namestr(const SwigType *t) {
503 char *c = strstr(d, "<(");
505 if (!c || !strstr(c + 2, ")>"))
508 r = NewStringWithSize(d, c - d);
513 p = SwigType_parmlist(c + 1);
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))
527 suffix = SwigType_templatesuffix(t);
534 /* -----------------------------------------------------------------------------
537 * Create a C string representation of a datatype.
538 * ----------------------------------------------------------------------------- */
540 String *SwigType_str(SwigType *s, const_String_or_char_ptr id) {
542 String *element = 0, *nextelement;
547 result = NewString(id);
549 result = NewStringEmpty();
552 elements = SwigType_split(s);
553 nelements = Len(elements);
556 element = Getitem(elements, 0);
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);
565 if (SwigType_isqualifier(element)) {
567 q = SwigType_parm(element);
568 Insert(result, 0, " ");
569 Insert(result, 0, q);
571 } else if (SwigType_ispointer(element)) {
572 Insert(result, 0, "*");
573 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
574 Insert(result, 0, "(");
577 } else if (SwigType_ismemberpointer(element)) {
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, "(");
587 } else if (SwigType_isreference(element)) {
588 Insert(result, 0, "&");
589 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
590 Insert(result, 0, "(");
593 } else if (SwigType_isarray(element)) {
596 size = SwigType_parm(element);
597 Append(result, size);
600 } else if (SwigType_isfunction(element)) {
604 parms = SwigType_parmlist(element);
606 for (j = 0; j < plen; j++) {
607 p = SwigType_str(Getitem(parms, j), 0);
615 if (strcmp(Char(element), "v(...)") == 0) {
616 Insert(result, 0, "...");
618 String *bs = SwigType_namestr(element);
619 Insert(result, 0, " ");
620 Insert(result, 0, bs);
624 element = nextelement;
631 /* -----------------------------------------------------------------------------
632 * SwigType_ltype(SwigType *ty)
634 * Create a locally assignable type
635 * ----------------------------------------------------------------------------- */
637 SwigType *SwigType_ltype(SwigType *s) {
640 SwigType *td, *tc = 0;
646 result = NewStringEmpty();
648 /* Nuke all leading qualifiers */
649 while (SwigType_isqualifier(tc)) {
650 Delete(SwigType_pop(tc));
652 if (SwigType_issimple(tc)) {
653 /* Resolve any typedef definitions */
654 SwigType *tt = Copy(tc);
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 */
672 elements = SwigType_split(tc);
673 nelements = Len(elements);
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)) {
682 if (SwigType_isqualifier(element)) {
683 /* Do nothing. Ignore */
684 } else if (SwigType_ispointer(element)) {
685 Append(result, element);
687 } else if (SwigType_ismemberpointer(element)) {
688 Append(result, element);
690 } else if (SwigType_isreference(element)) {
692 Append(result, element);
694 Append(result, "p.");
697 } else if (SwigType_isarray(element) && firstarray) {
699 Append(result, element);
701 Append(result, "p.");
704 } else if (SwigType_isenum(element)) {
705 int anonymous_enum = (Cmp(element, "enum ") == 0);
706 if (notypeconv || !anonymous_enum) {
707 Append(result, element);
709 Append(result, "int");
712 Append(result, element);
720 /* -----------------------------------------------------------------------------
721 * SwigType_lstr(DOH *s, DOH *id)
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.
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 * -------------------------------------------------------------------- */
735 String *SwigType_lstr(SwigType *s, const_String_or_char_ptr id) {
739 tc = SwigType_ltype(s);
740 result = SwigType_str(tc, id);
745 /* -----------------------------------------------------------------------------
746 * SwigType_rcaststr()
748 * Produces a casting string that maps the type returned by lstr() to the real
749 * datatype printed by str().
750 * ----------------------------------------------------------------------------- */
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;
763 result = NewStringEmpty();
765 if (SwigType_isconst(s)) {
767 Delete(SwigType_pop(tc));
773 if ((SwigType_isconst(rs) || SwigType_isarray(rs) || SwigType_isreference(rs))) {
776 td = SwigType_typedef_resolve(rs);
780 if ((SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td))) {
781 elements = SwigType_split(td);
783 elements = SwigType_split(rs);
787 elements = SwigType_split(rs);
789 nelements = Len(elements);
791 element = Getitem(elements, 0);
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);
800 if (SwigType_isqualifier(element)) {
802 q = SwigType_parm(element);
803 Insert(result, 0, " ");
804 Insert(result, 0, q);
807 } else if (SwigType_ispointer(element)) {
808 Insert(result, 0, "*");
809 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
810 Insert(result, 0, "(");
814 } else if (SwigType_ismemberpointer(element)) {
816 Insert(result, 0, "::*");
817 q = SwigType_parm(element);
818 Insert(result, 0, q);
820 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
821 Insert(result, 0, "(");
825 } else if (SwigType_isreference(element)) {
826 Insert(result, 0, "&");
827 if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
828 Insert(result, 0, "(");
832 } else if (SwigType_isarray(element)) {
834 if (firstarray && !isreference) {
835 Append(result, "(*)");
839 size = SwigType_parm(element);
840 Append(result, size);
846 } else if (SwigType_isfunction(element)) {
850 parms = SwigType_parmlist(element);
852 for (j = 0; j < plen; j++) {
853 p = SwigType_str(Getitem(parms, j), 0);
862 String *bs = SwigType_namestr(element);
863 Insert(result, 0, " ");
864 Insert(result, 0, bs);
867 element = nextelement;
871 cast = NewStringEmpty();
873 cast = NewStringf("(%s)", result);
889 /* -----------------------------------------------------------------------------
890 * SwigType_lcaststr()
892 * Casts a variable from the real type to the local datatype.
893 * ----------------------------------------------------------------------------- */
895 String *SwigType_lcaststr(SwigType *s, const_String_or_char_ptr name) {
898 result = NewStringEmpty();
900 if (SwigType_isarray(s)) {
901 String *lstr = SwigType_lstr(s, 0);
902 Printf(result, "(%s)%s", lstr, name);
904 } else if (SwigType_isreference(s)) {
905 String *str = SwigType_str(s, 0);
906 Printf(result, "(%s)", str);
909 Append(result, name);
910 } else if (SwigType_isqualifier(s)) {
911 String *lstr = SwigType_lstr(s, 0);
912 Printf(result, "(%s)%s", lstr, name);
916 Append(result, name);
922 /* keep old mangling since Java codes need it */
923 String *SwigType_manglestr_default(SwigType *s) {
928 SwigType *sr = SwigType_typedef_qualified(s);
929 SwigType *ss = SwigType_typedef_resolve_all(sr);
933 if (SwigType_istemplate(ss)) {
934 SwigType *ty = Swig_symbol_template_deftype(ss, 0);
941 lt = SwigType_ltype(s);
942 result = SwigType_prefix(lt);
943 base = SwigType_base(lt);
947 if (!isalnum((int) *c))
951 if (SwigType_istemplate(base)) {
952 String *b = SwigType_namestr(base);
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);
980 else if (!isalnum((int) *c))
984 Append(result, base);
985 Insert(result, 0, "_");
993 String *SwigType_manglestr(SwigType *s) {
994 return SwigType_manglestr_default(s);
997 /* -----------------------------------------------------------------------------
998 * SwigType_typename_replace()
1000 * Replaces a typename in a type with something else. Needed for templates.
1001 * ----------------------------------------------------------------------------- */
1003 void SwigType_typename_replace(SwigType *t, String *pat, String *rep) {
1008 if (!Strstr(t, pat))
1011 if (Equal(t, pat)) {
1012 Replace(t, pat, rep, DOH_REPLACE_ANY);
1015 nt = NewStringEmpty();
1016 elem = SwigType_split(t);
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);
1033 List *tparms = SwigType_parmlist(e);
1035 String *nt = SwigType_templateprefix(e);
1038 for (j = 0; j < jlen; j++) {
1039 SwigType_typename_replace(Getitem(tparms, j), pat, rep);
1040 Append(nt, Getitem(tparms, j));
1044 tsuffix = SwigType_templatesuffix(e);
1045 Printf(nt, ")>%s", tsuffix);
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);
1059 Printv(e, first, "::", rest, NIL);
1063 } else if (SwigType_isfunction(e)) {
1065 List *fparms = SwigType_parmlist(e);
1069 for (j = 0; j < jlen; j++) {
1070 SwigType_typename_replace(Getitem(fparms, j), pat, rep);
1071 Append(e, Getitem(fparms, j));
1077 } else if (SwigType_isarray(e)) {
1078 Replace(e, pat, rep, DOH_REPLACE_ID);
1088 /* -----------------------------------------------------------------------------
1089 * SwigType_check_decl()
1091 * Checks type declarators for a match
1092 * ----------------------------------------------------------------------------- */
1094 int SwigType_check_decl(SwigType *ty, const SwigType *decl) {
1095 SwigType *t, *t1, *t2;
1097 t = SwigType_typedef_resolve_all(ty);
1098 t1 = SwigType_strip_qualifiers(t);
1099 t2 = SwigType_prefix(t1);
1100 r = Equal(t2, decl);