/tags/rel-2.0.1/Source/Modules/csharp.cxx

# · C++ · 1761 lines · 1257 code · 248 blank · 256 comment · 312 complexity · 342b4754cea09ac4873ab439710a62b9 MD5 · raw file

Large files are truncated click here to view the full file

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