PageRenderTime 87ms CodeModel.GetById 50ms app.highlight 32ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/Root-branch-php-utl/SWIG/Source/Swig/stype.c

#
C | 1086 lines | 812 code | 71 blank | 203 comment | 274 complexity | 54b85066f07e2e47526e113a6e5da30d MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
   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[] = "$Header$";
  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{
 158  if (!cons) return;
 159  if (!Len(cons)) return;
 160
 161  if (Len(t)) {
 162    char *c = Char(cons);
 163    if (c[strlen(c)-1] != '.')
 164      Insert(t,0,".");
 165  }
 166  Insert(t,0,cons);
 167}
 168
 169/* -----------------------------------------------------------------------------
 170 * SwigType_ispointer()
 171 * SwigType_ispointer_return()
 172 * SwigType_isarray()
 173 * SwigType_isreference()
 174 * SwigType_isfunction()
 175 * SwigType_isqualifier()
 176 *
 177 * Testing functions for querying a raw datatype
 178 * ----------------------------------------------------------------------------- */
 179
 180int SwigType_ispointer_return(SwigType *t) {
 181  char* c;
 182  int idx;
 183  if (!t) return 0;
 184  c = Char(t);
 185  idx = strlen(c)-4;
 186  if (idx >= 0) {
 187       return (strcmp(c+idx, ").p.") == 0);
 188  }
 189  return 0;
 190}
 191
 192int SwigType_isreference_return(SwigType *t) {
 193  char* c;
 194  int idx;
 195  if (!t) return 0;
 196  c = Char(t);
 197  idx = strlen(c)-4;
 198  if (idx >= 0) {
 199       return (strcmp(c+idx, ").r.") == 0);
 200  }
 201  return 0;
 202}
 203
 204int SwigType_isconst(SwigType *t) {
 205  char *c;
 206  if (!t) return 0;
 207  c = Char(t);
 208  if (strncmp(c,"q(",2) == 0) {
 209    String *q = SwigType_parm(t);
 210    if (strstr(Char(q),"const")) {
 211      Delete(q);
 212      return 1;
 213    }
 214    Delete(q);
 215  }
 216  /* Hmmm. Might be const through a typedef */
 217  if (SwigType_issimple(t)) {
 218    int ret;
 219    SwigType *td = SwigType_typedef_resolve(t);
 220    if (td) {
 221      ret = SwigType_isconst(td);
 222      Delete(td);
 223      return ret;
 224    }
 225  }
 226  return 0;
 227}
 228
 229int SwigType_ismutable(SwigType *t) {
 230  int r;
 231  SwigType *qt = SwigType_typedef_resolve_all(t);
 232  if (SwigType_isreference(qt) || SwigType_isarray(qt)) {
 233    Delete(SwigType_pop(qt));
 234  }
 235  r = SwigType_isconst(qt);
 236  Delete(qt);
 237  return r ? 0 : 1;
 238}
 239
 240int SwigType_isenum(SwigType *t) {
 241  char *c = Char(t);
 242  if (!t) 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) return 0;
 252  while (*c) {
 253    if (*c == '<') {
 254      int nest = 1;
 255      c++;
 256      while (*c && nest) {
 257	if (*c == '<') nest++;
 258	if (*c == '>') nest--;
 259	c++;
 260      }
 261      c--;
 262    }
 263    if (*c == '.') return 0;
 264    c++;
 265  }
 266  return 1;
 267}
 268
 269/* -----------------------------------------------------------------------------
 270 * SwigType_default()
 271 *
 272 * Create the default string for this datatype.   This takes a type and strips it
 273 * down to its most primitive form--resolving all typedefs and removing operators.
 274 *
 275 * Rules:
 276 *     Pointers:      p.SWIGTYPE
 277 *     References:    r.SWIGTYPE
 278 *     Arrays:        a().SWIGTYPE
 279 *     Types:         SWIGTYPE
 280 *     MemberPointer: m(CLASS).SWIGTYPE
 281 *     Enums:         enum SWIGTYPE
 282 *
 283 * Note: if this function is applied to a primitive type, it returns NULL.  This
 284 * allows recursive application for special types like arrays.
 285 * ----------------------------------------------------------------------------- */
 286
 287#ifdef SWIG_DEFAULT_CACHE
 288static Hash *default_cache = 0;
 289#endif
 290
 291#define SWIG_NEW_TYPE_DEFAULT
 292/* The new default type resolution method:
 293
 2941.- It preserves the original mixed types, then it goes 'backward'
 295    first deleting the qualifier, then the inner types
 296    
 297    typedef A *Aptr;
 298    const Aptr&;
 299    r.q(const).Aptr       -> r.q(const).p.SWIGTYPE
 300    r.q(const).p.SWIGTYPE -> r.p.SWIGTYPE
 301    r.p.SWIGTYPE          -> r.SWIGTYPE
 302    r.SWIGTYPE            -> SWIGTYPE
 303
 304
 305    enum Hello {};
 306    const Hello& hi;
 307    r.q(const).Hello          -> r.q(const).enum SWIGTYPE
 308    r.q(const).enum SWIGTYPE  -> r.enum SWIGTYPE
 309    r.enum SWIGTYPE           -> r.SWIGTYPE
 310    r.SWIGTYPE                -> SWIGTYPE
 311
 312    int a[2][4];
 313    a(2).a(4).int           -> a(ANY).a(ANY).SWIGTYPE
 314    a(ANY).a(ANY).SWIGTYPE  -> a(ANY).a().SWIGTYPE
 315    a(ANY).a().SWIGTYPE     -> a(ANY).p.SWIGTYPE
 316    a(ANY).p.SWIGTYPE       -> a(ANY).SWIGTYPE
 317    a(ANY).SWIGTYPE         -> a().SWIGTYPE
 318    a().SWIGTYPE            -> p.SWIGTYPE
 319    p.SWIGTYPE              -> SWIGTYPE
 320*/
 321
 322static 
 323void SwigType_add_default(String *def, SwigType *nr)
 324{
 325  if (Strcmp(nr,"SWIGTYPE") == 0) {
 326    StringAppend(def,"SWIGTYPE");
 327  } else {
 328    String *q = SwigType_isqualifier(nr) ? SwigType_pop(nr) : 0;
 329    if (q && strstr(Char(nr),"SWIGTYPE")) {
 330      StringAppend(def, nr);
 331    } else {
 332      String *nd = SwigType_default(nr);
 333      if (nd) {
 334	String *bdef = nd;
 335	if (q) {
 336	  bdef = NewStringf("%s%s", q, nd);
 337	  if ((Strcmp(nr,bdef) == 0)) {
 338	    Delete(bdef);
 339	    bdef = nd;
 340	  } else {
 341	    Delete(nd);
 342	  }
 343	}
 344	StringAppend(def,bdef);
 345	Delete(bdef);
 346      } else {
 347	StringAppend(def,nr);
 348      }
 349    }
 350    Delete(q);
 351  }
 352}
 353
 354
 355SwigType *SwigType_default(SwigType *t) {
 356  String *r1, *def;
 357  String *r = 0;
 358  char *cr;
 359
 360#ifdef SWIG_DEFAULT_CACHE
 361  if (!default_cache) default_cache = NewHash();
 362  
 363  r = Getattr(default_cache,t);
 364  if (r) {
 365    return Copy(r);
 366  }
 367#endif
 368 
 369  if (SwigType_isvarargs(t)) {
 370    return 0;
 371  }
 372
 373  r = t;
 374  while ((r1 = SwigType_typedef_resolve(r))) {
 375    if (r != t) Delete(r);
 376    r = r1;
 377  }
 378  if (SwigType_isqualifier(r)) {
 379    String *q;
 380    if (r == t) r = Copy(t);
 381    q = SwigType_pop(r);
 382    if (strstr(Char(r),"SWIGTYPE")) {
 383      Delete(q);
 384      def = r;
 385      return def;
 386    }
 387    Delete(q);
 388  }
 389  cr = Char(r);
 390  if (strcmp(cr,"p.SWIGTYPE") == 0) {
 391    def = NewString("SWIGTYPE");
 392  } else if (SwigType_ispointer(r)) {
 393#ifdef SWIG_NEW_TYPE_DEFAULT
 394    SwigType *nr = Copy(r);
 395    SwigType_del_pointer(nr);
 396    def = SwigType_isfunction(nr) ? 
 397      NewStringEmpty() : NewString("p.");
 398    SwigType_add_default(def, nr);
 399    Delete(nr);
 400#else
 401    def = NewString("p.SWIGTYPE");
 402#endif
 403  } else if (strcmp(cr,"r.SWIGTYPE") == 0) {
 404    def = NewString("SWIGTYPE");
 405  } else if (SwigType_isreference(r)) {
 406#ifdef SWIG_NEW_TYPE_DEFAULT
 407    SwigType *nr = Copy(r);
 408    SwigType_del_reference(nr);
 409    def = NewString("r.");
 410    SwigType_add_default(def, nr);
 411    Delete(nr);
 412#else
 413    def = NewString("r.SWIGTYPE");
 414#endif
 415  } else if (SwigType_isarray(r)) {
 416    if (strcmp(cr,"a().SWIGTYPE") == 0) {
 417      def = NewString("p.SWIGTYPE");
 418    } else if (strcmp(cr,"a(ANY).SWIGTYPE") == 0) {
 419      def = NewString("a().SWIGTYPE");
 420    } else {
 421      int i, empty = 0;
 422      int ndim = SwigType_array_ndim(r);
 423      SwigType *nr = Copy(r);
 424      for (i = 0; i < ndim; i++) {
 425	String *dim = SwigType_array_getdim(r,i);
 426	if (!Len(dim)) {
 427	  char *c = Char(nr);
 428	  empty = strstr(c,"a(ANY).") != c;
 429	}
 430	Delete(dim);
 431      }
 432      if (empty) {
 433	def = NewString("a().");
 434      } else {
 435	def = NewString("a(ANY).");
 436      }
 437#ifdef SWIG_NEW_TYPE_DEFAULT
 438      SwigType_del_array(nr);
 439      SwigType_add_default(def, nr);
 440#else
 441      StringAppend(def,"SWIGTYPE");
 442#endif
 443      Delete(nr);
 444    }
 445  } else if (SwigType_ismemberpointer(r)) {
 446    if (strcmp(cr,"m(CLASS).SWIGTYPE") == 0) {
 447      def = NewString("p.SWIGTYPE");
 448    } else {
 449      def = NewString("m(CLASS).SWIGTYPE");
 450    }
 451  } else if (SwigType_isenum(r)) {
 452    if (strcmp(cr,"enum SWIGTYPE") == 0) {
 453      def = NewString("SWIGTYPE");
 454    } else {
 455      def = NewString("enum SWIGTYPE");
 456    }
 457  } else if (SwigType_isfunction(r)) {
 458    if (strcmp(cr,"f(ANY).SWIGTYPE") == 0) {
 459      def = NewString("p.SWIGTYPE");
 460    } else {
 461      def = NewString("p.f(ANY).SWIGTYPE");
 462    }
 463  } else {
 464    def = NewString("SWIGTYPE");
 465  }
 466  if (r != t) Delete(r);
 467  if (StringEqual(def,t)) {
 468    Delete(def);
 469    def = 0;
 470  }
 471
 472#ifdef SWIG_DEFAULT_CACHE
 473  /* The cache produces strange results, see enum_template.i case */
 474  if (def) {
 475    String *cdef  = Copy(def);
 476    Setattr(default_cache,t, cdef); 
 477    Delete(cdef);
 478  }
 479#endif
 480
 481  /* Printf(stderr,"type : def %s : %s\n", t, def);  */
 482
 483  return def;
 484}
 485
 486/* -----------------------------------------------------------------------------
 487 * SwigType_namestr()
 488 *
 489 * Returns a string of the base type.  Takes care of template expansions
 490 * ----------------------------------------------------------------------------- */
 491
 492String *
 493SwigType_namestr(const SwigType *t) {
 494  String *r;
 495  String *suffix;
 496  List   *p;
 497  int     i, sz;
 498  char   *d = Char(t);
 499  char   *c = strstr(d,"<(");
 500
 501  if (!c || !strstr(c+2,")>")) return NewString(t);
 502
 503  r = NewStringWithSize(d, c - d);
 504  if (*(c - 1) == '<')  Putc(' ',r);
 505  Putc('<',r);
 506  
 507  p = SwigType_parmlist(c+1);
 508  sz = Len(p);
 509  for (i = 0; i < sz; i++) {
 510    String *str = SwigType_str(Getitem(p,i),0);
 511    StringAppend(r,str);
 512    if ((i+1) < sz) Putc(',',r);
 513    Delete(str);
 514  }
 515  Putc(' ',r);
 516  Putc('>',r);
 517  suffix = SwigType_templatesuffix(t);
 518  StringAppend(r,suffix);
 519  Delete(suffix);
 520  Delete(p);
 521  return r;
 522}
 523
 524/* -----------------------------------------------------------------------------
 525 * SwigType_str()
 526 *
 527 * Create a C string representation of a datatype.
 528 * ----------------------------------------------------------------------------- */
 529
 530String *
 531SwigType_str(SwigType *s, const String_or_char *id)
 532{
 533  String *result;
 534  String *element = 0, *nextelement;
 535  List *elements;
 536  int nelements, i;
 537
 538  if (id) {
 539    result = NewString(id);
 540  } else {
 541    result = NewStringEmpty();
 542  }
 543
 544  elements = SwigType_split(s);
 545  nelements = Len(elements);
 546
 547  if (nelements > 0) {
 548    element = Getitem(elements,0);
 549  }
 550  /* Now, walk the type list and start emitting */
 551  for (i = 0; i < nelements; i++) {
 552    if (i < (nelements - 1)) {
 553      nextelement = Getitem(elements,i+1);
 554    } else {
 555      nextelement = 0;
 556    }
 557    if (SwigType_isqualifier(element)) {
 558      DOH *q = 0;
 559      q = SwigType_parm(element);
 560      Insert(result,0," ");
 561      Insert(result,0,q);
 562      Delete(q);
 563    } else if (SwigType_ispointer(element)) {
 564      Insert(result,0,"*");
 565      if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
 566	Insert(result,0,"(");
 567	StringAppend(result,")");
 568      }
 569    } else if (SwigType_ismemberpointer(element)) {
 570      String *q;
 571      q = SwigType_parm(element);
 572      Insert(result,0,"::*");
 573      Insert(result,0,q);
 574      if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
 575	Insert(result,0,"(");
 576	StringAppend(result,")");
 577      }
 578      Delete(q);
 579    }
 580    else if (SwigType_isreference(element)) {
 581      Insert(result,0,"&");
 582      if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
 583	Insert(result,0,"(");
 584	StringAppend(result,")");
 585      }
 586    }  else if (SwigType_isarray(element)) {
 587      DOH *size;
 588      StringAppend(result,"[");
 589      size = SwigType_parm(element);
 590      StringAppend(result,size);
 591      StringAppend(result,"]");
 592      Delete(size);
 593    } else if (SwigType_isfunction(element)) {
 594      DOH *parms, *p;
 595      int j, plen;
 596      StringAppend(result,"(");
 597      parms = SwigType_parmlist(element);
 598      plen = Len(parms);
 599      for (j = 0; j < plen; j++) {
 600	p = SwigType_str(Getitem(parms,j),0);
 601	StringAppend(result,p);
 602	if (j < (plen-1)) StringAppend(result,",");
 603      }
 604      StringAppend(result,")");
 605      Delete(parms);
 606    } else {
 607      if (strcmp(Char(element),"v(...)") == 0) {
 608	Insert(result,0,"...");
 609      } else {
 610	String *bs = SwigType_namestr(element);
 611	Insert(result,0," ");
 612	Insert(result,0,bs);
 613	Delete(bs);
 614      }
 615    }
 616    element = nextelement;
 617  }
 618  Delete(elements);
 619  Chop(result);
 620  return result;
 621}
 622
 623/* -----------------------------------------------------------------------------
 624 * SwigType_ltype(SwigType *ty)
 625 *
 626 * Create a locally assignable type
 627 * ----------------------------------------------------------------------------- */
 628
 629SwigType *
 630SwigType_ltype(SwigType *s) {
 631  String *result;
 632  String *element;
 633  SwigType *td, *tc = 0;
 634  List *elements;
 635  int nelements, i;
 636  int firstarray = 1;
 637  int notypeconv = 0;
 638
 639  result = NewStringEmpty();
 640  tc = Copy(s);
 641  /* Nuke all leading qualifiers */
 642  while (SwigType_isqualifier(tc)) {
 643    Delete(SwigType_pop(tc));
 644  }
 645  if (SwigType_issimple(tc)) {
 646    /* Resolve any typedef definitions */
 647    SwigType *tt  = Copy(tc);
 648    td = 0;
 649    while ((td = SwigType_typedef_resolve(tt))) {      
 650      if (td && (SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td))) {
 651	/* We need to use the typedef type */
 652	Delete(tt);
 653	tt = td;
 654	break;
 655      } else if (td) {
 656	Delete(tt);
 657	tt = td;
 658      }
 659    }
 660    if (td) {
 661      Delete(tc);
 662      tc = td;      
 663    }
 664  }
 665  elements = SwigType_split(tc);
 666  nelements = Len(elements);
 667
 668  /* Now, walk the type list and start emitting */
 669  for (i = 0; i < nelements; i++) {
 670    element = Getitem(elements,i);
 671    /* when we see a function, we need to preserve the following types */
 672    if (SwigType_isfunction(element)) {
 673      notypeconv = 1;
 674    }
 675    if (SwigType_isqualifier(element)) {
 676      /* Do nothing. Ignore */
 677    } else if (SwigType_ispointer(element)) {
 678      StringAppend(result,element);
 679      firstarray = 0;
 680    } else if (SwigType_ismemberpointer(element)) {
 681      StringAppend(result,element);
 682      firstarray = 0;
 683    } else if (SwigType_isreference(element)) {
 684      if (notypeconv) {
 685	StringAppend(result,element);
 686      } else {
 687	StringAppend(result,"p.");
 688      }
 689      firstarray = 0;
 690    } else if (SwigType_isarray(element) && firstarray) {
 691      if (notypeconv) {
 692	StringAppend(result,element);
 693      } else {
 694	StringAppend(result,"p.");
 695      }
 696      firstarray = 0;
 697    } else if (SwigType_isenum(element)) {
 698      int anonymous_enum = (Cmp(element,"enum ") == 0); 
 699      if (notypeconv || !anonymous_enum) {
 700	StringAppend(result,element);
 701      } else {
 702	StringAppend(result,"int");
 703      }
 704    } else {
 705      StringAppend(result,element);
 706    }
 707  }
 708  Delete(elements);
 709  Delete(tc);
 710  return result;
 711}
 712
 713/* -----------------------------------------------------------------------------
 714 * SwigType_lstr(DOH *s, DOH *id)
 715 *
 716 * Produces a type-string that is suitable as a lvalue in an expression.
 717 * That is, a type that can be freely assigned a value without violating
 718 * any C assignment rules.
 719 *
 720 *      -   Qualifiers such as 'const' and 'volatile' are stripped.
 721 *      -   Arrays are converted into a *single* pointer (i.e.,
 722 *          double [][] becomes double *).
 723 *      -   References are converted into a pointer.
 724 *      -   Typedef names that refer to read-only types will be replaced
 725 *          with an equivalent assignable version.
 726 * -------------------------------------------------------------------- */
 727
 728String *
 729SwigType_lstr(SwigType *s, const String_or_char *id)
 730{
 731  String *result;
 732  SwigType  *tc;
 733
 734  tc = SwigType_ltype(s);
 735  result = SwigType_str(tc,id);
 736  Delete(tc);
 737  return result;
 738}
 739
 740/* -----------------------------------------------------------------------------
 741 * SwigType_rcaststr()
 742 *
 743 * Produces a casting string that maps the type returned by lstr() to the real 
 744 * datatype printed by str().
 745 * ----------------------------------------------------------------------------- */
 746
 747String *SwigType_rcaststr(SwigType *s, const String_or_char *name) {
 748  String *result, *cast;
 749  String *element = 0, *nextelement;
 750  SwigType *td, *rs, *tc = 0;
 751  List *elements;
 752  int      nelements, i;
 753  int      clear = 1;
 754  int      firstarray = 1;
 755  int      isreference = 0;
 756  int      isarray = 0;
 757
 758  result = NewStringEmpty();
 759
 760  if (SwigType_isconst(s)) {
 761    tc = Copy(s);
 762    Delete(SwigType_pop(tc));
 763    rs = tc;
 764  } else {
 765    rs = s;
 766  }
 767
 768  if ((SwigType_isconst(rs) || SwigType_isarray(rs) || SwigType_isreference(rs))) {
 769    td = 0;
 770  } else {
 771    td = SwigType_typedef_resolve(rs);
 772  }
 773  
 774  if (td) {
 775    if ((SwigType_isconst(td) || SwigType_isarray(td) || SwigType_isreference(td))) {
 776      elements = SwigType_split(td);
 777    } else {
 778      elements = SwigType_split(rs);
 779    } 
 780    Delete(td);
 781  } else {
 782    elements = SwigType_split(rs);
 783  }
 784  nelements = Len(elements);
 785  if (nelements > 0) {
 786    element = Getitem(elements,0);
 787  }
 788  /* Now, walk the type list and start emitting */
 789  for (i = 0; i < nelements; i++) {
 790    if (i < (nelements - 1)) {
 791      nextelement = Getitem(elements,i+1);
 792    } else {
 793      nextelement = 0;
 794    }
 795    if (SwigType_isqualifier(element)) {
 796      DOH *q = 0;
 797      q = SwigType_parm(element);
 798      Insert(result,0," ");
 799      Insert(result,0,q);
 800      Delete(q);
 801      clear = 0;
 802    } else if (SwigType_ispointer(element)) {
 803      Insert(result,0,"*");
 804      if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
 805	Insert(result,0,"(");
 806	StringAppend(result,")");
 807      }
 808      firstarray = 0;
 809    } else  if (SwigType_ismemberpointer(element)) {
 810      String *q;
 811      Insert(result,0,"::*");
 812      q = SwigType_parm(element);
 813      Insert(result,0,q);
 814      Delete(q);
 815      if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
 816	Insert(result,0,"(");
 817	StringAppend(result,")");
 818      }
 819      firstarray = 0;
 820    } else if (SwigType_isreference(element)) {
 821	Insert(result,0,"&");
 822	if ((nextelement) && ((SwigType_isfunction(nextelement) || (SwigType_isarray(nextelement))))) {
 823	  Insert(result,0,"(");
 824	  StringAppend(result,")");
 825	}
 826	isreference = 1;
 827    } else if (SwigType_isarray(element)) {
 828      DOH *size;
 829      if (firstarray && !isreference) {
 830	StringAppend(result,"(*)");
 831	firstarray = 0;
 832      } else {
 833	StringAppend(result,"[");
 834	size = SwigType_parm(element);
 835	StringAppend(result,size);
 836	StringAppend(result,"]");
 837	Delete(size);
 838	clear = 0;
 839      }
 840      isarray = 1;
 841    } else if (SwigType_isfunction(element)) {
 842      DOH *parms, *p;
 843      int j, plen;
 844      StringAppend(result,"(");
 845      parms = SwigType_parmlist(element);
 846      plen = Len(parms);
 847      for (j = 0; j < plen; j++) {
 848	p = SwigType_str(Getitem(parms,j),0);
 849	StringAppend(result,p);
 850	Delete(p);
 851	if (j < (plen-1)) StringAppend(result,",");
 852      }
 853      StringAppend(result,")");
 854      Delete(parms);
 855    } else {
 856      String *bs = SwigType_namestr(element);
 857      Insert(result,0," ");
 858      Insert(result,0,bs);
 859      Delete(bs);
 860    }
 861    element = nextelement;
 862  }
 863  Delete(elements);
 864  if (clear) {
 865    cast = NewStringEmpty();
 866  } else {
 867    cast = NewStringf("(%s)",result);
 868  }
 869  if (name) {
 870    if (isreference) {
 871      if (isarray) Clear(cast);
 872      StringAppend(cast,"*");
 873    }
 874    StringAppend(cast,name);
 875  }
 876  Delete(result);
 877  Delete(tc);
 878  return cast;
 879}
 880
 881
 882/* -----------------------------------------------------------------------------
 883 * SwigType_lcaststr()
 884 *
 885 * Casts a variable from the real type to the local datatype.
 886 * ----------------------------------------------------------------------------- */
 887
 888String *SwigType_lcaststr(SwigType *s, const String_or_char *name) {
 889  String *result;
 890
 891  result = NewStringEmpty();
 892
 893  if (SwigType_isarray(s)) {
 894    String *lstr = SwigType_lstr(s,0);
 895    Printf(result,"(%s)%s", lstr,name);
 896    Delete(lstr);
 897  } else if (SwigType_isreference(s)) {
 898    String *str = SwigType_str(s,0);
 899    Printf(result,"(%s)", str);
 900    Delete(str);
 901    if (name) 
 902      StringAppend(result,name);
 903  } else if (SwigType_isqualifier(s)) {
 904    String *lstr = SwigType_lstr(s,0);
 905    Printf(result,"(%s)%s", lstr,name);
 906    Delete(lstr);
 907  } else {
 908    if (name)
 909      StringAppend(result,name);
 910  }
 911  return result;
 912}
 913
 914
 915/* keep old mangling since Java codes need it */
 916String *SwigType_manglestr_default(SwigType *s) {
 917  char *c;
 918  String *result = 0;
 919  String *base = 0;
 920  SwigType *lt;
 921  SwigType *sr = SwigType_typedef_qualified(s);
 922  SwigType *ss = SwigType_typedef_resolve_all(sr);
 923  
 924  s = ss;
 925
 926  if (SwigType_istemplate(ss)) {
 927    SwigType *ty = Swig_symbol_template_deftype(ss,0);
 928    Delete(ss);
 929    ss = ty;
 930    s = ss;
 931  }
 932  Delete(sr);
 933
 934  lt = SwigType_ltype(s);
 935  result = SwigType_prefix(lt);
 936  base = SwigType_base(lt);
 937
 938  c = Char(result);
 939  while (*c) {
 940    if (!isalnum((int)*c)) *c = '_';
 941    c++;
 942  }
 943  if (SwigType_istemplate(base)) {
 944    String *b = SwigType_namestr(base);
 945    Delete(base);
 946    base = b;
 947  }
 948
 949  Replace(base,"struct ","", DOH_REPLACE_ANY);     /* This might be problematic */
 950  Replace(base,"class ","", DOH_REPLACE_ANY);
 951  Replace(base,"union ","", DOH_REPLACE_ANY);
 952  Replace(base,"enum ","", DOH_REPLACE_ANY);
 953
 954  c = Char(base);
 955  while (*c) {
 956    if (*c == '<') *c = 'T';
 957    else if (*c == '>') *c = 't';
 958    else if (*c == '*') *c = 'p';
 959    else if (*c == '[') *c = 'a';
 960    else if (*c == ']') *c = 'A';
 961    else if (*c == '&') *c = 'R';
 962    else if (*c == '(') *c = 'f';
 963    else if (*c == ')') *c = 'F';
 964    else if (!isalnum((int)*c)) *c = '_';
 965    c++;
 966  }
 967  StringAppend(result,base);
 968  Insert(result,0,"_");
 969  Delete(lt);
 970  Delete(base);
 971  if (ss) Delete(ss);
 972  return result;
 973}
 974
 975String *SwigType_manglestr(SwigType *s) {
 976  return SwigType_manglestr_default(s);
 977}
 978
 979/* -----------------------------------------------------------------------------
 980 * SwigType_typename_replace()
 981 *
 982 * Replaces a typename in a type with something else.  Needed for templates.
 983 * ----------------------------------------------------------------------------- */
 984
 985void
 986SwigType_typename_replace(SwigType *t, String *pat, String *rep) {
 987  String *nt;
 988  int    i, ilen;
 989  List   *elem;
 990
 991  if (!Strstr(t,pat)) return;
 992
 993  if (StringEqual(t,pat)) {
 994    Replace(t,pat,rep,DOH_REPLACE_ANY);
 995    return;
 996  }
 997  nt = NewStringEmpty();
 998  elem = SwigType_split(t);
 999  ilen = Len(elem);
1000  for (i = 0; i < ilen; i++) {
1001    String *e = Getitem(elem,i);
1002    if (SwigType_issimple(e)) {
1003      if (StringEqual(e,pat)) {
1004	/* Replaces a type of the form 'pat' with 'rep<args>' */
1005	Replace(e,pat,rep,DOH_REPLACE_ANY);
1006      } else if (SwigType_istemplate(e)) {
1007         /* Replaces a type of the form 'pat<args>' with 'rep' */
1008	if (StringEqual(e,pat)) {
1009	  String *repbase = SwigType_templateprefix(rep);
1010	  Replace(e,pat,repbase,DOH_REPLACE_ID | DOH_REPLACE_FIRST);
1011	  Delete(repbase);
1012	} 
1013	{
1014	  String *tsuffix;
1015	  List *tparms = SwigType_parmlist(e);
1016	  int j, jlen;
1017	  String *nt = SwigType_templateprefix(e);
1018	  StringAppend(nt,"<(");
1019	  jlen = Len(tparms);
1020	  for (j = 0; j < jlen; j++) {
1021	    SwigType_typename_replace(Getitem(tparms,j), pat, rep);
1022	    StringAppend(nt,Getitem(tparms,j));
1023	    if (j < (jlen-1)) Putc(',',nt);
1024	  }
1025	  tsuffix = SwigType_templatesuffix(e);
1026	  Printf(nt,")>%s", tsuffix);
1027	  Delete(tsuffix);
1028	  Clear(e);
1029	  StringAppend(e,nt);
1030	  Delete(nt);
1031	  Delete(tparms);
1032	}
1033      } else if (Swig_scopename_check(e)) {
1034	String *first, *rest;
1035	first = Swig_scopename_first(e);
1036	rest = Swig_scopename_suffix(e);
1037	SwigType_typename_replace(rest,pat,rep);
1038	SwigType_typename_replace(first,pat,rep);
1039	Clear(e);
1040	Printv(e,first,"::",rest,NIL);
1041	Delete(first);
1042	Delete(rest);
1043      }
1044    } else if (SwigType_isfunction(e)) {
1045      int j, jlen;
1046      List *fparms = SwigType_parmlist(e);
1047      Clear(e);
1048      StringAppend(e,"f(");
1049      jlen = Len(fparms);
1050      for (j = 0; j < jlen; j++) {
1051	SwigType_typename_replace(Getitem(fparms,j), pat, rep);
1052	StringAppend(e,Getitem(fparms,j));
1053	if (j < (jlen-1)) Putc(',',e);
1054      }
1055      StringAppend(e,").");
1056      Delete(fparms);
1057    } else if (SwigType_isarray(e)) {
1058      Replace(e,pat,rep, DOH_REPLACE_ID);
1059    }
1060    StringAppend(nt,e);
1061  }
1062  Clear(t);
1063  StringAppend(t,nt);
1064  Delete(nt);
1065  Delete(elem);
1066}
1067
1068/* -----------------------------------------------------------------------------
1069 * SwigType_check_decl()
1070 *
1071 * Checks type declarators for a match
1072 * ----------------------------------------------------------------------------- */
1073
1074int
1075SwigType_check_decl(SwigType *ty, const SwigType *decl) {
1076  SwigType *t,*t1,*t2;
1077  int r;
1078  t = SwigType_typedef_resolve_all(ty);
1079  t1 = SwigType_strip_qualifiers(t);
1080  t2 = SwigType_prefix(t1);
1081  r = Equal(t2,decl);
1082  Delete(t);
1083  Delete(t1);
1084  Delete(t2);
1085  return r == 1;
1086}