PageRenderTime 155ms CodeModel.GetById 27ms app.highlight 115ms RepoModel.GetById 1ms app.codeStats 1ms

/trunk/Source/Modules/csharp.cxx

#
C++ | 1760 lines | 1260 code | 248 blank | 252 comment | 315 complexity | b79e1b52544bd3dacf035110a22b9107 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 * csharp.cxx
  10 *
  11 * C# language module for SWIG.
  12 * ----------------------------------------------------------------------------- */
  13
  14char cvsroot_csharp_cxx[] = "$Id: csharp.cxx 12892 2012-01-07 22:09:28Z wsfulton $";
  15
  16#include "swigmod.h"
  17#include <limits.h>		// for INT_MAX
  18#include "cparse.h"
  19#include <ctype.h>
  20
  21/* Hash type used for upcalls from C/C++ */
  22typedef DOH UpcallData;
  23
  24class CSHARP:public Language {
  25  static const char *usage;
  26  const String *empty_string;
  27  const String *public_string;
  28  const String *protected_string;
  29
  30  Hash *swig_types_hash;
  31  File *f_begin;
  32  File *f_runtime;
  33  File *f_runtime_h;
  34  File *f_header;
  35  File *f_wrappers;
  36  File *f_init;
  37  File *f_directors;
  38  File *f_directors_h;
  39  List *filenames_list;
  40
  41  bool proxy_flag;		// Flag for generating proxy classes
  42  bool native_function_flag;	// Flag for when wrapping a native function
  43  bool enum_constant_flag;	// Flag for when wrapping an enum or constant
  44  bool static_flag;		// Flag for when wrapping a static functions or member variables
  45  bool variable_wrapper_flag;	// Flag for when wrapping a nonstatic member variable
  46  bool wrapping_member_flag;	// Flag for when wrapping a member variable/enum/const
  47  bool global_variable_flag;	// Flag for when wrapping a global variable
  48  bool old_variable_names;	// Flag for old style variable names in the intermediary class
  49  bool generate_property_declaration_flag;	// Flag for generating properties
  50
  51  String *imclass_name;		// intermediary class name
  52  String *module_class_name;	// module class name
  53  String *imclass_class_code;	// intermediary class code
  54  String *proxy_class_def;
  55  String *proxy_class_code;
  56  String *module_class_code;
  57  String *proxy_class_name;	// proxy class name
  58  String *full_proxy_class_name;// fully qualified proxy class name when using nspace feature, otherwise same as proxy_class_name
  59  String *full_imclass_name;	// fully qualified intermediary class name when using nspace feature, otherwise same as imclass_name
  60  String *variable_name;	//Name of a variable being wrapped
  61  String *proxy_class_constants_code;
  62  String *module_class_constants_code;
  63  String *enum_code;
  64  String *dllimport;		// DllImport attribute name
  65  String *namespce;		// Optional namespace name
  66  String *imclass_imports;	//intermediary class imports from %pragma
  67  String *module_imports;	//module imports from %pragma
  68  String *imclass_baseclass;	//inheritance for intermediary class class from %pragma
  69  String *module_baseclass;	//inheritance for module class from %pragma
  70  String *imclass_interfaces;	//interfaces for intermediary class class from %pragma
  71  String *module_interfaces;	//interfaces for module class from %pragma
  72  String *imclass_class_modifiers;	//class modifiers for intermediary class overriden by %pragma
  73  String *module_class_modifiers;	//class modifiers for module class overriden by %pragma
  74  String *upcasts_code;		//C++ casts for inheritance hierarchies C++ code
  75  String *imclass_cppcasts_code;	//C++ casts up inheritance hierarchies intermediary class code
  76  String *director_callback_typedefs;	// Director function pointer typedefs for callbacks
  77  String *director_callbacks;	// Director callback function pointer member variables
  78  String *director_delegate_callback;	// Director callback method that delegates are set to call
  79  String *director_delegate_definitions;	// Director delegates definitions in proxy class
  80  String *director_delegate_instances;	// Director delegates member variables in proxy class
  81  String *director_method_types;	// Director method types
  82  String *director_connect_parms;	// Director delegates parameter list for director connect call
  83  String *destructor_call;	//C++ destructor call if any
  84
  85  // Director method stuff:
  86  List *dmethods_seq;
  87  Hash *dmethods_table;
  88  int n_dmethods;
  89  int n_directors;
  90  int first_class_dmethod;
  91  int curr_class_dmethod;
  92
  93  enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
  94
  95public:
  96
  97  /* -----------------------------------------------------------------------------
  98   * CSHARP()
  99   * ----------------------------------------------------------------------------- */
 100
 101   CSHARP():empty_string(NewString("")),
 102      public_string(NewString("public")),
 103      protected_string(NewString("protected")),
 104      swig_types_hash(NULL),
 105      f_begin(NULL),
 106      f_runtime(NULL),
 107      f_runtime_h(NULL),
 108      f_header(NULL),
 109      f_wrappers(NULL),
 110      f_init(NULL),
 111      f_directors(NULL),
 112      f_directors_h(NULL),
 113      filenames_list(NULL),
 114      proxy_flag(true),
 115      native_function_flag(false),
 116      enum_constant_flag(false),
 117      static_flag(false),
 118      variable_wrapper_flag(false),
 119      wrapping_member_flag(false),
 120      global_variable_flag(false),
 121      old_variable_names(false),
 122      generate_property_declaration_flag(false),
 123      imclass_name(NULL),
 124      module_class_name(NULL),
 125      imclass_class_code(NULL),
 126      proxy_class_def(NULL),
 127      proxy_class_code(NULL),
 128      module_class_code(NULL),
 129      proxy_class_name(NULL),
 130      full_proxy_class_name(NULL),
 131      full_imclass_name(NULL),
 132      variable_name(NULL),
 133      proxy_class_constants_code(NULL),
 134      module_class_constants_code(NULL),
 135      enum_code(NULL),
 136      dllimport(NULL),
 137      namespce(NULL),
 138      imclass_imports(NULL),
 139      module_imports(NULL),
 140      imclass_baseclass(NULL),
 141      module_baseclass(NULL),
 142      imclass_interfaces(NULL),
 143      module_interfaces(NULL),
 144      imclass_class_modifiers(NULL),
 145      module_class_modifiers(NULL),
 146      upcasts_code(NULL),
 147      imclass_cppcasts_code(NULL),
 148      director_callback_typedefs(NULL),
 149      director_callbacks(NULL),
 150      director_delegate_callback(NULL),
 151      director_delegate_definitions(NULL),
 152      director_delegate_instances(NULL),
 153      director_method_types(NULL),
 154      director_connect_parms(NULL),
 155      destructor_call(NULL),
 156      dmethods_seq(NULL),
 157      dmethods_table(NULL),
 158      n_dmethods(0),
 159      n_directors(0) {
 160    /* for now, multiple inheritance in directors is disabled, this
 161       should be easy to implement though */
 162    director_multiple_inheritance = 0;
 163    director_language = 1;
 164  }
 165
 166  /* -----------------------------------------------------------------------------
 167   * getProxyName()
 168   *
 169   * Test to see if a type corresponds to something wrapped with a proxy class.
 170   * Return NULL if not otherwise the proxy class name, fully qualified with
 171   * a namespace if the nspace feature is used.
 172   * ----------------------------------------------------------------------------- */
 173  
 174   String *getProxyName(SwigType *t) {
 175     String *proxyname = NULL;
 176     if (proxy_flag) {
 177       Node *n = classLookup(t);
 178       if (n) {
 179	 proxyname = Getattr(n, "proxyname");
 180	 if (!proxyname) {
 181	   String *nspace = Getattr(n, "sym:nspace");
 182	   String *symname = Getattr(n, "sym:name");
 183	   if (nspace) {
 184	     if (namespce)
 185	       proxyname = NewStringf("%s.%s.%s", namespce, nspace, symname);
 186	     else
 187	       proxyname = NewStringf("%s.%s", nspace, symname);
 188	   } else {
 189	     proxyname = Copy(symname);
 190	   }
 191	   Setattr(n, "proxyname", proxyname);
 192	   Delete(proxyname);
 193	 }
 194       }
 195     }
 196     return proxyname;
 197   }
 198
 199  /* -----------------------------------------------------------------------------
 200   * directorClassName()
 201   * ----------------------------------------------------------------------------- */
 202
 203  String *directorClassName(Node *n) {
 204    String *dirclassname;
 205    const char *attrib = "director:classname";
 206
 207    if (!(dirclassname = Getattr(n, attrib))) {
 208      String *classname = Getattr(n, "sym:name");
 209
 210      dirclassname = NewStringf("SwigDirector_%s", classname);
 211      Setattr(n, attrib, dirclassname);
 212    }
 213
 214    return dirclassname;
 215  }
 216
 217  /* ------------------------------------------------------------
 218   * main()
 219   * ------------------------------------------------------------ */
 220
 221  virtual void main(int argc, char *argv[]) {
 222
 223    SWIG_library_directory("csharp");
 224
 225    // Look for certain command line options
 226    for (int i = 1; i < argc; i++) {
 227      if (argv[i]) {
 228	if (strcmp(argv[i], "-dllimport") == 0) {
 229	  if (argv[i + 1]) {
 230	    dllimport = NewString("");
 231	    Printf(dllimport, argv[i + 1]);
 232	    Swig_mark_arg(i);
 233	    Swig_mark_arg(i + 1);
 234	    i++;
 235	  } else {
 236	    Swig_arg_error();
 237	  }
 238	} else if (strcmp(argv[i], "-namespace") == 0) {
 239	  if (argv[i + 1]) {
 240	    namespce = NewString("");
 241	    Printf(namespce, argv[i + 1]);
 242	    if (Len(namespce) == 0) {
 243	      Delete(namespce);
 244	      namespce = 0;
 245	    }
 246	    Swig_mark_arg(i);
 247	    Swig_mark_arg(i + 1);
 248	    i++;
 249	  } else {
 250	    Swig_arg_error();
 251	  }
 252	} else if ((strcmp(argv[i], "-noproxy") == 0)) {
 253	  Swig_mark_arg(i);
 254	  proxy_flag = false;
 255	} else if (strcmp(argv[i], "-oldvarnames") == 0) {
 256	  Swig_mark_arg(i);
 257	  old_variable_names = true;
 258	} else if (strcmp(argv[i], "-help") == 0) {
 259	  Printf(stdout, "%s\n", usage);
 260	}
 261      }
 262    }
 263
 264    // Add a symbol to the parser for conditional compilation
 265    Preprocessor_define("SWIGCSHARP 1", 0);
 266
 267    // Add typemap definitions
 268    SWIG_typemap_lang("csharp");
 269    SWIG_config_file("csharp.swg");
 270
 271    allow_overloading();
 272  }
 273
 274  /* ---------------------------------------------------------------------
 275   * top()
 276   * --------------------------------------------------------------------- */
 277
 278  virtual int top(Node *n) {
 279
 280    // Get any options set in the module directive
 281    Node *optionsnode = Getattr(Getattr(n, "module"), "options");
 282
 283    if (optionsnode) {
 284      if (Getattr(optionsnode, "imclassname"))
 285	imclass_name = Copy(Getattr(optionsnode, "imclassname"));
 286      /* check if directors are enabled for this module.  note: this 
 287       * is a "master" switch, without which no director code will be
 288       * emitted.  %feature("director") statements are also required
 289       * to enable directors for individual classes or methods.
 290       *
 291       * use %module(directors="1") modulename at the start of the 
 292       * interface file to enable director generation.
 293       */
 294      if (Getattr(optionsnode, "directors")) {
 295	allow_directors();
 296      }
 297      if (Getattr(optionsnode, "dirprot")) {
 298	allow_dirprot();
 299      }
 300      allow_allprotected(GetFlag(optionsnode, "allprotected"));
 301    }
 302
 303    /* Initialize all of the output files */
 304    String *outfile = Getattr(n, "outfile");
 305    String *outfile_h = Getattr(n, "outfile_h");
 306
 307    if (!outfile) {
 308      Printf(stderr, "Unable to determine outfile\n");
 309      SWIG_exit(EXIT_FAILURE);
 310    }
 311
 312    f_begin = NewFile(outfile, "w", SWIG_output_files());
 313    if (!f_begin) {
 314      FileErrorDisplay(outfile);
 315      SWIG_exit(EXIT_FAILURE);
 316    }
 317
 318    if (directorsEnabled()) {
 319      if (!outfile_h) {
 320        Printf(stderr, "Unable to determine outfile_h\n");
 321        SWIG_exit(EXIT_FAILURE);
 322      }
 323      f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
 324      if (!f_runtime_h) {
 325	FileErrorDisplay(outfile_h);
 326	SWIG_exit(EXIT_FAILURE);
 327      }
 328    }
 329
 330    f_runtime = NewString("");
 331    f_init = NewString("");
 332    f_header = NewString("");
 333    f_wrappers = NewString("");
 334    f_directors_h = NewString("");
 335    f_directors = NewString("");
 336
 337    /* Register file targets with the SWIG file handler */
 338    Swig_register_filebyname("header", f_header);
 339    Swig_register_filebyname("wrapper", f_wrappers);
 340    Swig_register_filebyname("begin", f_begin);
 341    Swig_register_filebyname("runtime", f_runtime);
 342    Swig_register_filebyname("init", f_init);
 343    Swig_register_filebyname("director", f_directors);
 344    Swig_register_filebyname("director_h", f_directors_h);
 345
 346    swig_types_hash = NewHash();
 347    filenames_list = NewList();
 348
 349    // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
 350    if (!imclass_name) {
 351      imclass_name = NewStringf("%sPINVOKE", Getattr(n, "name"));
 352      module_class_name = Copy(Getattr(n, "name"));
 353    } else {
 354      // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
 355      if (Cmp(imclass_name, Getattr(n, "name")) == 0)
 356	module_class_name = NewStringf("%sModule", Getattr(n, "name"));
 357      else
 358	module_class_name = Copy(Getattr(n, "name"));
 359    }
 360
 361    // module class and intermediary classes are always created
 362    addSymbol(imclass_name, n);
 363    addSymbol(module_class_name, n);
 364
 365    imclass_class_code = NewString("");
 366    proxy_class_def = NewString("");
 367    proxy_class_code = NewString("");
 368    module_class_constants_code = NewString("");
 369    imclass_baseclass = NewString("");
 370    imclass_interfaces = NewString("");
 371    imclass_class_modifiers = NewString("");
 372    module_class_code = NewString("");
 373    module_baseclass = NewString("");
 374    module_interfaces = NewString("");
 375    module_imports = NewString("");
 376    module_class_modifiers = NewString("");
 377    imclass_imports = NewString("");
 378    imclass_cppcasts_code = NewString("");
 379    director_connect_parms = NewString("");
 380    upcasts_code = NewString("");
 381    dmethods_seq = NewList();
 382    dmethods_table = NewHash();
 383    n_dmethods = 0;
 384    n_directors = 0;
 385    if (!dllimport)
 386      dllimport = Copy(module_class_name);
 387
 388    Swig_banner(f_begin);
 389
 390    Printf(f_runtime, "\n");
 391    Printf(f_runtime, "#define SWIGCSHARP\n");
 392
 393    if (directorsEnabled()) {
 394      Printf(f_runtime, "#define SWIG_DIRECTORS\n");
 395
 396      /* Emit initial director header and director code: */
 397      Swig_banner(f_directors_h);
 398      Printf(f_directors_h, "\n");
 399      Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
 400      Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
 401
 402      Printf(f_directors, "\n\n");
 403      Printf(f_directors, "/* ---------------------------------------------------\n");
 404      Printf(f_directors, " * C++ director class methods\n");
 405      Printf(f_directors, " * --------------------------------------------------- */\n\n");
 406      if (outfile_h)
 407	Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
 408    }
 409
 410    Printf(f_runtime, "\n");
 411
 412    Swig_name_register("wrapper", "CSharp_%f");
 413    if (old_variable_names) {
 414      Swig_name_register("set", "set_%n%v");
 415      Swig_name_register("get", "get_%n%v");
 416    }
 417
 418    Printf(f_wrappers, "\n#ifdef __cplusplus\n");
 419    Printf(f_wrappers, "extern \"C\" {\n");
 420    Printf(f_wrappers, "#endif\n\n");
 421
 422    /* Emit code */
 423    Language::top(n);
 424
 425    if (directorsEnabled()) {
 426      // Insert director runtime into the f_runtime file (make it occur before %header section)
 427      Swig_insert_file("director.swg", f_runtime);
 428    }
 429    // Generate the intermediary class
 430    {
 431      String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), imclass_name);
 432      File *f_im = NewFile(filen, "w", SWIG_output_files());
 433      if (!f_im) {
 434	FileErrorDisplay(filen);
 435	SWIG_exit(EXIT_FAILURE);
 436      }
 437      Append(filenames_list, Copy(filen));
 438      Delete(filen);
 439      filen = NULL;
 440
 441      // Start writing out the intermediary class file
 442      emitBanner(f_im);
 443
 444      addOpenNamespace(0, f_im);
 445
 446      if (imclass_imports)
 447	Printf(f_im, "%s\n", imclass_imports);
 448
 449      if (Len(imclass_class_modifiers) > 0)
 450	Printf(f_im, "%s ", imclass_class_modifiers);
 451      Printf(f_im, "%s ", imclass_name);
 452
 453      if (imclass_baseclass && *Char(imclass_baseclass))
 454	Printf(f_im, ": %s ", imclass_baseclass);
 455      if (Len(imclass_interfaces) > 0)
 456	Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
 457      Printf(f_im, "{\n");
 458
 459      // Add the intermediary class methods
 460      Replaceall(imclass_class_code, "$module", module_class_name);
 461      Replaceall(imclass_class_code, "$imclassname", imclass_name);
 462      Replaceall(imclass_class_code, "$dllimport", dllimport);
 463      Printv(f_im, imclass_class_code, NIL);
 464      Printv(f_im, imclass_cppcasts_code, NIL);
 465
 466      // Finish off the class
 467      Printf(f_im, "}\n");
 468      addCloseNamespace(0, f_im);
 469
 470      Close(f_im);
 471    }
 472
 473    // Generate the C# module class
 474    {
 475      String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), module_class_name);
 476      File *f_module = NewFile(filen, "w", SWIG_output_files());
 477      if (!f_module) {
 478	FileErrorDisplay(filen);
 479	SWIG_exit(EXIT_FAILURE);
 480      }
 481      Append(filenames_list, Copy(filen));
 482      Delete(filen);
 483      filen = NULL;
 484
 485      // Start writing out the module class file
 486      emitBanner(f_module);
 487
 488      addOpenNamespace(0, f_module);
 489
 490      if (module_imports)
 491	Printf(f_module, "%s\n", module_imports);
 492
 493      if (Len(module_class_modifiers) > 0)
 494	Printf(f_module, "%s ", module_class_modifiers);
 495      Printf(f_module, "%s ", module_class_name);
 496
 497      if (module_baseclass && *Char(module_baseclass))
 498	Printf(f_module, ": %s ", module_baseclass);
 499      if (Len(module_interfaces) > 0)
 500	Printv(f_module, "implements ", module_interfaces, " ", NIL);
 501      Printf(f_module, "{\n");
 502
 503      Replaceall(module_class_code, "$module", module_class_name);
 504      Replaceall(module_class_constants_code, "$module", module_class_name);
 505
 506      Replaceall(module_class_code, "$imclassname", imclass_name);
 507      Replaceall(module_class_constants_code, "$imclassname", imclass_name);
 508
 509      Replaceall(module_class_code, "$dllimport", dllimport);
 510      Replaceall(module_class_constants_code, "$dllimport", dllimport);
 511
 512      // Add the wrapper methods
 513      Printv(f_module, module_class_code, NIL);
 514
 515      // Write out all the global constants
 516      Printv(f_module, module_class_constants_code, NIL);
 517
 518      // Finish off the class
 519      Printf(f_module, "}\n");
 520      addCloseNamespace(0, f_module);
 521
 522      Close(f_module);
 523    }
 524
 525    if (upcasts_code)
 526      Printv(f_wrappers, upcasts_code, NIL);
 527
 528    Printf(f_wrappers, "#ifdef __cplusplus\n");
 529    Printf(f_wrappers, "}\n");
 530    Printf(f_wrappers, "#endif\n");
 531
 532    // Output a C# type wrapper class for each SWIG type
 533    for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
 534      emitTypeWrapperClass(swig_type.key, swig_type.item);
 535    }
 536
 537    // Check for overwriting file problems on filesystems that are case insensitive
 538    Iterator it1;
 539    Iterator it2;
 540    for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
 541      String *item1_lower = Swig_string_lower(it1.item);
 542      for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
 543	String *item2_lower = Swig_string_lower(it2.item);
 544	if (it1.item && it2.item) {
 545	  if (Strcmp(item1_lower, item2_lower) == 0) {
 546	    Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
 547			 "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
 548			 "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
 549	  }
 550	}
 551	Delete(item2_lower);
 552      }
 553      Delete(item1_lower);
 554    }
 555
 556    Delete(swig_types_hash);
 557    swig_types_hash = NULL;
 558    Delete(filenames_list);
 559    filenames_list = NULL;
 560    Delete(imclass_name);
 561    imclass_name = NULL;
 562    Delete(imclass_class_code);
 563    imclass_class_code = NULL;
 564    Delete(proxy_class_def);
 565    proxy_class_def = NULL;
 566    Delete(proxy_class_code);
 567    proxy_class_code = NULL;
 568    Delete(module_class_constants_code);
 569    module_class_constants_code = NULL;
 570    Delete(imclass_baseclass);
 571    imclass_baseclass = NULL;
 572    Delete(imclass_interfaces);
 573    imclass_interfaces = NULL;
 574    Delete(imclass_class_modifiers);
 575    imclass_class_modifiers = NULL;
 576    Delete(module_class_name);
 577    module_class_name = NULL;
 578    Delete(module_class_code);
 579    module_class_code = NULL;
 580    Delete(module_baseclass);
 581    module_baseclass = NULL;
 582    Delete(module_interfaces);
 583    module_interfaces = NULL;
 584    Delete(module_imports);
 585    module_imports = NULL;
 586    Delete(module_class_modifiers);
 587    module_class_modifiers = NULL;
 588    Delete(imclass_imports);
 589    imclass_imports = NULL;
 590    Delete(imclass_cppcasts_code);
 591    imclass_cppcasts_code = NULL;
 592    Delete(upcasts_code);
 593    upcasts_code = NULL;
 594    Delete(dmethods_seq);
 595    dmethods_seq = NULL;
 596    Delete(dmethods_table);
 597    dmethods_table = NULL;
 598    Delete(namespce);
 599    namespce = NULL;
 600    n_dmethods = 0;
 601
 602    /* Close all of the files */
 603    Dump(f_runtime, f_begin);
 604    Dump(f_header, f_begin);
 605
 606    if (directorsEnabled()) {
 607      Dump(f_directors, f_begin);
 608      Dump(f_directors_h, f_runtime_h);
 609
 610      Printf(f_runtime_h, "\n");
 611      Printf(f_runtime_h, "#endif\n");
 612
 613      Close(f_runtime_h);
 614      Delete(f_runtime_h);
 615      f_runtime_h = NULL;
 616      Delete(f_directors);
 617      f_directors = NULL;
 618      Delete(f_directors_h);
 619      f_directors_h = NULL;
 620    }
 621
 622    Dump(f_wrappers, f_begin);
 623    Wrapper_pretty_print(f_init, f_begin);
 624    Delete(f_header);
 625    Delete(f_wrappers);
 626    Delete(f_init);
 627    Close(f_begin);
 628    Delete(f_runtime);
 629    Delete(f_begin);
 630    return SWIG_OK;
 631  }
 632
 633  /* -----------------------------------------------------------------------------
 634   * emitBanner()
 635   * ----------------------------------------------------------------------------- */
 636
 637  void emitBanner(File *f) {
 638    Printf(f, "/* ----------------------------------------------------------------------------\n");
 639    Swig_banner_target_lang(f, " *");
 640    Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
 641  }
 642
 643  /*-----------------------------------------------------------------------
 644   * Add new director upcall signature
 645   *----------------------------------------------------------------------*/
 646
 647  UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *decl, String *overloaded_name) {
 648    UpcallData *udata;
 649    String *class_methodidx;
 650    Hash *new_udata;
 651    String *key = NewStringf("%s|%s", imclass_method, decl);
 652
 653    ++curr_class_dmethod;
 654
 655    /* Do we know about this director class already? */
 656    if ((udata = Getattr(dmethods_table, key))) {
 657      Delete(key);
 658      return Getattr(udata, "methodoff");
 659    }
 660
 661    class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
 662    n_dmethods++;
 663
 664    new_udata = NewHash();
 665    Append(dmethods_seq, new_udata);
 666    Setattr(dmethods_table, key, new_udata);
 667
 668    Setattr(new_udata, "method", Copy(class_method));
 669    Setattr(new_udata, "class_methodidx", class_methodidx);
 670    Setattr(new_udata, "decl", Copy(decl));
 671    Setattr(new_udata, "overname", Copy(overloaded_name));
 672
 673    Delete(key);
 674    return new_udata;
 675  }
 676
 677  /*-----------------------------------------------------------------------
 678   * Get director upcall signature
 679   *----------------------------------------------------------------------*/
 680
 681  /*
 682     UpcallData * getUpcallMethodData(String *director_class, String *decl) {
 683     String             *key = NewStringf("%s|%s", director_class, decl);
 684     UpcallData         *udata = Getattr(dmethods_table, key);
 685
 686     Delete(key);
 687     return udata;
 688     }
 689   */
 690
 691  /* ----------------------------------------------------------------------
 692   * nativeWrapper()
 693   * ---------------------------------------------------------------------- */
 694
 695  virtual int nativeWrapper(Node *n) {
 696    String *wrapname = Getattr(n, "wrap:name");
 697
 698    if (!addSymbol(wrapname, n, imclass_name))
 699      return SWIG_ERROR;
 700
 701    if (Getattr(n, "type")) {
 702      Swig_save("nativeWrapper", n, "name", NIL);
 703      Setattr(n, "name", wrapname);
 704      native_function_flag = true;
 705      functionWrapper(n);
 706      Swig_restore(n);
 707      native_function_flag = false;
 708    } else {
 709      Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
 710    }
 711
 712    return SWIG_OK;
 713  }
 714
 715  /* ----------------------------------------------------------------------
 716   * functionWrapper()
 717   * ---------------------------------------------------------------------- */
 718
 719  virtual int functionWrapper(Node *n) {
 720    String *symname = Getattr(n, "sym:name");
 721    SwigType *t = Getattr(n, "type");
 722    ParmList *l = Getattr(n, "parms");
 723    String *tm;
 724    Parm *p;
 725    int i;
 726    String *c_return_type = NewString("");
 727    String *im_return_type = NewString("");
 728    String *cleanup = NewString("");
 729    String *outarg = NewString("");
 730    String *body = NewString("");
 731    String *im_outattributes = 0;
 732    int num_arguments = 0;
 733    bool is_void_return;
 734    String *overloaded_name = getOverloadedName(n);
 735
 736    if (!Getattr(n, "sym:overloaded")) {
 737      if (!addSymbol(Getattr(n, "sym:name"), n, imclass_name))
 738	return SWIG_ERROR;
 739    }
 740
 741    /*
 742       The rest of this function deals with generating the intermediary class wrapper function (that wraps
 743       a c/c++ function) and generating the PInvoke c code. Each C# wrapper function has a 
 744       matching PInvoke c function call.
 745     */
 746
 747    // A new wrapper function object
 748    Wrapper *f = NewWrapper();
 749
 750    // Make a wrapper name for this function
 751    String *wname = Swig_name_wrapper(overloaded_name);
 752
 753    /* Attach the non-standard typemaps to the parameter list. */
 754    Swig_typemap_attach_parms("ctype", l, f);
 755    Swig_typemap_attach_parms("imtype", l, f);
 756
 757    /* Get return types */
 758    if ((tm = Swig_typemap_lookup("ctype", n, "", 0))) {
 759      String *ctypeout = Getattr(n, "tmap:ctype:out");	// the type in the ctype typemap's out attribute overrides the type in the typemap
 760      if (ctypeout)
 761	tm = ctypeout;
 762      Printf(c_return_type, "%s", tm);
 763    } else {
 764      Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(t, 0));
 765    }
 766
 767    if ((tm = Swig_typemap_lookup("imtype", n, "", 0))) {
 768      String *imtypeout = Getattr(n, "tmap:imtype:out");	// the type in the imtype typemap's out attribute overrides the type in the typemap
 769      if (imtypeout)
 770	tm = imtypeout;
 771      Printf(im_return_type, "%s", tm);
 772      im_outattributes = Getattr(n, "tmap:imtype:outattributes");
 773    } else {
 774      Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(t, 0));
 775    }
 776
 777    is_void_return = (Cmp(c_return_type, "void") == 0);
 778    if (!is_void_return)
 779      Wrapper_add_localv(f, "jresult", c_return_type, "jresult", NIL);
 780
 781    Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL);
 782
 783    // Emit all of the local variables for holding arguments.
 784    emit_parameter_variables(l, f);
 785
 786    /* Attach the standard typemaps */
 787    emit_attach_parmmaps(l, f);
 788
 789    // Parameter overloading
 790    Setattr(n, "wrap:parms", l);
 791    Setattr(n, "wrap:name", wname);
 792
 793    // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
 794    if (Getattr(n, "sym:overloaded")) {
 795      // Emit warnings for the few cases that can't be overloaded in C# and give up on generating wrapper
 796      Swig_overload_check(n);
 797      if (Getattr(n, "overload:ignore"))
 798	return SWIG_OK;
 799    }
 800
 801    Printv(imclass_class_code, "\n  [DllImport(\"", dllimport, "\", EntryPoint=\"", wname, "\")]\n", NIL);
 802
 803    if (im_outattributes)
 804      Printf(imclass_class_code, "  %s\n", im_outattributes);
 805
 806    Printf(imclass_class_code, "  public static extern %s %s(", im_return_type, overloaded_name);
 807
 808
 809    /* Get number of required and total arguments */
 810    num_arguments = emit_num_arguments(l);
 811    int gencomma = 0;
 812
 813    // Now walk the function parameter list and generate code to get arguments
 814    for (i = 0, p = l; i < num_arguments; i++) {
 815
 816      while (checkAttribute(p, "tmap:in:numinputs", "0")) {
 817	p = Getattr(p, "tmap:in:next");
 818      }
 819
 820      SwigType *pt = Getattr(p, "type");
 821      String *ln = Getattr(p, "lname");
 822      String *im_param_type = NewString("");
 823      String *c_param_type = NewString("");
 824      String *arg = NewString("");
 825
 826      Printf(arg, "j%s", ln);
 827
 828      /* Get the ctype types of the parameter */
 829      if ((tm = Getattr(p, "tmap:ctype"))) {
 830	Printv(c_param_type, tm, NIL);
 831      } else {
 832	Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0));
 833      }
 834
 835      /* Get the intermediary class parameter types of the parameter */
 836      if ((tm = Getattr(p, "tmap:imtype"))) {
 837	const String *inattributes = Getattr(p, "tmap:imtype:inattributes");
 838	Printf(im_param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
 839      } else {
 840	Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0));
 841      }
 842
 843      /* Add parameter to intermediary class method */
 844      if (gencomma)
 845	Printf(imclass_class_code, ", ");
 846      Printf(imclass_class_code, "%s %s", im_param_type, arg);
 847
 848      // Add parameter to C function
 849      Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
 850
 851      gencomma = 1;
 852
 853      // Get typemap for this argument
 854      if ((tm = Getattr(p, "tmap:in"))) {
 855	canThrow(n, "in", p);
 856	Replaceall(tm, "$source", arg);	/* deprecated */
 857	Replaceall(tm, "$target", ln);	/* deprecated */
 858	Replaceall(tm, "$arg", arg);	/* deprecated? */
 859	Replaceall(tm, "$input", arg);
 860	Setattr(p, "emit:input", arg);
 861	Printf(f->code, "%s\n", tm);
 862	p = Getattr(p, "tmap:in:next");
 863      } else {
 864	Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
 865	p = nextSibling(p);
 866      }
 867      Delete(im_param_type);
 868      Delete(c_param_type);
 869      Delete(arg);
 870    }
 871
 872    /* Insert constraint checking code */
 873    for (p = l; p;) {
 874      if ((tm = Getattr(p, "tmap:check"))) {
 875	canThrow(n, "check", p);
 876	Replaceall(tm, "$target", Getattr(p, "lname"));	/* deprecated */
 877	Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */
 878	Replaceall(tm, "$input", Getattr(p, "emit:input"));
 879	Printv(f->code, tm, "\n", NIL);
 880	p = Getattr(p, "tmap:check:next");
 881      } else {
 882	p = nextSibling(p);
 883      }
 884    }
 885
 886    /* Insert cleanup code */
 887    for (p = l; p;) {
 888      if ((tm = Getattr(p, "tmap:freearg"))) {
 889	canThrow(n, "freearg", p);
 890	Replaceall(tm, "$source", Getattr(p, "emit:input"));	/* deprecated */
 891	Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */
 892	Replaceall(tm, "$input", Getattr(p, "emit:input"));
 893	Printv(cleanup, tm, "\n", NIL);
 894	p = Getattr(p, "tmap:freearg:next");
 895      } else {
 896	p = nextSibling(p);
 897      }
 898    }
 899
 900    /* Insert argument output code */
 901    for (p = l; p;) {
 902      if ((tm = Getattr(p, "tmap:argout"))) {
 903	canThrow(n, "argout", p);
 904	Replaceall(tm, "$source", Getattr(p, "emit:input"));	/* deprecated */
 905	Replaceall(tm, "$target", Getattr(p, "lname"));	/* deprecated */
 906	Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */
 907	Replaceall(tm, "$result", "jresult");
 908	Replaceall(tm, "$input", Getattr(p, "emit:input"));
 909	Printv(outarg, tm, "\n", NIL);
 910	p = Getattr(p, "tmap:argout:next");
 911      } else {
 912	p = nextSibling(p);
 913      }
 914    }
 915
 916    // Look for usage of throws typemap and the canthrow flag
 917    ParmList *throw_parm_list = NULL;
 918    if ((throw_parm_list = Getattr(n, "catchlist"))) {
 919      Swig_typemap_attach_parms("throws", throw_parm_list, f);
 920      for (p = throw_parm_list; p; p = nextSibling(p)) {
 921	if ((tm = Getattr(p, "tmap:throws"))) {
 922	  canThrow(n, "throws", p);
 923	}
 924      }
 925    }
 926
 927    String *null_attribute = 0;
 928    // Now write code to make the function call
 929    if (!native_function_flag) {
 930      if (Cmp(nodeType(n), "constant") == 0) {
 931        // Wrapping a constant hack
 932        Swig_save("functionWrapper", n, "wrap:action", NIL);
 933
 934        // below based on Swig_VargetToFunction()
 935        SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
 936        Setattr(n, "wrap:action", NewStringf("%s = (%s)(%s);", Swig_cresult_name(), SwigType_lstr(ty, 0), Getattr(n, "value")));
 937      }
 938
 939      Swig_director_emit_dynamic_cast(n, f);
 940      String *actioncode = emit_action(n);
 941
 942      if (Cmp(nodeType(n), "constant") == 0)
 943        Swig_restore(n);
 944
 945      /* Return value if necessary  */
 946      if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
 947	canThrow(n, "out", n);
 948	Replaceall(tm, "$source", Swig_cresult_name());	/* deprecated */
 949	Replaceall(tm, "$target", "jresult");	/* deprecated */
 950	Replaceall(tm, "$result", "jresult");
 951
 952        if (GetFlag(n, "feature:new"))
 953          Replaceall(tm, "$owner", "1");
 954        else
 955          Replaceall(tm, "$owner", "0");
 956
 957	Printf(f->code, "%s", tm);
 958	null_attribute = Getattr(n, "tmap:out:null");
 959	if (Len(tm))
 960	  Printf(f->code, "\n");
 961      } else {
 962	Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t, 0), Getattr(n, "name"));
 963      }
 964      emit_return_variable(n, t, f);
 965    }
 966
 967    /* Output argument output code */
 968    Printv(f->code, outarg, NIL);
 969
 970    /* Output cleanup code */
 971    Printv(f->code, cleanup, NIL);
 972
 973    /* Look to see if there is any newfree cleanup code */
 974    if (GetFlag(n, "feature:new")) {
 975      if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
 976	canThrow(n, "newfree", n);
 977	Replaceall(tm, "$source", Swig_cresult_name());	/* deprecated */
 978	Printf(f->code, "%s\n", tm);
 979      }
 980    }
 981
 982    /* See if there is any return cleanup code */
 983    if (!native_function_flag) {
 984      if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
 985	canThrow(n, "ret", n);
 986	Replaceall(tm, "$source", Swig_cresult_name());	/* deprecated */
 987	Printf(f->code, "%s\n", tm);
 988      }
 989    }
 990
 991    /* Finish C function and intermediary class function definitions */
 992    Printf(imclass_class_code, ")");
 993    Printf(imclass_class_code, ";\n");
 994
 995    Printf(f->def, ") {");
 996
 997    if (!is_void_return)
 998      Printv(f->code, "    return jresult;\n", NIL);
 999    Printf(f->code, "}\n");
