1/* -----------------------------------------------------------------------------
2 * See the LICENSE file for information on copyright, usage and redistribution
3 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
4 *
5 * csharp.cxx
6 *
7 * C# language module for SWIG.
8 * ----------------------------------------------------------------------------- */
9
10char cvsroot_csharp_cxx[] = "$Id: csharp.cxx 11583 2009-08-15 23:22:20Z wsfulton $";
11
12#include "swigmod.h"
13#include <limits.h>		// for INT_MAX
14#include "cparse.h"
15#include <ctype.h>
16
17/* Hash type used for upcalls from C/C++ */
18typedef DOH UpcallData;
19
20class CSHARP:public Language {
21  static const char *usage;
22  const String *empty_string;
23  const String *public_string;
24  const String *protected_string;
25
26  Hash *swig_types_hash;
27  File *f_begin;
28  File *f_runtime;
29  File *f_runtime_h;
30  File *f_header;
31  File *f_wrappers;
32  File *f_init;
33  File *f_directors;
34  File *f_directors_h;
35  List *filenames_list;
36
37  bool proxy_flag;		// Flag for generating proxy classes
38  bool native_function_flag;	// Flag for when wrapping a native function
39  bool enum_constant_flag;	// Flag for when wrapping an enum or constant
40  bool static_flag;		// Flag for when wrapping a static functions or member variables
41  bool variable_wrapper_flag;	// Flag for when wrapping a nonstatic member variable
42  bool wrapping_member_flag;	// Flag for when wrapping a member variable/enum/const
43  bool global_variable_flag;	// Flag for when wrapping a global variable
44  bool old_variable_names;	// Flag for old style variable names in the intermediary class
45  bool generate_property_declaration_flag;	// Flag for generating properties
46
47  String *imclass_name;		// intermediary class name
48  String *module_class_name;	// module class name
49  String *imclass_class_code;	// intermediary class code
50  String *proxy_class_def;
51  String *proxy_class_code;
52  String *module_class_code;
53  String *proxy_class_name;
54  String *variable_name;	//Name of a variable being wrapped
55  String *proxy_class_constants_code;
56  String *module_class_constants_code;
57  String *enum_code;
58  String *dllimport;		// DllImport attribute name
59  String *namespce;		// Optional namespace name
60  String *imclass_imports;	//intermediary class imports from %pragma
61  String *module_imports;	//module imports from %pragma
62  String *imclass_baseclass;	//inheritance for intermediary class class from %pragma
63  String *module_baseclass;	//inheritance for module class from %pragma
64  String *imclass_interfaces;	//interfaces for intermediary class class from %pragma
65  String *module_interfaces;	//interfaces for module class from %pragma
66  String *imclass_class_modifiers;	//class modifiers for intermediary class overriden by %pragma
67  String *module_class_modifiers;	//class modifiers for module class overriden by %pragma
68  String *upcasts_code;		//C++ casts for inheritance hierarchies C++ code
69  String *imclass_cppcasts_code;	//C++ casts up inheritance hierarchies intermediary class code
70  String *director_callback_typedefs;	// Director function pointer typedefs for callbacks
71  String *director_callbacks;	// Director callback function pointer member variables
72  String *director_delegate_callback;	// Director callback method that delegates are set to call
73  String *director_delegate_definitions;	// Director delegates definitions in proxy class
74  String *director_delegate_instances;	// Director delegates member variables in proxy class
75  String *director_method_types;	// Director method types
76  String *director_connect_parms;	// Director delegates parameter list for director connect call
77  String *destructor_call;	//C++ destructor call if any
78
79  // Director method stuff:
80  List *dmethods_seq;
81  Hash *dmethods_table;
82  int n_dmethods;
83  int n_directors;
84  int first_class_dmethod;
85  int curr_class_dmethod;
86
87  enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
88
89  static Parm *NewParmFromNode(SwigType *type, const_String_or_char_ptr name, Node *n) {
90    Parm *p = NewParm(type, name);
91    Setfile(p, Getfile(n));
92    Setline(p, Getline(n));
93    return p;
94  }
95
96public:
97
98  /* -----------------------------------------------------------------------------
99   * CSHARP()
100   * ----------------------------------------------------------------------------- */
101
102   CSHARP():empty_string(NewString("")),
103      public_string(NewString("public")),
104      protected_string(NewString("protected")),
105      swig_types_hash(NULL),
106      f_begin(NULL),
107      f_runtime(NULL),
108      f_runtime_h(NULL),
109      f_header(NULL),
110      f_wrappers(NULL),
111      f_init(NULL),
112      f_directors(NULL),
113      f_directors_h(NULL),
114      filenames_list(NULL),
115      proxy_flag(true),
116      native_function_flag(false),
117      enum_constant_flag(false),
118      static_flag(false),
119      variable_wrapper_flag(false),
120      wrapping_member_flag(false),
121      global_variable_flag(false),
122      old_variable_names(false),
123      generate_property_declaration_flag(false),
124      imclass_name(NULL),
125      module_class_name(NULL),
126      imclass_class_code(NULL),
127      proxy_class_def(NULL),
128      proxy_class_code(NULL),
129      module_class_code(NULL),
130      proxy_class_name(NULL),
131      variable_name(NULL),
132      proxy_class_constants_code(NULL),
133      module_class_constants_code(NULL),
134      enum_code(NULL),
135      dllimport(NULL),
136      namespce(NULL),
137      imclass_imports(NULL),
138      module_imports(NULL),
139      imclass_baseclass(NULL),
140      module_baseclass(NULL),
141      imclass_interfaces(NULL),
142      module_interfaces(NULL),
143      imclass_class_modifiers(NULL),
144      module_class_modifiers(NULL),
145      upcasts_code(NULL),
146      imclass_cppcasts_code(NULL),
147      director_callback_typedefs(NULL),
148      director_callbacks(NULL),
149      director_delegate_callback(NULL),
150      director_delegate_definitions(NULL),
151      director_delegate_instances(NULL),
152      director_method_types(NULL),
153      director_connect_parms(NULL),
154      destructor_call(NULL),
155      dmethods_seq(NULL),
156      dmethods_table(NULL),
157      n_dmethods(0),
158      n_directors(0) {
159    /* for now, multiple inheritance in directors is disabled, this
160       should be easy to implement though */
161    director_multiple_inheritance = 0;
162    director_language = 1;
163  }
164
165  /* -----------------------------------------------------------------------------
166   * getProxyName()
167   *
168   * Test to see if a type corresponds to something wrapped with a proxy class
169   * Return NULL if not otherwise the proxy class name
170   * ----------------------------------------------------------------------------- */
171
172   String *getProxyName(SwigType *t) {
173    if (proxy_flag) {
174      Node *n = classLookup(t);
175      if (n) {
176	return Getattr(n, "sym:name");
177      }
178    }
179    return NULL;
180  }
181
182  /* -----------------------------------------------------------------------------
183   * directorClassName()
184   * ----------------------------------------------------------------------------- */
185
186  String *directorClassName(Node *n) {
187    String *dirclassname;
188    const char *attrib = "director:classname";
189
190    if (!(dirclassname = Getattr(n, attrib))) {
191      String *classname = Getattr(n, "sym:name");
192
193      dirclassname = NewStringf("SwigDirector_%s", classname);
194      Setattr(n, attrib, dirclassname);
195    }
196
197    return dirclassname;
198  }
199
200  /* ------------------------------------------------------------
201   * main()
202   * ------------------------------------------------------------ */
203
204  virtual void main(int argc, char *argv[]) {
205
206    SWIG_library_directory("csharp");
207
208    // Look for certain command line options
209    for (int i = 1; i < argc; i++) {
210      if (argv[i]) {
211	if (strcmp(argv[i], "-dllimport") == 0) {
212	  if (argv[i + 1]) {
213	    dllimport = NewString("");
214	    Printf(dllimport, argv[i + 1]);
215	    Swig_mark_arg(i);
216	    Swig_mark_arg(i + 1);
217	    i++;
218	  } else {
219	    Swig_arg_error();
220	  }
221	} else if (strcmp(argv[i], "-namespace") == 0) {
222	  if (argv[i + 1]) {
223	    namespce = NewString("");
224	    Printf(namespce, argv[i + 1]);
225	    Swig_mark_arg(i);
226	    Swig_mark_arg(i + 1);
227	    i++;
228	  } else {
229	    Swig_arg_error();
230	  }
231	} else if ((strcmp(argv[i], "-noproxy") == 0)) {
232	  Swig_mark_arg(i);
233	  proxy_flag = false;
234	} else if (strcmp(argv[i], "-oldvarnames") == 0) {
235	  Swig_mark_arg(i);
236	  old_variable_names = true;
237	} else if (strcmp(argv[i], "-help") == 0) {
238	  Printf(stdout, "%s\n", usage);
239	}
240      }
241    }
242
243    // Add a symbol to the parser for conditional compilation
244    Preprocessor_define("SWIGCSHARP 1", 0);
245
246    // Add typemap definitions
247    SWIG_typemap_lang("csharp");
248    SWIG_config_file("csharp.swg");
249
250    allow_overloading();
251  }
252
253  /* ---------------------------------------------------------------------
254   * top()
255   * --------------------------------------------------------------------- */
256
257  virtual int top(Node *n) {
258
259    // Get any options set in the module directive
260    Node *optionsnode = Getattr(Getattr(n, "module"), "options");
261
262    if (optionsnode) {
263      if (Getattr(optionsnode, "imclassname"))
264	imclass_name = Copy(Getattr(optionsnode, "imclassname"));
265      /* check if directors are enabled for this module.  note: this
266       * is a "master" switch, without which no director code will be
267       * emitted.  %feature("director") statements are also required
268       * to enable directors for individual classes or methods.
269       *
270       * use %module(directors="1") modulename at the start of the
271       * interface file to enable director generation.
272       */
273      if (Getattr(optionsnode, "directors")) {
274	allow_directors();
275      }
276      if (Getattr(optionsnode, "dirprot")) {
277	allow_dirprot();
278      }
279      allow_allprotected(GetFlag(optionsnode, "allprotected"));
280    }
281
282    /* Initialize all of the output files */
283    String *outfile = Getattr(n, "outfile");
284    String *outfile_h = Getattr(n, "outfile_h");
285
286    if (!outfile) {
287      Printf(stderr, "Unable to determine outfile\n");
288      SWIG_exit(EXIT_FAILURE);
289    }
290
291    f_begin = NewFile(outfile, "w", SWIG_output_files());
292    if (!f_begin) {
293      FileErrorDisplay(outfile);
294      SWIG_exit(EXIT_FAILURE);
295    }
296
297    if (directorsEnabled()) {
298      if (!outfile_h) {
299        Printf(stderr, "Unable to determine outfile_h\n");
300        SWIG_exit(EXIT_FAILURE);
301      }
302      f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
303      if (!f_runtime_h) {
304	FileErrorDisplay(outfile_h);
305	SWIG_exit(EXIT_FAILURE);
306      }
307    }
308
309    f_runtime = NewString("");
310    f_init = NewString("");
311    f_header = NewString("");
312    f_wrappers = NewString("");
313    f_directors_h = NewString("");
314    f_directors = NewString("");
315
316    /* Register file targets with the SWIG file handler */
317    Swig_register_filebyname("header", f_header);
318    Swig_register_filebyname("wrapper", f_wrappers);
319    Swig_register_filebyname("begin", f_begin);
320    Swig_register_filebyname("runtime", f_runtime);
321    Swig_register_filebyname("init", f_init);
322    Swig_register_filebyname("director", f_directors);
323    Swig_register_filebyname("director_h", f_directors_h);
324
325    swig_types_hash = NewHash();
326    filenames_list = NewList();
327
328    // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
329    if (!imclass_name) {
330      imclass_name = NewStringf("%sPINVOKE", Getattr(n, "name"));
331      module_class_name = Copy(Getattr(n, "name"));
332    } else {
333      // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
334      if (Cmp(imclass_name, Getattr(n, "name")) == 0)
335	module_class_name = NewStringf("%sModule", Getattr(n, "name"));
336      else
337	module_class_name = Copy(Getattr(n, "name"));
338    }
339
340    imclass_class_code = NewString("");
341    proxy_class_def = NewString("");
342    proxy_class_code = NewString("");
343    module_class_constants_code = NewString("");
344    imclass_baseclass = NewString("");
345    imclass_interfaces = NewString("");
346    imclass_class_modifiers = NewString("");
347    module_class_code = NewString("");
348    module_baseclass = NewString("");
349    module_interfaces = NewString("");
350    module_imports = NewString("");
351    module_class_modifiers = NewString("");
352    imclass_imports = NewString("");
353    imclass_cppcasts_code = NewString("");
354    director_connect_parms = NewString("");
355    upcasts_code = NewString("");
356    dmethods_seq = NewList();
357    dmethods_table = NewHash();
358    n_dmethods = 0;
359    n_directors = 0;
360    if (!namespce)
361      namespce = NewString("");
362    if (!dllimport)
363      dllimport = Copy(module_class_name);
364
365    Swig_banner(f_begin);
366
367    Printf(f_runtime, "\n");
368    Printf(f_runtime, "#define SWIGCSHARP\n");
369
370    if (directorsEnabled()) {
371      Printf(f_runtime, "#define SWIG_DIRECTORS\n");
372
373      /* Emit initial director header and director code: */
374      Swig_banner(f_directors_h);
375      Printf(f_directors_h, "\n");
376      Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
377      Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
378
379      Printf(f_directors, "\n\n");
380      Printf(f_directors, "/* ---------------------------------------------------\n");
381      Printf(f_directors, " * C++ director class methods\n");
382      Printf(f_directors, " * --------------------------------------------------- */\n\n");
383      if (outfile_h)
384	Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
385    }
386
387    Printf(f_runtime, "\n");
388
389    Swig_name_register((char *) "wrapper", (char *) "CSharp_%f");
390    if (old_variable_names) {
391      Swig_name_register((char *) "set", (char *) "set_%v");
392      Swig_name_register((char *) "get", (char *) "get_%v");
393    }
394
395    Printf(f_wrappers, "\n#ifdef __cplusplus\n");
396    Printf(f_wrappers, "extern \"C\" {\n");
397    Printf(f_wrappers, "#endif\n\n");
398
399    /* Emit code */
400    Language::top(n);
401
402    if (directorsEnabled()) {
403      // Insert director runtime into the f_runtime file (make it occur before %header section)
404      Swig_insert_file("director.swg", f_runtime);
405    }
406    // Generate the intermediary class
407    {
408      String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), imclass_name);
409      File *f_im = NewFile(filen, "w", SWIG_output_files());
410      if (!f_im) {
411	FileErrorDisplay(filen);
412	SWIG_exit(EXIT_FAILURE);
413      }
414      Append(filenames_list, Copy(filen));
415      Delete(filen);
416      filen = NULL;
417
418      // Start writing out the intermediary class file
419      emitBanner(f_im);
420
421      addOpenNamespace(namespce, f_im);
422
423      if (imclass_imports)
424	Printf(f_im, "%s\n", imclass_imports);
425
426      if (Len(imclass_class_modifiers) > 0)
427	Printf(f_im, "%s ", imclass_class_modifiers);
428      Printf(f_im, "%s ", imclass_name);
429
430      if (imclass_baseclass && *Char(imclass_baseclass))
431	Printf(f_im, ": %s ", imclass_baseclass);
432      if (Len(imclass_interfaces) > 0)
433	Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
434      Printf(f_im, "{\n");
435
436      // Add the intermediary class methods
437      Replaceall(imclass_class_code, "$module", module_class_name);
438      Replaceall(imclass_class_code, "$imclassname", imclass_name);
439      Replaceall(imclass_class_code, "$dllimport", dllimport);
440      Printv(f_im, imclass_class_code, NIL);
441      Printv(f_im, imclass_cppcasts_code, NIL);
442
443      // Finish off the class
444      Printf(f_im, "}\n");
445      addCloseNamespace(namespce, f_im);
446
447      Close(f_im);
448    }
449
450    // Generate the C# module class
451    {
452      String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), module_class_name);
453      File *f_module = NewFile(filen, "w", SWIG_output_files());
454      if (!f_module) {
455	FileErrorDisplay(filen);
456	SWIG_exit(EXIT_FAILURE);
457      }
458      Append(filenames_list, Copy(filen));
459      Delete(filen);
460      filen = NULL;
461
462      // Start writing out the module class file
463      emitBanner(f_module);
464
465      addOpenNamespace(namespce, f_module);
466
467      if (module_imports)
468	Printf(f_module, "%s\n", module_imports);
469
470      if (Len(module_class_modifiers) > 0)
471	Printf(f_module, "%s ", module_class_modifiers);
472      Printf(f_module, "%s ", module_class_name);
473
474      if (module_baseclass && *Char(module_baseclass))
475	Printf(f_module, ": %s ", module_baseclass);
476      if (Len(module_interfaces) > 0)
477	Printv(f_module, "implements ", module_interfaces, " ", NIL);
478      Printf(f_module, "{\n");
479
480      Replaceall(module_class_code, "$module", module_class_name);
481      Replaceall(module_class_constants_code, "$module", module_class_name);
482
483      Replaceall(module_class_code, "$imclassname", imclass_name);
484      Replaceall(module_class_constants_code, "$imclassname", imclass_name);
485
486      Replaceall(module_class_code, "$dllimport", dllimport);
487      Replaceall(module_class_constants_code, "$dllimport", dllimport);
488
489      // Add the wrapper methods
490      Printv(f_module, module_class_code, NIL);
491
492      // Write out all the global constants
493      Printv(f_module, module_class_constants_code, NIL);
494
495      // Finish off the class
496      Printf(f_module, "}\n");
497      addCloseNamespace(namespce, f_module);
498
499      Close(f_module);
500    }
501
502    if (upcasts_code)
503      Printv(f_wrappers, upcasts_code, NIL);
504
505    Printf(f_wrappers, "#ifdef __cplusplus\n");
506    Printf(f_wrappers, "}\n");
507    Printf(f_wrappers, "#endif\n");
508
509    // Output a C# type wrapper class for each SWIG type
510    for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
511      emitTypeWrapperClass(swig_type.key, swig_type.item);
512    }
513
514    // Check for overwriting file problems on filesystems that are case insensitive
515    Iterator it1;
516    Iterator it2;
517    for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
518      String *item1_lower = Swig_string_lower(it1.item);
519      for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
520	String *item2_lower = Swig_string_lower(it2.item);
521	if (it1.item && it2.item) {
522	  if (Strcmp(item1_lower, item2_lower) == 0) {
523	    Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
524			 "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
525			 "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
526	  }
527	}
528	Delete(item2_lower);
529      }
530      Delete(item1_lower);
531    }
532
533    Delete(swig_types_hash);
534    swig_types_hash = NULL;
535    Delete(filenames_list);
536    filenames_list = NULL;
537    Delete(imclass_name);
538    imclass_name = NULL;
539    Delete(imclass_class_code);
540    imclass_class_code = NULL;
541    Delete(proxy_class_def);
542    proxy_class_def = NULL;
543    Delete(proxy_class_code);
544    proxy_class_code = NULL;
545    Delete(module_class_constants_code);
546    module_class_constants_code = NULL;
547    Delete(imclass_baseclass);
548    imclass_baseclass = NULL;
549    Delete(imclass_interfaces);
550    imclass_interfaces = NULL;
551    Delete(imclass_class_modifiers);
552    imclass_class_modifiers = NULL;
553    Delete(module_class_name);
554    module_class_name = NULL;
555    Delete(module_class_code);
556    module_class_code = NULL;
557    Delete(module_baseclass);
558    module_baseclass = NULL;
559    Delete(module_interfaces);
560    module_interfaces = NULL;
561    Delete(module_imports);
562    module_imports = NULL;
563    Delete(module_class_modifiers);
564    module_class_modifiers = NULL;
565    Delete(imclass_imports);
566    imclass_imports = NULL;
567    Delete(imclass_cppcasts_code);
568    imclass_cppcasts_code = NULL;
569    Delete(upcasts_code);
570    upcasts_code = NULL;
571    Delete(dmethods_seq);
572    dmethods_seq = NULL;
573    Delete(dmethods_table);
574    dmethods_table = NULL;
575    Delete(namespce);
576    namespce = NULL;
577    n_dmethods = 0;
578
579    /* Close all of the files */
580    Dump(f_runtime, f_begin);
581    Dump(f_header, f_begin);
582
583    if (directorsEnabled()) {
584      Dump(f_directors, f_begin);
585      Dump(f_directors_h, f_runtime_h);
586
587      Printf(f_runtime_h, "\n");
588      Printf(f_runtime_h, "#endif\n");
589
590      Close(f_runtime_h);
591      Delete(f_runtime_h);
592      f_runtime_h = NULL;
593      Delete(f_directors);
594      f_directors = NULL;
595      Delete(f_directors_h);
596      f_directors_h = NULL;
597    }
598
599    Dump(f_wrappers, f_begin);
600    Wrapper_pretty_print(f_init, f_begin);
601    Delete(f_header);
602    Delete(f_wrappers);
603    Delete(f_init);
604    Close(f_begin);
605    Delete(f_runtime);
606    Delete(f_begin);
607    return SWIG_OK;
608  }
609
610  /* -----------------------------------------------------------------------------
611   * emitBanner()
612   * ----------------------------------------------------------------------------- */
613
614  void emitBanner(File *f) {
615    Printf(f, "/* ----------------------------------------------------------------------------\n");
616    Swig_banner_target_lang(f, " *");
617    Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
618  }
619
620  /*-----------------------------------------------------------------------
621   * Add new director upcall signature
622   *----------------------------------------------------------------------*/
623
624  UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *decl, String *overloaded_name) {
625    UpcallData *udata;
626    String *imclass_methodidx;
627    String *class_methodidx;
628    Hash *new_udata;
629    String *key = NewStringf("%s|%s", imclass_method, decl);
630
631    ++curr_class_dmethod;
632
633    /* Do we know about this director class already? */
634    if ((udata = Getattr(dmethods_table, key))) {
635      Delete(key);
636      return Getattr(udata, "methodoff");
637    }
638
639    imclass_methodidx = NewStringf("%d", n_dmethods);
640    class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
641    n_dmethods++;
642
643    new_udata = NewHash();
644    Append(dmethods_seq, new_udata);
645    Setattr(dmethods_table, key, new_udata);
646
647    Setattr(new_udata, "method", Copy(class_method));
648    // TODO: remove fdesc
649//    Setattr(new_udata, "fdesc", Copy(class_desc));
650//    Setattr(new_udata, "imclass_method", Copy(imclass_method));
651//    Setattr(new_udata, "imclass_methodidx", imclass_methodidx);
652    Setattr(new_udata, "class_methodidx", class_methodidx);
653    Setattr(new_udata, "decl", Copy(decl));
654    Setattr(new_udata, "overname", Copy(overloaded_name));
655
656    Delete(key);
657    return new_udata;
658  }
659
660  /*-----------------------------------------------------------------------
661   * Get director upcall signature
662   *----------------------------------------------------------------------*/
663
664  /*
665     UpcallData * getUpcallMethodData(String *director_class, String *decl) {
666     String             *key = NewStringf("%s|%s", director_class, decl);
667     UpcallData         *udata = Getattr(dmethods_table, key);
668
669     Delete(key);
670     return udata;
671     }
672   */
673
674  /* ----------------------------------------------------------------------
675   * nativeWrapper()
676   * ---------------------------------------------------------------------- */
677
678  virtual int nativeWrapper(Node *n) {
679    String *wrapname = Getattr(n, "wrap:name");
680
681    if (!addSymbol(wrapname, n))
682      return SWIG_ERROR;
683
684    if (Getattr(n, "type")) {
685      Swig_save("nativeWrapper", n, "name", NIL);
686      Setattr(n, "name", wrapname);
687      native_function_flag = true;
688      functionWrapper(n);
689      Swig_restore(n);
690      native_function_flag = false;
691    } else {
692      Printf(stderr, "%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, Getattr(n, "wrap:name"));
693    }
694
695    return SWIG_OK;
696  }
697
698  /* ----------------------------------------------------------------------
699   * functionWrapper()
700   * ---------------------------------------------------------------------- */
701
702  virtual int functionWrapper(Node *n) {
703    String *symname = Getattr(n, "sym:name");
704    SwigType *t = Getattr(n, "type");
705    ParmList *l = Getattr(n, "parms");
706    String *tm;
707    Parm *p;
708    int i;
709    String *c_return_type = NewString("");
710    String *im_return_type = NewString("");
711    String *cleanup = NewString("");
712    String *outarg = NewString("");
713    String *body = NewString("");
714    String *im_outattributes = 0;
715    int num_arguments = 0;
716    int num_required = 0;
717    bool is_void_return;
718    String *overloaded_name = getOverloadedName(n);
719
720    if (!Getattr(n, "sym:overloaded")) {
721      if (!addSymbol(Getattr(n, "sym:name"), n))
722	return SWIG_ERROR;
723    }
724
725    /*
726       The rest of this function deals with generating the intermediary class wrapper function (that wraps
727       a c/c++ function) and generating the PInvoke c code. Each C# wrapper function has a
728       matching PInvoke c function call.
729     */
730
731    // A new wrapper function object
732    Wrapper *f = NewWrapper();
733
734    // Make a wrapper name for this function
735    String *wname = Swig_name_wrapper(overloaded_name);
736
737    /* Attach the non-standard typemaps to the parameter list. */
738    Swig_typemap_attach_parms("ctype", l, f);
739    Swig_typemap_attach_parms("imtype", l, f);
740
741    /* Get return types */
742    if ((tm = Swig_typemap_lookup("ctype", n, "", 0))) {
743      String *ctypeout = Getattr(n, "tmap:ctype:out");	// the type in the ctype typemap's out attribute overrides the type in the typemap
744      if (ctypeout)
745	tm = ctypeout;
746      Printf(c_return_type, "%s", tm);
747    } else {
748      Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(t, 0));
749    }
750
751    if ((tm = Swig_typemap_lookup("imtype", n, "", 0))) {
752      String *imtypeout = Getattr(n, "tmap:imtype:out");	// the type in the imtype typemap's out attribute overrides the type in the typemap
753      if (imtypeout)
754	tm = imtypeout;
755      Printf(im_return_type, "%s", tm);
756      im_outattributes = Getattr(n, "tmap:imtype:outattributes");
757    } else {
758      Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(t, 0));
759    }
760
761    is_void_return = (Cmp(c_return_type, "void") == 0);
762    if (!is_void_return)
763      Wrapper_add_localv(f, "jresult", c_return_type, "jresult", NIL);
764
765    Printv(f->def, " SWIGEXPORT ", c_return_type, " SWIGSTDCALL ", wname, "(", NIL);
766
767    // Emit all of the local variables for holding arguments.
768    emit_parameter_variables(l, f);
769
770    /* Attach the standard typemaps */
771    emit_attach_parmmaps(l, f);
772
773    // Parameter overloading
774    Setattr(n, "wrap:parms", l);
775    Setattr(n, "wrap:name", wname);
776
777    // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
778    if (Getattr(n, "sym:overloaded")) {
779      // Emit warnings for the few cases that can't be overloaded in C# and give up on generating wrapper
780      Swig_overload_check(n);
781      if (Getattr(n, "overload:ignore"))
782	return SWIG_OK;
783    }
784
785    Printv(imclass_class_code, "\n  [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", overloaded_name, "\")]\n", NIL);
786
787    if (im_outattributes)
788      Printf(imclass_class_code, "  %s\n", im_outattributes);
789
790    Printf(imclass_class_code, "  public static extern %s %s(", im_return_type, overloaded_name);
791
792
793    /* Get number of required and total arguments */
794    num_arguments = emit_num_arguments(l);
795    num_required = emit_num_required(l);
796    int gencomma = 0;
797
798    // Now walk the function parameter list and generate code to get arguments
799    for (i = 0, p = l; i < num_arguments; i++) {
800
801      while (checkAttribute(p, "tmap:in:numinputs", "0")) {
802	p = Getattr(p, "tmap:in:next");
803      }
804
805      SwigType *pt = Getattr(p, "type");
806      String *ln = Getattr(p, "lname");
807      String *im_param_type = NewString("");
808      String *c_param_type = NewString("");
809      String *arg = NewString("");
810
811      Printf(arg, "j%s", ln);
812
813      /* Get the ctype types of the parameter */
814      if ((tm = Getattr(p, "tmap:ctype"))) {
815	Printv(c_param_type, tm, NIL);
816      } else {
817	Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0));
818      }
819
820      /* Get the intermediary class parameter types of the parameter */
821      if ((tm = Getattr(p, "tmap:imtype"))) {
822	const String *inattributes = Getattr(p, "tmap:imtype:inattributes");
823	Printf(im_param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
824      } else {
825	Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0));
826      }
827
828      /* Add parameter to intermediary class method */
829      if (gencomma)
830	Printf(imclass_class_code, ", ");
831      Printf(imclass_class_code, "%s %s", im_param_type, arg);
832
833      // Add parameter to C function
834      Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
835
836      gencomma = 1;
837
838      // Get typemap for this argument
839      if ((tm = Getattr(p, "tmap:in"))) {
840	canThrow(n, "in", p);
841	Replaceall(tm, "$source", arg);	/* deprecated */
842	Replaceall(tm, "$target", ln);	/* deprecated */
843	Replaceall(tm, "$arg", arg);	/* deprecated? */
844	Replaceall(tm, "$input", arg);
845	Setattr(p, "emit:input", arg);
846	Printf(f->code, "%s\n", tm);
847	p = Getattr(p, "tmap:in:next");
848      } else {
849	Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
850	p = nextSibling(p);
851      }
852      Delete(im_param_type);
853      Delete(c_param_type);
854      Delete(arg);
855    }
856
857    /* Insert constraint checking code */
858    for (p = l; p;) {
859      if ((tm = Getattr(p, "tmap:check"))) {
860	canThrow(n, "check", p);
861	Replaceall(tm, "$target", Getattr(p, "lname"));	/* deprecated */
862	Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */
863	Replaceall(tm, "$input", Getattr(p, "emit:input"));
864	Printv(f->code, tm, "\n", NIL);
865	p = Getattr(p, "tmap:check:next");
866      } else {
867	p = nextSibling(p);
868      }
869    }
870
871    /* Insert cleanup code */
872    for (p = l; p;) {
873      if ((tm = Getattr(p, "tmap:freearg"))) {
874	canThrow(n, "freearg", p);
875	Replaceall(tm, "$source", Getattr(p, "emit:input"));	/* deprecated */
876	Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */
877	Replaceall(tm, "$input", Getattr(p, "emit:input"));
878	Printv(cleanup, tm, "\n", NIL);
879	p = Getattr(p, "tmap:freearg:next");
880      } else {
881	p = nextSibling(p);
882      }
883    }
884
885    /* Insert argument output code */
886    for (p = l; p;) {
887      if ((tm = Getattr(p, "tmap:argout"))) {
888	canThrow(n, "argout", p);
889	Replaceall(tm, "$source", Getattr(p, "emit:input"));	/* deprecated */
890	Replaceall(tm, "$target", Getattr(p, "lname"));	/* deprecated */
891	Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */
892	Replaceall(tm, "$result", "jresult");
893	Replaceall(tm, "$input", Getattr(p, "emit:input"));
894	Printv(outarg, tm, "\n", NIL);
895	p = Getattr(p, "tmap:argout:next");
896      } else {
897	p = nextSibling(p);
898      }
899    }
900
901    // Look for usage of throws typemap and the canthrow flag
902    ParmList *throw_parm_list = NULL;
903    if ((throw_parm_list = Getattr(n, "catchlist"))) {
904      Swig_typemap_attach_parms("throws", throw_parm_list, f);
905      for (p = throw_parm_list; p; p = nextSibling(p)) {
906	if ((tm = Getattr(p, "tmap:throws"))) {
907	  canThrow(n, "throws", p);
908	}
909      }
910    }
911
912    String *null_attribute = 0;
913    // Now write code to make the function call
914    if (!native_function_flag) {
915      if (Cmp(nodeType(n), "constant") == 0) {
916        // Wrapping a constant hack
917        Swig_save("functionWrapper", n, "wrap:action", NIL);
918
919        // below based on Swig_VargetToFunction()
920        SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
921        Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value")));
922      }
923
924      Swig_director_emit_dynamic_cast(n, f);
925      String *actioncode = emit_action(n);
926
927      if (Cmp(nodeType(n), "constant") == 0)
928        Swig_restore(n);
929
930      /* Return value if necessary  */
931      if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
932	canThrow(n, "out", n);
933	Replaceall(tm, "$source", "result");	/* deprecated */
934	Replaceall(tm, "$target", "jresult");	/* deprecated */
935	Replaceall(tm, "$result", "jresult");
936
937        if (GetFlag(n, "feature:new"))
938          Replaceall(tm, "$owner", "1");
939        else
940          Replaceall(tm, "$owner", "0");
941
942	Printf(f->code, "%s", tm);
943	null_attribute = Getattr(n, "tmap:out:null");
944	if (Len(tm))
945	  Printf(f->code, "\n");
946      } else {
947	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"));
948      }
949      emit_return_variable(n, t, f);
950    }
951
952    /* Output argument output code */
953    Printv(f->code, outarg, NIL);
954
955    /* Output cleanup code */
956    Printv(f->code, cleanup, NIL);
957
958    /* Look to see if there is any newfree cleanup code */
959    if (GetFlag(n, "feature:new")) {
960      if ((tm = Swig_typemap_lookup("newfree", n, "result", 0))) {
961	canThrow(n, "newfree", n);
962	Replaceall(tm, "$source", "result");	/* deprecated */
963	Printf(f->code, "%s\n", tm);
964      }
965    }
966
967    /* See if there is any return cleanup code */
968    if (!native_function_flag) {
969      if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
970	canThrow(n, "ret", n);
971	Replaceall(tm, "$source", "result");	/* deprecated */
972	Printf(f->code, "%s\n", tm);
973      }
974    }
975
976    /* Finish C function and intermediary class function definitions */
977    Printf(imclass_class_code, ")");
978    Printf(imclass_class_code, ";\n");
979
980    Printf(f->def, ") {");
981
982    if (!is_void_return)
983      Printv(f->code, "    return jresult;\n", NIL);
984    Printf(f->code, "}\n");
985
986    /* Substitute the cleanup code */
987    Replaceall(f->code, "$cleanup", cleanup);
988
989    /* Substitute the function name */
990    Replaceall(f->code, "$symname", symname);
991
992    /* Contract macro modification */
993    if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) {
994      Setattr(n, "csharp:canthrow", "1");
995    }
996
997    if (!null_attribute)
998      Replaceall(f->code, "$null", "0");
999    else
1000      Replaceall(f->code, "$null", null_attribute);
1001
1002    /* Dump the function out */
1003    if (!native_function_flag) {
1004      Wrapper_print(f, f_wrappers);
1005
1006      // Handle %csexception which sets the canthrow attribute
1007      if (Getattr(n, "feature:except:canthrow"))
1008	Setattr(n, "csharp:canthrow", "1");
1009
1010      // A very simple check (it is not foolproof) to help typemap/feature writers for
1011      // throwing C# exceptions from unmanaged code. It checks for the common methods which
1012      // set a pending C# exception... the 'canthrow' typemap/feature attribute must be set
1013      // so that code which checks for pending exceptions is added in the C# proxy method.
1014      if (!Getattr(n, "csharp:canthrow")) {
1015	if (Strstr(f->code, "SWIG_exception")) {
1016	  Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
1017		       "Unmanaged code contains a call to SWIG_exception and C# code does not handle pending exceptions via the canthrow attribute.\n");
1018	} else if (Strstr(f->code, "SWIG_CSharpSetPendingException")) {
1019	  Swig_warning(WARN_CSHARP_CANTHROW, input_file, line_number,
1020		       "Unmanaged code contains a call to a SWIG_CSharpSetPendingException method and C# code does not handle pending exceptions via the canthrow attribute.\n");
1021	}
1022      }
1023    }
1024
1025    if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
1026      moduleClassFunctionHandler(n);
1027    }
1028
1029    /*
1030     * Generate the proxy class properties for public member variables.
1031     * Not for enums and constants.
1032     */
1033    if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
1034      // Capitalize the first letter in the variable in the getter/setter function name
1035      bool getter_flag = Cmp(symname, Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) != 0;
1036
1037      String *getter_setter_name = NewString("");
1038      if (!getter_flag)
1039	Printf(getter_setter_name, "set");
1040      else
1041	Printf(getter_setter_name, "get");
1042      Putc(toupper((int) *Char(variable_name)), getter_setter_name);
1043      Printf(getter_setter_name, "%s", Char(variable_name) + 1);
1044
1045      Setattr(n, "proxyfuncname", getter_setter_name);
1046      Setattr(n, "imfuncname", symname);
1047
1048      proxyClassFunctionHandler(n);
1049      Delete(getter_setter_name);
1050    }
1051
1052    Delete(c_return_type);
1053    Delete(im_return_type);
1054    Delete(cleanup);
1055    Delete(outarg);
1056    Delete(body);
1057    Delete(overloaded_name);
1058    DelWrapper(f);
1059    return SWIG_OK;
1060  }
1061
1062  /* -----------------------------------------------------------------------
1063   * variableWrapper()
1064   * ----------------------------------------------------------------------- */
1065
1066  virtual int variableWrapper(Node *n) {
1067    Language::variableWrapper(n);
1068    return SWIG_OK;
1069  }
1070
1071  /* -----------------------------------------------------------------------
1072   * globalvariableHandler()
1073   * ------------------------------------------------------------------------ */
1074
1075  virtual int globalvariableHandler(Node *n) {
1076
1077    generate_property_declaration_flag = true;
1078    variable_name = Getattr(n, "sym:name");
1079    global_variable_flag = true;
1080    int ret = Language::globalvariableHandler(n);
1081    global_variable_flag = false;
1082    generate_property_declaration_flag = false;
1083
1084    if (proxy_flag) {
1085      Printf(module_class_code, "\n  }\n\n");
1086    }
1087
1088    return ret;
1089  }
1090
1091  /* ----------------------------------------------------------------------
1092   * enumDeclaration()
1093   *
1094   * C/C++ enums can be mapped in one of 4 ways, depending on the cs:enum feature specified:
1095   * 1) Simple enums - simple constant within the proxy class or module class
1096   * 2) Typeunsafe enums - simple constant in a C# class (class named after the c++ enum name)
1097   * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
1098   * 4) Proper enums - proper C# enum
1099   * Anonymous enums always default to 1)
1100   * ---------------------------------------------------------------------- */
1101
1102  virtual int enumDeclaration(Node *n) {
1103
1104    if (!ImportMode) {
1105      if (getCurrentClass() && (cplus_mode != PUBLIC))
1106	return SWIG_NOWRAP;
1107
1108      enum_code = NewString("");
1109      String *symname = Getattr(n, "sym:name");
1110      String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
1111      EnumFeature enum_feature = decodeEnumFeature(n);
1112      String *typemap_lookup_type = Getattr(n, "name");
1113
1114      if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
1115	// Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
1116
1117	// Pure C# baseclass and interfaces
1118	const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE);
1119	const String *pure_interfaces = typemapLookup(n, "csinterfaces", typemap_lookup_type, WARN_NONE);
1120
1121	// Class attributes
1122	const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
1123	if (csattributes && *Char(csattributes))
1124	  Printf(enum_code, "%s\n", csattributes);
1125
1126	// Emit the enum
1127	Printv(enum_code, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF),	// Class modifiers (enum modifiers really)
1128	       " ", symname, (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ?	// Interfaces
1129	       ", " : "", pure_interfaces, " {\n", NIL);
1130      } else {
1131	// Wrap C++ enum with integers - just indicate start of enum with a comment, no comment for anonymous enums of any sort
1132	if (symname && !Getattr(n, "unnamedinstance"))
1133	  Printf(constants_code, "  // %s \n", symname);
1134      }
1135
1136      // Emit each enum item
1137      Language::enumDeclaration(n);
1138
1139      if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
1140	// Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper C# enum
1141	// Finish the enum declaration
1142	// Typemaps are used to generate the enum definition in a similar manner to proxy classes.
1143	Printv(enum_code, (enum_feature == ProperEnum) ? "\n" : typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF),	// main body of class
1144	       typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE),	// extra C# code
1145	       "}", NIL);
1146
1147	Replaceall(enum_code, "$csclassname", symname);
1148
1149	// Substitute $enumvalues - intended usage is for typesafe enums
1150	if (Getattr(n, "enumvalues"))
1151	  Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
1152	else
1153	  Replaceall(enum_code, "$enumvalues", "");
1154
1155	if (proxy_flag && is_wrapping_class()) {
1156	  // Enums defined within the C++ class are defined within the proxy class
1157
1158	  // Add extra indentation
1159	  Replaceall(enum_code, "\n", "\n  ");
1160	  Replaceall(enum_code, "  \n", "\n");
1161
1162	  Printv(proxy_class_constants_code, "  ", enum_code, "\n\n", NIL);
1163	} else {
1164	  // Global enums are defined in their own file
1165	  String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), symname);
1166	  File *f_enum = NewFile(filen, "w", SWIG_output_files());
1167	  if (!f_enum) {
1168	    FileErrorDisplay(filen);
1169	    SWIG_exit(EXIT_FAILURE);
1170	  }
1171	  Append(filenames_list, Copy(filen));
1172	  Delete(filen);
1173	  filen = NULL;
1174
1175	  // Start writing out the enum file
1176	  emitBanner(f_enum);
1177
1178	  addOpenNamespace(namespce, f_enum);
1179
1180	  Printv(f_enum, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE), // Import statements
1181		 "\n", enum_code, "\n", NIL);
1182
1183	  addCloseNamespace(namespce, f_enum);
1184
1185	  Close(f_enum);
1186	}
1187      } else {
1188	// Wrap C++ enum with simple constant
1189	Printf(enum_code, "\n");
1190	if (proxy_flag && is_wrapping_class())
1191	  Printv(proxy_class_constants_code, enum_code, NIL);
1192	else
1193	  Printv(module_class_constants_code, enum_code, NIL);
1194      }
1195
1196      Delete(enum_code);
1197      enum_code = NULL;
1198    }
1199    return SWIG_OK;
1200  }
1201
1202  /* ----------------------------------------------------------------------
1203   * enumvalueDeclaration()
1204   * ---------------------------------------------------------------------- */
1205
1206  virtual int enumvalueDeclaration(Node *n) {
1207    if (getCurrentClass() && (cplus_mode != PUBLIC))
1208      return SWIG_NOWRAP;
1209
1210    Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
1211    String *symname = Getattr(n, "sym:name");
1212    String *value = Getattr(n, "value");
1213    String *name = Getattr(n, "name");
1214    String *tmpValue;
1215
1216    // Strange hack from parent method
1217    if (value)
1218      tmpValue = NewString(value);
1219    else
1220      tmpValue = NewString(name);
1221    // Note that this is used in enumValue() amongst other places
1222    Setattr(n, "value", tmpValue);
1223
1224    {
1225      EnumFeature enum_feature = decodeEnumFeature(parentNode(n));
1226
1227      if ((enum_feature == ProperEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) {
1228	// Wrap (non-anonymous) C/C++ enum with a proper C# enum
1229	// Emit the enum item.
1230	if (!GetFlag(n, "firstenumitem"))
1231	  Printf(enum_code, ",\n");
1232	Printf(enum_code, "  %s", symname);
1233
1234	// Check for the %csconstvalue feature
1235	String *value = Getattr(n, "feature:cs:constvalue");
1236
1237	// Note that the enum value must be a true constant and cannot be set from a PINVOKE call, thus no support for %csconst(0)
1238	value = value ? value : Getattr(n, "enumvalue");
1239	if (value) {
1240	  Printf(enum_code, " = %s", value);
1241	}
1242      } else {
1243	// Wrap C/C++ enums with constant integers or use the typesafe enum pattern
1244	const String *parent_name = Getattr(parentNode(n), "name");
1245	String *typemap_lookup_type = parent_name ? Copy(parent_name) : NewString("int");
1246	const String *tm = typemapLookup(n, "cstype", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF);
1247	String *return_type = Copy(tm);
1248	Delete(typemap_lookup_type);
1249	typemap_lookup_type = NULL;
1250
1251	// The %csconst feature determines how the constant value is obtained
1252	int const_feature_flag = GetFlag(n, "feature:cs:const");
1253
1254        const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
1255        methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1256
1257	if ((enum_feature == TypesafeEnum) && Getattr(parentNode(n), "sym:name") && !Getattr(parentNode(n), "unnamedinstance")) {
1258	  // Wrap (non-anonymouse) enum using the typesafe enum pattern
1259	  if (Getattr(n, "enumvalue")) {
1260	    String *value = enumValue(n);
1261	    Printf(enum_code, "  %s static readonly %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
1262	    Delete(value);
1263	  } else {
1264	    Printf(enum_code, "  %s static readonly %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
1265	  }
1266	} else {
1267	  // Simple integer constants
1268	  // Note these are always generated for anonymous enums, no matter what enum_feature is specified
1269	  // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
1270	  const char *const_readonly = const_feature_flag ? "const" : "static readonly";
1271	  String *value = enumValue(n);
1272	  Printf(enum_code, "  %s %s %s %s = %s;\n", methodmods, const_readonly, return_type, symname, value);
1273	  Delete(value);
1274	}
1275      }
1276
1277      // Add the enum value to the comma separated list being constructed in the enum declaration.
1278      String *enumvalues = Getattr(parentNode(n), "enumvalues");
1279      if (!enumvalues)
1280	Setattr(parentNode(n), "enumvalues", Copy(symname));
1281      else
1282	Printv(enumvalues, ", ", symname, NIL);
1283    }
1284
1285    Delete(tmpValue);
1286    Swig_restore(n);
1287    return SWIG_OK;
1288  }
1289
1290  /* -----------------------------------------------------------------------
1291   * constantWrapper()
1292   * Used for wrapping constants - #define or %constant.
1293   * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
1294   * C# static const variables are generated for these.
1295   * If the %csconst(1) feature is used then the C constant value is used to initialise the C# const variable.
1296   * If not, a PINVOKE method is generated to get the C constant value for initialisation of the C# const variable.
1297   * However, if the %csconstvalue feature is used, it overrides all other ways to generate the initialisation.
1298   * Also note that this method might be called for wrapping enum items (when the enum is using %csconst(0)).
1299   * ------------------------------------------------------------------------ */
1300
1301  virtual int constantWrapper(Node *n) {
1302    String *symname = Getattr(n, "sym:name");
1303    SwigType *t = Getattr(n, "type");
1304    ParmList *l = Getattr(n, "parms");
1305    String *tm;
1306    String *return_type = NewString("");
1307    String *constants_code = NewString("");
1308
1309    if (!addSymbol(symname, n))
1310      return SWIG_ERROR;
1311
1312    bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
1313
1314    // The %csconst feature determines how the constant value is obtained
1315    int const_feature_flag = GetFlag(n, "feature:cs:const");
1316
1317    /* Adjust the enum type for the Swig_typemap_lookup.
1318     * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
1319    if (is_enum_item) {
1320      t = Getattr(parentNode(n), "enumtype");
1321      Setattr(n, "type", t);
1322    }
1323
1324    /* Attach the non-standard typemaps to the parameter list. */
1325    Swig_typemap_attach_parms("cstype", l, NULL);
1326
1327    /* Get C# return types */
1328    bool classname_substituted_flag = false;
1329
1330    if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
1331      String *cstypeout = Getattr(n, "tmap:cstype:out");	// the type in the cstype typemap's out attribute overrides the type in the typemap
1332      if (cstypeout)
1333	tm = cstypeout;
1334      classname_substituted_flag = substituteClassname(t, tm);
1335      Printf(return_type, "%s", tm);
1336    } else {
1337      Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
1338    }
1339
1340    // Add the stripped quotes back in
1341    String *new_value = NewString("");
1342    Swig_save("constantWrapper", n, "value", NIL);
1343    if (SwigType_type(t) == T_STRING) {
1344      Printf(new_value, "\"%s\"", Copy(Getattr(n, "value")));
1345      Setattr(n, "value", new_value);
1346    } else if (SwigType_type(t) == T_CHAR) {
1347      Printf(new_value, "\'%s\'", Copy(Getattr(n, "value")));
1348      Setattr(n, "value", new_value);
1349    }
1350
1351    const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
1352    if (outattributes)
1353      Printf(constants_code, "  %s\n", outattributes);
1354    const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
1355
1356    const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
1357    methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1358
1359    Printf(constants_code, "  %s %s %s %s = ", methodmods, (const_feature_flag ? "const" : "static readonly"), return_type, itemname);
1360
1361    // Check for the %csconstvalue feature
1362    String *value = Getattr(n, "feature:cs:constvalue");
1363
1364    if (value) {
1365      Printf(constants_code, "%s;\n", value);
1366    } else if (!const_feature_flag) {
1367      // Default enum and constant handling will work with any type of C constant and initialises the C# variable from C through a PINVOKE call.
1368
1369      if (classname_substituted_flag) {
1370	if (SwigType_isenum(t)) {
1371	  // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
1372	  Printf(constants_code, "(%s)%s.%s();\n", return_type, imclass_name, Swig_name_get(symname));
1373	} else {
1374	  // This handles function pointers using the %constant directive
1375	  Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, imclass_name, Swig_name_get(symname));
1376	}
1377      } else
1378	Printf(constants_code, "%s.%s();\n", imclass_name, Swig_name_get(symname));
1379
1380      // Each constant and enum value is wrapped with a separate PInvoke function call
1381      SetFlag(n, "feature:immutable");
1382      enum_constant_flag = true;
1383      variableWrapper(n);
1384      enum_constant_flag = false;
1385    } else {
1386      // Alternative constant handling will use the C syntax to make a true C# constant and hope that it compiles as C# code
1387      Printf(constants_code, "%s;\n", Getattr(n, "value"));
1388    }
1389
1390    // Emit the generated code to appropriate place
1391    // Enums only emit the intermediate and PINVOKE methods, so no proxy or module class wrapper methods needed
1392    if (!is_enum_item) {
1393      if (proxy_flag && wrapping_member_flag)
1394	Printv(proxy_class_constants_code, constants_code, NIL);
1395      else
1396	Printv(module_class_constants_code, constants_code, NIL);
1397    }
1398    // Cleanup
1399    Swig_restore(n);
1400    Delete(new_value);
1401    Delete(return_type);
1402    Delete(constants_code);
1403    return SWIG_OK;
1404  }
1405
1406  /* -----------------------------------------------------------------------------
1407   * insertDirective()
1408   * ----------------------------------------------------------------------------- */
1409
1410  virtual int insertDirective(Node *n) {
1411    String *code = Getattr(n, "code");
1412    Replaceall(code, "$module", module_class_name);
1413    Replaceall(code, "$imclassname", imclass_name);
1414    Replaceall(code, "$dllimport", dllimport);
1415    return Language::insertDirective(n);
1416  }
1417
1418  /* -----------------------------------------------------------------------------
1419   * pragmaDirective()
1420   *
1421   * Valid Pragmas:
1422   * imclassbase            - base (extends) for the intermediary class
1423   * imclassclassmodifiers  - class modifiers for the intermediary class
1424   * imclasscode            - text (C# code) is copied verbatim to the intermediary class
1425   * imclassimports         - import statements for the intermediary class
1426   * imclassinterfaces      - interface (implements) for the intermediary class
1427   *
1428   * modulebase              - base (extends) for the module class
1429   * moduleclassmodifiers    - class modifiers for the module class
1430   * modulecode              - text (C# code) is copied verbatim to the module class
1431   * moduleimports           - import statements for the module class
1432   * moduleinterfaces        - interface (implements) for the module class
1433   *
1434   * ----------------------------------------------------------------------------- */
1435
1436  virtual int pragmaDirective(Node *n) {
1437    if (!ImportMode) {
1438      String *lang = Getattr(n, "lang");
1439      String *code = Getattr(n, "name");
1440      String *value = Getattr(n, "value");
1441
1442      if (Strcmp(lang, "csharp") == 0) {
1443
1444	String *strvalue = NewString(value);
1445	Replaceall(strvalue, "\\\"", "\"");
1446
1447	if (Strcmp(code, "imclassbase") == 0) {
1448	  Delete(imclass_baseclass);
1449	  imclass_baseclass = Copy(strvalue);
1450	} else if (Strcmp(code, "imclassclassmodifiers") == 0) {
1451	  Delete(imclass_class_modifiers);
1452	  imclass_class_modifiers = Copy(strvalue);
1453	} else if (Strcmp(code, "imclasscode") == 0) {
1454	  Printf(imclass_class_code, "%s\n", strvalue);
1455	} else if (Strcmp(code, "imclassimports") == 0) {
1456	  Delete(imclass_imports);
1457	  imclass_imports = Copy(strvalue);
1458	} else if (Strcmp(code, "imclassinterfaces") == 0) {
1459	  Delete(imclass_interfaces);
1460	  imclass_interfaces = Copy(strvalue);
1461	} else if (Strcmp(code, "modulebase") == 0) {
1462	  Delete(module_baseclass);
1463	  module_baseclass = Copy(strvalue);
1464	} else if (Strcmp(code, "moduleclassmodifiers") == 0) {
1465	  Delete(module_class_modifiers);
1466	  module_class_modifiers = Copy(strvalue);
1467	} else if (Strcmp(code, "modulecode") == 0) {
1468	  Printf(module_class_code, "%s\n", strvalue);
1469	} else if (Strcmp(code, "moduleimports") == 0) {
1470	  Delete(module_imports);
1471	  module_imports = Copy(strvalue);
1472	} else if (Strcmp(code, "moduleinterfaces") == 0) {
1473	  Delete(module_interfaces);
1474	  module_interfaces = Copy(strvalue);
1475	} else {
1476	  Printf(stderr, "%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
1477	}
1478	Delete(strvalue);
1479      }
1480    }
1481    return Language::pragmaDirective(n);
1482  }
1483
1484  /* -----------------------------------------------------------------------------
1485   * emitProxyClassDefAndCPPCasts()
1486   * ----------------------------------------------------------------------------- */
1487
1488  void emitProxyClassDefAndCPPCasts(Node *n) {
1489    String *c_classname = SwigType_namestr(Getattr(n, "name"));
1490    String *c_baseclass = NULL;
1491    String *baseclass = NULL;
1492    String *c_baseclassname = NULL;
1493    SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
1494    bool feature_director = Swig_directorclass(n) ? true : false;
1495
1496    // Inheritance from pure C# classes
1497    Node *attributes = NewHash();
1498    const String *pure_baseclass = typemapLookup(n, "csbase", typemap_lookup_type, WARN_NONE, attributes);
1499    bool purebase_replace = GetFlag(attributes, "tmap:csbase:replace") ? true : false;
1500    bool purebase_notderived = GetFlag(attributes, "tmap:csbase:notderived") ? true : false;
1501    Delete(attributes);
1502
1503    // C++ inheritance
1504    if (!purebase_replace) {
1505      List *baselist = Getattr(n, "bases");
1506      if (baselist) {
1507        Iterator base = First(baselist);
1508        while (base.item && GetFlag(base.item, "feature:ignore")) {
1509          base = Next(base);
1510        }
1511        if (base.item) {
1512          c_baseclassname = Getattr(base.item, "name");
1513          baseclass = Copy(getProxyName(c_baseclassname));
1514          if (baseclass)
1515            c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
1516          base = Next(base);
1517          /* Warn about multiple inheritance for additional base class(es) */
1518          while (base.item) {
1519            if (GetFlag(base.item, "feature:ignore")) {
1520              base = Next(base);
1521              continue;
1522            }
1523            String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
1524            String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
1525            Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number,
1526                         "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", proxyclassname, baseclassname);
1527            base = Next(base);
1528          }
1529        }
1530      }
1531    }
1532
1533    bool derived = baseclass && getProxyName(c_baseclassname);
1534    if (derived && purebase_notderived)
1535      pure_baseclass = empty_string;
1536    const String *wanted_base = baseclass ? baseclass : pure_baseclass;
1537
1538    if (purebase_replace) {
1539      wanted_base = pure_baseclass;
1540      derived = false;
1541      Delete(baseclass);
1542      baseclass = NULL;
1543      if (purebase_notderived)
1544        Swig_error(input_file, line_number, "The csbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
1545    } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
1546      Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number,
1547		   "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#. "
1548		   "Perhaps you need one of the 'replace' or 'notderived' attributes in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
1549    }
1550
1551    // Pure C# interfaces
1552    const String *pure_interfaces = typemapLookup(n, derived ? "csinterfaces_derived" : "csinterfaces", typemap_lookup_type, WARN_NONE);
1553    // Start writing the proxy class
1554    Printv(proxy_class_def, typemapLookup(n, "csimports", typemap_lookup_type, WARN_NONE),	// Import statements
1555	   "\n", NIL);
1556
1557    // Class attributes
1558    const String *csattributes = typemapLookup(n, "csattributes", typemap_lookup_type, WARN_NONE);
1559    if (csattributes && *Char(csattributes))
1560      Printf(proxy_class_def, "%s\n", csattributes);
1561
1562    Printv(proxy_class_def, typemapLookup(n, "csclassmodifiers", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF),	// Class modifiers
1563	   " $csclassname",	// Class name and base class
1564	   (*Char(wanted_base) || *Char(pure_interfaces)) ? " : " : "", wanted_base, (*Char(wanted_base) && *Char(pure_interfaces)) ?	// Interfaces
1565	   ", " : "", pure_interfaces, " {", derived ? typemapLookup(n, "csbody_derived", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF) :	// main body of class
1566	   typemapLookup(n, "csbody", typemap_lookup_type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF),	// main body of class
1567	   NIL);
1568
1569    // C++ destructor is wrapped by the Dispose method
1570    // Note that the method name is specified in a typemap attribute called methodname
1571    String *destruct = NewString("");
1572    const String *tm = NULL;
1573    attributes = NewHash();
1574    String *destruct_methodname = NULL;
1575    String *destruct_methodmodifiers = NULL;
1576    if (derived) {
1577      tm = typemapLookup(n, "csdestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
1578      destruct_methodname = Getattr(attributes, "tmap:csdestruct_derived:methodname");
1579      destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct_derived:methodmodifiers");
1580    } else {
1581      tm = typemapLookup(n, "csdestruct", typemap_lookup_type, WARN_NONE, attributes);
1582      destruct_methodname = Getattr(attributes, "tmap:csdestruct:methodname");
1583      destruct_methodmodifiers = Getattr(attributes, "tmap:csdestruct:methodmodifiers");
1584    }
1585    if (tm && *Char(tm)) {
1586      if (!destruct_methodname) {
1587	Swig_error(input_file, line_number, "No methodname attribute defined in csdestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
1588      }
1589      if (!destruct_methodmodifiers) {
1590	Swig_error(input_file, line_number,
1591		   "No methodmodifiers attribute defined in csdestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
1592      }
1593    }
1594    // Emit the Finalize and Dispose methods
1595    if (tm) {
1596      // Finalize method
1597      if (*Char(destructor_call)) {
1598	Printv(proxy_class_def, typemapLookup(n, "csfinalize", typemap_lookup_type, WARN_NONE), NIL);
1599      }
1600      // Dispose method
1601      Printv(destruct, tm, NIL);
1602      if (*Char(destructor_call))
1603	Replaceall(destruct, "$imcall", destructor_call);
1604      else
1605	Replaceall(destruct, "$imcall", "throw new MethodAccessException(\"C++ destructor does not have public access\")");
1606      if (*Char(destruct))
1607	Printv(proxy_class_def, "\n  ", destruct_methodmodifiers, " ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n",
1608	       NIL);
1609    }
1610
1611    if (feature_director) {
1612      // Generate director connect method
1613      // put this in classDirectorEnd ???
1614      Printf(proxy_class_code, "  private void SwigDirectorConnect() {\n");
1615
1616      int i;
1617      for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
1618	UpcallData *udata = Getitem(dmethods_seq, i);
1619	String *method = Getattr(udata, "method");
1620	String *methid = Getattr(udata, "class_methodidx");
1621	String *overname = Getattr(udata, "overname");
1622	Printf(proxy_class_code, "    if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s))\n", method, methid);
1623	Printf(proxy_class_code, "      swigDelegate%s = new SwigDelegate%s_%s(SwigDirector%s);\n", methid, proxy_class_name, methid, overname);
1624      }
1625      Printf(proxy_class_code, "    %s.%s_director_connect(swigCPtr", imclass_name, proxy_class_name);
1626      for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
1627	UpcallData *udata = Getitem(dmethods_seq, i);
1628	String *methid = Getattr(udata, "class_methodidx");
1629	Printf(proxy_class_code, ", swigDelegate%s", methid);
1630      }
1631      Printf(proxy_class_code, ");\n");
1632      Printf(proxy_class_code, "  }\n");
1633
1634      if (first_class_dmethod < curr_class_dmethod) {
1635	// Only emit if there is at least one director method
1636	Printf(proxy_class_code, "\n");
1637	Printf(proxy_class_code, "  private bool SwigDerivedClassHasMethod(string methodName, Type[] methodTypes) {\n");
1638	Printf(proxy_class_code,
1639	       "    System.Reflection.MethodInfo methodInfo = this.GetType().GetMethod(methodName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance, null, methodTypes, null);\n");
1640	Printf(proxy_class_code, "    bool hasDerivedMethod = methodInfo.DeclaringType.IsSubclassOf(typeof(%s));\n", proxy_class_name);
1641	/* Could add this code to cover corner case where the GetMethod() returns a method which allows type
1642	 * promotion, eg it will return foo(double), if looking for foo(int).
1643	 if (hasDerivedMethod) {
1644	 hasDerivedMethod = false;
1645	 if (methodInfo != null)
1646	 {
1647	 hasDerivedMethod = true;
1648	 ParameterInfo[] parameterArray1 = methodInfo.GetParameters();
1649	 for (int i=0; i<methodTypes.Length; i++)
1650	 {
1651	 if (parameterArray1[0].ParameterType != methodTypes[0])
1652	 {
1653	 hasDerivedMethod = false;
1654	 break;
1655	 }
1656	 }
1657	 }
1658	 }
1659	 */
1660	Printf(proxy_class_code, "    return hasDerivedMethod;\n");
1661	Printf(proxy_class_code, "  }\n");
1662      }
1663
1664      if (Len(director_delegate_callback) > 0)
1665	Printv(proxy_class_code, director_delegate_callback, NIL);
1666      if (Len(director_delegate_definitions) > 0)
1667	Printv(proxy_class_code, "\n", director_delegate_definitions, NIL);
1668      if (Len(director_delegate_instances) > 0)
1669	Printv(proxy_class_code, "\n", director_delegate_instances, NIL);
1670      if (Len(director_method_types) > 0)
1671	Printv(proxy_class_code, "\n", director_method_types, NIL);
1672
1673      Delete(director_callback_typedefs);
1674      director_callback_typedefs = NULL;
1675      Delete(director_callbacks);
1676      director_callbacks = NULL;
1677      Delete(director_delegate_callback);
1678      director_delegate_callback = NULL;
1679      Delete(director_delegate_definitions);
1680      director_delegate_definitions = NULL;
1681      Delete(director_delegate_instances);
1682      director_delegate_instances = NULL;
1683      Delete(director_method_types);
1684      director_method_types = NULL;
1685      Delete(director_connect_parms);
1686      director_connect_parms = NULL;
1687    }
1688
1689    Delete(attributes);
1690    Delete(destruct);
1691
1692    // Emit extra user code
1693    Printv(proxy_class_def, typemapLookup(n, "cscode", typemap_lookup_type, WARN_NONE),	// extra C# code
1694	   "\n", NIL);
1695
1696    // Substitute various strings into the above template
1697    Replaceall(proxy_class_code, "$csclassname", proxy_class_name);
1698    Replaceall(proxy_class_def, "$csclassname", proxy_class_name);
1699
1700    Replaceall(proxy_class_def, "$module", module_class_name);
1701    Replaceall(proxy_class_code, "$module", module_class_name);
1702
1703    Replaceall(proxy_class_def, "$imclassname", imclass_name);
1704    Replaceall(proxy_class_code, "$imclassname", imclass_name);
1705
1706    Replaceall(proxy_class_def, "$dllimport", dllimport);
1707    Replaceall(proxy_class_code, "$dllimport", dllimport);
1708
1709    // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
1710    if (derived) {
1711      Printv(imclass_cppcasts_code, "\n  [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", proxy_class_name, "Upcast", "\")]\n", NIL);
1712      Printf(imclass_cppcasts_code, "  public static extern IntPtr $csclassnameUpcast(IntPtr objectRef);\n");
1713
1714      Replaceall(imclass_cppcasts_code, "$csclassname", proxy_class_name);
1715
1716      Printv(upcasts_code,
1717	     "SWIGEXPORT $cbaseclass * SWIGSTDCALL CSharp_$imclazznameUpcast",
1718	     "($cclass *objectRef) {\n", "    return ($cbaseclass *)objectRef;\n" "}\n", "\n", NIL);
1719
1720      Replaceall(upcasts_code, "$cbaseclass", c_baseclass);
1721      Replaceall(upcasts_code, "$imclazzname", proxy_class_name);
1722      Replaceall(upcasts_code, "$cclass", c_classname);
1723    }
1724    Delete(baseclass);
1725  }
1726
1727  /* ----------------------------------------------------------------------
1728   * classHandler()
1729   * ---------------------------------------------------------------------- */
1730
1731  virtual int classHandler(Node *n) {
1732
1733    File *f_proxy = NULL;
1734    if (proxy_flag) {
1735      proxy_class_name = NewString(Getattr(n, "sym:name"));
1736
1737      if (!addSymbol(proxy_class_name, n))
1738	return SWIG_ERROR;
1739
1740      if (Cmp(proxy_class_name, imclass_name) == 0) {
1741	Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
1742	SWIG_exit(EXIT_FAILURE);
1743      }
1744
1745      if (Cmp(proxy_class_name, module_class_name) == 0) {
1746	Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
1747	SWIG_exit(EXIT_FAILURE);
1748      }
1749
1750      String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), proxy_class_name);
1751      f_proxy = NewFile(filen, "w", SWIG_output_files());
1752      if (!f_proxy) {
1753	FileErrorDisplay(filen);
1754	SWIG_exit(EXIT_FAILURE);
1755      }
1756      Append(filenames_list, Copy(filen));
1757      Delete(filen);
1758      filen = NULL;
1759
1760      // Start writing out the proxy class file
1761      emitBanner(f_proxy);
1762
1763      addOpenNamespace(namespce, f_proxy);
1764
1765      Clear(proxy_class_def);
1766      Clear(proxy_class_code);
1767
1768      destructor_call = NewString("");
1769      proxy_class_constants_code = NewString("");
1770    }
1771
1772    Language::classHandler(n);
1773
1774    if (proxy_flag) {
1775
1776      emitProxyClassDefAndCPPCasts(n);
1777
1778      Replaceall(proxy_class_def, "$module", module_class_name);
1779      Replaceall(proxy_class_code, "$module", module_class_name);
1780      Replaceall(proxy_class_constants_code, "$module", module_class_name);
1781      Replaceall(proxy_class_def, "$imclassname", imclass_name);
1782      Replaceall(proxy_class_code, "$imclassname", imclass_name);
1783      Replaceall(proxy_class_constants_code, "$imclassname", imclass_name);
1784      Replaceall(proxy_class_def, "$dllimport", dllimport);
1785      Replaceall(proxy_class_code, "$dllimport", dllimport);
1786      Replaceall(proxy_class_constants_code, "$dllimport", dllimport);
1787
1788      Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
1789
1790      // Write out all the constants
1791      if (Len(proxy_class_constants_code) != 0)
1792	Printv(f_proxy, proxy_class_constants_code, NIL);
1793
1794      Printf(f_proxy, "}\n");
1795      addCloseNamespace(namespce, f_proxy);
1796      Close(f_proxy);
1797      f_proxy = NULL;
1798
1799      /* Output the downcast method, if necessary. Note: There's no other really
1800         good place to put this code, since Abstract Base Classes (ABCs) can and should have
1801         downcasts, making the constructorHandler() a bad place (because ABCs don't get to
1802         have constructors emitted.) */
1803      if (GetFlag(n, "feature:javadowncast")) {
1804	String *norm_name = SwigType_namestr(Getattr(n, "name"));
1805
1806	Printf(imclass_class_code, "  public final static native %s downcast%s(long cPtrBase, boolean cMemoryOwn);\n", proxy_class_name, proxy_class_name);
1807
1808	Wrapper *dcast_wrap = NewWrapper();
1809
1810	Printf(dcast_wrap->def, "SWIGEXPORT jobject SWIGSTDCALL CSharp_downcast%s(JNIEnv *jenv, jclass jcls, jlong jCPtrBase, jboolean cMemoryOwn) {",
1811	       proxy_class_name);
1812	Printf(dcast_wrap->code, "  Swig::Director *director = (Swig::Director *) 0;\n");
1813	Printf(dcast_wrap->code, "  jobject jresult = (jobject) 0;\n");
1814	Printf(dcast_wrap->code, "  %s *obj = *((%s **)&jCPtrBase);\n", norm_name, norm_name);
1815	Printf(dcast_wrap->code, "  if (obj) director = dynamic_cast<Swig::Director *>(obj);\n");
1816	Printf(dcast_wrap->code, "  if (director) jresult = director->swig_get_self(jenv);\n");
1817	Printf(dcast_wrap->code, "  return jresult;\n");
1818	Printf(dcast_wrap->code, "}\n");
1819
1820	Wrapper_print(dcast_wrap, f_wrappers);
1821	DelWrapper(dcast_wrap);
1822      }
1823
1824      emitDirectorExtraMethods(n);
1825
1826      Delete(proxy_class_name);
1827      proxy_class_name = NULL;
1828      Delete(destructor_call);
1829      destructor_call = NULL;
1830      Delete(proxy_class_constants_code);
1831      proxy_class_constants_code = NULL;
1832    }
1833
1834    return SWIG_OK;
1835  }
1836
1837  /* ----------------------------------------------------------------------
1838   * memberfunctionHandler()
1839   * ---------------------------------------------------------------------- */
1840
1841  virtual int memberfunctionHandler(Node *n) {
1842    Language::memberfunctionHandler(n);
1843
1844    if (proxy_flag) {
1845      String *overloaded_name = getOverloadedName(n);
1846      String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
1847      Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
1848      Setattr(n, "imfuncname", intermediary_function_name);
1849      proxyClassFunctionHandler(n);
1850      Delete(overloaded_name);
1851    }
1852    return SWIG_OK;
1853  }
1854
1855  /* ----------------------------------------------------------------------
1856   * staticmemberfunctionHandler()
1857   * ---------------------------------------------------------------------- */
1858
1859  virtual int staticmemberfunctionHandler(Node *n) {
1860
1861    static_flag = true;
1862    Language::staticmemberfunctionHandler(n);
1863
1864    if (proxy_flag) {
1865      String *overloaded_name = getOverloadedName(n);
1866      String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
1867      Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
1868      Setattr(n, "imfuncname", intermediary_function_name);
1869      proxyClassFunctionHandler(n);
1870      Delete(overloaded_name);
1871    }
1872    static_flag = false;
1873
1874    return SWIG_OK;
1875  }
1876
1877
1878  /* -----------------------------------------------------------------------------
1879   * proxyClassFunctionHandler()
1880   *
1881   * Function called for creating a C# wrapper function around a c++ function in the
1882   * proxy class. Used for both static and non-static C++ class functions.
1883   * C++ class static functions map to C# static functions.
1884   * Two extra attributes in the Node must be available. These are "proxyfuncname" -
1885   * the name of the C# class proxy function, which in turn will call "imfuncname" -
1886   * the intermediary (PInvoke) function name in the intermediary class.
1887   * ----------------------------------------------------------------------------- */
1888
1889  void proxyClassFunctionHandler(Node *n) {
1890    SwigType *t = Getattr(n, "type");
1891    ParmList *l = Getattr(n, "parms");
1892    String *intermediary_function_name = Getattr(n, "imfuncname");
1893    String *proxy_function_name = Getattr(n, "proxyfuncname");
1894    String *tm;
1895    Parm *p;
1896    Parm *last_parm = 0;
1897    int i;
1898    String *imcall = NewString("");
1899    String *return_type = NewString("");
1900    String *function_code = NewString("");
1901    bool setter_flag = false;
1902    String *pre_code = NewString("");
1903    String *post_code = NewString("");
1904    String *terminator_code = NewString("");
1905
1906    if (!proxy_flag)
1907      return;
1908
1909    // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
1910    if (Getattr(n, "overload:ignore"))
1911      return;
1912
1913    // Don't generate proxy method for additional explicitcall method used in directors
1914    if (GetFlag(n, "explicitcall"))
1915      return;
1916
1917    if (l) {
1918      if (SwigType_type(Getattr(l, "type")) == T_VOID) {
1919	l = nextSibling(l);
1920      }
1921    }
1922
1923    /* Attach the non-standard typemaps to the parameter list */
1924    Swig_typemap_attach_parms("in", l, NULL);
1925    Swig_typemap_attach_parms("cstype", l, NULL);
1926    Swig_typemap_attach_parms("csin", l, NULL);
1927
1928    /* Get return types */
1929    if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
1930      // Note that in the case of polymorphic (covariant) return types, the method's return type is changed to be the base of the C++ return type
1931      SwigType *covariant = Getattr(n, "covariant");
1932      String *cstypeout = Getattr(n, "tmap:cstype:out");	// the type in the cstype typemap's out attribute overrides the type in the typemap
1933      if (cstypeout)
1934	tm = cstypeout;
1935      substituteClassname(covariant ? covariant : t, tm);
1936      Printf(return_type, "%s", tm);
1937      if (covariant)
1938	Swig_warning(WARN_CSHARP_COVARIANT_RET, input_file, line_number,
1939		     "Covariant return types not supported in C#. Proxy method will return %s.\n", SwigType_str(covariant, 0));
1940    } else {
1941      Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
1942    }
1943
1944    if (wrapping_member_flag && !enum_constant_flag) {
1945      // Properties
1946      setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(Swig_name_member(proxy_class_name, variable_name))) == 0);
1947      if (setter_flag)
1948        Swig_typemap_attach_parms("csvarin", l, NULL);
1949    }
1950
1951    /* Start generating the proxy function */
1952    const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
1953    if (outattributes)
1954      Printf(function_code, "  %s\n", outattributes);
1955    const String *csattributes = Getattr(n, "feature:cs:attributes");
1956    if (csattributes)
1957      Printf(function_code, "  %s\n", csattributes);
1958    const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
1959    if (methodmods) {
1960      if (is_smart_pointer()) {
1961	// Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
1962	String *mmods = Copy(methodmods);
1963	Replaceall(mmods, "override", "");
1964	Replaceall(mmods, "virtual", "");
1965	Replaceall(mmods, "new", "");
1966	Chop(mmods);		// remove trailing whitespace
1967	Printf(function_code, "  %s ", mmods);
1968	Delete(mmods);
1969      } else {
1970	Printf(function_code, "  %s ", methodmods);
1971      }
1972    } else {
1973      methodmods = (is_public(n) ? public_string : protected_string);
1974      Printf(function_code, "  %s ", methodmods);
1975      if (!is_smart_pointer()) {
1976	// Smart pointer classes do not mirror the inheritance hierarchy of the underlying pointer type, so no virtual/override/new required.
1977	if (Getattr(n, "override"))
1978	  Printf(function_code, "override ");
1979	else if (checkAttribute(n, "storage", "virtual"))
1980	  Printf(function_code, "virtual ");
1981	if (Getattr(n, "hides"))
1982	  Printf(function_code, "new ");
1983      }
1984    }
1985    if (static_flag)
1986      Printf(function_code, "static ");
1987    Printf(function_code, "%s %s(", return_type, proxy_function_name);
1988
1989    Printv(imcall, imclass_name, ".$imfuncname(", NIL);
1990    if (!static_flag)
1991      Printf(imcall, "swigCPtr");
1992
1993    emit_mark_varargs(l);
1994
1995    int gencomma = !static_flag;
1996
1997    /* Output each parameter */
1998    for (i = 0, p = l; p; i++) {
1999
2000      /* Ignored varargs */
2001      if (checkAttribute(p, "varargs:ignore", "1")) {
2002	p = nextSibling(p);
2003	continue;
2004      }
2005
2006      /* Ignored parameters */
2007      if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2008	p = Getattr(p, "tmap:in:next");
2009	continue;
2010      }
2011
2012      /* Ignore the 'this' argument for variable wrappers */
2013      if (!(variable_wrapper_flag && i == 0)) {
2014	SwigType *pt = Getattr(p, "type");
2015	String *param_type = NewString("");
2016        if (setter_flag)
2017          last_parm = p;
2018
2019	/* Get the C# parameter type */
2020	if ((tm = Getattr(p, "tmap:cstype"))) {
2021	  substituteClassname(pt, tm);
2022	  const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
2023	  Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
2024	} else {
2025	  Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
2026	}
2027
2028	if (gencomma)
2029	  Printf(imcall, ", ");
2030
2031	String *arg = makeParameterName(n, p, i, setter_flag);
2032
2033	// Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
2034	if ((tm = Getattr(p, "tmap:csin"))) {
2035	  substituteClassname(pt, tm);
2036	  Replaceall(tm, "$csinput", arg);
2037          String *pre = Getattr(p, "tmap:csin:pre");
2038          if (pre) {
2039            substituteClassname(pt, pre);
2040            Replaceall(pre, "$csinput", arg);
2041            if (Len(pre_code) > 0)
2042              Printf(pre_code, "\n");
2043            Printv(pre_code, pre, NIL);
2044          }
2045          String *post = Getattr(p, "tmap:csin:post");
2046          if (post) {
2047            substituteClassname(pt, post);
2048            Replaceall(post, "$csinput", arg);
2049            if (Len(post_code) > 0)
2050              Printf(post_code, "\n");
2051            Printv(post_code, post, NIL);
2052          }
2053          String *terminator = Getattr(p, "tmap:csin:terminator");
2054          if (terminator) {
2055            substituteClassname(pt, terminator);
2056            Replaceall(terminator, "$csinput", arg);
2057            if (Len(terminator_code) > 0)
2058              Insert(terminator_code, 0, "\n");
2059            Insert(terminator_code, 0, terminator);
2060          }
2061	  Printv(imcall, tm, NIL);
2062	} else {
2063	  Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
2064	}
2065
2066	/* Add parameter to proxy function */
2067	if (gencomma >= 2)
2068	  Printf(function_code, ", ");
2069	gencomma = 2;
2070	Printf(function_code, "%s %s", param_type, arg);
2071
2072	Delete(arg);
2073	Delete(param_type);
2074      }
2075      p = Getattr(p, "tmap:in:next");
2076    }
2077
2078    Printf(imcall, ")");
2079    Printf(function_code, ")");
2080
2081    // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in proxy class)
2082    if ((tm = Swig_typemap_lookup("csout", n, "", 0))) {
2083      excodeSubstitute(n, tm, "csout", n);
2084      bool is_pre_code = Len(pre_code) > 0;
2085      bool is_post_code = Len(post_code) > 0;
2086      bool is_terminator_code = Len(terminator_code) > 0;
2087      if (is_pre_code || is_post_code || is_terminator_code) {
2088        Replaceall(tm, "\n ", "\n   "); // add extra indentation to code in typemap
2089        if (is_post_code) {
2090          Insert(tm, 0, "\n    try ");
2091          Printv(tm, " finally {\n", post_code, "\n    }", NIL);
2092        } else {
2093          Insert(tm, 0, "\n    ");
2094        }
2095        if (is_pre_code) {
2096          Insert(tm, 0, pre_code);
2097          Insert(tm, 0, "\n");
2098        }
2099        if (is_terminator_code) {
2100          Printv(tm, "\n", terminator_code, NIL);
2101        }
2102	Insert(tm, 0, "{");
2103	Printf(tm, "\n  }");
2104      }
2105      if (GetFlag(n, "feature:new"))
2106	Replaceall(tm, "$owner", "true");
2107      else
2108	Replaceall(tm, "$owner", "false");
2109      substituteClassname(t, tm);
2110
2111      // For director methods: generate code to selectively make a normal polymorphic call or
2112      // an explicit method call - needed to prevent infinite recursion calls in director methods.
2113      Node *explicit_n = Getattr(n, "explicitcallnode");
2114      if (explicit_n) {
2115	String *ex_overloaded_name = getOverloadedName(explicit_n);
2116	String *ex_intermediary_function_name = Swig_name_member(proxy_class_name, ex_overloaded_name);
2117
2118	String *ex_imcall = Copy(imcall);
2119	Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
2120	Replaceall(imcall, "$imfuncname", intermediary_function_name);
2121
2122	String *excode = NewString("");
2123	if (!Cmp(return_type, "void"))
2124	  Printf(excode, "if (this.GetType() == typeof(%s)) %s; else %s", proxy_class_name, imcall, ex_imcall);
2125	else
2126	  Printf(excode, "((this.GetType() == typeof(%s)) ? %s : %s)", proxy_class_name, imcall, ex_imcall);
2127
2128	Clear(imcall);
2129	Printv(imcall, excode, NIL);
2130	Delete(ex_overloaded_name);
2131	Delete(excode);
2132      } else {
2133	Replaceall(imcall, "$imfuncname", intermediary_function_name);
2134      }
2135      Replaceall(tm, "$imcall", imcall);
2136    } else {
2137      Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0));
2138    }
2139
2140    if (wrapping_member_flag && !enum_constant_flag) {
2141      // Properties
2142      if (generate_property_declaration_flag) {	// Ensure the declaration is generated just once should the property contain both a set and get
2143	// Get the C# variable type - obtained differently depending on whether a setter is required.
2144	String *variable_type = return_type;
2145	if (setter_flag) {
2146	  p = last_parm;	// (last parameter is the only parameter for properties)
2147	  SwigType *pt = Getattr(p, "type");
2148	  if ((tm = Getattr(p, "tmap:cstype"))) {
2149	    substituteClassname(pt, tm);
2150            String *cstypeout = Getattr(p, "tmap:cstype:out");	// the type in the cstype typemap's out attribute overrides the type in the typemap
2151	    variable_type = cstypeout ? cstypeout : tm;
2152	  } else {
2153	    Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
2154	  }
2155	}
2156	const String *csattributes = Getattr(n, "feature:cs:attributes");
2157	if (csattributes)
2158	  Printf(proxy_class_code, "  %s\n", csattributes);
2159	const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
2160	if (!methodmods)
2161	  methodmods = (is_public(n) ? public_string : protected_string);
2162	Printf(proxy_class_code, "  %s %s%s %s {", methodmods, static_flag ? "static " : "", variable_type, variable_name);
2163      }
2164      generate_property_declaration_flag = false;
2165
2166      if (setter_flag) {
2167	// Setter method
2168	p = last_parm;		// (last parameter is the only parameter for properties)
2169	SwigType *pt = Getattr(p, "type");
2170	if ((tm = Getattr(p, "tmap:csvarin"))) {
2171	  substituteClassname(pt, tm);
2172	  Replaceall(tm, "$imcall", imcall);
2173	  excodeSubstitute(n, tm, "csvarin", p);
2174	  Printf(proxy_class_code, "%s", tm);
2175	} else {
2176	  Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
2177	}
2178      } else {
2179	// Getter method
2180	if ((tm = Swig_typemap_lookup("csvarout", n, "", 0))) {
2181	  if (GetFlag(n, "feature:new"))
2182	    Replaceall(tm, "$owner", "true");
2183	  else
2184	    Replaceall(tm, "$owner", "false");
2185	  substituteClassname(t, tm);
2186	  Replaceall(tm, "$imcall", imcall);
2187	  excodeSubstitute(n, tm, "csvarout", n);
2188	  Printf(proxy_class_code, "%s", tm);
2189	} else {
2190	  Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t, 0));
2191	}
2192      }
2193    } else {
2194      // Normal function call
2195      Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
2196      Printv(proxy_class_code, function_code, NIL);
2197    }
2198
2199    Delete(pre_code);
2200    Delete(post_code);
2201    Delete(terminator_code);
2202    Delete(function_code);
2203    Delete(return_type);
2204    Delete(imcall);
2205  }
2206
2207  /* ----------------------------------------------------------------------
2208   * constructorHandler()
2209   * ---------------------------------------------------------------------- */
2210
2211  virtual int constructorHandler(Node *n) {
2212
2213    ParmList *l = Getattr(n, "parms");
2214    String *tm;
2215    Parm *p;
2216    int i;
2217    String *function_code = NewString("");
2218    String *helper_code = NewString(""); // Holds code for the constructor helper method generated only when the csin typemap has code in the pre or post attributes
2219    String *helper_args = NewString("");
2220    String *pre_code = NewString("");
2221    String *post_code = NewString("");
2222    String *terminator_code = NewString("");
2223    String *im_return_type = NewString("");
2224    bool feature_director = (parentNode(n) && Swig_directorclass(n));
2225
2226    Language::constructorHandler(n);
2227
2228    // Wrappers not wanted for some methods where the parameters cannot be overloaded in C#
2229    if (Getattr(n, "overload:ignore"))
2230      return SWIG_OK;
2231
2232    if (proxy_flag) {
2233      String *overloaded_name = getOverloadedName(n);
2234      String *mangled_overname = Swig_name_construct(overloaded_name);
2235      String *imcall = NewString("");
2236
2237      const String *csattributes = Getattr(n, "feature:cs:attributes");
2238      if (csattributes) {
2239	Printf(function_code, "  %s\n", csattributes);
2240	Printf(helper_code, "  %s\n", csattributes);
2241      }
2242      const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
2243      methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
2244
2245      tm = Getattr(n, "tmap:imtype"); // typemaps were attached earlier to the node
2246      String *imtypeout = Getattr(n, "tmap:imtype:out");	// the type in the imtype typemap's out attribute overrides the type in the typemap
2247      if (imtypeout)
2248	tm = imtypeout;
2249      Printf(im_return_type, "%s", tm);
2250
2251      Printf(function_code, "  %s %s(", methodmods, proxy_class_name);
2252      Printf(helper_code, "  static private %s SwigConstruct%s(", im_return_type, proxy_class_name);
2253
2254      Printv(imcall, imclass_name, ".", mangled_overname, "(", NIL);
2255
2256      /* Attach the non-standard typemaps to the parameter list */
2257      Swig_typemap_attach_parms("in", l, NULL);
2258      Swig_typemap_attach_parms("cstype", l, NULL);
2259      Swig_typemap_attach_parms("csin", l, NULL);
2260
2261      emit_mark_varargs(l);
2262
2263      int gencomma = 0;
2264
2265      /* Output each parameter */
2266      for (i = 0, p = l; p; i++) {
2267
2268	/* Ignored varargs */
2269	if (checkAttribute(p, "varargs:ignore", "1")) {
2270	  p = nextSibling(p);
2271	  continue;
2272	}
2273
2274	/* Ignored parameters */
2275	if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2276	  p = Getattr(p, "tmap:in:next");
2277	  continue;
2278	}
2279
2280	SwigType *pt = Getattr(p, "type");
2281	String *param_type = NewString("");
2282
2283	/* Get the C# parameter type */
2284	if ((tm = Getattr(p, "tmap:cstype"))) {
2285	  substituteClassname(pt, tm);
2286	  const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
2287	  Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
2288	} else {
2289	  Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
2290	}
2291
2292	if (gencomma)
2293	  Printf(imcall, ", ");
2294
2295	String *arg = makeParameterName(n, p, i, false);
2296        String *cshin = 0;
2297
2298	// Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
2299	if ((tm = Getattr(p, "tmap:csin"))) {
2300	  substituteClassname(pt, tm);
2301	  Replaceall(tm, "$csinput", arg);
2302          String *pre = Getattr(p, "tmap:csin:pre");
2303          if (pre) {
2304            substituteClassname(pt, pre);
2305            Replaceall(pre, "$csinput", arg);
2306            if (Len(pre_code) > 0)
2307              Printf(pre_code, "\n");
2308            Printv(pre_code, pre, NIL);
2309          }
2310          String *post = Getattr(p, "tmap:csin:post");
2311          if (post) {
2312            substituteClassname(pt, post);
2313            Replaceall(post, "$csinput", arg);
2314            if (Len(post_code) > 0)
2315              Printf(post_code, "\n");
2316            Printv(post_code, post, NIL);
2317          }
2318          String *terminator = Getattr(p, "tmap:csin:terminator");
2319          if (terminator) {
2320            substituteClassname(pt, terminator);
2321            Replaceall(terminator, "$csinput", arg);
2322            if (Len(terminator_code) > 0)
2323              Insert(terminator_code, 0, "\n");
2324            Insert(terminator_code, 0, terminator);
2325          }
2326          cshin = Getattr(p, "tmap:csin:cshin");
2327          if (cshin)
2328            Replaceall(cshin, "$csinput", arg);
2329	  Printv(imcall, tm, NIL);
2330	} else {
2331	  Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
2332	}
2333
2334	/* Add parameter to proxy function */
2335	if (gencomma) {
2336	  Printf(function_code, ", ");
2337	  Printf(helper_code, ", ");
2338	  Printf(helper_args, ", ");
2339        }
2340	Printf(function_code, "%s %s", param_type, arg);
2341	Printf(helper_code, "%s %s", param_type, arg);
2342	Printf(helper_args, "%s", cshin ? cshin : arg);
2343	++gencomma;
2344
2345	Delete(cshin);
2346	Delete(arg);
2347	Delete(param_type);
2348	p = Getattr(p, "tmap:in:next");
2349      }
2350
2351      Printf(imcall, ")");
2352
2353      Printf(function_code, ")");
2354      Printf(helper_code, ")");
2355
2356      /* Insert the csconstruct typemap, doing the replacement for $directorconnect, as needed */
2357      Hash *attributes = NewHash();
2358      String *construct_tm = Copy(typemapLookup(n, "csconstruct", Getattr(n, "name"),
2359						WARN_CSHARP_TYPEMAP_CSCONSTRUCT_UNDEF, attributes));
2360      if (construct_tm) {
2361	if (!feature_director) {
2362	  Replaceall(construct_tm, "$directorconnect", "");
2363	} else {
2364	  String *connect_attr = Getattr(attributes, "tmap:csconstruct:directorconnect");
2365
2366	  if (connect_attr) {
2367	    Replaceall(construct_tm, "$directorconnect", connect_attr);
2368	  } else {
2369	    Swig_warning(WARN_CSHARP_NO_DIRECTORCONNECT_ATTR, input_file, line_number, "\"directorconnect\" attribute missing in %s \"csconstruct\" typemap.\n",
2370			 Getattr(n, "name"));
2371	    Replaceall(construct_tm, "$directorconnect", "");
2372	  }
2373	}
2374
2375	Printv(function_code, " ", construct_tm, NIL);
2376      }
2377
2378      excodeSubstitute(n, function_code, "csconstruct", attributes);
2379
2380      bool is_pre_code = Len(pre_code) > 0;
2381      bool is_post_code = Len(post_code) > 0;
2382      bool is_terminator_code = Len(terminator_code) > 0;
2383      if (is_pre_code || is_post_code || is_terminator_code) {
2384        Printf(helper_code, " {\n");
2385        if (is_pre_code) {
2386          Printv(helper_code, pre_code, "\n", NIL);
2387        }
2388        if (is_post_code) {
2389          Printf(helper_code, "    try {\n");
2390          Printv(helper_code, "      return ", imcall, ";\n", NIL);
2391          Printv(helper_code, "    } finally {\n", post_code, "\n    }", NIL);
2392        } else {
2393          Printv(helper_code, "    return ", imcall, ";", NIL);
2394        }
2395        if (is_terminator_code) {
2396          Printv(helper_code, "\n", terminator_code, NIL);
2397        }
2398        Printf(helper_code, "\n  }\n");
2399        String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
2400        String *im_outattributes = Getattr(n, "tmap:imtype:outattributes");
2401        if (im_outattributes)
2402          Printf(proxy_class_code, "  %s\n", im_outattributes);
2403        Printv(proxy_class_code, helper_code, "\n", NIL);
2404        Replaceall(function_code, "$imcall", helper_name);
2405        Delete(helper_name);
2406      } else {
2407        Replaceall(function_code, "$imcall", imcall);
2408      }
2409
2410      Printv(proxy_class_code, function_code, "\n", NIL);
2411
2412      Delete(helper_args);
2413      Delete(im_return_type);
2414      Delete(pre_code);
2415      Delete(post_code);
2416      Delete(terminator_code);
2417      Delete(construct_tm);
2418      Delete(attributes);
2419      Delete(overloaded_name);
2420      Delete(imcall);
2421    }
2422
2423    return SWIG_OK;
2424  }
2425
2426  /* ----------------------------------------------------------------------
2427   * destructorHandler()
2428   * ---------------------------------------------------------------------- */
2429
2430  virtual int destructorHandler(Node *n) {
2431    Language::destructorHandler(n);
2432    String *symname = Getattr(n, "sym:name");
2433
2434    if (proxy_flag) {
2435      Printv(destructor_call, imclass_name, ".", Swig_name_destroy(symname), "(swigCPtr)", NIL);
2436    }
2437    return SWIG_OK;
2438  }
2439
2440  /* ----------------------------------------------------------------------
2441   * membervariableHandler()
2442   * ---------------------------------------------------------------------- */
2443
2444  virtual int membervariableHandler(Node *n) {
2445
2446    generate_property_declaration_flag = true;
2447    variable_name = Getattr(n, "sym:name");
2448    wrapping_member_flag = true;
2449    variable_wrapper_flag = true;
2450    Language::membervariableHandler(n);
2451    wrapping_member_flag = false;
2452    variable_wrapper_flag = false;
2453    generate_property_declaration_flag = false;
2454
2455    Printf(proxy_class_code, "\n  }\n\n");
2456
2457    return SWIG_OK;
2458  }
2459
2460  /* ----------------------------------------------------------------------
2461   * staticmembervariableHandler()
2462   * ---------------------------------------------------------------------- */
2463
2464  virtual int staticmembervariableHandler(Node *n) {
2465
2466    bool static_const_member_flag = (Getattr(n, "value") == 0);
2467
2468    generate_property_declaration_flag = true;
2469    variable_name = Getattr(n, "sym:name");
2470    wrapping_member_flag = true;
2471    static_flag = true;
2472    Language::staticmembervariableHandler(n);
2473    wrapping_member_flag = false;
2474    static_flag = false;
2475    generate_property_declaration_flag = false;
2476
2477    if (static_const_member_flag)
2478      Printf(proxy_class_code, "\n  }\n\n");
2479
2480    return SWIG_OK;
2481  }
2482
2483  /* ----------------------------------------------------------------------
2484   * memberconstantHandler()
2485   * ---------------------------------------------------------------------- */
2486
2487  virtual int memberconstantHandler(Node *n) {
2488    variable_name = Getattr(n, "sym:name");
2489    wrapping_member_flag = true;
2490    Language::memberconstantHandler(n);
2491    wrapping_member_flag = false;
2492    return SWIG_OK;
2493  }
2494
2495  /* -----------------------------------------------------------------------------
2496   * getOverloadedName()
2497   * ----------------------------------------------------------------------------- */
2498
2499  String *getOverloadedName(Node *n) {
2500
2501    /* A C# HandleRef is used for all classes in the SWIG intermediary class.
2502     * The intermediary class methods are thus mangled when overloaded to give
2503     * a unique name. */
2504    String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name"));
2505
2506    if (Getattr(n, "sym:overloaded")) {
2507      Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
2508    }
2509
2510    return overloaded_name;
2511  }
2512
2513  /* -----------------------------------------------------------------------------
2514   * moduleClassFunctionHandler()
2515   * ----------------------------------------------------------------------------- */
2516
2517  void moduleClassFunctionHandler(Node *n) {
2518    SwigType *t = Getattr(n, "type");
2519    ParmList *l = Getattr(n, "parms");
2520    String *tm;
2521    Parm *p;
2522    Parm *last_parm = 0;
2523    int i;
2524    String *imcall = NewString("");
2525    String *return_type = NewString("");
2526    String *function_code = NewString("");
2527    int num_arguments = 0;
2528    int num_required = 0;
2529    String *overloaded_name = getOverloadedName(n);
2530    String *func_name = NULL;
2531    bool setter_flag = false;
2532    String *pre_code = NewString("");
2533    String *post_code = NewString("");
2534    String *terminator_code = NewString("");
2535
2536    if (l) {
2537      if (SwigType_type(Getattr(l, "type")) == T_VOID) {
2538	l = nextSibling(l);
2539      }
2540    }
2541
2542    /* Attach the non-standard typemaps to the parameter list */
2543    Swig_typemap_attach_parms("cstype", l, NULL);
2544    Swig_typemap_attach_parms("csin", l, NULL);
2545
2546    /* Get return types */
2547    if ((tm = Swig_typemap_lookup("cstype", n, "", 0))) {
2548      String *cstypeout = Getattr(n, "tmap:cstype:out");	// the type in the cstype typemap's out attribute overrides the type in the typemap
2549      if (cstypeout)
2550	tm = cstypeout;
2551      substituteClassname(t, tm);
2552      Printf(return_type, "%s", tm);
2553    } else {
2554      Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(t, 0));
2555    }
2556
2557    /* Change function name for global variables */
2558    if (proxy_flag && global_variable_flag) {
2559      // Capitalize the first letter in the variable to create the getter/setter function name
2560      func_name = NewString("");
2561      setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(variable_name)) == 0);
2562      if (setter_flag)
2563	Printf(func_name, "set");
2564      else
2565	Printf(func_name, "get");
2566      Putc(toupper((int) *Char(variable_name)), func_name);
2567      Printf(func_name, "%s", Char(variable_name) + 1);
2568      if (setter_flag)
2569        Swig_typemap_attach_parms("csvarin", l, NULL);
2570    } else {
2571      func_name = Copy(Getattr(n, "sym:name"));
2572    }
2573
2574    /* Start generating the function */
2575    const String *outattributes = Getattr(n, "tmap:cstype:outattributes");
2576    if (outattributes)
2577      Printf(function_code, "  %s\n", outattributes);
2578    const String *csattributes = Getattr(n, "feature:cs:attributes");
2579    if (csattributes)
2580      Printf(function_code, "  %s\n", csattributes);
2581    const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
2582    methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
2583    Printf(function_code, "  %s static %s %s(", methodmods, return_type, func_name);
2584    Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL);
2585
2586    /* Get number of required and total arguments */
2587    num_arguments = emit_num_arguments(l);
2588    num_required = emit_num_required(l);
2589
2590    bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag);
2591    int gencomma = 0;
2592
2593    /* Output each parameter */
2594    for (i = 0, p = l; i < num_arguments; i++) {
2595
2596      /* Ignored parameters */
2597      while (checkAttribute(p, "tmap:in:numinputs", "0")) {
2598	p = Getattr(p, "tmap:in:next");
2599      }
2600
2601      SwigType *pt = Getattr(p, "type");
2602      String *param_type = NewString("");
2603      last_parm = p;
2604
2605      /* Get the C# parameter type */
2606      if ((tm = Getattr(p, "tmap:cstype"))) {
2607	substituteClassname(pt, tm);
2608	const String *inattributes = Getattr(p, "tmap:cstype:inattributes");
2609	Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
2610      } else {
2611	Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
2612      }
2613
2614      if (gencomma)
2615	Printf(imcall, ", ");
2616
2617      String *arg = makeParameterName(n, p, i, global_or_member_variable);
2618
2619      // Use typemaps to transform type used in C# wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
2620      if ((tm = Getattr(p, "tmap:csin"))) {
2621	substituteClassname(pt, tm);
2622	Replaceall(tm, "$csinput", arg);
2623	String *pre = Getattr(p, "tmap:csin:pre");
2624	if (pre) {
2625	  substituteClassname(pt, pre);
2626	  Replaceall(pre, "$csinput", arg);
2627          if (Len(pre_code) > 0)
2628            Printf(pre_code, "\n");
2629	  Printv(pre_code, pre, NIL);
2630	}
2631	String *post = Getattr(p, "tmap:csin:post");
2632	if (post) {
2633	  substituteClassname(pt, post);
2634	  Replaceall(post, "$csinput", arg);
2635          if (Len(post_code) > 0)
2636            Printf(post_code, "\n");
2637	  Printv(post_code, post, NIL);
2638	}
2639        String *terminator = Getattr(p, "tmap:csin:terminator");
2640        if (terminator) {
2641          substituteClassname(pt, terminator);
2642          Replaceall(terminator, "$csinput", arg);
2643          if (Len(terminator_code) > 0)
2644            Insert(terminator_code, 0, "\n");
2645          Insert(terminator_code, 0, terminator);
2646        }
2647	Printv(imcall, tm, NIL);
2648      } else {
2649	Swig_warning(WARN_CSHARP_TYPEMAP_CSIN_UNDEF, input_file, line_number, "No csin typemap defined for %s\n", SwigType_str(pt, 0));
2650      }
2651
2652      /* Add parameter to module class function */
2653      if (gencomma >= 2)
2654	Printf(function_code, ", ");
2655      gencomma = 2;
2656      Printf(function_code, "%s %s", param_type, arg);
2657
2658      p = Getattr(p, "tmap:in:next");
2659      Delete(arg);
2660      Delete(param_type);
2661    }
2662
2663    Printf(imcall, ")");
2664    Printf(function_code, ")");
2665
2666    // Transform return type used in PInvoke function (in intermediary class) to type used in C# wrapper function (in module class)
2667    if ((tm = Swig_typemap_lookup("csout", n, "", 0))) {
2668      excodeSubstitute(n, tm, "csout", n);
2669      bool is_pre_code = Len(pre_code) > 0;
2670      bool is_post_code = Len(post_code) > 0;
2671      bool is_terminator_code = Len(terminator_code) > 0;
2672      if (is_pre_code || is_post_code || is_terminator_code) {
2673        Replaceall(tm, "\n ", "\n   "); // add extra indentation to code in typemap
2674        if (is_post_code) {
2675          Insert(tm, 0, "\n    try ");
2676          Printv(tm, " finally {\n", post_code, "\n    }", NIL);
2677        } else {
2678          Insert(tm, 0, "\n    ");
2679        }
2680        if (is_pre_code) {
2681          Insert(tm, 0, pre_code);
2682          Insert(tm, 0, "\n");
2683        }
2684        if (is_terminator_code) {
2685          Printv(tm, "\n", terminator_code, NIL);
2686        }
2687	Insert(tm, 0, "{");
2688	Printf(tm, "\n  }");
2689      }
2690      if (GetFlag(n, "feature:new"))
2691	Replaceall(tm, "$owner", "true");
2692      else
2693	Replaceall(tm, "$owner", "false");
2694      substituteClassname(t, tm);
2695      Replaceall(tm, "$imcall", imcall);
2696    } else {
2697      Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csout typemap defined for %s\n", SwigType_str(t, 0));
2698    }
2699
2700    if (proxy_flag && global_variable_flag) {
2701      // Properties
2702      if (generate_property_declaration_flag) {	// Ensure the declaration is generated just once should the property contain both a set and get
2703	// Get the C# variable type - obtained differently depending on whether a setter is required.
2704	String *variable_type = return_type;
2705	if (setter_flag) {
2706	  p = last_parm;	// (last parameter is the only parameter for properties)
2707	  SwigType *pt = Getattr(p, "type");
2708	  if ((tm = Getattr(p, "tmap:cstype"))) {
2709	    substituteClassname(pt, tm);
2710            String *cstypeout = Getattr(p, "tmap:cstype:out");	// the type in the cstype typemap's out attribute overrides the type in the typemap
2711	    variable_type = cstypeout ? cstypeout : tm;
2712	  } else {
2713	    Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
2714	  }
2715	}
2716	const String *csattributes = Getattr(n, "feature:cs:attributes");
2717	if (csattributes)
2718	  Printf(module_class_code, "  %s\n", csattributes);
2719	const String *methodmods = Getattr(n, "feature:cs:methodmodifiers");
2720	if (!methodmods)
2721	  methodmods = (is_public(n) ? public_string : protected_string);
2722	Printf(module_class_code, "  %s static %s %s {", methodmods, variable_type, variable_name);
2723      }
2724      generate_property_declaration_flag = false;
2725
2726      if (setter_flag) {
2727	// Setter method
2728	p = last_parm;		// (last parameter is the only parameter for properties)
2729	SwigType *pt = Getattr(p, "type");
2730	if ((tm = Getattr(p, "tmap:csvarin"))) {
2731	  substituteClassname(pt, tm);
2732	  Replaceall(tm, "$csinput", "value");
2733	  Replaceall(tm, "$imcall", imcall);
2734	  excodeSubstitute(n, tm, "csvarin", p);
2735	  Printf(module_class_code, "%s", tm);
2736	} else {
2737	  Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarin typemap defined for %s\n", SwigType_str(pt, 0));
2738	}
2739      } else {
2740	// Getter method
2741	if ((tm = Swig_typemap_lookup("csvarout", n, "", 0))) {
2742	  if (GetFlag(n, "feature:new"))
2743	    Replaceall(tm, "$owner", "true");
2744	  else
2745	    Replaceall(tm, "$owner", "false");
2746	  substituteClassname(t, tm);
2747	  Replaceall(tm, "$imcall", imcall);
2748	  excodeSubstitute(n, tm, "csvarout", n);
2749	  Printf(module_class_code, "%s", tm);
2750	} else {
2751	  Swig_warning(WARN_CSHARP_TYPEMAP_CSOUT_UNDEF, input_file, line_number, "No csvarout typemap defined for %s\n", SwigType_str(t, 0));
2752	}
2753      }
2754    } else {
2755      // Normal function call
2756      Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
2757      Printv(module_class_code, function_code, NIL);
2758    }
2759
2760    Delete(pre_code);
2761    Delete(post_code);
2762    Delete(terminator_code);
2763    Delete(function_code);
2764    Delete(return_type);
2765    Delete(imcall);
2766    Delete(func_name);
2767  }
2768
2769  /*----------------------------------------------------------------------
2770   * replaceSpecialVariables()
2771   *--------------------------------------------------------------------*/
2772
2773  virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
2774    (void)method;
2775    SwigType *type = Getattr(parm, "type");
2776    substituteClassname(type, tm);
2777  }
2778
2779  /*----------------------------------------------------------------------
2780   * decodeEnumFeature()
2781   * Decode the possible enum features, which are one of:
2782   *   %csenum(simple)
2783   *   %csenum(typeunsafe) - default
2784   *   %csenum(typesafe)
2785   *   %csenum(proper)
2786   *--------------------------------------------------------------------*/
2787
2788  EnumFeature decodeEnumFeature(Node *n) {
2789    EnumFeature enum_feature = TypeunsafeEnum;
2790    String *feature = Getattr(n, "feature:cs:enum");
2791    if (feature) {
2792      if (Cmp(feature, "simple") == 0)
2793	enum_feature = SimpleEnum;
2794      else if (Cmp(feature, "typesafe") == 0)
2795	enum_feature = TypesafeEnum;
2796      else if (Cmp(feature, "proper") == 0)
2797	enum_feature = ProperEnum;
2798    }
2799    return enum_feature;
2800  }
2801
2802  /* -----------------------------------------------------------------------
2803   * enumValue()
2804   * This method will return a string with an enum value to use in C# generated
2805   * code. If the %csconst feature is not used, the string will contain the intermediary
2806   * class call to obtain the enum value. The intermediary class and PINVOKE methods to obtain
2807   * the enum value will be generated. Otherwise the C/C++ enum value will be used if there
2808   * is one and hopefully it will compile as C# code - e.g. 20 as in: enum E{e=20};
2809   * The %csconstvalue feature overrides all other ways to generate the constant value.
2810   * The caller must delete memory allocated for the returned string.
2811   * ------------------------------------------------------------------------ */
2812
2813  String *enumValue(Node *n) {
2814    String *symname = Getattr(n, "sym:name");
2815
2816    // Check for the %csconstvalue feature
2817    String *value = Getattr(n, "feature:cs:constvalue");
2818
2819    if (!value) {
2820      // The %csconst feature determines how the constant value is obtained
2821      int const_feature_flag = GetFlag(n, "feature:cs:const");
2822
2823      if (const_feature_flag) {
2824	// Use the C syntax to make a true C# constant and hope that it compiles as C# code
2825	value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex"));
2826      } else {
2827	// Get the enumvalue from a PINVOKE call
2828	if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) {
2829	  // Strange hack to change the name
2830	  Setattr(n, "name", Getattr(n, "value"));	/* for wrapping of enums in a namespace when emit_action is used */
2831	  constantWrapper(n);
2832	  value = NewStringf("%s.%s()", imclass_name, Swig_name_get(symname));
2833	} else {
2834	  memberconstantHandler(n);
2835	  value = NewStringf("%s.%s()", imclass_name, Swig_name_get(Swig_name_member(proxy_class_name, symname)));
2836	}
2837      }
2838    }
2839    return value;
2840  }
2841
2842  /* -----------------------------------------------------------------------------
2843   * getEnumName()
2844   * ----------------------------------------------------------------------------- */
2845
2846  String *getEnumName(SwigType *t) {
2847    Node *enum_name = NULL;
2848    Node *n = enumLookup(t);
2849    if (n) {
2850      String *symname = Getattr(n, "sym:name");
2851      if (symname) {
2852	// Add in class scope when referencing enum if not a global enum
2853	String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
2854	String *proxyname = 0;
2855	if (scopename_prefix) {
2856	  proxyname = getProxyName(scopename_prefix);
2857	}
2858	if (proxyname)
2859	  enum_name = NewStringf("%s.%s", proxyname, symname);
2860	else
2861	  enum_name = NewStringf("%s", symname);
2862	Delete(scopename_prefix);
2863      }
2864    }
2865
2866    return enum_name;
2867  }
2868
2869  /* -----------------------------------------------------------------------------
2870   * substituteClassname()
2871   *
2872   * Substitute the special variable $csclassname with the proxy class name for classes/structs/unions
2873   * that SWIG knows about. Also substitutes enums with enum name.
2874   * Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution
2875   * is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
2876   * Inputs:
2877   *   pt - parameter type
2878   *   tm - typemap contents that might contain the special variable to be replaced
2879   * Outputs:
2880   *   tm - typemap contents complete with the special variable substitution
2881   * Return:
2882   *   substitution_performed - flag indicating if a substitution was performed
2883   * ----------------------------------------------------------------------------- */
2884
2885  bool substituteClassname(SwigType *pt, String *tm) {
2886    bool substitution_performed = false;
2887    SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
2888    SwigType *strippedtype = SwigType_strip_qualifiers(type);
2889
2890    if (Strstr(tm, "$csclassname")) {
2891      SwigType *classnametype = Copy(strippedtype);
2892      substituteClassnameSpecialVariable(classnametype, tm, "$csclassname");
2893      substitution_performed = true;
2894      Delete(classnametype);
2895    }
2896    if (Strstr(tm, "$*csclassname")) {
2897      SwigType *classnametype = Copy(strippedtype);
2898      Delete(SwigType_pop(classnametype));
2899      substituteClassnameSpecialVariable(classnametype, tm, "$*csclassname");
2900      substitution_performed = true;
2901      Delete(classnametype);
2902    }
2903    if (Strstr(tm, "$&csclassname")) {
2904      SwigType *classnametype = Copy(strippedtype);
2905      SwigType_add_pointer(classnametype);
2906      substituteClassnameSpecialVariable(classnametype, tm, "$&csclassname");
2907      substitution_performed = true;
2908      Delete(classnametype);
2909    }
2910
2911    Delete(strippedtype);
2912    Delete(type);
2913
2914    return substitution_performed;
2915  }
2916
2917  /* -----------------------------------------------------------------------------
2918   * substituteClassnameSpecialVariable()
2919   * ----------------------------------------------------------------------------- */
2920
2921  void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable) {
2922    if (SwigType_isenum(classnametype)) {
2923      String *enumname = getEnumName(classnametype);
2924      if (enumname)
2925	Replaceall(tm, classnamespecialvariable, enumname);
2926      else
2927	Replaceall(tm, classnamespecialvariable, NewStringf("int"));
2928    } else {
2929      String *classname = getProxyName(classnametype);
2930      if (classname) {
2931	Replaceall(tm, classnamespecialvariable, classname);	// getProxyName() works for pointers to classes too
2932      } else {			// use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
2933	String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
2934	Replaceall(tm, classnamespecialvariable, descriptor);
2935
2936	// Add to hash table so that the type wrapper classes can be created later
2937	Setattr(swig_types_hash, descriptor, classnametype);
2938	Delete(descriptor);
2939      }
2940    }
2941  }
2942
2943  /* -----------------------------------------------------------------------------
2944   * makeParameterName()
2945   *
2946   * Inputs:
2947   *   n - Node
2948   *   p - parameter node
2949   *   arg_num - parameter argument number
2950   *   setter  - set this flag when wrapping variables
2951   * Return:
2952   *   arg - a unique parameter name
2953   * ----------------------------------------------------------------------------- */
2954
2955  String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) {
2956
2957    String *arg = 0;
2958    String *pn = Getattr(p, "name");
2959
2960    // Use C parameter name unless it is a duplicate or an empty parameter name
2961    int count = 0;
2962    ParmList *plist = Getattr(n, "parms");
2963    while (plist) {
2964      if ((Cmp(pn, Getattr(plist, "name")) == 0))
2965        count++;
2966      plist = nextSibling(plist);
2967    }
2968    String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0;
2969    arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn);
2970
2971    if (setter && Cmp(arg, "self") != 0) {
2972      // Note that in C# properties, the input variable name is always called 'value'
2973      Delete(arg);
2974      arg = NewString("value");
2975    }
2976
2977    return arg;
2978  }
2979
2980  /* -----------------------------------------------------------------------------
2981   * emitTypeWrapperClass()
2982   * ----------------------------------------------------------------------------- */
2983
2984  void emitTypeWrapperClass(String *classname, SwigType *type) {
2985    Node *n = NewHash();
2986    Setfile(n, input_file);
2987    Setline(n, line_number);
2988
2989    String *swigtype = NewString("");
2990    String *filen = NewStringf("%s%s.cs", SWIG_output_directory(), classname);
2991    File *f_swigtype = NewFile(filen, "w", SWIG_output_files());
2992    if (!f_swigtype) {
2993      FileErrorDisplay(filen);
2994      SWIG_exit(EXIT_FAILURE);
2995    }
2996    Append(filenames_list, Copy(filen));
2997    Delete(filen);
2998    filen = NULL;
2999
3000    // Start writing out the type wrapper class file
3001    emitBanner(f_swigtype);
3002
3003    addOpenNamespace(namespce, f_swigtype);
3004
3005    // Pure C# baseclass and interfaces
3006    const String *pure_baseclass = typemapLookup(n, "csbase", type, WARN_NONE);
3007    const String *pure_interfaces = typemapLookup(n, "csinterfaces", type, WARN_NONE);
3008
3009    // Emit the class
3010    Printv(swigtype, typemapLookup(n, "csimports", type, WARN_NONE),	// Import statements
3011	   "\n", NIL);
3012
3013    // Class attributes
3014    const String *csattributes = typemapLookup(n, "csattributes", type, WARN_NONE);
3015    if (csattributes && *Char(csattributes))
3016      Printf(swigtype, "%s\n", csattributes);
3017
3018    Printv(swigtype, typemapLookup(n, "csclassmodifiers", type, WARN_CSHARP_TYPEMAP_CLASSMOD_UNDEF),	// Class modifiers
3019	   " $csclassname",	// Class name and base class
3020	   (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass, ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ?	// Interfaces
3021	   ", " : "", pure_interfaces, " {", typemapLookup(n, "csbody", type, WARN_CSHARP_TYPEMAP_CSBODY_UNDEF),	// main body of class
3022	   typemapLookup(n, "cscode", type, WARN_NONE),	// extra C# code
3023	   "}\n", NIL);
3024
3025    Replaceall(swigtype, "$csclassname", classname);
3026    Replaceall(swigtype, "$module", module_class_name);
3027    Replaceall(swigtype, "$imclassname", imclass_name);
3028    Replaceall(swigtype, "$dllimport", dllimport);
3029
3030    Printv(f_swigtype, swigtype, NIL);
3031
3032    addCloseNamespace(namespce, f_swigtype);
3033
3034    Close(f_swigtype);
3035    Delete(swigtype);
3036    Delete(n);
3037  }
3038
3039  /* -----------------------------------------------------------------------------
3040   * typemapLookup()
3041   * n - for input only and must contain info for Getfile(n) and Getline(n) to work
3042   * tmap_method - typemap method name
3043   * type - typemap type to lookup
3044   * warning - warning number to issue if no typemaps found
3045   * typemap_attributes - the typemap attributes are attached to this node and will
3046   *   also be used for temporary storage if non null
3047   * return is never NULL, unlike Swig_typemap_lookup()
3048   * ----------------------------------------------------------------------------- */
3049
3050  const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
3051    Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
3052    Setattr(node, "type", type);
3053    Setfile(node, Getfile(n));
3054    Setline(node, Getline(n));
3055    const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
3056    if (!tm) {
3057      tm = empty_string;
3058      if (warning != WARN_NONE)
3059	Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
3060    }
3061    if (!typemap_attributes)
3062      Delete(node);
3063    return tm;
3064  }
3065
3066  /* -----------------------------------------------------------------------------
3067   * canThrow()
3068   * Determine whether the code in the typemap can throw a C# exception.
3069   * If so, note it for later when excodeSubstitute() is called.
3070   * ----------------------------------------------------------------------------- */
3071
3072  void canThrow(Node *n, const String *typemap, Node *parameter) {
3073    String *canthrow_attribute = NewStringf("tmap:%s:canthrow", typemap);
3074    String *canthrow = Getattr(parameter, canthrow_attribute);
3075    if (canthrow)
3076      Setattr(n, "csharp:canthrow", "1");
3077    Delete(canthrow_attribute);
3078  }
3079
3080  /* -----------------------------------------------------------------------------
3081   * excodeSubstitute()
3082   * If a method can throw a C# exception, additional exception code is added to
3083   * check for the pending exception so that it can then throw the exception. The
3084   * $excode special variable is replaced by the exception code in the excode
3085   * typemap attribute.
3086   * ----------------------------------------------------------------------------- */
3087
3088  void excodeSubstitute(Node *n, String *code, const String *typemap, Node *parameter) {
3089    String *excode_attribute = NewStringf("tmap:%s:excode", typemap);
3090    String *excode = Getattr(parameter, excode_attribute);
3091    if (Getattr(n, "csharp:canthrow")) {
3092      int count = Replaceall(code, "$excode", excode);
3093      if (count < 1 || !excode) {
3094	Swig_warning(WARN_CSHARP_EXCODE, input_file, line_number,
3095		     "C# exception may not be thrown - no $excode or excode attribute in '%s' typemap.\n", typemap);
3096      }
3097    } else {
3098      Replaceall(code, "$excode", empty_string);
3099    }
3100    Delete(excode_attribute);
3101  }
3102
3103  /* -----------------------------------------------------------------------------
3104   * addOpenNamespace()
3105   * ----------------------------------------------------------------------------- */
3106
3107  void addOpenNamespace(String *namspace, File *file) {
3108    if (namspace)
3109      if (Len(namspace) > 0)
3110	Printf(file, "namespace %s {\n", namspace);
3111  }
3112
3113  /* -----------------------------------------------------------------------------
3114   * addCloseNamespace()
3115   * ----------------------------------------------------------------------------- */
3116
3117  void addCloseNamespace(String *namspace, File *file) {
3118    if (namspace)
3119      if (Len(namspace) > 0)
3120	Printf(file, "\n}\n");
3121  }
3122
3123  /*----------------------------------------------------------------------
3124   * Start of director methods
3125   *--------------------------------------------------------------------*/
3126
3127#if 0
3128  /*----------------------------------------------------------------------
3129   * emitDirectorUpcalls()
3130   *--------------------------------------------------------------------*/
3131
3132  void emitDirectorUpcalls() {
3133    if (n_dmethods) {
3134      Wrapper *w = NewWrapper();
3135      String *dmethod_data = NewString("");
3136      int n_methods = 0;
3137      Iterator udata_iter;
3138
3139      udata_iter = First(dmethods_seq);
3140      while (udata_iter.item) {
3141	UpcallData *udata = udata_iter.item;
3142	Printf(dmethod_data, "  { \"%s\", \"%s\" }", Getattr(udata, "imclass_method"), Getattr(udata, "imclass_fdesc"));
3143	++n_methods;
3144
3145	udata_iter = Next(udata_iter);
3146
3147	if (udata_iter.item)
3148	  Putc(',', dmethod_data);
3149	Putc('\n', dmethod_data);
3150      }
3151
3152
3153      Wrapper_print(w, f_wrappers);
3154      Delete(dmethod_data);
3155      Delete(swig_module_init);
3156      DelWrapper(w);
3157    }
3158  }
3159#endif
3160
3161  /*----------------------------------------------------------------------
3162   * emitDirectorExtraMethods()
3163   *
3164   * This is where the director connect method is
3165   * generated.
3166   *--------------------------------------------------------------------*/
3167  void emitDirectorExtraMethods(Node *n) {
3168    if (!Swig_directorclass(n))
3169      return;
3170
3171    // Output the director connect method:
3172    String *norm_name = SwigType_namestr(Getattr(n, "name"));
3173    String *swig_director_connect = NewStringf("%s_director_connect", proxy_class_name);
3174    String *sym_name = Getattr(n, "sym:name");
3175    Wrapper *code_wrap;
3176
3177    Printv(imclass_class_code, "\n  [DllImport(\"", dllimport, "\", EntryPoint=\"CSharp_", swig_director_connect, "\")]\n", NIL);
3178    Printf(imclass_class_code, "  public static extern void %s(HandleRef jarg1", swig_director_connect);
3179
3180    code_wrap = NewWrapper();
3181    Printf(code_wrap->def, "SWIGEXPORT void SWIGSTDCALL CSharp_%s(void *objarg", swig_director_connect);
3182
3183    Printf(code_wrap->code, "  %s *obj = (%s *)objarg;\n", norm_name, norm_name);
3184    Printf(code_wrap->code, "  SwigDirector_%s *director = dynamic_cast<SwigDirector_%s *>(obj);\n", sym_name, sym_name);
3185    // TODO: if statement not needed?? - Java too
3186    Printf(code_wrap->code, "  if (director) {\n");
3187    Printf(code_wrap->code, "    director->swig_connect_director(");
3188
3189    for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
3190      UpcallData *udata = Getitem(dmethods_seq, i);
3191      String *methid = Getattr(udata, "class_methodidx");
3192
3193      Printf(code_wrap->def, ", ");
3194      if (i != first_class_dmethod)
3195	Printf(code_wrap->code, ", ");
3196      Printf(code_wrap->def, "SwigDirector_%s::SWIG_Callback%s_t callback%s", sym_name, methid, methid);
3197      Printf(code_wrap->code, "callback%s", methid);
3198      Printf(imclass_class_code, ", %s.SwigDelegate%s_%s delegate%s", sym_name, sym_name, methid, methid);
3199    }
3200
3201    Printf(code_wrap->def, ") {\n");
3202    Printf(code_wrap->code, ");\n");
3203    Printf(imclass_class_code, ");\n");
3204    Printf(code_wrap->code, "  }\n");
3205    Printf(code_wrap->code, "}\n");
3206
3207    Wrapper_print(code_wrap, f_wrappers);
3208    DelWrapper(code_wrap);
3209
3210    Delete(swig_director_connect);
3211  }
3212
3213  /* ---------------------------------------------------------------
3214   * classDirectorMethod()
3215   *
3216   * Emit a virtual director method to pass a method call on to the
3217   * underlying Java object.
3218   *
3219   * --------------------------------------------------------------- */
3220
3221  int classDirectorMethod(Node *n, Node *parent, String *super) {
3222    String *empty_str = NewString("");
3223    String *classname = Getattr(parent, "sym:name");
3224    String *c_classname = Getattr(parent, "name");
3225    String *name = Getattr(n, "name");
3226    String *symname = Getattr(n, "sym:name");
3227    SwigType *type = Getattr(n, "type");
3228    SwigType *returntype = Getattr(n, "returntype");
3229    String *overloaded_name = getOverloadedName(n);
3230    String *storage = Getattr(n, "storage");
3231    String *value = Getattr(n, "value");
3232    String *decl = Getattr(n, "decl");
3233    String *declaration = NewString("");
3234    String *tm;
3235    Parm *p;
3236    int i;
3237    Wrapper *w = NewWrapper();
3238    ParmList *l = Getattr(n, "parms");
3239    bool is_void = !(Cmp(returntype, "void"));
3240    String *qualified_return = NewString("");
3241    bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
3242    int status = SWIG_OK;
3243    bool output_director = true;
3244    String *dirclassname = directorClassName(parent);
3245    String *qualified_name = NewStringf("%s::%s", dirclassname, name);
3246    SwigType *c_ret_type = NULL;
3247    String *jupcall_args = NewString("");
3248    String *imclass_dmethod;
3249    String *callback_typedef_parms = NewString("");
3250    String *delegate_parms = NewString("");
3251    String *proxy_method_types = NewString("");
3252    String *callback_def = NewString("");
3253    String *callback_code = NewString("");
3254    String *imcall_args = NewString("");
3255    int gencomma = 0;
3256    bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
3257
3258    // Kludge Alert: functionWrapper sets sym:overload properly, but it
3259    // isn't at this point, so we have to manufacture it ourselves. At least
3260    // we're consistent with the sym:overload name in functionWrapper. (?? when
3261    // does the overloaded method name get set?)
3262
3263    imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(classname, overloaded_name));
3264
3265    if (returntype) {
3266
3267      qualified_return = SwigType_rcaststr(returntype, "c_result");
3268
3269      if (!is_void && !ignored_method) {
3270	if (!SwigType_isclass(returntype)) {
3271	  if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
3272            String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
3273	    Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
3274            Delete(construct_result);
3275	  } else {
3276	    String *base_typename = SwigType_base(returntype);
3277	    String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
3278	    Symtab *symtab = Getattr(n, "sym:symtab");
3279	    Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
3280
3281	    if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstract"))) {
3282	      /* initialize pointers to something sane. Same for abstract
3283	         classes when a reference is returned. */
3284	      Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
3285	    } else {
3286	      /* If returning a reference, initialize the pointer to a sane
3287	         default - if a C# exception occurs, then the pointer returns
3288	         something other than a NULL-initialized reference. */
3289	      String *non_ref_type = Copy(returntype);
3290
3291	      /* Remove reference and const qualifiers */
3292	      Replaceall(non_ref_type, "r.", "");
3293	      Replaceall(non_ref_type, "q(const).", "");
3294	      Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL);
3295	      Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL);
3296
3297	      Delete(non_ref_type);
3298	    }
3299
3300	    Delete(base_typename);
3301	    Delete(resolved_typename);
3302	  }
3303	} else {
3304	  SwigType *vt;
3305
3306	  vt = cplus_value_type(returntype);
3307	  if (!vt) {
3308	    Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
3309	  } else {
3310	    Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
3311	    Delete(vt);
3312	  }
3313	}
3314      }
3315
3316      /* Create the intermediate class wrapper */
3317      Parm *tp = NewParmFromNode(returntype, empty_str, n);
3318
3319      tm = Swig_typemap_lookup("imtype", tp, "", 0);
3320      if (tm) {
3321	String *imtypeout = Getattr(tp, "tmap:imtype:out");	// the type in the imtype typemap's out attribute overrides the type in the typemap
3322	if (imtypeout)
3323	  tm = imtypeout;
3324        const String *im_directoroutattributes = Getattr(tp, "tmap:imtype:directoroutattributes");
3325        if (im_directoroutattributes) {
3326          Printf(callback_def, "  %s\n", im_directoroutattributes);
3327          Printf(director_delegate_definitions, "  %s\n", im_directoroutattributes);
3328        }
3329
3330	Printf(callback_def, "  private %s SwigDirector%s(", tm, overloaded_name);
3331	if (!ignored_method)
3332	  Printf(director_delegate_definitions, "  public delegate %s", tm);
3333      } else {
3334	Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(returntype, 0));
3335      }
3336
3337      Parm *retpm = NewParmFromNode(returntype, empty_str, n);
3338
3339      if ((c_ret_type = Swig_typemap_lookup("ctype", retpm, "", 0))) {
3340
3341	if (!is_void && !ignored_method) {
3342	  String *jretval_decl = NewStringf("%s jresult", c_ret_type);
3343	  Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
3344	  Delete(jretval_decl);
3345	}
3346      } else {
3347	Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
3348	    SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3349	output_director = false;
3350      }
3351
3352      Delete(retpm);
3353    }
3354
3355    /* Go through argument list, attach lnames for arguments */
3356    for (i = 0, p = l; p; p = nextSibling(p), ++i) {
3357      String *arg = Getattr(p, "name");
3358      String *lname = NewString("");
3359
3360      if (!arg && Cmp(Getattr(p, "type"), "void")) {
3361	lname = NewStringf("arg%d", i);
3362	Setattr(p, "name", lname);
3363      } else
3364	lname = arg;
3365
3366      Setattr(p, "lname", lname);
3367    }
3368
3369    /* Attach the standard typemaps */
3370    Swig_typemap_attach_parms("out", l, 0);
3371    Swig_typemap_attach_parms("ctype", l, 0);
3372    Swig_typemap_attach_parms("imtype", l, 0);
3373    Swig_typemap_attach_parms("cstype", l, 0);
3374    Swig_typemap_attach_parms("directorin", l, 0);
3375    Swig_typemap_attach_parms("csdirectorin", l, 0);
3376
3377    /* Preamble code */
3378    if (!ignored_method)
3379      Printf(w->code, "if (!swig_callback%s) {\n", overloaded_name);
3380
3381    if (!pure_virtual) {
3382      String *super_call = Swig_method_call(super, l);
3383      if (is_void) {
3384	Printf(w->code, "%s;\n", super_call);
3385	if (!ignored_method)
3386	  Printf(w->code, "return;\n");
3387      } else {
3388	Printf(w->code, "return %s;\n", super_call);
3389      }
3390      Delete(super_call);
3391    } else {
3392      Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
3393    }
3394
3395    if (!ignored_method)
3396      Printf(w->code, "} else {\n");
3397
3398    /* Go through argument list, convert from native to Java */
3399    for (p = l; p; /* empty */ ) {
3400      /* Is this superfluous? */
3401      while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
3402	p = Getattr(p, "tmap:directorin:next");
3403      }
3404
3405      SwigType *pt = Getattr(p, "type");
3406      String *ln = Copy(Getattr(p, "name"));
3407      String *c_param_type = NULL;
3408      String *c_decl = NewString("");
3409      String *arg = NewString("");
3410
3411      Printf(arg, "j%s", ln);
3412
3413      /* And add to the upcall args */
3414      if (gencomma > 0)
3415	Printf(jupcall_args, ", ");
3416      Printf(jupcall_args, "%s", arg);
3417
3418      /* Get parameter's intermediary C type */
3419      if ((c_param_type = Getattr(p, "tmap:ctype"))) {
3420	String *ctypeout = Getattr(p, "tmap:ctype:out");	// the type in the ctype typemap's out attribute overrides the type in the typemap
3421	if (ctypeout)
3422	  c_param_type = ctypeout;
3423
3424	Parm *tp = NewParmFromNode(c_param_type, empty_str, n);
3425	String *desc_tm = NULL;
3426
3427	/* Add to local variables */
3428	Printf(c_decl, "%s %s", c_param_type, arg);
3429	if (!ignored_method)
3430	  Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
3431
3432	/* Add input marshalling code */
3433	if ((desc_tm = Swig_typemap_lookup("directorin", tp, "", 0))
3434	    && (tm = Getattr(p, "tmap:directorin"))) {
3435
3436	  Replaceall(tm, "$input", arg);
3437	  Replaceall(tm, "$owner", "0");
3438
3439	  if (Len(tm))
3440	    if (!ignored_method)
3441	      Printf(w->code, "%s\n", tm);
3442
3443	  Delete(tm);
3444
3445	  /* Add C type to callback typedef */
3446	  if (gencomma > 0)
3447	    Printf(callback_typedef_parms, ", ");
3448	  Printf(callback_typedef_parms, "%s", c_param_type);
3449
3450	  /* Add parameter to the intermediate class code if generating the
3451	   * intermediate's upcall code */
3452	  if ((tm = Getattr(p, "tmap:imtype"))) {
3453
3454	    String *imtypeout = Getattr(p, "tmap:imtype:out");	// the type in the imtype typemap's out attribute overrides the type in the typemap
3455	    if (imtypeout)
3456	      tm = imtypeout;
3457            const String *im_directorinattributes = Getattr(p, "tmap:imtype:directorinattributes");
3458
3459	    String *din = Copy(Getattr(p, "tmap:csdirectorin"));
3460
3461	    if (din) {
3462	      Replaceall(din, "$module", module_class_name);
3463	      Replaceall(din, "$imclassname", imclass_name);
3464	      substituteClassname(pt, din);
3465	      Replaceall(din, "$iminput", ln);
3466
3467	      if (gencomma > 0) {
3468		Printf(delegate_parms, ", ");
3469		Printf(proxy_method_types, ", ");
3470		Printf(imcall_args, ", ");
3471	      }
3472	      Printf(delegate_parms, "%s%s %s", im_directorinattributes ? im_directorinattributes : empty_string, tm, ln);
3473
3474	      if (Cmp(din, ln)) {
3475		Printv(imcall_args, din, NIL);
3476	      } else
3477		Printv(imcall_args, ln, NIL);
3478
3479	      /* Get the C# parameter type */
3480	      if ((tm = Getattr(p, "tmap:cstype"))) {
3481		substituteClassname(pt, tm);
3482		Printf(proxy_method_types, "typeof(%s)", tm);
3483	      } else {
3484		Swig_warning(WARN_CSHARP_TYPEMAP_CSWTYPE_UNDEF, input_file, line_number, "No cstype typemap defined for %s\n", SwigType_str(pt, 0));
3485	      }
3486	    } else {
3487	      Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number, "No csdirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",
3488		  SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3489	      output_director = false;
3490	    }
3491	  } else {
3492	    Swig_warning(WARN_CSHARP_TYPEMAP_CSTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s for use in %s::%s (skipping director method)\n",
3493		SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3494	    output_director = false;
3495	  }
3496
3497	  p = Getattr(p, "tmap:directorin:next");
3498
3499	  Delete(desc_tm);
3500	} else {
3501	  if (!desc_tm) {
3502	    Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number,
3503			 "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
3504			 SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3505	    p = nextSibling(p);
3506	  } else if (!tm) {
3507	    Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number,
3508			 "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
3509			 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3510	    p = nextSibling(p);
3511	  }
3512
3513	  output_director = false;
3514	}
3515
3516	Delete(tp);
3517      } else {
3518	Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
3519	    SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3520	output_director = false;
3521	p = nextSibling(p);
3522      }
3523
3524      gencomma++;
3525      Delete(arg);
3526      Delete(c_decl);
3527      Delete(c_param_type);
3528    }
3529
3530    /* header declaration, start wrapper definition */
3531    String *target;
3532    SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
3533    target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
3534    Printf(w->def, "%s", target);
3535    Delete(qualified_name);
3536    Delete(target);
3537    target = Swig_method_decl(rtype, decl, name, l, 0, 1);
3538    Printf(declaration, "    virtual %s", target);
3539    Delete(target);
3540
3541    // Add any exception specifications to the methods in the director class
3542    ParmList *throw_parm_list = NULL;
3543    if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
3544      int gencomma = 0;
3545
3546      Append(w->def, " throw(");
3547      Append(declaration, " throw(");
3548
3549      if (throw_parm_list)
3550	Swig_typemap_attach_parms("throws", throw_parm_list, 0);
3551      for (p = throw_parm_list; p; p = nextSibling(p)) {
3552	if ((tm = Getattr(p, "tmap:throws"))) {
3553	  if (gencomma++) {
3554	    Append(w->def, ", ");
3555	    Append(declaration, ", ");
3556	  }
3557	  Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
3558	  Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
3559	}
3560      }
3561
3562      Append(w->def, ")");
3563      Append(declaration, ")");
3564    }
3565
3566    Append(w->def, " {");
3567    Append(declaration, ";\n");
3568
3569    /* Finish off the inherited upcall's definition */
3570
3571    Printf(callback_def, "%s)", delegate_parms);
3572    Printf(callback_def, " {\n");
3573
3574    /* Emit the intermediate class's upcall to the actual class */
3575
3576    String *upcall = NewStringf("%s(%s)", symname, imcall_args);
3577
3578    if (!is_void) {
3579      Parm *tp = NewParmFromNode(returntype, empty_str, n);
3580
3581      if ((tm = Swig_typemap_lookup("csdirectorout", tp, "", 0))) {
3582	substituteClassname(returntype, tm);
3583	Replaceall(tm, "$cscall", upcall);
3584
3585	Printf(callback_code, "    return %s;\n", tm);
3586      }
3587
3588      Delete(tm);
3589      Delete(tp);
3590    } else
3591      Printf(callback_code, "    %s;\n", upcall);
3592
3593    Printf(callback_code, "  }\n");
3594    Delete(upcall);
3595
3596    if (!ignored_method) {
3597      if (!is_void)
3598	Printf(w->code, "jresult = (%s) ", c_ret_type);
3599
3600      Printf(w->code, "swig_callback%s(%s);\n", overloaded_name, jupcall_args);
3601
3602      if (!is_void) {
3603	String *jresult_str = NewString("jresult");
3604	String *result_str = NewString("c_result");
3605	Parm *tp = NewParmFromNode(returntype, result_str, n);
3606
3607	/* Copy jresult into c_result... */
3608	if ((tm = Swig_typemap_lookup("directorout", tp, result_str, w))) {
3609	  Replaceall(tm, "$input", jresult_str);
3610	  Replaceall(tm, "$result", result_str);
3611	  Printf(w->code, "%s\n", tm);
3612	} else {
3613	  Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
3614		       "Unable to use return type %s used in %s::%s (skipping director method)\n",
3615		       SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
3616	  output_director = false;
3617	}
3618
3619	Delete(tp);
3620	Delete(jresult_str);
3621	Delete(result_str);
3622      }
3623
3624      /* Terminate wrapper code */
3625      Printf(w->code, "}\n");
3626      if (!is_void)
3627	Printf(w->code, "return %s;", qualified_return);
3628    }
3629
3630    Printf(w->code, "}");
3631
3632    // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
3633    String *inline_extra_method = NewString("");
3634    if (dirprot_mode() && !is_public(n) && !pure_virtual) {
3635      Printv(inline_extra_method, declaration, NIL);
3636      String *extra_method_name = NewStringf("%sSwigPublic", name);
3637      Replaceall(inline_extra_method, name, extra_method_name);
3638      Replaceall(inline_extra_method, ";\n", " {\n      ");
3639      if (!is_void)
3640	Printf(inline_extra_method, "return ");
3641      String *methodcall = Swig_method_call(super, l);
3642      Printv(inline_extra_method, methodcall, ";\n    }\n", NIL);
3643      Delete(methodcall);
3644      Delete(extra_method_name);
3645    }
3646
3647    /* emit code */
3648    if (status == SWIG_OK && output_director) {
3649      if (!is_void) {
3650	Replaceall(w->code, "$null", qualified_return);
3651      } else {
3652	Replaceall(w->code, "$null", "");
3653      }
3654      if (!ignored_method)
3655	Printv(director_delegate_callback, "\n", callback_def, callback_code, NIL);
3656      if (!Getattr(n, "defaultargs")) {
3657	Wrapper_print(w, f_directors);
3658	Printv(f_directors_h, declaration, NIL);
3659	Printv(f_directors_h, inline_extra_method, NIL);
3660      }
3661    }
3662
3663    if (!ignored_method) {
3664      /* Emit the actual upcall through */
3665      UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, decl, overloaded_name);
3666      String *methid = Getattr(udata, "class_methodidx");
3667
3668      Printf(director_callback_typedefs, "    typedef %s (SWIGSTDCALL* SWIG_Callback%s_t)(", c_ret_type, methid);
3669      Printf(director_callback_typedefs, "%s);\n", callback_typedef_parms);
3670      Printf(director_callbacks, "    SWIG_Callback%s_t swig_callback%s;\n", methid, overloaded_name);
3671
3672      Printf(director_delegate_definitions, " SwigDelegate%s_%s(%s);\n", classname, methid, delegate_parms);
3673      Printf(director_delegate_instances, "  private SwigDelegate%s_%s swigDelegate%s;\n", classname, methid, methid);
3674      Printf(director_method_types, "  private static Type[] swigMethodTypes%s = new Type[] { %s };\n", methid, proxy_method_types);
3675      Printf(director_connect_parms, "SwigDirector%s%s delegate%s", classname, methid, methid);
3676    }
3677
3678    Delete(qualified_return);
3679    Delete(c_ret_type);
3680    Delete(declaration);
3681    Delete(callback_typedef_parms);
3682    Delete(delegate_parms);
3683    Delete(proxy_method_types);
3684    Delete(callback_def);
3685    Delete(callback_code);
3686    DelWrapper(w);
3687
3688    return status;
3689  }
3690
3691  /* ------------------------------------------------------------
3692   * classDirectorConstructor()
3693   * ------------------------------------------------------------ */
3694
3695  int classDirectorConstructor(Node *n) {
3696    Node *parent = parentNode(n);
3697    String *decl = Getattr(n, "decl");;
3698    String *supername = Swig_class_name(parent);
3699    String *classname = directorClassName(parent);
3700    String *sub = NewString("");
3701    Parm *p;
3702    ParmList *superparms = Getattr(n, "parms");
3703    ParmList *parms;
3704    int argidx = 0;
3705
3706    /* Assign arguments to superclass's parameters, if not already done */
3707    for (p = superparms; p; p = nextSibling(p)) {
3708      String *pname = Getattr(p, "name");
3709
3710      if (!pname) {
3711	pname = NewStringf("arg%d", argidx++);
3712	Setattr(p, "name", pname);
3713      }
3714    }
3715
3716    // TODO: Is this copy needed?
3717    parms = CopyParmList(superparms);
3718
3719    if (!Getattr(n, "defaultargs")) {
3720      /* constructor */
3721      {
3722	String *basetype = Getattr(parent, "classtype");
3723	String *target = Swig_method_decl(0, decl, classname, parms, 0, 0);
3724	String *call = Swig_csuperclass_call(0, basetype, superparms);
3725	String *classtype = SwigType_namestr(Getattr(n, "name"));
3726
3727	Printf(f_directors, "%s::%s : %s, %s {\n", classname, target, call, Getattr(parent, "director:ctor"));
3728	Printf(f_directors, "  swig_init_callbacks();\n");
3729	Printf(f_directors, "}\n\n");
3730
3731	Delete(classtype);
3732	Delete(target);
3733	Delete(call);
3734      }
3735
3736      /* constructor header */
3737      {
3738	String *target = Swig_method_decl(0, decl, classname, parms, 0, 1);
3739	Printf(f_directors_h, "    %s;\n", target);
3740	Delete(target);
3741      }
3742    }
3743
3744    Delete(sub);
3745    Delete(supername);
3746    Delete(parms);
3747    return Language::classDirectorConstructor(n);
3748  }
3749
3750  /* ------------------------------------------------------------
3751   * classDirectorDefaultConstructor()
3752   * ------------------------------------------------------------ */
3753
3754  int classDirectorDefaultConstructor(Node *n) {
3755    String *classname = Swig_class_name(n);
3756    String *classtype = SwigType_namestr(Getattr(n, "name"));
3757    Wrapper *w = NewWrapper();
3758
3759    Printf(w->def, "SwigDirector_%s::SwigDirector_%s() : %s {", classname, classname, Getattr(n, "director:ctor"));
3760    Printf(w->code, "}\n");
3761    Wrapper_print(w, f_directors);
3762
3763    Printf(f_directors_h, "    SwigDirector_%s();\n", classname);
3764    DelWrapper(w);
3765    Delete(classtype);
3766    Delete(classname);
3767    return Language::classDirectorDefaultConstructor(n);
3768  }
3769
3770
3771  /* ------------------------------------------------------------
3772   * classDirectorInit()
3773   * ------------------------------------------------------------ */
3774
3775  int classDirectorInit(Node *n) {
3776    Delete(none_comparison);
3777    none_comparison = NewString("");	// not used
3778
3779    Delete(director_ctor_code);
3780    director_ctor_code = NewString("$director_new");
3781
3782    Java_director_declaration(n);
3783
3784    Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl"));
3785    Printf(f_directors_h, "\npublic:\n");
3786
3787    /* Keep track of the director methods for this class */
3788    first_class_dmethod = curr_class_dmethod = n_dmethods;
3789
3790    director_callback_typedefs = NewString("");
3791    director_callbacks = NewString("");
3792    director_delegate_callback = NewString("");
3793    director_delegate_definitions = NewString("");
3794    director_delegate_instances = NewString("");
3795    director_method_types = NewString("");
3796    director_connect_parms = NewString("");
3797
3798    return Language::classDirectorInit(n);
3799  }
3800
3801  /* ----------------------------------------------------------------------
3802   * classDirectorDestructor()
3803   * ---------------------------------------------------------------------- */
3804
3805  int classDirectorDestructor(Node *n) {
3806    Node *current_class = getCurrentClass();
3807    String *full_classname = Getattr(current_class, "name");
3808    String *classname = Swig_class_name(current_class);
3809    Wrapper *w = NewWrapper();
3810
3811    if (Getattr(n, "throw")) {
3812      Printf(f_directors_h, "    virtual ~SwigDirector_%s() throw ();\n", classname);
3813      Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() throw () {\n", classname, classname);
3814    } else {
3815      Printf(f_directors_h, "    virtual ~SwigDirector_%s();\n", classname);
3816      Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() {\n", classname, classname);
3817    }
3818
3819    /* Ensure that correct directordisconnect typemap's method name is called
3820     * here: */
3821
3822    const String *disconn_tm = NULL;
3823    Node *disconn_attr = NewHash();
3824    String *disconn_methodname = NULL;
3825
3826    disconn_tm = typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr);
3827    disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname");
3828
3829    Printv(w->code, "}\n", NIL);
3830
3831    Wrapper_print(w, f_directors);
3832
3833    DelWrapper(w);
3834    Delete(disconn_attr);
3835    Delete(classname);
3836    return SWIG_OK;
3837  }
3838
3839  /* ------------------------------------------------------------
3840   * classDirectorEnd()
3841   * ------------------------------------------------------------ */
3842
3843  int classDirectorEnd(Node *n) {
3844    int i;
3845    String *director_classname = directorClassName(n);
3846
3847    Wrapper *w = NewWrapper();
3848
3849    if (Len(director_callback_typedefs) > 0) {
3850      Printf(f_directors_h, "\n%s", director_callback_typedefs);
3851    }
3852
3853    Printf(f_directors_h, "    void swig_connect_director(");
3854
3855    Printf(w->def, "void %s::swig_connect_director(", director_classname);
3856
3857    for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
3858      UpcallData *udata = Getitem(dmethods_seq, i);
3859      String *methid = Getattr(udata, "class_methodidx");
3860      String *overname = Getattr(udata, "overname");
3861
3862      Printf(f_directors_h, "SWIG_Callback%s_t callback%s", methid, overname);
3863      Printf(w->def, "SWIG_Callback%s_t callback%s", methid, overname);
3864      Printf(w->code, "swig_callback%s = callback%s;\n", overname, overname);
3865      if (i != curr_class_dmethod - 1) {
3866	Printf(f_directors_h, ", ");
3867	Printf(w->def, ", ");
3868      }
3869    }
3870
3871    Printf(f_directors_h, ");\n");
3872    Printf(w->def, ") {");
3873
3874
3875    if (Len(director_callback_typedefs) > 0) {
3876      Printf(f_directors_h, "\nprivate:\n%s", director_callbacks);
3877    }
3878    Printf(f_directors_h, "    void swig_init_callbacks();\n");
3879    Printf(f_directors_h, "};\n\n");
3880    Printf(w->code, "}\n\n");
3881
3882    Printf(w->code, "void %s::swig_init_callbacks() {\n", director_classname);
3883    for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
3884      UpcallData *udata = Getitem(dmethods_seq, i);
3885      String *overname = Getattr(udata, "overname");
3886      Printf(w->code, "swig_callback%s = 0;\n", overname);
3887    }
3888    Printf(w->code, "}");
3889
3890    Wrapper_print(w, f_directors);
3891
3892    DelWrapper(w);
3893
3894    return Language::classDirectorEnd(n);
3895  }
3896
3897  /* --------------------------------------------------------------------
3898   * classDirectorDisown()
3899   * ------------------------------------------------------------------*/
3900  virtual int classDirectorDisown(Node *n) {
3901    (void) n;
3902    return SWIG_OK;
3903  }
3904
3905  /*----------------------------------------------------------------------
3906   * extraDirectorProtectedCPPMethodsRequired()
3907   *--------------------------------------------------------------------*/
3908
3909  bool extraDirectorProtectedCPPMethodsRequired() const {
3910    return false;
3911  }
3912
3913  /*----------------------------------------------------------------------
3914   * Java_director_declaration()
3915   *
3916   * Generate the director class's declaration
3917   * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
3918   *--------------------------------------------------------------------*/
3919
3920  void Java_director_declaration(Node *n) {
3921
3922    String *base = Getattr(n, "classtype");
3923    String *class_ctor = NewString("Swig::Director()");
3924
3925    String *classname = Swig_class_name(n);
3926    String *directorname = NewStringf("SwigDirector_%s", classname);
3927    String *declaration = Swig_class_declaration(n, directorname);
3928
3929    Printf(declaration, " : public %s, public Swig::Director", base);
3930
3931    // Stash stuff for later.
3932    Setattr(n, "director:decl", declaration);
3933    Setattr(n, "director:ctor", class_ctor);
3934  }
3935
3936};				/* class CSHARP */
3937
3938/* -----------------------------------------------------------------------------
3939 * swig_csharp()    - Instantiate module
3940 * ----------------------------------------------------------------------------- */
3941
3942static Language *new_swig_csharp() {
3943  return new CSHARP();
3944}
3945extern "C" Language *swig_csharp(void) {
3946  return new_swig_csharp();
3947}
3948
3949/* -----------------------------------------------------------------------------
3950 * Static member variables
3951 * ----------------------------------------------------------------------------- */
3952
3953const char *CSHARP::usage = (char *) "\
3954C# Options (available with -csharp)\n\
3955     -dllimport <dl> - Override DllImport attribute name to <dl>\n\
3956     -namespace <nm> - Generate wrappers into C# namespace <nm>\n\
3957     -noproxy        - Generate the low-level functional interface instead\n\
3958                       of proxy classes\n\
3959     -oldvarnames    - old intermediary method names for variable wrappers\n\
3960\n";
3961