PageRenderTime 128ms CodeModel.GetById 48ms app.highlight 74ms RepoModel.GetById 0ms app.codeStats 0ms

/tags/rel-1-3-25/SWIG/Source/Swig/stype.c

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