1000
1001    /* Substitute the cleanup code */
1002    Replaceall(f->code, "$cleanup", cleanup);
1003
1004    /* Substitute the function name */
1005    Replaceall(f->code, "$symname", symname);
1006
1007    /* Contract macro modification */
1008    if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) {
1009      Setattr(n, "csharp:canthrow", "1");
1010    }
1011
1012    if (!null_attribute)
1013      Replaceall(f->code, "$null", "0");
1014    else
1015      Replaceall(f->code, "$null", null_attribute);
1016
1017    /* Dump the function out */
1018    if (!native_function_flag) {
1019      Wrapper_print(f, f_wrappers);
1020
1021      // Handle %csexception which sets the canthrow attribute
1022      if (Getattr(n, "feature:except:canthrow"))
1023	Setattr(n, "csharp:canthrow", "1");
1024
1025      // A very simple check (it is not foolproof) to help typemap/feature writers for
1026      // throwing C# exceptions from unmanaged code. It checks for the common methods which
1027      // set a pending C# exception... the 'canthrow' typemap/feature attribute must be set
1028      // so that code which checks for pending exceptions is added in the C# proxy method.
1029      if (!Getattr(n, "csharp:canthrow")) {
1030	if (Strstr(f->code, "SWIG_exception")) {
1031	  Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
1032		       "Unmanaged code contains a call to SWIG_exception and C# code does not handle pending exceptions via the canthrow attribute.\n");
1033	} else if (Strstr(f->code, "SWIG_CSharpSetPendingException")) {
1034	  Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
1035		       "Unmanaged code contains a call to a SWIG_CSharpSetPendingException method and C# code does not handle pending exceptions via the canthrow attribute.\n");
1036	}
1037      }
1038    }
1039
1040    if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
1041      moduleClassFunctionHandler(n);
1042    }
1043
1044    /* 
1045     * Generate the proxy class properties for public member variables.
1046     * Not for enums and constants.
1047     */
1048    if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
1049      // Capitalize the first letter in the variable in the getter/setter function name
1050      bool getter_flag = Cmp(symname, Swig_name_set(getNSpace(), Swig_name_member(0, proxy_class_name, variable_name))) != 0;
1051
1052      String *getter_setter_name = NewString("");
1053      if (!getter_flag)
1054	Printf(getter_setter_name, "set");
1055      else
1056	Printf(getter_setter_name, "get");
1057      Putc(toupper((int) *Char(variable_name)), getter_setter_name);
1058      Printf(getter_setter_name, "%s", Char(variable_name) + 1);
1059
1060      Setattr(n, "proxyfuncname", getter_setter_name);
1061      Setattr(n, "imfuncname", symname);
1062
1063      proxyClassFunctionHandler(n);
1064      Delete(getter_setter_name);
1065    }
1066
1067    Delete(c_return_type);
1068    Delete(im_return_type);
1069    Delete(cleanup);
1070    Delete(outarg);
1071    Delete(body);
1072    Delete(overloaded_name);
1073    DelWrapper(f);
1074    return SWIG_OK;
1075  }
1076
1077  /* -----------------------------------------------------------------------
1078   * variableWrapper()
1079   * ----------------------------------------------------------------------- */
1080
1081  virtual int variableWrapper(Node *n) {
1082    Language::variableWrapper(n);
1083    return SWIG_OK;
1084  }
1085
1086  /* -----------------------------------------------------------------------
1087   * globalvariableHandler()
1088   * ------------------------------------------------------------------------ */
1089
1090  virtual int globalvariableHandler(Node *n) {
1091
1092    generate_property_declaration_flag = true;
1093    variable_name = Getattr(n, "sym:name");
1094    global_variable_flag = true;
1095    int ret = Language::globalvariableHandler(n);
1096    global_variable_flag = false;
1097    generate_property_declaration_flag = false;
1098
1099    if (proxy_flag) {
1100      Printf(module_class_code, "\n  }\n\n");
1101    }
1102
1103    return ret;
1104  }
1105
1106  /* ----------------------------------------------------------------------
1107   * enumDeclaration()
1108   *
1109   * C/C++ enums can be mapped in one of 4 ways, depending on the cs:enum feature specified:
1110   * 1) Simple enums - simple constant within the proxy class or module class
1111   * 2) Typeunsafe enums - simple constant in a C# class (class named after the c++ enum name)
1112   * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
1113   * 4) Proper enums - proper C# enum
1114   * Anonymous enums always default to 1)
1115   * ---------------------------------------------------------------------- */
1116
1117  virtual int enumDeclaration(Node *n) {
1118
1119    if (!ImportMode) {
1120      if (getCurrentClass() && (cplus_mode != PUBLIC))
1121	return SWIG_NOWRAP;
1122
1123      String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call
1124      if (proxy_flag && !is_wrapping_class()) {
1125	// Global enums / enums in a namespace
1126	assert(!full_imclass_name);
1127
1128	if (!nspace) {
1129	  full_imclass_name = NewStringf("%s", imclass_name);
1130	} else {
1131	  if (namespce) {
1132	    full_imclass_name = NewStringf("%s.%s", namespce, imclass_name);
1133	  } else {
1134	    full_imclass_name = NewStringf("%s", imclass_name);
1135	  }
1136	}
1137      }
1138
1139      enum_code = NewString("");
1140      String *symname = Getattr(n, "sym:name");
1141      String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
1142      EnumFeature enum_feature = decodeEnumFeature(n);
1143      String *typemap_lookup_type = Getattr(n, "name");
1144
1145      if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
1146	// Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
1147
1148	String *scope = 0;
1149	if (nspace || proxy_class_name) {
1150	  scope = NewString("");
1151	  if (nspace)
1152	    Printf(scope, "%s", nspace);
1153	  if (proxy_class_name)
1154	    Printv(scope, nspace ? "." : "", proxy_class_name, NIL);
1155	}
1156	if (!addSymbol(symname, n, scope))
1157	  return SWIG_ERROR;
1158
1159	// Pure C# baseclass and interfaces
1160	const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE);
1161	const String *pure_interfaces = typemapLookup(n, "csinterfaces", typemap_lookup_type, WARN_NONE);
1162
1163	// Class attributes
1164	const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
1165	if (csattributes && *Char(csattributes))
1166	  Printf(enum_code, "%s\n", csattributes);
1167
1168	// Emit the enum
1169	Printv(enum_code, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF),	// Class modifiers (enum modifiers really)
1170	       " ", symname, (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ?	// Interfaces
1171	       ", " : "", pure_interfaces, " {\n", NIL);
1172	Delete(scope);
1173      } else {
1174	// Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort
1175	if (symname && !Getattr(n, "unnamedinstance"))
1176	  Printf(constants_code, "  // %s \n", symname);
1177      }
1178
1179      // Emit each enum item
1180      Language::enumDeclaration(n);
1181
1182      if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
1183	// Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
1184	// Finish the enum declaration
1185	// Typemaps are used to generate the enum definition in a similar manner to proxy classes.
1186	Printv(enum_code, (enum_feature == ProperEnum) ? "\n" : typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF),	// main body of class
1187	       typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE),	// extra C# code
1188	       "}", NIL);
1189
1190	Replaceall(enum_code, "$csclassname", symname);
1191
1192	// Substitute $enumvalues - intended usage is for typesafe enums
1193	if (Getattr(n, "enumvalues"))
1194	  Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
1195	else
1196	  Replaceall(enum_code, "$enumvalues", "");
1197
1198	if (proxy_flag && is_wrapping_class()) {
1199	  // Enums defined within the C++ class are defined within the proxy class
1200
1201	  // Add extra indentation
1202	  Replaceall(enum_code, "\n", "\n  ");
1203	  Replaceall(enum_code, "  \n", "\n");
1204
1205	  Printv(proxy_class_constants_code, "  ", enum_code, "\n\n", NIL);
1206	} else {
1207	  // Global enums are defined in their own file
1208	  String *output_directory = outputDirectory(nspace);
1209	  String *filen = NewStringf("%s%s.cs", output_directory, symname);
1210	  File *f_enum = NewFile(filen, "w", SWIG_output_files());
1211	  if (!f_enum) {
1212	    FileErrorDisplay(filen);
1213	    SWIG_exit(EXIT_FAILURE);
1214	  }
1215	  Append(filenames_list, Copy(filen));
1216	  Delete(filen);
1217	  filen = NULL;
1218
1219	  // Start writing out the enum file
1220	  emitBanner(f_enum);
1221
1222	  addOpenNamespace(nspace, f_enum);
1223
1224	  Printv(f_enum, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
1225		 "\n", enum_code, "\n", NIL);
1226
1227	  addCloseNamespace(nspace, f_enum);
1228	  Close(f_enum);
1229	  Delete(output_directory);
1230	}
1231      } else {
1232	// Wrap C++ enum with simple constant
1233	Printf(enum_code, "\n");
1234	if (proxy_flag && is_wrapping_class())
1235	  Printv(proxy_class_constants_code, enum_code, NIL);
1236	else
1237	  Printv(module_class_constants_code, enum_code, NIL);
1238      }
1239
1240      Delete(enum_code);
1241      enum_code = NULL;
1242
1243      if (proxy_flag && !is_wrapping_class()) {
1244	Delete(full_imclass_name);
1245	full_imclass_name = 0;
1246      }
1247    }
1248    return SWIG_OK;
1249  }
1250
1251  /* ----------------------------------------------------------------------
1252   * enumvalueDeclaration()
1253   * ---------------------------------------------------------------------- */
1254
1255  virtual int enumvalueDeclaration(Node *n) {
1256    if (getCurrentClass() && (cplus_mode != PUBLIC))
1257      return SWIG_NOWRAP;
1258
1259    Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
1260    String *symname = Getattr(n, "sym:name");
1261    String *value = Getattr(n, "value");
1262    String *name = Getattr(n, "name");
1263    Node *parent = parentNode(n);
1264    int unnamedinstance = GetFlag(parent, "unnamedinstance");
1265    String *parent_name = Getattr(parent, "name");
1266    String *nspace = getNSpace();
1267    String *tmpValue;
1268
1269    // Strange hack from parent method
1270    if (value)
1271      tmpValue = NewString(value);
1272    else
1273      tmpValue = NewString(name);
1274    // Note that this is used in enumValue() amongst other places
1275    Setattr(n, "value", tmpValue);
1276
1277    // Deal with enum values that are not int
1278    int swigtype = SwigType_type(Getattr(n, "type"));
1279    if (swigtype == T_BOOL) {
1280      const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0";
1281      Setattr(n, "enumvalue", val);
1282    } else if (swigtype == T_CHAR) {
1283      String *val = NewStringf("'%s'", Getattr(n, "enumvalue"));
1284      Setattr(n, "enumvalue", val);
1285      Delete(val);
1286    }
1287
1288    {
1289      EnumFeature enum_feature = decodeEnumFeature(parent);
1290
1291      // Add to language symbol table
1292      String *scope = 0;
1293      if (unnamedinstance || !parent_name || enum_feature == SimpleEnum) {
1294	if (proxy_class_name) {
1295	  scope = NewString("");
1296	  if (nspace)
1297	    Printf(scope, "%s.", nspace);
1298	  Printf(scope, "%s", proxy_class_name);
1299	} else {
1300	  scope = Copy(module_class_name);
1301	}
1302      } else {
1303	scope = NewString("");
1304	if (nspace)
1305	  Printf(scope, "%s.", nspace);
1306	if (proxy_class_name)
1307	  Printf(scope, "%s.", proxy_class_name);
1308	Printf(scope, "%s",Getattr(parent, "sym:name"));
1309      }
1310      if (!addSymbol(name, n, scope))
1311	return SWIG_ERROR;
1312
1313      const String *csattributes = Getattr(n, "feature:cs:attributes");
1314
1315      if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
1316	// Wrap (non-anonymous) C/C++ enum with a proper C# enum
1317	// Emit the enum item.
1318	if (!GetFlag(n, "firstenumitem"))
1319	  Printf(enum_code, ",\n");
1320
1321	if (csattributes)
1322	  Printf(enum_code, "  %s\n", csattributes);
1323
1324	Printf(enum_code, "  %s", symname);
1325
1326	// Check for the %csconstvalue feature
1327	String *value = Getattr(n, "feature:cs:constvalue");
1328
1329	// Note that the enum value must be a true constant and cannot be set from a PINVOKE call, thus no support for %csconst(0)
1330	value = value ? value : Getattr(n, "enumvalue");
1331	if (value) {
1332	  Printf(enum_code, " = %s", value);
1333	}
1334      } else {
1335	// Wrap C/C++ enums with constant integers or use the typesafe enum pattern
1336	SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
1337	Setattr(n, "type", typemap_lookup_type);
1338	const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF);
1339
1340	String *return_type = Copy(tm);
1341	substituteClassname(typemap_lookup_type, return_type);
1342        const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
1343        methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1344
1345	if (csattributes)
1346	  Printf(enum_code, "  %s\n", csattributes);
1347
1348	if ((enum_feature == TypesafeEnum) && parent_name && !unnamedinstance) {
1349	  // Wrap (non-anonymous) enum using the typesafe enum pattern
1350	  if (Getattr(n, "enumvalue")) {
1351	    String *value = enumValue(n);
1352	    Printf(enum_code, "  %s static readonly %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
1353	    Delete(value);
1354	  } else {
1355	    Printf(enum_code, "  %s static readonly %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
1356	  }
1357	} else {
1358	  // Simple integer constants
1359	  // Note these are always generated for anonymous enums, no matter what enum_feature is specified
1360	  // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
1361
1362	  // The %csconst feature determines how the constant value is obtained
1363	  int const_feature_flag = GetFlag(n, "feature:cs:const");
1364
1365	  const char *const_readonly = const_feature_flag ? "const" : "static readonly";
1366	  String *value = enumValue(n);
1367	  Printf(enum_code, "  %s %s %s %s = %s;\n", methodmods, const_readonly, return_type, symname, value);
1368	  Delete(value);
1369	}
1370	Delete(return_type);
1371      }
1372
1373      // Add the enum value to the comma separated list being constructed in the enum declaration.
1374      String *enumvalues = Getattr(parent, "enumvalues");
1375      if (!enumvalues)
1376	Setattr(parent, "enumvalues", Copy(symname));
1377      else
1378	Printv(enumvalues, ", ", symname, NIL);
1379      Delete(scope);
1380    }
1381
1382    Delete(tmpValue);
1383    Swig_restore(n);
1384    return SWIG_OK;
1385  }
1386
1387  /* -----------------------------------------------------------------------
1388   * constantWrapper()
1389   * Used for wrapping constants - #define or %constant.
1390   * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
1391   * C# static const variables are generated for these.
1392   * If the %csconst(1) feature is used then the C constant value is used to initialise the C# const variable.
1393   * If not, a PINVOKE method is generated to get the C constant value for initialisation of the C# const variable.
1394   * However, if the %csconstvalue feature is used, it overrides all other ways to generate the initialisation.
1395   * Also note that this method might be called for wrapping enum items (when the enum is using %csconst(0)).
1396   * ------------------------------------------------------------------------ */
1397
1398  virtual int constantWrapper(Node *n) {
1399    String *symname = Getattr(n, "sym:name");
1400    SwigType *t = Getattr(n, "type");
1401    ParmList *l = Getattr(n, "parms");
1402    String *tm;
1403    String *return_type = NewString("");
1404    String *constants_code = NewString("");
1405    Swig_save("constantWrapper", n, "value", NIL);
1406    Swig_save("constantWrapper", n, "tmap:ctype:out", "tmap:imtype:out", "tmap:cstype:out", "tmap:out:null", "tmap:imtype:outattributes", "tmap:cstype:outattributes", NIL);
1407
1408    bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
1409
1410    const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
1411    if (!is_enum_item) {
1412      String *scope = 0;
1413      if (proxy_class_name) {
1414	String *nspace = getNSpace();
1415	scope = NewString("");
1416	if (nspace)
1417	  Printf(scope, "%s.", nspace);
1418	Printf(scope, "%s", prox

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