import source from 1.3.40
[external/swig.git] / Source / Modules / csharp.cxx
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
10 char 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++ */
18 typedef DOH UpcallData;
19
20 class 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
96 public:
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
3942 static Language *new_swig_csharp() {
3943   return new CSHARP();
3944 }
3945 extern "C" Language *swig_csharp(void) {
3946   return new_swig_csharp();
3947 }
3948
3949 /* -----------------------------------------------------------------------------
3950  * Static member variables
3951  * ----------------------------------------------------------------------------- */
3952
3953 const char *CSHARP::usage = (char *) "\
3954 C# 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";