PageRenderTime 146ms CodeModel.GetById 14ms app.highlight 119ms RepoModel.GetById 1ms app.codeStats 1ms

/trunk/Source/Modules/modula3.cxx

#
C++ | 1989 lines | 1329 code | 217 blank | 443 comment | 410 complexity | 77bcef6f2edb8e97a88f2d4725146fc0 MD5 | raw file

Large files files are truncated, but you can click here to view the full 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 * modula3.cxx
  10 *
  11 * Modula3 language module for SWIG.
  12 * ----------------------------------------------------------------------------- */
  13
  14char cvsroot_modula3_cxx[] = "$Id: modula3.cxx 12830 2011-10-30 21:51:50Z wsfulton $";
  15
  16/*
  17  Text formatted with
  18    indent -sob -br -ce -nut -npsl
  19*/
  20
  21/*
  22  Report:
  23   - It's not a good concept to use member variables or global variables
  24     for passing parameters to functions.
  25     It's not a good concept to use functions of superclasses for specific services.
  26     E.g. For SWIG this means: Generating accessor functions for member variables
  27     is the most common but no general task to be processed in membervariableHandler.
  28     Better provide a service function which generates accessor function code
  29     and equip this service function with all parameters needed for input (parse node)
  30     and output (generated code).
  31   - How can I make globalvariableHandler not to generate
  32     interface functions to two accessor functions
  33     (that don't exist) ?
  34   - How can I generate a typemap that turns every C reference argument into
  35     its Modula 3 counterpart, that is
  36       void test(Complex &z);
  37       PROCEDURE test(VAR z:Complex);
  38   - neither $*n_mangle nor $*n_type nor $*n_ltype return the type without
  39     pointer converted to Modula3 equivalent,
  40     $*n_mangle is the variant closest to what I expect
  41   - using a typemap like
  42         typemap(m3wrapintype) int * %{VAR $1_name: INTEGER%}
  43     has the advantages:
  44       - one C parameter can be turned into multiple M3 parameters
  45       - the argument can be renamed
  46   - using typemaps like
  47         typemap(m3wrapinmode) int * "VAR"
  48         typemap(m3wrapintype) int * "INTEGER"
  49     has the advantages:
  50       - multiple parameters with same type and default value can be bundled
  51       - more conform to the other language modules
  52   - Where takes the reduction of multi-typemaps place?
  53     How can I preserve all parameters for functions of the intermediary class?
  54     The answer is Getattrs(n,"tmap:m3rawintype:next")
  55   - Char() can be used to transform a String to (char *)
  56     which can be used for output with printf
  57   - What is the while (checkAttribute()) loop in functionWrapper good for?
  58     Appearently for skipping (numinputs=0) typemaps.
  59   - SWIGTYPE const * - typemap is ignored, whereas
  60     SWIGTYPE *       - typemap is invoked, why?
  61     Had it been (const SWIGTYPE *) instead?
  62   - enumeration items should definitely be equipped
  63     with its plain numerical value
  64     One could add tag 'numvalue' in CParse/parser.y,
  65     but it is still possible that someone declares an
  66     enumeration using a symbolic constant.
  67     I have quickly hacked
  68     that the successive number is assigned
  69     if "enumvalue" has suffix "+1".
  70     The ultimate solution would be to generate a C program
  71     which includes the header and outputs all constants.
  72     This program might be compiled and run
  73     by 'make' or by SWIG and the resulting output is fed back to SWIG.
  74   - It's a bad idea to interpret feature value ""
  75     'disable feature' because the value ""
  76     might be sensible in case of feature:modula3:oldprefix.
  77   - What's the difference between "sym:name" and "name" ?
  78     "name" is the original name and
  79     "sym:name" is probably modified by the user using %rename
  80   - Is it possible for 'configure' to find out if m3pp is installed
  81     and to invoke it for generated Modula3 files?
  82   - It would be better to separate an arguments purpose and its name,
  83     because an output variable with name "OUTPUT" is not very descriptive.
  84     In case of PLPlot this could be solved by typedefs
  85     that assign special purposes to the array types.
  86   - Can one interpret $n_basetype as the identifier matched with SWIGTYPE ?
  87
  88  SWIG's odds:
  89   - arguments of type (Node *) for SWIG functions
  90     should be most often better (const Node *):
  91     Swig_symbol_qualified, Getattr, nodeType, parentNode
  92   - unique identifier style instead of
  93     NewString, Getattr, firstChild
  94   - 'class'.name is qualified,
  95     'enum'.name and 'enumitem'.name is not
  96   - Swig_symbol_qualified() returns NIL for enumeration nodes
  97
  98   - Is there a function that creates a C representation of a SWIG type string?
  99
 100  ToDo:
 101   - create WeakRefs only for resources returned by function marked with %newobject
 102      -> part of output conversion
 103   - clean typemap conception
 104      - should a multi-typemap for m3wrapouttype skip the corresponding input parameters?
 105        when yes - How to handle inout-arguments? In this case like in-argument.
 106   - C++ classes
 107   - C++ exceptions
 108   - allow for moving RECORD and OBJECT definitions
 109     to separate files, with the main type called T
 110   - call-back functions
 111   - special option: fast access to class members by pointer arithmetic,
 112       member offsets can be determined by a C++ program that print them.
 113   - emit enumeration definitions when its first item is declared,
 114       currently enumerations are emitted at the beginning of the file
 115
 116  Done:
 117   - addThrow should convert the typemap by itself
 118      - not possible because routine for attaching mapped types to parameter nodes
 119        won't work for the function node
 120   - turning error codes into exceptions
 121      -> part of output value checking
 122   - create WeakRefs for resources allocated by the library
 123      -> part of output conversion
 124   - TRY..FINALLY..END; can be omitted
 125      - if there is no m3wrapfreearg
 126      - no exception can be raised in the body (empty RAISES) list
 127*/
 128
 129#include "swigmod.h"
 130
 131#include <limits.h>		// for INT_MAX
 132#include <ctype.h>
 133
 134#define USAGE_ARG_DIR "m3wrapargdir typemap expect values: in, out, inout\n"
 135
 136class MODULA3:public Language {
 137public:
 138  enum block_type { no_block, constant, variable, blocktype, revelation };
 139
 140private:
 141  struct M3File {
 142    String *f;
 143    Hash *import;
 144    block_type bt;
 145    /* VC++ 6 doesn't allow the access to 'no_block'
 146       if it is a private member of MODULA3 class */
 147    M3File():f(NewString("")), import(NewHash()), bt(no_block) {
 148    }
 149    ~M3File() {
 150      Delete(f);
 151      Delete(import);
 152    }
 153
 154    /* -----------------------------------------------------------------------------
 155     * enterBlock()
 156     *
 157     * Make sure that a given declaration is written to the right declaration block,
 158     * that is constants are written after "CONST" and so on ...
 159     * ----------------------------------------------------------------------------- */
 160    void enterBlock(block_type newbt) {
 161      static const char *ident[] = { "", "\nCONST\n", "\nVAR\n", "\nTYPE\n", "\nREVEAL\n" };
 162#ifdef DEBUG
 163      if ((bt < 0) || (4 < bt)) {
 164	printf("bt %d out of range\n", bt);
 165      }
 166#endif
 167      if (newbt != bt) {
 168	Append(f, ident[newbt]);
 169	bt = newbt;
 170      }
 171    }
 172
 173  };
 174
 175  static const char *usage;
 176  const String *empty_string;
 177
 178  Hash *swig_types_hash;
 179  File *f_begin;
 180  File *f_runtime;
 181  File *f_header;
 182  File *f_wrappers;
 183  File *f_init;
 184
 185  bool proxy_flag;		// Flag for generating proxy classes
 186  bool have_default_constructor_flag;
 187  bool native_function_flag;	// Flag for when wrapping a native function
 188  bool enum_constant_flag;	// Flag for when wrapping an enum or constant
 189  bool static_flag;		// Flag for when wrapping a static functions or member variables
 190  bool variable_wrapper_flag;	// Flag for when wrapping a nonstatic member variable
 191  bool wrapping_member_flag;	// Flag for when wrapping a member variable/enum/const
 192  bool global_variable_flag;	// Flag for when wrapping a global variable
 193  bool old_variable_names;	// Flag for old style variable names in the intermediary class
 194  bool unsafe_module;
 195
 196  String *m3raw_name;		// raw interface name
 197  M3File m3raw_intf;		// raw interface
 198  M3File m3raw_impl;		// raw implementation (usually empty)
 199  String *m3wrap_name;		// wrapper module
 200  M3File m3wrap_intf;
 201  M3File m3wrap_impl;
 202  String *m3makefile;
 203  String *targetlibrary;
 204  String *proxy_class_def;
 205  String *proxy_class_code;
 206  String *proxy_class_name;
 207  String *variable_name;	//Name of a variable being wrapped
 208  String *variable_type;	//Type of this variable
 209  String *enumeration_name;	//Name of the current enumeration type
 210  Hash *enumeration_items;	//and its members
 211  int enumeration_max;
 212  Hash *enumeration_coll;	//Collection of all enumerations.
 213  /* The items are nodes with members:
 214     "items"  - hash of with key 'itemname' and content 'itemvalue'
 215     "max"    - maximum value in item list
 216   */
 217  String *constant_values;
 218  String *constantfilename;
 219  String *renamefilename;
 220  String *typemapfilename;
 221  String *m3raw_imports;	//intermediary class imports from %pragma
 222  String *module_imports;	//module imports from %pragma
 223  String *m3raw_baseclass;	//inheritance for intermediary class class from %pragma
 224  String *module_baseclass;	//inheritance for module class from %pragma
 225  String *m3raw_interfaces;	//interfaces for intermediary class class from %pragma
 226  String *module_interfaces;	//interfaces for module class from %pragma
 227  String *m3raw_class_modifiers;	//class modifiers for intermediary class overriden by %pragma
 228  String *m3wrap_modifiers;	//class modifiers for module class overriden by %pragma
 229  String *upcasts_code;		//C++ casts for inheritance hierarchies C++ code
 230  String *m3raw_cppcasts_code;	//C++ casts up inheritance hierarchies intermediary class code
 231  String *destructor_call;	//C++ destructor call if any
 232  String *outfile;
 233
 234  enum type_additions { none, pointer, reference };
 235
 236public:
 237
 238  /* -----------------------------------------------------------------------------
 239   * MODULA3()
 240   * ----------------------------------------------------------------------------- */
 241
 242MODULA3():
 243  empty_string(NewString("")),
 244      swig_types_hash(NULL),
 245      f_begin(NULL),
 246      f_runtime(NULL),
 247      f_header(NULL),
 248      f_wrappers(NULL),
 249      f_init(NULL),
 250      proxy_flag(true),
 251      have_default_constructor_flag(false),
 252      native_function_flag(false),
 253      enum_constant_flag(false),
 254      static_flag(false),
 255      variable_wrapper_flag(false),
 256      wrapping_member_flag(false),
 257      global_variable_flag(false),
 258      old_variable_names(false),
 259      unsafe_module(false),
 260      m3raw_name(NULL),
 261      m3raw_intf(),
 262      m3raw_impl(),
 263      m3wrap_name(NULL),
 264      m3wrap_intf(),
 265      m3wrap_impl(),
 266      m3makefile(NULL),
 267      targetlibrary(NULL),
 268      proxy_class_def(NULL),
 269      proxy_class_code(NULL),
 270      proxy_class_name(NULL),
 271      variable_name(NULL),
 272      variable_type(NULL),
 273      enumeration_name(NULL),
 274      enumeration_items(NULL),
 275      enumeration_max(0),
 276      enumeration_coll(NULL),
 277      constant_values(NULL),
 278      constantfilename(NULL),
 279      renamefilename(NULL),
 280      typemapfilename(NULL),
 281      m3raw_imports(NULL),
 282      module_imports(NULL),
 283      m3raw_baseclass(NULL),
 284      module_baseclass(NULL),
 285      m3raw_interfaces(NULL),
 286      module_interfaces(NULL),
 287      m3raw_class_modifiers(NULL),
 288      m3wrap_modifiers(NULL),
 289      upcasts_code(NULL),
 290      m3raw_cppcasts_code(NULL),
 291      destructor_call(NULL),
 292      outfile(NULL) {
 293  }
 294
 295  /************** some utility functions ***************/
 296
 297  /* -----------------------------------------------------------------------------
 298   * getMappedType()
 299   *
 300   * Return the type of 'p' mapped by 'map'.
 301   * Print a standard warning if 'p' can't be mapped.
 302   * ----------------------------------------------------------------------------- */
 303
 304  String *getMappedType(Node *p, const char *map) {
 305    String *mapattr = NewString("tmap:");
 306    Append(mapattr, map);
 307
 308    String *tm = Getattr(p, mapattr);
 309    if (tm == NIL) {
 310      Swig_warning(WARN_MODULA3_TYPEMAP_TYPE_UNDEF, input_file, line_number,
 311		   "No '%s' typemap defined for type '%s'\n", map, SwigType_str(Getattr(p, "type"), 0));
 312    }
 313    Delete(mapattr);
 314    return tm;
 315  }
 316
 317  /* -----------------------------------------------------------------------------
 318   * getMappedTypeNew()
 319   *
 320   * Similar to getMappedType but uses Swig_type_lookup_new.
 321   * ----------------------------------------------------------------------------- */
 322
 323  String *getMappedTypeNew(Node *n, const char *map, const char *lname = "", bool warn = true) {
 324    String *tm = Swig_typemap_lookup(map, n, lname, 0);
 325    if ((tm == NIL) && warn) {
 326      Swig_warning(WARN_MODULA3_TYPEMAP_TYPE_UNDEF, input_file, line_number,
 327		   "No '%s' typemap defined for type '%s'\n", map, SwigType_str(Getattr(n, "type"), 0));
 328    }
 329    return tm;
 330  }
 331
 332  /* -----------------------------------------------------------------------------
 333   * attachMappedType()
 334   *
 335   * Obtain the type mapped by 'map' and attach it to the node
 336   * ----------------------------------------------------------------------------- */
 337
 338  void attachMappedType(Node *n, const char *map, const char *lname = "") {
 339    String *tm = Swig_typemap_lookup(map, n, lname, 0);
 340    if (tm != NIL) {
 341      String *attr = NewStringf("tmap:%s", map);
 342      Setattr(n, attr, tm);
 343      Delete(attr);
 344    }
 345  }
 346
 347  /* -----------------------------------------------------------------------------
 348   * skipIgnored()
 349   *
 350   * Skip all parameters that have 'numinputs=0'
 351   * with respect to a given typemap.
 352   * ----------------------------------------------------------------------------- */
 353
 354  Node *skipIgnored(Node *p, const char *map) {
 355    String *niattr = NewStringf("tmap:%s:numinputs", map);
 356    String *nextattr = NewStringf("tmap:%s:next", map);
 357
 358    while ((p != NIL) && checkAttribute(p, niattr, "0")) {
 359      p = Getattr(p, nextattr);
 360    }
 361
 362    Delete(nextattr);
 363    Delete(niattr);
 364    return p;
 365  }
 366
 367  /* -----------------------------------------------------------------------------
 368   * isInParam()
 369   * isOutParam()
 370   *
 371   * Check if the parameter is intended for input or for output.
 372   * ----------------------------------------------------------------------------- */
 373
 374  bool isInParam(Node *p) {
 375    String *dir = Getattr(p, "tmap:m3wrapargdir");
 376//printf("dir for %s: %s\n", Char(Getattr(p,"name")), Char(dir));
 377    if ((dir == NIL) || (Strcmp(dir, "in") == 0)
 378	|| (Strcmp(dir, "inout") == 0)) {
 379      return true;
 380    } else if (Strcmp(dir, "out") == 0) {
 381      return false;
 382    } else {
 383      printf("%s", USAGE_ARG_DIR);
 384      return false;
 385    }
 386  }
 387
 388  bool isOutParam(Node *p) {
 389    String *dir = Getattr(p, "tmap:m3wrapargdir");
 390    if ((dir == NIL) || (Strcmp(dir, "in") == 0)) {
 391      return false;
 392    } else if ((Strcmp(dir, "out") == 0) || (Strcmp(dir, "inout") == 0)) {
 393      return true;
 394    } else {
 395      printf("%s", USAGE_ARG_DIR);
 396      return false;
 397    }
 398  }
 399
 400  /* -----------------------------------------------------------------------------
 401   * printAttrs()
 402   *
 403   * For debugging: Show all attributes of a node and their values.
 404   * ----------------------------------------------------------------------------- */
 405  void printAttrs(Node *n) {
 406    Iterator it;
 407    for (it = First(n); it.key != NIL; it = Next(it)) {
 408      printf("%s = %s\n", Char(it.key), Char(Getattr(n, it.key)));
 409    }
 410  }
 411
 412  /* -----------------------------------------------------------------------------
 413   * hasPrefix()
 414   *
 415   * Check if a string have a given prefix.
 416   * ----------------------------------------------------------------------------- */
 417  bool hasPrefix(const String *str, const String *prefix) {
 418    int len_prefix = Len(prefix);
 419    return (Len(str) > len_prefix)
 420	&& (Strncmp(str, prefix, len_prefix) == 0);
 421  }
 422
 423  /* -----------------------------------------------------------------------------
 424   * getQualifiedName()
 425   *
 426   * Return fully qualified identifier of n.
 427   * ----------------------------------------------------------------------------- */
 428#if 0
 429  // Swig_symbol_qualified returns NIL for enumeration nodes
 430  String *getQualifiedName(Node *n) {
 431    String *qual = Swig_symbol_qualified(n);
 432    String *name = Getattr(n, "name");
 433    if (hasContent(qual)) {
 434      return NewStringf("%s::%s", qual, name);
 435    } else {
 436      return name;
 437    }
 438  }
 439#else
 440  String *getQualifiedName(Node *n) {
 441    String *name = Copy(Getattr(n, "name"));
 442    n = parentNode(n);
 443    while (n != NIL) {
 444      const String *type = nodeType(n);
 445      if ((Strcmp(type, "class") == 0) || (Strcmp(type, "struct") == 0) || (Strcmp(type, "namespace") == 0)) {
 446	String *newname = NewStringf("%s::%s", Getattr(n, "name"), name);
 447	Delete(name);
 448	//name = newname;
 449	// Hmpf, the class name is already qualified.
 450	return newname;
 451      }
 452      n = parentNode(n);
 453    }
 454    //printf("qualified name: %s\n", Char(name));
 455    return name;
 456  }
 457#endif
 458
 459  /* -----------------------------------------------------------------------------
 460   * nameToModula3()
 461   *
 462   * Turn usual C identifiers like "this_is_an_identifier"
 463   * into usual Modula 3 identifier like "thisIsAnIdentifier"
 464   * ----------------------------------------------------------------------------- */
 465  String *nameToModula3(const String *sym, bool leadingCap) {
 466    int len_sym = Len(sym);
 467    char *csym = Char(sym);
 468    char *m3sym = new char[len_sym + 1];
 469    int i, j;
 470    bool cap = leadingCap;
 471    for (i = 0, j = 0; j < len_sym; j++) {
 472      char c = csym[j];
 473      if ((c == '_') || (c == ':')) {
 474	cap = true;
 475      } else {
 476	if (isdigit(c)) {
 477	  m3sym[i] = c;
 478	  cap = true;
 479	} else {
 480	  if (cap) {
 481	    m3sym[i] = (char)toupper(c);
 482	  } else {
 483	    m3sym[i] = (char)tolower(c);
 484	  }
 485	  cap = false;
 486	}
 487	i++;
 488      }
 489    }
 490    m3sym[i] = 0;
 491    String *result = NewString(m3sym);
 492    delete[]m3sym;
 493    return result;
 494  }
 495
 496  /* -----------------------------------------------------------------------------
 497   * capitalizeFirst()
 498   *
 499   * Make the first character upper case.
 500   * ----------------------------------------------------------------------------- */
 501  String *capitalizeFirst(const String *str) {
 502    return NewStringf("%c%s", toupper(*Char(str)), Char(str) + 1);
 503  }
 504
 505  /* -----------------------------------------------------------------------------
 506   * prefixedNameToModula3()
 507   *
 508   * If feature modula3:oldprefix and modula3:newprefix is present
 509   * and the C identifier has leading 'oldprefix'
 510   * then it is replaced by the 'newprefix'.
 511   * The rest is converted to Modula style.
 512   * ----------------------------------------------------------------------------- */
 513  String *prefixedNameToModula3(Node *n, const String *sym, bool leadingCap) {
 514    String *oldPrefix = Getattr(n, "feature:modula3:oldprefix");
 515    String *newPrefix = Getattr(n, "feature:modula3:newprefix");
 516    String *result = NewString("");
 517    char *short_sym = Char(sym);
 518    // if at least one prefix feature is present
 519    // the replacement takes place
 520    if ((oldPrefix != NIL) || (newPrefix != NIL)) {
 521      if ((oldPrefix == NIL) || hasPrefix(sym, oldPrefix)) {
 522	short_sym += Len(oldPrefix);
 523	if (newPrefix != NIL) {
 524	  Append(result, newPrefix);
 525	}
 526      }
 527    }
 528    String *suffix = nameToModula3(short_sym, leadingCap || hasContent(newPrefix));
 529    Append(result, suffix);
 530    Delete(suffix);
 531    return result;
 532  }
 533
 534  /* -----------------------------------------------------------------------------
 535   * hasContent()
 536   *
 537   * Check if the string exists and contains something.
 538   * ----------------------------------------------------------------------------- */
 539  bool hasContent(const String *str) {
 540    return (str != NIL) && (Strcmp(str, "") != 0);
 541  }
 542
 543  /* -----------------------------------------------------------------------------
 544   * openWriteFile()
 545   *
 546   * Caution: The file must be freshly allocated and will be destroyed
 547   *          by this routine.
 548   * ----------------------------------------------------------------------------- */
 549
 550  File *openWriteFile(String *name) {
 551    File *file = NewFile(name, "w", SWIG_output_files());
 552    if (!file) {
 553      FileErrorDisplay(name);
 554      SWIG_exit(EXIT_FAILURE);
 555    }
 556    Delete(name);
 557    return file;
 558  }
 559
 560  /* -----------------------------------------------------------------------------
 561   * aToL()
 562   *
 563   * like atol but with additional user warning
 564   * ----------------------------------------------------------------------------- */
 565
 566  long aToL(const String *value) {
 567    char *endptr;
 568    long numvalue = strtol(Char(value), &endptr, 0);
 569    if (*endptr != 0) {
 570      Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "The string <%s> does not denote a numeric value.\n", value);
 571    }
 572    return numvalue;
 573  }
 574
 575  /* -----------------------------------------------------------------------------
 576   * strToL()
 577   *
 578   * like strtol but returns if the conversion was successful
 579   * ----------------------------------------------------------------------------- */
 580
 581  bool strToL(const String *value, long &numvalue) {
 582    char *endptr;
 583    numvalue = strtol(Char(value), &endptr, 0);
 584    return (*endptr == 0);
 585  }
 586
 587  /* -----------------------------------------------------------------------------
 588   * evalExpr()
 589   *
 590   * Evaluate simple expression as they may occur in "enumvalue" attributes.
 591   * ----------------------------------------------------------------------------- */
 592
 593  bool evalExpr(String *value, long &numvalue) {
 594    // Split changes file status of String and thus cannot receive 'const' strings
 595//printf("evaluate <%s>\n", Char(value));
 596    List *summands = Split(value, '+', INT_MAX);
 597    Iterator sm = First(summands);
 598    numvalue = 0;
 599    for (; sm.item != NIL; sm = Next(sm)) {
 600      String *smvalue = Getattr(constant_values, sm.item);
 601      long smnumvalue;
 602      if (smvalue != NIL) {
 603	if (!strToL(smvalue, smnumvalue)) {
 604//printf("evaluation: abort 0 <%s>\n", Char(smvalue));
 605	  return false;
 606	}
 607      } else {
 608	if (!strToL(sm.item, smnumvalue)) {
 609//printf("evaluation: abort 1 <%s>\n", Char(sm));
 610	  return false;
 611	}
 612      }
 613      numvalue += smnumvalue;
 614    }
 615//printf("evaluation: return %ld\n", numvalue);
 616    return true;
 617  }
 618
 619  /* -----------------------------------------------------------------------------
 620   * log2()
 621   *
 622   * Determine the position of the single bit of a power of two.
 623   * Returns true if the given number is a power of two.
 624   * ----------------------------------------------------------------------------- */
 625
 626  bool log2(long n, long &exp) {
 627    exp = 0;
 628    while (n > 0) {
 629      if ((n & 1) != 0) {
 630	return n == 1;
 631      }
 632      exp++;
 633      n >>= 1;
 634    }
 635    return false;
 636  }
 637
 638  /* -----------------------------------------------------------------------------
 639   * writeArg
 640   *
 641   * Write a function argument or RECORD entry definition.
 642   * Bundles arguments of same type and default value.
 643   * 'name.next==NIL' denotes the end of the entry or argument list.
 644   * ----------------------------------------------------------------------------- */
 645
 646  bool equalNilStr(const String *str0, const String *str1) {
 647    if (str0 == NIL) {
 648      return (str1 == NIL);
 649      //return (str0==NIL) == (str1==NIL);
 650    } else {
 651      return (str1 != NIL) && (Cmp(str0, str1) == 0);
 652      //return Cmp(str0,str1)==0;
 653    }
 654  }
 655
 656  struct writeArgState {
 657    String *mode, *name, *type, *value;
 658    bool hold;
 659     writeArgState():mode(NIL), name(NIL), type(NIL), value(NIL), hold(false) {
 660    }
 661  };
 662
 663  void writeArg(File *f, writeArgState & state, String *mode, String *name, String *type, String *value) {
 664    /* skip the first argument,
 665       only store the information for the next call in this case */
 666    if (state.name != NIL) {
 667      if ((!state.hold) && (state.mode != NIL)) {
 668	Printf(f, "%s ", state.mode);
 669      }
 670      if ((name != NIL) && equalNilStr(state.mode, mode) && equalNilStr(state.type, type) && (state.value == NIL) && (value == NIL)
 671	  /* the same expression may have different values
 672	     due to side effects of the called function */
 673	  /*equalNilStr(state.value,value) */
 674	  ) {
 675	Printf(f, "%s, ", state.name);
 676	state.hold = true;
 677      } else {
 678	Append(f, state.name);
 679	if (state.type != NIL) {
 680	  Printf(f, ": %s", state.type);
 681	}
 682	if (state.value != NIL) {
 683	  Printf(f, ":= %s", state.value);
 684	}
 685	Append(f, ";\n");
 686	state.hold = false;
 687      }
 688    }
 689    /* at the next call the current argument will be the previous one */
 690    state.mode = mode;
 691    state.name = name;
 692    state.type = type;
 693    state.value = value;
 694  }
 695
 696  /* -----------------------------------------------------------------------------
 697   * getProxyName()
 698   *
 699   * Test to see if a type corresponds to something wrapped with a proxy class
 700   * Return NULL if not otherwise the proxy class name
 701   * ----------------------------------------------------------------------------- */
 702
 703  String *getProxyName(SwigType *t) {
 704    if (proxy_flag) {
 705      Node *n = classLookup(t);
 706      if (n) {
 707	return Getattr(n, "sym:name");
 708      }
 709    }
 710    return NULL;
 711  }
 712
 713  /*************** language processing ********************/
 714
 715  /* ------------------------------------------------------------
 716   * main()
 717   * ------------------------------------------------------------ */
 718
 719  virtual void main(int argc, char *argv[]) {
 720
 721    SWIG_library_directory("modula3");
 722
 723    // Look for certain command line options
 724    for (int i = 1; i < argc; i++) {
 725      if (argv[i]) {
 726	if (strcmp(argv[i], "-generateconst") == 0) {
 727	  if (argv[i + 1]) {
 728	    constantfilename = NewString(argv[i + 1]);
 729	    Swig_mark_arg(i);
 730	    Swig_mark_arg(i + 1);
 731	    i++;
 732	  } else {
 733	    Swig_arg_error();
 734	  }
 735	} else if (strcmp(argv[i], "-generaterename") == 0) {
 736	  if (argv[i + 1]) {
 737	    renamefilename = NewString(argv[i + 1]);
 738	    Swig_mark_arg(i);
 739	    Swig_mark_arg(i + 1);
 740	    i++;
 741	  } else {
 742	    Swig_arg_error();
 743	  }
 744	} else if (strcmp(argv[i], "-generatetypemap") == 0) {
 745	  if (argv[i + 1]) {
 746	    typemapfilename = NewString(argv[i + 1]);
 747	    Swig_mark_arg(i);
 748	    Swig_mark_arg(i + 1);
 749	    i++;
 750	  } else {
 751	    Swig_arg_error();
 752	  }
 753	} else if (strcmp(argv[i], "-noproxy") == 0) {
 754	  Swig_mark_arg(i);
 755	  proxy_flag = false;
 756	} else if (strcmp(argv[i], "-oldvarnames") == 0) {
 757	  Swig_mark_arg(i);
 758	  old_variable_names = true;
 759	} else if (strcmp(argv[i], "-help") == 0) {
 760	  Printf(stdout, "%s\n", usage);
 761	}
 762      }
 763    }
 764
 765    // Add a symbol to the parser for conditional compilation
 766    Preprocessor_define("SWIGMODULA3 1", 0);
 767
 768    // Add typemap definitions
 769    SWIG_typemap_lang("modula3");
 770    SWIG_config_file("modula3.swg");
 771
 772    allow_overloading();
 773  }
 774
 775  /* ---------------------------------------------------------------------
 776   * top()
 777   * --------------------------------------------------------------------- */
 778
 779  virtual int top(Node *n) {
 780    if (hasContent(constantfilename) || hasContent(renamefilename) || hasContent(typemapfilename)) {
 781      int result = SWIG_OK;
 782      if (hasContent(constantfilename)) {
 783	result = generateConstantTop(n) && result;
 784      }
 785      if (hasContent(renamefilename)) {
 786	result = generateRenameTop(n) && result;
 787      }
 788      if (hasContent(typemapfilename)) {
 789	result = generateTypemapTop(n) && result;
 790      }
 791      return result;
 792    } else {
 793      return generateM3Top(n);
 794    }
 795  }
 796
 797  void scanConstant(File *file, Node *n) {
 798    Node *child = firstChild(n);
 799    while (child != NIL) {
 800      String *constname = NIL;
 801      String *type = nodeType(child);
 802      if ((Strcmp(type, "enumitem") == 0)
 803	  || (Strcmp(type, "constant") == 0)) {
 804#if 1
 805	constname = getQualifiedName(child);
 806#else
 807	constname = Getattr(child, "value");
 808	if ((!hasContent(constname))
 809	    || (('0' <= *Char(constname)) && (*Char(constname) <= '9'))) {
 810	  constname = Getattr(child, "name");
 811	}
 812#endif
 813      }
 814      if (constname != NIL) {
 815	Printf(file, "  printf(\"%%%%constnumeric(%%Lg) %s;\\n\", (long double)%s);\n", constname, constname);
 816      }
 817      scanConstant(file, child);
 818      child = nextSibling(child);
 819    }
 820  }
 821
 822  int generateConstantTop(Node *n) {
 823    File *file = openWriteFile(NewStringf("%s.c", constantfilename));
 824    if (CPlusPlus) {
 825      Printf(file, "#include <cstdio>\n");
 826    } else {
 827      Printf(file, "#include <stdio.h>\n");
 828    }
 829    Printf(file, "#include \"%s\"\n", input_file);
 830    Printf(file, "\n");
 831    Printf(file, "int main (int argc, char *argv[]) {\n");
 832    Printf(file, "\
 833/*This progam must work for floating point numbers and integers.\n\
 834  Thus all numbers are converted to double precision floating point format.*/\n");
 835    scanConstant(file, n);
 836    Printf(file, "  return 0;\n");
 837    Printf(file, "}\n");
 838    Close(file);
 839    return SWIG_OK;
 840  }
 841
 842  void scanRename(File *file, Node *n) {
 843    Node *child = firstChild(n);
 844    while (child != NIL) {
 845      String *type = nodeType(child);
 846      if (Strcmp(type, "cdecl") == 0) {
 847	ParmList *p = Getattr(child, "parms");
 848	if (p != NIL) {
 849	  String *name = getQualifiedName(child);
 850	  String *m3name = nameToModula3(name, true);
 851	  /*don't know how to get the original C type identifiers */
 852	  //String *arguments = createCSignature (child);
 853	  Printf(file, "%%rename(\"%s\") %s;\n", m3name, name);
 854	  /*Printf(file, "%%rename(\"%s\") %s %s(%s);\n",
 855	     m3name, Getattr(n,"type"), name, arguments); */
 856	  Delete(name);
 857	  Delete(m3name);
 858	  //Delete (arguments);
 859	}
 860      }
 861      scanRename(file, child);
 862      child = nextSibling(child);
 863    }
 864  }
 865
 866  int generateRenameTop(Node *n) {
 867    File *file = openWriteFile(NewStringf("%s.i", renamefilename));
 868    Printf(file, "\
 869/* This file was generated from %s\n\
 870   by SWIG with option -generaterename. */\n\
 871\n", input_file);
 872    scanRename(file, n);
 873    Close(file);
 874    return SWIG_OK;
 875  }
 876
 877  void scanTypemap(File *file, Node *n) {
 878    Node *child = firstChild(n);
 879    while (child != NIL) {
 880      String *type = nodeType(child);
 881      //printf("nodetype %s\n", Char(type));
 882      String *storage = Getattr(child, "storage");
 883      if ((Strcmp(type, "class") == 0) || ((Strcmp(type, "cdecl") == 0) && (storage != NIL)
 884					   && (Strcmp(storage, "typedef") == 0))) {
 885	String *name = getQualifiedName(child);
 886	String *m3name = nameToModula3(name, true);
 887	Printf(file, "%%typemap(\"m3wrapintype\") %s %%{%s%%}\n", name, m3name);
 888	Printf(file, "%%typemap(\"m3rawintype\") %s %%{%s%%}\n", name, m3name);
 889	Printf(file, "\n");
 890      }
 891      scanTypemap(file, child);
 892      child = nextSibling(child);
 893    }
 894  }
 895
 896  int generateTypemapTop(Node *n) {
 897    File *file = openWriteFile(NewStringf("%s.i", typemapfilename));
 898    Printf(file, "\
 899/* This file was generated from %s\n\
 900   by SWIG with option -generatetypemap. */\n\
 901\n", input_file);
 902    scanTypemap(file, n);
 903    Close(file);
 904    return SWIG_OK;
 905  }
 906
 907  int generateM3Top(Node *n) {
 908    /* Initialize all of the output files */
 909    outfile = Getattr(n, "outfile");
 910
 911    f_begin = NewFile(outfile, "w", SWIG_output_files());
 912    if (!f_begin) {
 913      FileErrorDisplay(outfile);
 914      SWIG_exit(EXIT_FAILURE);
 915    }
 916    f_runtime = NewString("");
 917    f_init = NewString("");
 918    f_header = NewString("");
 919    f_wrappers = NewString("");
 920
 921    m3makefile = NewString("");
 922
 923    /* Register file targets with the SWIG file handler */
 924    Swig_register_filebyname("header", f_header);
 925    Swig_register_filebyname("wrapper", f_wrappers);
 926    Swig_register_filebyname("begin", f_begin);
 927    Swig_register_filebyname("runtime", f_runtime);
 928    Swig_register_filebyname("init", f_init);
 929
 930    Swig_register_filebyname("m3rawintf", m3raw_intf.f);
 931    Swig_register_filebyname("m3rawimpl", m3raw_impl.f);
 932    Swig_register_filebyname("m3wrapintf", m3wrap_intf.f);
 933    Swig_register_filebyname("m3wrapimpl", m3wrap_impl.f);
 934    Swig_register_filebyname("m3makefile", m3makefile);
 935
 936    swig_types_hash = NewHash();
 937
 938    String *name = Getattr(n, "name");
 939    // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
 940    Node *optionsnode = Getattr(Getattr(n, "module"), "options");
 941    if (optionsnode != NIL) {
 942      String *m3raw_name_tmp = Getattr(optionsnode, "m3rawname");
 943      if (m3raw_name_tmp != NIL) {
 944	m3raw_name = Copy(m3raw_name_tmp);
 945      }
 946    }
 947    if (m3raw_name == NIL) {
 948      m3raw_name = NewStringf("%sRaw", name);
 949    }
 950    Setattr(m3wrap_impl.import, m3raw_name, "");
 951
 952    m3wrap_name = Copy(name);
 953
 954    proxy_class_def = NewString("");
 955    proxy_class_code = NewString("");
 956    m3raw_baseclass = NewString("");
 957    m3raw_interfaces = NewString("");
 958    m3raw_class_modifiers = NewString("");	// package access only to the intermediary class by default
 959    m3raw_imports = NewString("");
 960    m3raw_cppcasts_code = NewString("");
 961    m3wrap_modifiers = NewString("public");
 962    module_baseclass = NewString("");
 963    module_interfaces = NewString("");
 964    module_imports = NewString("");
 965    upcasts_code = NewString("");
 966
 967    Swig_banner(f_begin);
 968
 969    Printf(f_runtime, "\n");
 970    Printf(f_runtime, "#define SWIGMODULA3\n");
 971    Printf(f_runtime, "\n");
 972
 973    Swig_name_register("wrapper", "Modula3_%f");
 974    if (old_variable_names) {
 975      Swig_name_register("set", "set_%n%v");
 976      Swig_name_register("get", "get_%n%v");
 977    }
 978
 979    Printf(f_wrappers, "\n#ifdef __cplusplus\n");
 980    Printf(f_wrappers, "extern \"C\" {\n");
 981    Printf(f_wrappers, "#endif\n\n");
 982
 983    constant_values = NewHash();
 984    scanForConstPragmas(n);
 985    enumeration_coll = NewHash();
 986    collectEnumerations(enumeration_coll, n);
 987
 988    /* Emit code */
 989    Language::top(n);
 990
 991    // Generate m3makefile
 992    // This will be unnecessary if SWIG is invoked from Quake.
 993    {
 994      File *file = openWriteFile(NewStringf("%sm3makefile", Swig_file_dirname(outfile)));
 995
 996      Printf(file, "%% automatically generated quake file for %s\n\n", name);
 997
 998      /* Write the fragments written by '%insert'
 999         collected while 'top' processed the parse tree */
1000      Printv(file, m3makefile, NIL);
1001
1002      Printf(file, "import(\"libm3\")\n");
1003      //Printf(file, "import_lib(\"%s\",\"/usr/lib\")\n", name);
1004      Printf(file, "module(\"%s\")\n", m3raw_name);
1005      Printf(file, "module(\"%s\")\n\n", m3wrap_name);
1006
1007      if (targetlibrary != NIL) {
1008	Printf(file, "library(\"%s\")\n", targetlibrary);
1009      } else {
1010	Printf(file, "library(\"m3%s\")\n", name);
1011      }
1012      Close(file);
1013    }
1014
1015    // Generate the raw interface
1016    {
1017      File *file = openWriteFile(NewStringf("%s%s.i3", Swig_file_dirname(outfile), m3raw_name));
1018
1019      emitBanner(file);
1020
1021      Printf(file, "INTERFACE %s;\n\n", m3raw_name);
1022
1023      emitImportStatements(m3raw_intf.import, file);
1024      Printf(file, "\n");
1025
1026      // Write the interface generated within 'top'
1027      Printv(file, m3raw_intf.f, NIL);
1028
1029      Printf(file, "\nEND %s.\n", m3raw_name);
1030      Close(file);
1031    }
1032
1033    // Generate the raw module
1034    {
1035      File *file = openWriteFile(NewStringf("%s%s.m3", Swig_file_dirname(outfile), m3raw_name));
1036
1037      emitBanner(file);
1038
1039      Printf(file, "MODULE %s;\n\n", m3raw_name);
1040
1041      emitImportStatements(m3raw_impl.import, file);
1042      Printf(file, "\n");
1043
1044      // will be empty usually
1045      Printv(file, m3raw_impl.f, NIL);
1046
1047      Printf(file, "BEGIN\nEND %s.\n", m3raw_name);
1048      Close(file);
1049    }
1050
1051    // Generate the interface for the comfort wrappers
1052    {
1053      File *file = openWriteFile(NewStringf("%s%s.i3", Swig_file_dirname(outfile), m3wrap_name));
1054
1055      emitBanner(file);
1056
1057      Printf(file, "INTERFACE %s;\n", m3wrap_name);
1058
1059      emitImportStatements(m3wrap_intf.import, file);
1060      Printf(file, "\n");
1061
1062      {
1063	Iterator it = First(enumeration_coll);
1064	if (it.key != NIL) {
1065	  Printf(file, "TYPE\n");
1066	}
1067	for (; it.key != NIL; it = Next(it)) {
1068	  Printf(file, "\n");
1069	  emitEnumeration(file, it.key, it.item);
1070	}
1071      }
1072
1073      // Add the wrapper methods
1074      Printv(file, m3wrap_intf.f, NIL);
1075
1076      // Finish off the class
1077      Printf(file, "\nEND %s.\n", m3wrap_name);
1078      Close(file);
1079    }
1080
1081    // Generate the wrapper routines implemented in Modula 3
1082    {
1083      File *file = openWriteFile(NewStringf("%s%s.m3", Swig_file_dirname(outfile), m3wrap_name));
1084
1085      emitBanner(file);
1086
1087      if (unsafe_module) {
1088	Printf(file, "UNSAFE ");
1089      }
1090      Printf(file, "MODULE %s;\n\n", m3wrap_name);
1091
1092      emitImportStatements(m3wrap_impl.import, file);
1093      Printf(file, "\n");
1094
1095      // Add the wrapper methods
1096      Printv(file, m3wrap_impl.f, NIL);
1097
1098      Printf(file, "\nBEGIN\nEND %s.\n", m3wrap_name);
1099      Close(file);
1100    }
1101
1102    if (upcasts_code)
1103      Printv(f_wrappers, upcasts_code, NIL);
1104
1105    Printf(f_wrappers, "#ifdef __cplusplus\n");
1106    Printf(f_wrappers, "}\n");
1107    Printf(f_wrappers, "#endif\n");
1108
1109    // Output a Modula 3 type wrapper class for each SWIG type
1110    for (Iterator swig_type = First(swig_types_hash); swig_type.item != NIL; swig_type = Next(swig_type)) {
1111      emitTypeWrapperClass(swig_type.key, swig_type.item);
1112    }
1113
1114    Delete(swig_types_hash);
1115    swig_types_hash = NULL;
1116    Delete(constant_values);
1117    constant_values = NULL;
1118    Delete(enumeration_coll);
1119    enumeration_coll = NULL;
1120    Delete(m3raw_name);
1121    m3raw_name = NULL;
1122    Delete(m3raw_baseclass);
1123    m3raw_baseclass = NULL;
1124    Delete(m3raw_interfaces);
1125    m3raw_interfaces = NULL;
1126    Delete(m3raw_class_modifiers);
1127    m3raw_class_modifiers = NULL;
1128    Delete(m3raw_imports);
1129    m3raw_imports = NULL;
1130    Delete(m3raw_cppcasts_code);
1131    m3raw_cppcasts_code = NULL;
1132    Delete(proxy_class_def);
1133    proxy_class_def = NULL;
1134    Delete(proxy_class_code);
1135    proxy_class_code = NULL;
1136    Delete(m3wrap_name);
1137    m3wrap_name = NULL;
1138    Delete(m3wrap_modifiers);
1139    m3wrap_modifiers = NULL;
1140    Delete(targetlibrary);
1141    targetlibrary = NULL;
1142    Delete(module_baseclass);
1143    module_baseclass = NULL;
1144    Delete(module_interfaces);
1145    module_interfaces = NULL;
1146    Delete(module_imports);
1147    module_imports = NULL;
1148    Delete(upcasts_code);
1149    upcasts_code = NULL;
1150    Delete(constantfilename);
1151    constantfilename = NULL;
1152    Delete(renamefilename);
1153    renamefilename = NULL;
1154    Delete(typemapfilename);
1155    typemapfilename = NULL;
1156
1157    /* Close all of the files */
1158    Dump(f_runtime, f_begin);
1159    Dump(f_header, f_begin);
1160    Dump(f_wrappers, f_begin);
1161    Wrapper_pretty_print(f_init, f_begin);
1162    Delete(f_header);
1163    Delete(f_wrappers);
1164    Delete(f_init);
1165    Close(f_begin);
1166    Delete(f_runtime);
1167    Delete(f_begin);
1168    return SWIG_OK;
1169  }
1170
1171  /* -----------------------------------------------------------------------------
1172   * emitBanner()
1173   * ----------------------------------------------------------------------------- */
1174
1175  void emitBanner(File *f) {
1176    Printf(f, "(*******************************************************************************\n");
1177    Swig_banner_target_lang(f, " *");
1178    Printf(f, "*******************************************************************************)\n\n");
1179  }
1180
1181  /* ----------------------------------------------------------------------
1182   * nativeWrapper()
1183   * ---------------------------------------------------------------------- */
1184
1185  virtual int nativeWrapper(Node *n) {
1186    String *wrapname = Getattr(n, "wrap:name");
1187
1188    if (!addSymbol(wrapname, n))
1189      return SWIG_ERROR;
1190
1191    if (Getattr(n, "type")) {
1192      Swig_save("nativeWrapper", n, "name", NIL);
1193      Setattr(n, "name", wrapname);
1194      native_function_flag = true;
1195      functionWrapper(n);
1196      Swig_restore(n);
1197      native_function_flag = false;
1198    } else {
1199      Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
1200    }
1201
1202    return SWIG_OK;
1203  }
1204
1205  /* ----------------------------------------------------------------------
1206   * functionWrapper()
1207   * ---------------------------------------------------------------------- */
1208
1209  virtual int functionWrapper(Node *n) {
1210    String *type = nodeType(n);
1211    String *funcType = Getattr(n, "modula3:functype");
1212    String *rawname = Getattr(n, "name");
1213    String *symname = Getattr(n, "sym:name");
1214    String *capname = capitalizeFirst(symname);
1215    //String *wname = Swig_name_wrapper(symname);
1216
1217    //printf("function: %s\n", Char(symname));
1218    //printf(" purpose: %s\n", Char(funcType));
1219
1220    if (Strcmp(type, "cdecl") == 0) {
1221      if (funcType == NIL) {
1222	// no wrapper needed for plain functions
1223	emitM3RawPrototype(n, rawname, symname);
1224	emitM3Wrapper(n, symname);
1225      } else if (Strcmp(funcType, "method") == 0) {
1226	Setattr(n, "modula3:funcname", capname);
1227	emitCWrapper(n, capname);
1228	emitM3RawPrototype(n, capname, capname);
1229	emitM3Wrapper(n, capname);
1230      } else if (Strcmp(funcType, "accessor") == 0) {
1231	/*
1232	 * Generate the proxy class properties for public member variables.
1233	 * Not for enums and constants.
1234	 */
1235	if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
1236	  // Capitalize the first letter in the function name
1237	  Setattr(n, "proxyfuncname", capname);
1238	  Setattr(n, "imfuncname", symname);
1239	  if (hasPrefix(capname, "Set")) {
1240	    Setattr(n, "modula3:setname", capname);
1241	  } else {
1242	    Setattr(n, "modula3:getname", capname);
1243	  }
1244
1245	  emitCWrapper(n, capname);
1246	  emitM3RawPrototype(n, capname, capname);
1247	  emitM3Wrapper(n, capname);
1248	  //proxyClassFunctionHandler(n);
1249	}
1250#ifdef DEBUG
1251      } else {
1252	Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Function type <%s> unknown.\n", Char(funcType));
1253#endif
1254      }
1255    } else if ((Strcmp(type, "constructor") == 0) || (Strcmp(type, "destructor") == 0)) {
1256      emitCWrapper(n, capname);
1257      emitM3RawPrototype(n, capname, capname);
1258      emitM3Wrapper(n, capname);
1259    }
1260// a Java relict
1261#if 0
1262    if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
1263      emitM3Wrapper(n, capname);
1264    }
1265#endif
1266
1267    Delete(capname);
1268
1269    return SWIG_OK;
1270  }
1271
1272  /* ----------------------------------------------------------------------
1273   * emitCWrapper()
1274   *
1275   * Generate the wrapper in C which calls C++ methods.
1276   * ---------------------------------------------------------------------- */
1277
1278  virtual int emitCWrapper(Node *n, const String *wname) {
1279    String *rawname = Getattr(n, "name");
1280    String *c_return_type = NewString("");
1281    String *cleanup = NewString("");
1282    String *outarg = NewString("");
1283    String *body = NewString("");
1284    Hash *throws_hash = NewHash();
1285    ParmList *l = Getattr(n, "parms");
1286    SwigType *t = Getattr(n, "type");
1287    String *symname = Getattr(n, "sym:name");
1288
1289    if (!Getattr(n, "sym:overloaded")) {
1290      if (!addSymbol(wname, n)) {
1291	return SWIG_ERROR;
1292      }
1293    }
1294    // A new wrapper function object
1295    Wrapper *f = NewWrapper();
1296
1297    /* Attach the non-standard typemaps to the parameter list. */
1298    Swig_typemap_attach_parms("ctype", l, f);
1299
1300    /* Get return types */
1301    {
1302      String *tm = getMappedTypeNew(n, "ctype", "");
1303      if (tm != NIL) {
1304	Printf(c_return_type, "%s", tm);
1305      }
1306    }
1307
1308    bool is_void_return = (Cmp(c_return_type, "void") == 0);
1309    if (!is_void_return) {
1310      Wrapper_add_localv(f, "cresult", c_return_type, "cresult = 0", NIL);
1311    }
1312
1313    Printv(f->def, " SWIGEXPORT ", c_return_type, " ", wname, "(", NIL);
1314
1315    // Emit all of the local variables for holding arguments.
1316    emit_parameter_variables(l, f);
1317
1318    /* Attach the standard typemaps */
1319    emit_attach_parmmaps(l, f);
1320    Setattr(n, "wrap:parms", l);
1321
1322    // Generate signature and argument conversion for C wrapper
1323    {
1324      Parm *p;
1325      attachParameterNames(n, "tmap:name", "c:wrapname", "m3arg%d");
1326      bool gencomma = false;
1327      for (p = skipIgnored(l, "in"); p; p = skipIgnored(p, "in")) {
1328
1329	String *arg = Getattr(p, "c:wrapname");
1330	{
1331	  /* Get the ctype types of the parameter */
1332	  String *c_param_type = getMappedType(p, "ctype");
1333	  // Add parameter to C function
1334	  Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
1335	  Delete(c_param_type);
1336	  gencomma = true;
1337	}
1338
1339	// Get typemap for this argument
1340	String *tm = getMappedType(p, "in");
1341	if (tm != NIL) {
1342	  addThrows(throws_hash, "in", p);
1343	  Replaceall(tm, "$input", arg);
1344	  Setattr(p, "emit:input", arg);	/*??? */
1345	  Printf(f->code, "%s\n", tm);
1346	  p = Getattr(p, "tmap:in:next");
1347	} else {
1348	  p = nextSibling(p);
1349	}
1350      }
1351    }
1352
1353    /* Insert constraint checking code */
1354    {
1355      Parm *p;
1356      for (p = l; p;) {
1357	String *tm = Getattr(p, "tmap:check");
1358	if (tm != NIL) {
1359	  addThrows(throws_hash, "check", p);
1360	  Replaceall(tm, "$target", Getattr(p, "lname"));	/* deprecated */
1361	  Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */
1362	  Replaceall(tm, "$input", Getattr(p, "emit:input"));
1363	  Printv(f->code, tm, "\n", NIL);
1364	  p = Getattr(p, "tmap:check:next");
1365	} else {
1366	  p = nextSibling(p);
1367	}
1368      }
1369    }
1370
1371    /* Insert cleanup code */
1372    {
1373      Parm *p;
1374      for (p = l; p;) {
1375	String *tm = Getattr(p, "tmap:freearg");
1376	if (tm != NIL) {
1377	  addThrows(throws_hash, "freearg", p);
1378	  Replaceall(tm, "$source", Getattr(p, "emit:input"));	/* deprecated */
1379	  Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */
1380	  Replaceall(tm, "$input", Getattr(p, "emit:input"));
1381	  Printv(cleanup, tm, "\n", NIL);
1382	  p = Getattr(p, "tmap:freearg:next");
1383	} else {
1384	  p = nextSibling(p);
1385	}
1386      }
1387    }
1388
1389    /* Insert argument output code */
1390    {
1391      Parm *p;
1392      for (p = l; p;) {
1393	String *tm = Getattr(p, "tmap:argout");
1394	if (tm != NIL) {
1395	  addThrows(throws_hash, "argout", p);
1396	  Replaceall(tm, "$source", Getattr(p, "emit:input"));	/* deprecated */
1397	  Replaceall(tm, "$target", Getattr(p, "lname"));	/* deprecated */
1398	  Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */
1399	  Replaceall(tm, "$result", "cresult");
1400	  Replaceall(tm, "$input", Getattr(p, "emit:input"));
1401	  Printv(outarg, tm, "\n", NIL);
1402	  p = Getattr(p, "tmap:argout:next");
1403	} else {
1404	  p = nextSibling(p);
1405	}
1406      }
1407    }
1408
1409    // Get any Modula 3 exception classes in the throws typemap
1410    ParmList *throw_parm_list = NULL;
1411    if ((throw_parm_list = Getattr(n, "catchlist"))) {
1412      Swig_typemap_attach_parms("throws", throw_parm_list, f);
1413      Parm *p;
1414      for (p = throw_parm_list; p; p = nextSibling(p)) {
1415	addThrows(throws_hash, "throws", p);
1416      }
1417    }
1418
1419    if (Cmp(nodeType(n), "constant") == 0) {
1420      // Wrapping a constant hack
1421      Swig_save("functionWrapper", n, "wrap:action", NIL);
1422
1423      // below based on Swig_VargetToFunction()
1424      SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
1425      Setattr(n, "wrap:action", NewStringf("%s = (%s)(%s);", Swig_cresult_name(), SwigType_lstr(ty, 0), Getattr(n, "value")));
1426    }
1427
1428    Setattr(n, "wrap:name", wname);
1429
1430    // Now write code to make the function call
1431    if (!native_function_flag) {
1432      String *actioncode = emit_action(n);
1433
1434      if (Cmp(nodeType(n), "constant") == 0) {
1435        Swig_restore(n);
1436      }
1437
1438      /* Return value if necessary  */
1439      String *tm;
1440      if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
1441	addThrows(throws_hash, "out", n);
1442	Replaceall(tm, "$source", Swig_cresult_name());	/* deprecated */
1443	Replaceall(tm, "$target", "cresult");	/* deprecated */
1444	Replaceall(tm, "$result", "cresult");
1445	Printf(f->code, "%s", tm);
1446	if (hasContent(tm))
1447	  Printf(f->code, "\n");
1448      } else {
1449	Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t, 0), rawname);
1450      }
1451      emit_return_variable(n, t, f);
1452    }
1453
1454    /* Output argument output code */
1455    Printv(f->code, outarg, NIL);
1456
1457    /* Output cleanup code */
1458    Printv(f->code, cleanup, NIL);
1459
1460    /* Look to see if there is any newfree cleanup code */
1461    if (GetFlag(n, "feature:new")) {
1462      String *tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0);
1463      if (tm != NIL) {
1464	addThrows(throws_hash, "newfree", n);
1465	Replaceall(tm, "$source", Swig_cresult_name());	/* deprecated */
1466	Printf(f->code, "%s\n", tm);
1467      }
1468    }
1469
1470    /* See if there is any return cleanup code */
1471    if (!native_function_flag) {
1472      String *tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0);
1473      if (tm != NIL) {
1474	Replaceall(tm, "$source", Swig_cresult_name());	/* deprecated */
1475	Printf(f->code, "%s\n", tm);
1476      }
1477    }
1478
1479    /* Finish C wrapper */
1480    Printf(f->def, ") {");
1481
1482    if (!is_void_return)
1483      Printv(f->code, "    return cresult;\n", NIL);
1484    Printf(f->code, "}\n");
1485
1486    /* Substitute the cleanup code */
1487    Replaceall(f->code, "$cleanup", cleanup);
1488
1489    /* Substitute the function name */
1490    Replaceall(f->code, "$symname", symname);
1491
1492    if (!is_void_return) {
1493      Replaceall(f->code, "$null", "0");
1494    } else {
1495      Replaceall(f->code, "$null", "");
1496    }
1497
1498    /* Dump the function out */
1499    if (!native_function_flag) {
1500      Wrapper_print(f, f_wrappers);
1501    }
1502
1503    Delete(c_return_type);
1504    Delete(cleanup);
1505    Delete(outarg);
1506    Delete(body);
1507    Delete(throws_hash);
1508    DelWrapper(f);
1509    return SWIG_OK;
1510  }
1511
1512  /* ----------------------------------------------------------------------
1513   * emitM3RawPrototype()
1514   *
1515   * Generate an EXTERNAL procedure declaration in Modula 3
1516   * which is the interface to an existing C routine or a C wrapper.
1517   * ---------------------------------------------------------------------- */
1518
1519  virtual int emitM3RawPrototype(Node *n, const String *cname, const String *m3name) {
1520    String *im_return_type = NewString("");
1521    //String   *symname = Getattr(n,"sym:name");
1522    ParmList *l = Getattr(n, "parms");
1523
1524    /* Attach the non-standard typemaps to the parameter list. */
1525    Swig_typemap_attach_parms("m3rawinmode", l, NULL);
1526    Swig_typemap_attach_parms("m3rawintype", l, NULL);
1527
1528    /* Get return types */
1529    bool has_return;
1530    {
1531      String *tm = getMappedTypeNew(n, "m3rawrettype", "");
1532      if (tm != NIL) {
1533	Printf(im_return_type, "%s", tm);
1534  

Large files files are truncated, but you can click here to view the full file