PageRenderTime 61ms CodeModel.GetById 14ms app.highlight 39ms RepoModel.GetById 1ms app.codeStats 0ms

/trunk/Source/Swig/typeobj.c

#
C | 1212 lines | 725 code | 116 blank | 371 comment | 229 complexity | 915282a5ab291efab7de4d8817db1bd6 MD5 | raw file
   1/* -----------------------------------------------------------------------------
   2 * This file is part of SWIG, which is licensed as a whole under version 3 
   3 * (or any later version) of the GNU General Public License. Some additional
   4 * terms also apply to certain portions of SWIG. The full details of the SWIG
   5 * license and copyrights can be found in the LICENSE and COPYRIGHT files
   6 * included with the SWIG source code as distributed by the SWIG developers
   7 * and at http://www.swig.org/legal.html.
   8 *
   9 * typeobj.c
  10 *
  11 * This file provides functions for constructing, manipulating, and testing
  12 * type objects.   Type objects are merely the raw low-level representation
  13 * of C++ types.   They do not incorporate high-level type system features
  14 * like typedef, namespaces, etc.
  15 * ----------------------------------------------------------------------------- */
  16
  17char cvsroot_typeobj_c[] = "$Id: typeobj.c 12747 2011-06-20 17:46:38Z wsfulton $";
  18
  19#include "swig.h"
  20#include <ctype.h>
  21
  22/* -----------------------------------------------------------------------------
  23 * Synopsis
  24 *
  25 * This file provides a collection of low-level functions for constructing and
  26 * manipulating C++ data types.   In SWIG, C++ datatypes are encoded as simple
  27 * text strings.  This representation is compact, easy to debug, and easy to read.
  28 *
  29 * General idea:
  30 *
  31 * Types are represented by a base type (e.g., "int") and a collection of
  32 * type operators applied to the base (e.g., pointers, arrays, etc...).
  33 *
  34 * Encoding:
  35 *
  36 * Types are encoded as strings of type constructors such as follows:
  37 *
  38 *        String Encoding                 C Example
  39 *        ---------------                 ---------
  40 *        p.p.int                         int **
  41 *        a(300).a(400).int               int [300][400]
  42 *        p.q(const).char                 char const *
  43 *
  44 * All type constructors are denoted by a trailing '.':
  45 * 
  46 *  'p.'                = Pointer (*)
  47 *  'r.'                = Reference (&)
  48 *  'a(n).'             = Array of size n  [n]
  49 *  'f(..,..).'         = Function with arguments  (args)
  50 *  'q(str).'           = Qualifier (such as const or volatile) (const, volatile)
  51 *  'm(qual).'          = Pointer to member (qual::*)
  52 *
  53 *  The complete type representation for varargs is:
  54 *  'v(...)'
  55 *
  56 * The encoding follows the order that you might describe a type in words.
  57 * For example "p.a(200).int" is "A pointer to array of int's" and
  58 * "p.q(const).char" is "a pointer to a const char".
  59 *
  60 * This representation of types is fairly convenient because ordinary string
  61 * operations can be used for type manipulation. For example, a type could be
  62 * formed by combining two strings such as the following:
  63 *
  64 *        "p.p." + "a(400).int" = "p.p.a(400).int"
  65 *
  66 * For C++, typenames may be parameterized using <(...)>.  Here are some
  67 * examples:
  68 *
  69 *       String Encoding                  C++ Example
  70 *       ---------------                  ------------
  71 *       p.vector<(int)>                  vector<int> *
  72 *       r.foo<(int,p.double)>            foo<int,double *> &
  73 *
  74 * Contents of this file:
  75 *
  76 * Most of this functions in this file pertain to the low-level manipulation
  77 * of type objects.   There are constructor functions like this:
  78 *
  79 *       SwigType_add_pointer()
  80 *       SwigType_add_reference()
  81 *       SwigType_add_array()
  82 *
  83 * These are used to build new types.  There are also functions to undo these
  84 * operations.  For example:
  85 *
  86 *       SwigType_del_pointer()
  87 *       SwigType_del_reference()
  88 *       SwigType_del_array()
  89 *
  90 * In addition, there are query functions
  91 *
  92 *       SwigType_ispointer()
  93 *       SwigType_isreference()
  94 *       SwigType_isarray()
  95 *
  96 * Finally, there are some data extraction functions that can be used to
  97 * extract array dimensions, template arguments, and so forth.
  98 * 
  99 * It is very important for developers to realize that the functions in this
 100 * module do *NOT* incorporate higher-level type system features like typedef.
 101 * For example, you could have C code like this:
 102 *
 103 *        typedef  int  *intptr;
 104 *       
 105 * In this case, a SwigType of type 'intptr' will be treated as a simple type and
 106 * functions like SwigType_ispointer() will evaluate as false.  It is strongly
 107 * advised that developers use the TypeSys_* interface to check types in a more
 108 * reliable manner.
 109 * ----------------------------------------------------------------------------- */
 110
 111
 112/* -----------------------------------------------------------------------------
 113 * NewSwigType()
 114 *
 115 * Constructs a new type object.   Eventually, it would be nice for this function
 116 * to accept an initial value in the form a C/C++ abstract type (currently unimplemented).
 117 * ----------------------------------------------------------------------------- */
 118
 119#ifdef NEW
 120SwigType *NewSwigType(const_String_or_char_ptr initial) {
 121  return NewString(initial);
 122}
 123
 124#endif
 125
 126/* The next few functions are utility functions used in the construction and 
 127   management of types */
 128
 129/* -----------------------------------------------------------------------------
 130 * static element_size()
 131 *
 132 * This utility function finds the size of a single type element in a type string.
 133 * Type elements are always delimited by periods, but may be nested with
 134 * parentheses.  A nested element is always handled as a single item.
 135 *
 136 * Returns the integer size of the element (which can be used to extract a 
 137 * substring, to chop the element off, or for other purposes).
 138 * ----------------------------------------------------------------------------- */
 139
 140static int element_size(char *c) {
 141  int nparen;
 142  char *s = c;
 143  while (*c) {
 144    if (*c == '.') {
 145      c++;
 146      return (int) (c - s);
 147    } else if (*c == '(') {
 148      nparen = 1;
 149      c++;
 150      while (*c) {
 151	if (*c == '(')
 152	  nparen++;
 153	if (*c == ')') {
 154	  nparen--;
 155	  if (nparen == 0)
 156	    break;
 157	}
 158	c++;
 159      }
 160    }
 161    if (*c)
 162      c++;
 163  }
 164  return (int) (c - s);
 165}
 166
 167/* -----------------------------------------------------------------------------
 168 * SwigType_del_element()
 169 *
 170 * Deletes one type element from the type.  
 171 * ----------------------------------------------------------------------------- */
 172
 173SwigType *SwigType_del_element(SwigType *t) {
 174  int sz = element_size(Char(t));
 175  Delslice(t, 0, sz);
 176  return t;
 177}
 178
 179/* -----------------------------------------------------------------------------
 180 * SwigType_pop()
 181 * 
 182 * Pop one type element off the type.
 183 * Example: t in:  q(const).p.Integer
 184 *          t out: p.Integer
 185 *	   result: q(const).
 186 * ----------------------------------------------------------------------------- */
 187
 188SwigType *SwigType_pop(SwigType *t) {
 189  SwigType *result;
 190  char *c;
 191  int sz;
 192
 193  c = Char(t);
 194  if (!*c)
 195    return 0;
 196
 197  sz = element_size(c);
 198  result = NewStringWithSize(c, sz);
 199  Delslice(t, 0, sz);
 200  c = Char(t);
 201  if (*c == '.') {
 202    Delitem(t, 0);
 203  }
 204  return result;
 205}
 206
 207/* -----------------------------------------------------------------------------
 208 * SwigType_parm()
 209 *
 210 * Returns the parameter of an operator as a string
 211 * ----------------------------------------------------------------------------- */
 212
 213String *SwigType_parm(const SwigType *t) {
 214  char *start, *c;
 215  int nparens = 0;
 216
 217  c = Char(t);
 218  while (*c && (*c != '(') && (*c != '.'))
 219    c++;
 220  if (!*c || (*c == '.'))
 221    return 0;
 222  c++;
 223  start = c;
 224  while (*c) {
 225    if (*c == ')') {
 226      if (nparens == 0)
 227	break;
 228      nparens--;
 229    } else if (*c == '(') {
 230      nparens++;
 231    }
 232    c++;
 233  }
 234  return NewStringWithSize(start, (int) (c - start));
 235}
 236
 237/* -----------------------------------------------------------------------------
 238 * SwigType_split()
 239 *
 240 * Splits a type into it's component parts and returns a list of string.
 241 * ----------------------------------------------------------------------------- */
 242
 243List *SwigType_split(const SwigType *t) {
 244  String *item;
 245  List *list;
 246  char *c;
 247  int len;
 248
 249  c = Char(t);
 250  list = NewList();
 251  while (*c) {
 252    len = element_size(c);
 253    item = NewStringWithSize(c, len);
 254    Append(list, item);
 255    Delete(item);
 256    c = c + len;
 257    if (*c == '.')
 258      c++;
 259  }
 260  return list;
 261}
 262
 263/* -----------------------------------------------------------------------------
 264 * SwigType_parmlist()
 265 *
 266 * Splits a comma separated list of parameters into its component parts
 267 * The input is expected to contain the parameter list within () brackets
 268 * Returns 0 if no argument list in the input, ie there are no round brackets ()
 269 * Returns an empty List if there are no parameters in the () brackets
 270 * For example:
 271 *
 272 *     Foo(std::string,p.f().Bar<(int,double)>)
 273 *
 274 * returns 2 elements in the list:
 275 *    std::string
 276 *    p.f().Bar<(int,double)>
 277 * ----------------------------------------------------------------------------- */
 278 
 279List *SwigType_parmlist(const String *p) {
 280  String *item = 0;
 281  List *list;
 282  char *c;
 283  char *itemstart;
 284  int size;
 285
 286  assert(p);
 287  c = Char(p);
 288  while (*c && (*c != '(') && (*c != '.'))
 289    c++;
 290  if (!*c)
 291    return 0;
 292  assert(*c != '.'); /* p is expected to contain sub elements of a type */
 293  c++;
 294  list = NewList();
 295  itemstart = c;
 296  while (*c) {
 297    if (*c == ',') {
 298      size = (int) (c - itemstart);
 299      item = NewStringWithSize(itemstart, size);
 300      Append(list, item);
 301      Delete(item);
 302      itemstart = c + 1;
 303    } else if (*c == '(') {
 304      int nparens = 1;
 305      c++;
 306      while (*c) {
 307	if (*c == '(')
 308	  nparens++;
 309	if (*c == ')') {
 310	  nparens--;
 311	  if (nparens == 0)
 312	    break;
 313	}
 314	c++;
 315      }
 316    } else if (*c == ')') {
 317      break;
 318    }
 319    if (*c)
 320      c++;
 321  }
 322  size = (int) (c - itemstart);
 323  if (size > 0) {
 324    item = NewStringWithSize(itemstart, size);
 325    Append(list, item);
 326  }
 327  Delete(item);
 328  return list;
 329}
 330
 331/* -----------------------------------------------------------------------------
 332 *                                 Pointers
 333 *
 334 * SwigType_add_pointer()
 335 * SwigType_del_pointer()
 336 * SwigType_ispointer()
 337 *
 338 * Add, remove, and test if a type is a pointer.  The deletion and query
 339 * functions take into account qualifiers (if any).
 340 * ----------------------------------------------------------------------------- */
 341
 342SwigType *SwigType_add_pointer(SwigType *t) {
 343  Insert(t, 0, "p.");
 344  return t;
 345}
 346
 347SwigType *SwigType_del_pointer(SwigType *t) {
 348  char *c, *s;
 349  c = Char(t);
 350  s = c;
 351  /* Skip qualifiers, if any */
 352  if (strncmp(c, "q(", 2) == 0) {
 353    c = strchr(c, '.');
 354    assert(c);
 355    c++;
 356  }
 357  if (strncmp(c, "p.", 2)) {
 358    printf("Fatal error. SwigType_del_pointer applied to non-pointer.\n");
 359    abort();
 360  }
 361  Delslice(t, 0, (c - s) + 2);
 362  return t;
 363}
 364
 365int SwigType_ispointer(const SwigType *t) {
 366  char *c;
 367  if (!t)
 368    return 0;
 369  c = Char(t);
 370  /* Skip qualifiers, if any */
 371  if (strncmp(c, "q(", 2) == 0) {
 372    c = strchr(c, '.');
 373    if (!c)
 374      return 0;
 375    c++;
 376  }
 377  if (strncmp(c, "p.", 2) == 0) {
 378    return 1;
 379  }
 380  return 0;
 381}
 382
 383/* -----------------------------------------------------------------------------
 384 *                                 References
 385 *
 386 * SwigType_add_reference()
 387 * SwigType_del_reference()
 388 * SwigType_isreference()
 389 *
 390 * Add, remove, and test if a type is a reference.  The deletion and query
 391 * functions take into account qualifiers (if any).
 392 * ----------------------------------------------------------------------------- */
 393
 394SwigType *SwigType_add_reference(SwigType *t) {
 395  Insert(t, 0, "r.");
 396  return t;
 397}
 398
 399SwigType *SwigType_del_reference(SwigType *t) {
 400  char *c = Char(t);
 401  int check = strncmp(c, "r.", 2);
 402  assert(check == 0);
 403  Delslice(t, 0, 2);
 404  return t;
 405}
 406
 407int SwigType_isreference(const SwigType *t) {
 408  char *c;
 409  if (!t)
 410    return 0;
 411  c = Char(t);
 412  if (strncmp(c, "r.", 2) == 0) {
 413    return 1;
 414  }
 415  return 0;
 416}
 417
 418/* -----------------------------------------------------------------------------
 419 *                                  Qualifiers
 420 *
 421 * SwigType_add_qualifier()
 422 * SwigType_del_qualifier()
 423 * SwigType_is_qualifier()
 424 *
 425 * Adds type qualifiers like "const" and "volatile".   When multiple qualifiers
 426 * are added to a type, they are combined together into a single qualifier.
 427 * Repeated qualifications have no effect.  Moreover, the order of qualifications
 428 * is alphabetical---meaning that "const volatile" and "volatile const" are
 429 * stored in exactly the same way as "q(const volatile)".
 430 * ----------------------------------------------------------------------------- */
 431
 432SwigType *SwigType_add_qualifier(SwigType *t, const_String_or_char_ptr qual) {
 433  char temp[256], newq[256];
 434  int sz, added = 0;
 435  char *q, *cqual;
 436
 437  char *c = Char(t);
 438  cqual = Char(qual);
 439
 440  if (!(strncmp(c, "q(", 2) == 0)) {
 441    sprintf(temp, "q(%s).", cqual);
 442    Insert(t, 0, temp);
 443    return t;
 444  }
 445
 446  /* The type already has a qualifier on it.  In this case, we first check to
 447     see if the qualifier is already specified.  In that case do nothing.
 448     If it is a new qualifier, we add it to the qualifier list in alphabetical
 449     order */
 450
 451  sz = element_size(c);
 452  strncpy(temp, c, (sz < 256) ? sz : 256);
 453
 454  if (strstr(temp, cqual)) {
 455    /* Qualifier already added */
 456    return t;
 457  }
 458
 459  /* Add the qualifier to the existing list. */
 460
 461  strcpy(newq, "q(");
 462  q = temp + 2;
 463  q = strtok(q, " ).");
 464  while (q) {
 465    if (strcmp(cqual, q) < 0) {
 466      /* New qualifier is less that current qualifier.  We need to insert it */
 467      strcat(newq, cqual);
 468      strcat(newq, " ");
 469      strcat(newq, q);
 470      added = 1;
 471    } else {
 472      strcat(newq, q);
 473    }
 474    q = strtok(NULL, " ).");
 475    if (q) {
 476      strcat(newq, " ");
 477    }
 478  }
 479  if (!added) {
 480    strcat(newq, " ");
 481    strcat(newq, cqual);
 482  }
 483  strcat(newq, ").");
 484  Delslice(t, 0, sz);
 485  Insert(t, 0, newq);
 486  return t;
 487}
 488
 489SwigType *SwigType_del_qualifier(SwigType *t) {
 490  char *c = Char(t);
 491  int check = strncmp(c, "q(", 2);
 492  assert(check == 0);
 493  Delslice(t, 0, element_size(c));
 494  return t;
 495}
 496
 497int SwigType_isqualifier(const SwigType *t) {
 498  char *c;
 499  if (!t)
 500    return 0;
 501  c = Char(t);
 502  if (strncmp(c, "q(", 2) == 0) {
 503    return 1;
 504  }
 505  return 0;
 506}
 507
 508/* -----------------------------------------------------------------------------
 509 *                                Function Pointers
 510 * ----------------------------------------------------------------------------- */
 511
 512int SwigType_isfunctionpointer(const SwigType *t) {
 513  char *c;
 514  if (!t)
 515    return 0;
 516  c = Char(t);
 517  if (strncmp(c, "p.f(", 4) == 0) {
 518    return 1;
 519  }
 520  return 0;
 521}
 522
 523/* -----------------------------------------------------------------------------
 524 * SwigType_functionpointer_decompose
 525 *
 526 * Decompose the function pointer into the parameter list and the return type
 527 * t - input and on completion contains the return type
 528 * returns the function's parameters
 529 * ----------------------------------------------------------------------------- */
 530
 531SwigType *SwigType_functionpointer_decompose(SwigType *t) {
 532  String *p;
 533  assert(SwigType_isfunctionpointer(t));
 534  p = SwigType_pop(t);
 535  Delete(p);
 536  p = SwigType_pop(t);
 537  return p;
 538}
 539
 540/* -----------------------------------------------------------------------------
 541 *                                Member Pointers
 542 *
 543 * SwigType_add_memberpointer()
 544 * SwigType_del_memberpointer()
 545 * SwigType_ismemberpointer()
 546 *
 547 * Add, remove, and test for C++ pointer to members.
 548 * ----------------------------------------------------------------------------- */
 549
 550SwigType *SwigType_add_memberpointer(SwigType *t, const_String_or_char_ptr name) {
 551  String *temp = NewStringf("m(%s).", name);
 552  Insert(t, 0, temp);
 553  Delete(temp);
 554  return t;
 555}
 556
 557SwigType *SwigType_del_memberpointer(SwigType *t) {
 558  char *c = Char(t);
 559  int check = strncmp(c, "m(", 2);
 560  assert(check == 0);
 561  Delslice(t, 0, element_size(c));
 562  return t;
 563}
 564
 565int SwigType_ismemberpointer(const SwigType *t) {
 566  char *c;
 567  if (!t)
 568    return 0;
 569  c = Char(t);
 570  if (strncmp(c, "m(", 2) == 0) {
 571    return 1;
 572  }
 573  return 0;
 574}
 575
 576/* -----------------------------------------------------------------------------
 577 *                                    Arrays
 578 *
 579 * SwigType_add_array()
 580 * SwigType_del_array()
 581 * SwigType_isarray()
 582 *
 583 * Utility functions:
 584 *
 585 * SwigType_array_ndim()        - Calculate number of array dimensions.
 586 * SwigType_array_getdim()      - Get array dimension
 587 * SwigType_array_setdim()      - Set array dimension
 588 * SwigType_array_type()        - Return array type
 589 * SwigType_pop_arrays()        - Remove all arrays
 590 * ----------------------------------------------------------------------------- */
 591
 592SwigType *SwigType_add_array(SwigType *t, const_String_or_char_ptr size) {
 593  char temp[512];
 594  strcpy(temp, "a(");
 595  strcat(temp, Char(size));
 596  strcat(temp, ").");
 597  Insert(t, 0, temp);
 598  return t;
 599}
 600
 601SwigType *SwigType_del_array(SwigType *t) {
 602  char *c = Char(t);
 603  int check = strncmp(c, "a(", 2);
 604  assert(check == 0);
 605  Delslice(t, 0, element_size(c));
 606  return t;
 607}
 608
 609int SwigType_isarray(const SwigType *t) {
 610  char *c;
 611  if (!t)
 612    return 0;
 613  c = Char(t);
 614  if (strncmp(c, "a(", 2) == 0) {
 615    return 1;
 616  }
 617  return 0;
 618}
 619/*
 620 * SwigType_prefix_is_simple_1D_array
 621 *
 622 * Determine if the type is a 1D array type that is treated as a pointer within SWIG
 623 * eg Foo[], Foo[3] return true, but Foo[3][3], Foo*[], Foo*[3], Foo**[] return false
 624 */
 625int SwigType_prefix_is_simple_1D_array(const SwigType *t) {
 626  char *c = Char(t);
 627
 628  if (c && (strncmp(c, "a(", 2) == 0)) {
 629    c = strchr(c, '.');
 630    c++;
 631    return (*c == 0);
 632  }
 633  return 0;
 634}
 635
 636
 637/* Remove all arrays */
 638SwigType *SwigType_pop_arrays(SwigType *t) {
 639  String *ta;
 640  assert(SwigType_isarray(t));
 641  ta = NewStringEmpty();
 642  while (SwigType_isarray(t)) {
 643    SwigType *td = SwigType_pop(t);
 644    Append(ta, td);
 645    Delete(td);
 646  }
 647  return ta;
 648}
 649
 650/* Return number of array dimensions */
 651int SwigType_array_ndim(const SwigType *t) {
 652  int ndim = 0;
 653  char *c = Char(t);
 654
 655  while (c && (strncmp(c, "a(", 2) == 0)) {
 656    c = strchr(c, '.');
 657    c++;
 658    ndim++;
 659  }
 660  return ndim;
 661}
 662
 663/* Get nth array dimension */
 664String *SwigType_array_getdim(const SwigType *t, int n) {
 665  char *c = Char(t);
 666  while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
 667    c = strchr(c, '.');
 668    c++;
 669    n--;
 670  }
 671  if (n == 0) {
 672    String *dim = SwigType_parm(c);
 673    if (SwigType_istemplate(dim)) {
 674      String *ndim = SwigType_namestr(dim);
 675      Delete(dim);
 676      dim = ndim;
 677    }
 678
 679    return dim;
 680  }
 681
 682  return 0;
 683}
 684
 685/* Replace nth array dimension */
 686void SwigType_array_setdim(SwigType *t, int n, const_String_or_char_ptr rep) {
 687  String *result = 0;
 688  char temp;
 689  char *start;
 690  char *c = Char(t);
 691
 692  start = c;
 693  if (strncmp(c, "a(", 2))
 694    abort();
 695
 696  while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
 697    c = strchr(c, '.');
 698    c++;
 699    n--;
 700  }
 701  if (n == 0) {
 702    temp = *c;
 703    *c = 0;
 704    result = NewString(start);
 705    Printf(result, "a(%s)", rep);
 706    *c = temp;
 707    c = strchr(c, '.');
 708    Append(result, c);
 709  }
 710  Clear(t);
 711  Append(t, result);
 712  Delete(result);
 713}
 714
 715/* Return base type of an array */
 716SwigType *SwigType_array_type(const SwigType *ty) {
 717  SwigType *t;
 718  t = Copy(ty);
 719  while (SwigType_isarray(t)) {
 720    Delete(SwigType_pop(t));
 721  }
 722  return t;
 723}
 724
 725
 726/* -----------------------------------------------------------------------------
 727 *                                    Functions
 728 *
 729 * SwigType_add_function()
 730 * SwigType_del_function()
 731 * SwigType_isfunction()
 732 * SwigType_pop_function()
 733 *
 734 * Add, remove, and test for function types.
 735 * ----------------------------------------------------------------------------- */
 736
 737/* Returns the function type, t, constructed from the parameters, parms */
 738SwigType *SwigType_add_function(SwigType *t, ParmList *parms) {
 739  String *pstr;
 740  Parm *p;
 741
 742  Insert(t, 0, ").");
 743  pstr = NewString("f(");
 744  p = parms;
 745  for (p = parms; p; p = nextSibling(p)) {
 746    if (p != parms)
 747      Putc(',', pstr);
 748    Append(pstr, Getattr(p, "type"));
 749  }
 750  Insert(t, 0, pstr);
 751  Delete(pstr);
 752  return t;
 753}
 754
 755SwigType *SwigType_pop_function(SwigType *t) {
 756  SwigType *f = 0;
 757  SwigType *g = 0;
 758  char *c = Char(t);
 759  if (strncmp(c, "q(", 2) == 0) {
 760    f = SwigType_pop(t);
 761    c = Char(t);
 762  }
 763  if (strncmp(c, "f(", 2)) {
 764    printf("Fatal error. SwigType_pop_function applied to non-function.\n");
 765    abort();
 766  }
 767  g = SwigType_pop(t);
 768  if (f)
 769    SwigType_push(g, f);
 770  Delete(f);
 771  return g;
 772}
 773
 774int SwigType_isfunction(const SwigType *t) {
 775  char *c;
 776  if (!t) {
 777    return 0;
 778  }
 779  c = Char(t);
 780  if (strncmp(c, "q(", 2) == 0) {
 781    /* Might be a 'const' function.  Try to skip over the 'const' */
 782    c = strchr(c, '.');
 783    if (c)
 784      c++;
 785    else
 786      return 0;
 787  }
 788  if (strncmp(c, "f(", 2) == 0) {
 789    return 1;
 790  }
 791  return 0;
 792}
 793
 794/* Create a list of parameters from the type t, using the file_line_node Node for 
 795 * file and line numbering for the parameters */
 796ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node) {
 797  List *l = SwigType_parmlist(t);
 798  Hash *p, *pp = 0, *firstp = 0;
 799  Iterator o;
 800
 801  for (o = First(l); o.item; o = Next(o)) {
 802    p = file_line_node ? NewParm(o.item, 0, file_line_node) : NewParmWithoutFileLineInfo(o.item, 0);
 803    if (!firstp)
 804      firstp = p;
 805    if (pp) {
 806      set_nextSibling(pp, p);
 807      Delete(p);
 808    }
 809    pp = p;
 810  }
 811  Delete(l);
 812  return firstp;
 813}
 814
 815int SwigType_isvarargs(const SwigType *t) {
 816  if (Strcmp(t, "v(...)") == 0)
 817    return 1;
 818  return 0;
 819}
 820
 821/* -----------------------------------------------------------------------------
 822 *                                    Templates
 823 *
 824 * SwigType_add_template()
 825 *
 826 * Template handling.
 827 * ----------------------------------------------------------------------------- */
 828
 829/* -----------------------------------------------------------------------------
 830 * SwigType_add_template()
 831 *
 832 * Adds a template to a type.   This template is encoded in the SWIG type
 833 * mechanism and produces a string like this:
 834 *
 835 *  vector<int *> ----> "vector<(p.int)>"
 836 * ----------------------------------------------------------------------------- */
 837
 838SwigType *SwigType_add_template(SwigType *t, ParmList *parms) {
 839  Parm *p;
 840
 841  Append(t, "<(");
 842  p = parms;
 843  for (p = parms; p; p = nextSibling(p)) {
 844    String *v;
 845    if (Getattr(p, "default"))
 846      continue;
 847    if (p != parms)
 848      Append(t, ",");
 849    v = Getattr(p, "value");
 850    if (v) {
 851      Append(t, v);
 852    } else {
 853      Append(t, Getattr(p, "type"));
 854    }
 855  }
 856  Append(t, ")>");
 857  return t;
 858}
 859
 860
 861/* -----------------------------------------------------------------------------
 862 * SwigType_templateprefix()
 863 *
 864 * Returns the prefix before the first template definition.
 865 * Returns the type unmodified if not a template.
 866 * For example:
 867 *
 868 *     Foo<(p.int)>::bar  =>  Foo
 869 *     r.q(const).Foo<(p.int)>::bar => r.q(const).Foo
 870 *     Foo => Foo
 871 * ----------------------------------------------------------------------------- */
 872
 873String *SwigType_templateprefix(const SwigType *t) {
 874  const char *s = Char(t);
 875  const char *c = strstr(s, "<(");
 876  return c ? NewStringWithSize(s, c - s) : NewString(s);
 877}
 878
 879/* -----------------------------------------------------------------------------
 880 * SwigType_templatesuffix()
 881 *
 882 * Returns text after a template substitution.  Used to handle scope names
 883 * for example:
 884 *
 885 *        Foo<(p.int)>::bar
 886 *
 887 * returns "::bar"
 888 * ----------------------------------------------------------------------------- */
 889
 890String *SwigType_templatesuffix(const SwigType *t) {
 891  const char *c;
 892  c = Char(t);
 893  while (*c) {
 894    if ((*c == '<') && (*(c + 1) == '(')) {
 895      int nest = 1;
 896      c++;
 897      while (*c && nest) {
 898	if (*c == '<')
 899	  nest++;
 900	if (*c == '>')
 901	  nest--;
 902	c++;
 903      }
 904      return NewString(c);
 905    }
 906    c++;
 907  }
 908  return NewStringEmpty();
 909}
 910
 911/* -----------------------------------------------------------------------------
 912 * SwigType_istemplate_templateprefix()
 913 *
 914 * Combines SwigType_istemplate and SwigType_templateprefix efficiently into one function.
 915 * Returns the prefix before the first template definition.
 916 * Returns NULL if not a template.
 917 * For example:
 918 *
 919 *     Foo<(p.int)>::bar  =>  Foo
 920 *     r.q(const).Foo<(p.int)>::bar => r.q(const).Foo
 921 *     Foo => NULL
 922 * ----------------------------------------------------------------------------- */
 923
 924String *SwigType_istemplate_templateprefix(const SwigType *t) {
 925  const char *s = Char(t);
 926  const char *c = strstr(s, "<(");
 927  return c ? NewStringWithSize(s, c - s) : 0;
 928}
 929
 930/* -----------------------------------------------------------------------------
 931 * SwigType_istemplate_only_templateprefix()
 932 *
 933 * Similar to SwigType_istemplate_templateprefix() but only returns the template
 934 * prefix if the type is just the template and not a subtype/symbol within the template.
 935 * Returns NULL if not a template or is a template with a symbol within the template.
 936 * For example:
 937 *
 938 *     Foo<(p.int)>  =>  Foo
 939 *     Foo<(p.int)>::bar  =>  NULL
 940 *     r.q(const).Foo<(p.int)> => r.q(const).Foo
 941 *     r.q(const).Foo<(p.int)>::bar => NULL
 942 *     Foo => NULL
 943 * ----------------------------------------------------------------------------- */
 944
 945String *SwigType_istemplate_only_templateprefix(const SwigType *t) {
 946  int len = Len(t);
 947  const char *s = Char(t);
 948  if (len >= 4 && strcmp(s + len - 2, ")>") == 0) {
 949    const char *c = strstr(s, "<(");
 950    return c ? NewStringWithSize(s, c - s) : 0;
 951  } else {
 952    return 0;
 953  }
 954}
 955
 956/* -----------------------------------------------------------------------------
 957 * SwigType_templateargs()
 958 *
 959 * Returns the template arguments
 960 * For example:
 961 *
 962 *     Foo<(p.int)>::bar
 963 *
 964 * returns "<(p.int)>"
 965 * ----------------------------------------------------------------------------- */
 966
 967String *SwigType_templateargs(const SwigType *t) {
 968  const char *c;
 969  const char *start;
 970  c = Char(t);
 971  while (*c) {
 972    if ((*c == '<') && (*(c + 1) == '(')) {
 973      int nest = 1;
 974      start = c;
 975      c++;
 976      while (*c && nest) {
 977	if (*c == '<')
 978	  nest++;
 979	if (*c == '>')
 980	  nest--;
 981	c++;
 982      }
 983      return NewStringWithSize(start, c - start);
 984    }
 985    c++;
 986  }
 987  return 0;
 988}
 989
 990/* -----------------------------------------------------------------------------
 991 * SwigType_istemplate()
 992 *
 993 * Tests a type to see if it includes template parameters
 994 * ----------------------------------------------------------------------------- */
 995
 996int SwigType_istemplate(const SwigType *t) {
 997  char *ct = Char(t);
 998  ct = strstr(ct, "<(");
 999  if (ct && (strstr(ct + 2, ")>")))
1000    return 1;
1001  return 0;
1002}
1003
1004/* -----------------------------------------------------------------------------
1005 * SwigType_base()
1006 *
1007 * This function returns the base of a type.  For example, if you have a
1008 * type "p.p.int", the function would return "int".
1009 * ----------------------------------------------------------------------------- */
1010
1011SwigType *SwigType_base(const SwigType *t) {
1012  char *c;
1013  char *lastop = 0;
1014  c = Char(t);
1015
1016  lastop = c;
1017
1018  /* Search for the last type constructor separator '.' */
1019  while (*c) {
1020    if (*c == '.') {
1021      if (*(c + 1)) {
1022	lastop = c + 1;
1023      }
1024      c++;
1025      continue;
1026    }
1027    if (*c == '<') {
1028      /* Skip over template---it's part of the base name */
1029      int ntemp = 1;
1030      c++;
1031      while ((*c) && (ntemp > 0)) {
1032	if (*c == '>')
1033	  ntemp--;
1034	else if (*c == '<')
1035	  ntemp++;
1036	c++;
1037      }
1038      if (ntemp)
1039	break;
1040      continue;
1041    }
1042    if (*c == '(') {
1043      /* Skip over params */
1044      int nparen = 1;
1045      c++;
1046      while ((*c) && (nparen > 0)) {
1047	if (*c == '(')
1048	  nparen++;
1049	else if (*c == ')')
1050	  nparen--;
1051	c++;
1052      }
1053      if (nparen)
1054	break;
1055      continue;
1056    }
1057    c++;
1058  }
1059  return NewString(lastop);
1060}
1061
1062/* -----------------------------------------------------------------------------
1063 * SwigType_prefix()
1064 *
1065 * Returns the prefix of a datatype.  For example, the prefix of the
1066 * type "p.p.int" is "p.p.".
1067 * ----------------------------------------------------------------------------- */
1068
1069String *SwigType_prefix(const SwigType *t) {
1070  char *c, *d;
1071  String *r = 0;
1072
1073  c = Char(t);
1074  d = c + strlen(c);
1075
1076  /* Check for a type constructor */
1077  if ((d > c) && (*(d - 1) == '.'))
1078    d--;
1079
1080  while (d > c) {
1081    d--;
1082    if (*d == '>') {
1083      int nest = 1;
1084      d--;
1085      while ((d > c) && (nest)) {
1086	if (*d == '>')
1087	  nest++;
1088	if (*d == '<')
1089	  nest--;
1090	d--;
1091      }
1092    }
1093    if (*d == ')') {
1094      /* Skip over params */
1095      int nparen = 1;
1096      d--;
1097      while ((d > c) && (nparen)) {
1098	if (*d == ')')
1099	  nparen++;
1100	if (*d == '(')
1101	  nparen--;
1102	d--;
1103      }
1104    }
1105
1106    if (*d == '.') {
1107      char t = *(d + 1);
1108      *(d + 1) = 0;
1109      r = NewString(c);
1110      *(d + 1) = t;
1111      return r;
1112    }
1113  }
1114  return NewStringEmpty();
1115}
1116
1117/* -----------------------------------------------------------------------------
1118 * SwigType_strip_qualifiers()
1119 * 
1120 * Strip all qualifiers from a type and return a new type
1121 * ----------------------------------------------------------------------------- */
1122
1123SwigType *SwigType_strip_qualifiers(const SwigType *t) {
1124  static Hash *memoize_stripped = 0;
1125  SwigType *r;
1126  List *l;
1127  Iterator ei;
1128
1129  if (!memoize_stripped)
1130    memoize_stripped = NewHash();
1131  r = Getattr(memoize_stripped, t);
1132  if (r)
1133    return Copy(r);
1134
1135  l = SwigType_split(t);
1136  r = NewStringEmpty();
1137
1138  for (ei = First(l); ei.item; ei = Next(ei)) {
1139    if (SwigType_isqualifier(ei.item))
1140      continue;
1141    Append(r, ei.item);
1142  }
1143  Delete(l);
1144  {
1145    String *key, *value;
1146    key = Copy(t);
1147    value = Copy(r);
1148    Setattr(memoize_stripped, key, value);
1149    Delete(key);
1150    Delete(value);
1151  }
1152  return r;
1153}
1154
1155/* -----------------------------------------------------------------------------
1156 * SwigType_strip_single_qualifier()
1157 * 
1158 * If the type contains a qualifier, strip one qualifier and return a new type.
1159 * The left most qualifier is stripped first (when viewed as C source code) but
1160 * this is the equivalent to the right most qualifier using SwigType notation.
1161 * Example: 
1162 *    r.q(const).p.q(const).int => r.q(const).p.int
1163 *    r.q(const).p.int          => r.p.int
1164 *    r.p.int                   => r.p.int
1165 * ----------------------------------------------------------------------------- */
1166
1167SwigType *SwigType_strip_single_qualifier(const SwigType *t) {
1168  static Hash *memoize_stripped = 0;
1169  SwigType *r = 0;
1170  List *l;
1171  int numitems;
1172
1173  if (!memoize_stripped)
1174    memoize_stripped = NewHash();
1175  r = Getattr(memoize_stripped, t);
1176  if (r)
1177    return Copy(r);
1178
1179  l = SwigType_split(t);
1180
1181  numitems = Len(l);
1182  if (numitems >= 2) {
1183    int item;
1184    /* iterate backwards from last but one item */
1185    for (item = numitems - 2; item >= 0; --item) {
1186      String *subtype = Getitem(l, item);
1187      if (SwigType_isqualifier(subtype)) {
1188	Iterator it;
1189	Delitem(l, item);
1190	r = NewStringEmpty();
1191	for (it = First(l); it.item; it = Next(it)) {
1192	  Append(r, it.item);
1193	}
1194	break;
1195      }
1196    }
1197  }
1198  if (!r)
1199    r = Copy(t);
1200
1201  Delete(l);
1202  {
1203    String *key, *value;
1204    key = Copy(t);
1205    value = Copy(r);
1206    Setattr(memoize_stripped, key, value);
1207    Delete(key);
1208    Delete(value);
1209  }
1210  return r;
1211}
1212