PageRenderTime 61ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/trunk/Source/Modules/d.cxx

#
C++ | 1938 lines | 1269 code | 297 blank | 372 comment | 238 complexity | 10b1678babbe738037ae5bbff7e705ee MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  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. * d.cxx
  10. *
  11. * D language module for SWIG.
  12. * ----------------------------------------------------------------------------- */
  13. char cvsroot_d_cxx[] = "$Id$";
  14. #include "swigmod.h"
  15. #include "cparse.h"
  16. #include <ctype.h>
  17. // Hash type used for storing information about director callbacks for a class.
  18. typedef DOH UpcallData;
  19. class D : public Language {
  20. static const char *usage;
  21. const String *empty_string;
  22. const String *public_string;
  23. const String *protected_string;
  24. const String *static_string;
  25. /*
  26. * Files and file sections containing C/C++ code.
  27. */
  28. File *f_begin;
  29. File *f_runtime;
  30. File *f_runtime_h;
  31. File *f_header;
  32. File *f_wrappers;
  33. File *f_init;
  34. File *f_directors;
  35. File *f_directors_h;
  36. List *filenames_list;
  37. /*
  38. * Command line-set modes of operation.
  39. */
  40. // Whether a single proxy D module is generated or classes and enums are
  41. // written to their own files.
  42. bool split_proxy_dmodule;
  43. // The major D version targeted (currently 1 or 2).
  44. unsigned short d_version;
  45. /*
  46. * State variables which indicate what is being wrapped at the moment.
  47. * This is probably not the most elegant way of handling state, but it has
  48. * proven to work in the C# and Java modules.
  49. */
  50. // Indicates if wrapping a native function.
  51. bool native_function_flag;
  52. // Indicates if wrapping a static functions or member variables
  53. bool static_flag;
  54. // Indicates if wrapping a nonstatic member variable
  55. bool variable_wrapper_flag;
  56. // Indicates if wrapping a member variable/enum/const.
  57. bool wrapping_member_flag;
  58. // Indicates if wrapping a global variable.
  59. bool global_variable_flag;
  60. // Name of a variable being wrapped.
  61. String *variable_name;
  62. /*
  63. * Variables temporarily holding the generated C++ code.
  64. */
  65. // C++ code for the generated wrapper functions for casts up the C++
  66. // for inheritance hierarchies.
  67. String *upcasts_code;
  68. // Function pointer typedefs for handling director callbacks on the C++ side.
  69. String *director_callback_typedefs;
  70. // Variables for storing the function pointers to the director callbacks on
  71. // the C++ side.
  72. String *director_callback_pointers;
  73. /*
  74. * Names of generated D entities.
  75. */
  76. // The name of the D module containing the interface to the C wrapper.
  77. String *im_dmodule_name;
  78. // The fully qualified name of the wrap D module (package name included).
  79. String *im_dmodule_fq_name;
  80. // The name of the proxy module which exposes the (SWIG) module contents as a
  81. // D module.
  82. String *proxy_dmodule_name;
  83. // The fully qualified name of the proxy D module.
  84. String *proxy_dmodule_fq_name;
  85. // Optional: Package the D modules are placed in (set via the -package
  86. // command line option).
  87. String *package;
  88. // The directory the generated D module files are written to. Is constructed
  89. // from the package path if a target package is set, points to the general
  90. // output directory otherwise.
  91. String *dmodule_directory;
  92. // The name of the library which contains the C wrapper (used when generating
  93. // the dynamic library loader). Can be overridden via the -wrapperlibrary
  94. // command line flag.
  95. String *wrap_library_name;
  96. /*
  97. * Variables temporarily holding the generated D code.
  98. */
  99. // Import statements written to the intermediary D module header set via
  100. // %pragma(d) imdmoduleimports.
  101. String *im_dmodule_imports;
  102. // The code for the intermediary D module body.
  103. String *im_dmodule_code;
  104. // Import statements for all proxy modules (the main proxy module and, if in
  105. // split proxy module mode, the proxy class modules) from
  106. // %pragma(d) globalproxyimports.
  107. String *global_proxy_imports;
  108. // The D code for the main proxy modules. nspace_proxy_dmodules is a hash from
  109. // the namespace name as key to an {"imports", "code"}. If the nspace feature
  110. // is not active, only proxy_dmodule_imports and proxy_dmodule_code are used,
  111. // which contain the code for the root proxy module.
  112. //
  113. // These variables should not be accessed directly but rather via the
  114. // proxy{Imports, Code}Buffer)() helper functions which return the right
  115. // buffer for a given namespace. If not in split proxy mode, they contain the
  116. // whole proxy code.
  117. String *proxy_dmodule_imports;
  118. String *proxy_dmodule_code;
  119. Hash *nspace_proxy_dmodules;
  120. // The D code generated for the currently processed enum.
  121. String *proxy_enum_code;
  122. /*
  123. * D data for the current proxy class.
  124. *
  125. * These strings are mainly used to temporarily accumulate code from the
  126. * various member handling functions while a single class is processed and are
  127. * no longer relevant once that class has been finished, i.e. after
  128. * classHandler() has returned.
  129. */
  130. // The unqualified name of the current proxy class.
  131. String *proxy_class_name;
  132. // The name of the current proxy class, qualified with the name of the
  133. // namespace it is in, if any.
  134. String *proxy_class_qname;
  135. // The import directives for the current proxy class. They are written to the
  136. // same D module the proxy class is written to.
  137. String *proxy_class_imports;
  138. // Code for enumerations nested in the current proxy class. Is emitted earlier
  139. // than the rest of the body to work around forward referencing-issues.
  140. String *proxy_class_enums_code;
  141. // The generated D code making up the body of the current proxy class.
  142. String *proxy_class_body_code;
  143. // D code which is emitted right after the proxy class.
  144. String *proxy_class_epilogue_code;
  145. // The full code for the current proxy class, including the epilogue.
  146. String* proxy_class_code;
  147. // Contains a D call to the function wrapping C++ the destructor of the
  148. // current class (if there is a public C++ destructor).
  149. String *destructor_call;
  150. // D code for the director callbacks generated for the current class.
  151. String *director_dcallbacks_code;
  152. /*
  153. * Code for dynamically loading the wrapper library on the D side.
  154. */
  155. // D code which is inserted into the im D module if dynamic linking is used.
  156. String *wrapper_loader_code;
  157. // The D code to bind a function pointer to a library symbol.
  158. String *wrapper_loader_bind_command;
  159. // The cumulated binding commands binding all the functions declared in the
  160. // intermediary D module to the C/C++ library symbols.
  161. String *wrapper_loader_bind_code;
  162. /*
  163. * Director data.
  164. */
  165. List *dmethods_seq;
  166. Hash *dmethods_table;
  167. int n_dmethods;
  168. int first_class_dmethod;
  169. int curr_class_dmethod;
  170. /*
  171. * SWIG types data.
  172. */
  173. // Collects information about encountered types SWIG does not know about (e.g.
  174. // incomplete types). This is used later to generate type wrapper proxy
  175. // classes for the unknown types.
  176. Hash *unknown_types;
  177. public:
  178. /* ---------------------------------------------------------------------------
  179. * D::D()
  180. * --------------------------------------------------------------------------- */
  181. D():empty_string(NewString("")),
  182. public_string(NewString("public")),
  183. protected_string(NewString("protected")),
  184. f_begin(NULL),
  185. f_runtime(NULL),
  186. f_runtime_h(NULL),
  187. f_header(NULL),
  188. f_wrappers(NULL),
  189. f_init(NULL),
  190. f_directors(NULL),
  191. f_directors_h(NULL),
  192. filenames_list(NULL),
  193. split_proxy_dmodule(false),
  194. d_version(1),
  195. native_function_flag(false),
  196. static_flag(false),
  197. variable_wrapper_flag(false),
  198. wrapping_member_flag(false),
  199. global_variable_flag(false),
  200. variable_name(NULL),
  201. upcasts_code(NULL),
  202. director_callback_typedefs(NULL),
  203. director_callback_pointers(NULL),
  204. im_dmodule_name(NULL),
  205. im_dmodule_fq_name(NULL),
  206. proxy_dmodule_name(NULL),
  207. proxy_dmodule_fq_name(NULL),
  208. package(NULL),
  209. dmodule_directory(NULL),
  210. wrap_library_name(NULL),
  211. im_dmodule_imports(NULL),
  212. im_dmodule_code(NULL),
  213. global_proxy_imports(NULL),
  214. proxy_dmodule_imports(NULL),
  215. proxy_dmodule_code(NULL),
  216. nspace_proxy_dmodules(NULL),
  217. proxy_enum_code(NULL),
  218. proxy_class_name(NULL),
  219. proxy_class_qname(NULL),
  220. proxy_class_imports(NULL),
  221. proxy_class_enums_code(NULL),
  222. proxy_class_body_code(NULL),
  223. proxy_class_epilogue_code(NULL),
  224. proxy_class_code(NULL),
  225. destructor_call(NULL),
  226. director_dcallbacks_code(NULL),
  227. wrapper_loader_code(NULL),
  228. wrapper_loader_bind_command(NULL),
  229. wrapper_loader_bind_code(NULL),
  230. dmethods_seq(NULL),
  231. dmethods_table(NULL),
  232. n_dmethods(0),
  233. unknown_types(NULL) {
  234. // For now, multiple inheritance with directors is not possible. It should be
  235. // easy to implement though.
  236. director_multiple_inheritance = 0;
  237. director_language = 1;
  238. // Not used:
  239. Delete(none_comparison);
  240. none_comparison = NewString("");
  241. }
  242. /* ---------------------------------------------------------------------------
  243. * D::main()
  244. * --------------------------------------------------------------------------- */
  245. virtual void main(int argc, char *argv[]) {
  246. SWIG_library_directory("d");
  247. // Look for certain command line options
  248. for (int i = 1; i < argc; i++) {
  249. if (argv[i]) {
  250. if ((strcmp(argv[i], "-d2") == 0)) {
  251. Swig_mark_arg(i);
  252. d_version = 2;
  253. } else if (strcmp(argv[i], "-wrapperlibrary") == 0) {
  254. if (argv[i + 1]) {
  255. wrap_library_name = NewString("");
  256. Printf(wrap_library_name, argv[i + 1]);
  257. Swig_mark_arg(i);
  258. Swig_mark_arg(i + 1);
  259. i++;
  260. } else {
  261. Swig_arg_error();
  262. }
  263. } else if (strcmp(argv[i], "-package") == 0) {
  264. if (argv[i + 1]) {
  265. package = NewString("");
  266. Printf(package, argv[i + 1]);
  267. Swig_mark_arg(i);
  268. Swig_mark_arg(i + 1);
  269. i++;
  270. } else {
  271. Swig_arg_error();
  272. }
  273. } else if ((strcmp(argv[i], "-splitproxy") == 0)) {
  274. Swig_mark_arg(i);
  275. split_proxy_dmodule = true;
  276. } else if (strcmp(argv[i], "-help") == 0) {
  277. Printf(stdout, "%s\n", usage);
  278. }
  279. }
  280. }
  281. // Add a symbol to the parser for conditional compilation
  282. Preprocessor_define("SWIGD 1", 0);
  283. // Also make the target D version available as preprocessor symbol for
  284. // use in our library files.
  285. String *version_define = NewStringf("SWIG_D_VERSION %u", d_version);
  286. Preprocessor_define(version_define, 0);
  287. Delete(version_define);
  288. // Add typemap definitions
  289. SWIG_typemap_lang("d");
  290. SWIG_config_file("d.swg");
  291. allow_overloading();
  292. }
  293. /* ---------------------------------------------------------------------------
  294. * D::top()
  295. * --------------------------------------------------------------------------- */
  296. virtual int top(Node *n) {
  297. // Get any options set in the module directive
  298. Node *optionsnode = Getattr(Getattr(n, "module"), "options");
  299. if (optionsnode) {
  300. if (Getattr(optionsnode, "imdmodulename")) {
  301. im_dmodule_name = Copy(Getattr(optionsnode, "imdmodulename"));
  302. }
  303. if (Getattr(optionsnode, "directors")) {
  304. // Check if directors are enabled for this module. Note: This is a
  305. // "master switch", if it is not set, not director code will be emitted
  306. // at all. %feature("director") statements are also required to enable
  307. // directors for individual classes or methods.
  308. //
  309. // Use the ťdirectorsŤ attributte of the %module directive to enable
  310. // director generation (e.g. ť%module(directors="1") modulenameŤ).
  311. allow_directors();
  312. }
  313. if (Getattr(optionsnode, "dirprot")) {
  314. allow_dirprot();
  315. }
  316. allow_allprotected(GetFlag(optionsnode, "allprotected"));
  317. }
  318. /* Initialize all of the output files */
  319. String *outfile = Getattr(n, "outfile");
  320. String *outfile_h = Getattr(n, "outfile_h");
  321. if (!outfile) {
  322. Printf(stderr, "Unable to determine outfile\n");
  323. SWIG_exit(EXIT_FAILURE);
  324. }
  325. f_begin = NewFile(outfile, "w", SWIG_output_files());
  326. if (!f_begin) {
  327. FileErrorDisplay(outfile);
  328. SWIG_exit(EXIT_FAILURE);
  329. }
  330. if (directorsEnabled()) {
  331. if (!outfile_h) {
  332. Printf(stderr, "Unable to determine outfile_h\n");
  333. SWIG_exit(EXIT_FAILURE);
  334. }
  335. f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
  336. if (!f_runtime_h) {
  337. FileErrorDisplay(outfile_h);
  338. SWIG_exit(EXIT_FAILURE);
  339. }
  340. }
  341. f_runtime = NewString("");
  342. f_init = NewString("");
  343. f_header = NewString("");
  344. f_wrappers = NewString("");
  345. f_directors_h = NewString("");
  346. f_directors = NewString("");
  347. /* Register file targets with the SWIG file handler */
  348. Swig_register_filebyname("header", f_header);
  349. Swig_register_filebyname("wrapper", f_wrappers);
  350. Swig_register_filebyname("begin", f_begin);
  351. Swig_register_filebyname("runtime", f_runtime);
  352. Swig_register_filebyname("init", f_init);
  353. Swig_register_filebyname("director", f_directors);
  354. Swig_register_filebyname("director_h", f_directors_h);
  355. unknown_types = NewHash();
  356. filenames_list = NewList();
  357. // Make the package name and the resulting module output path.
  358. if (package) {
  359. // Append a dot so we can prepend the package variable directly to the
  360. // module names in the rest of the code.
  361. Printv(package, ".", NIL);
  362. } else {
  363. // Write the generated D modules to the ťrootŤ package by default.
  364. package = NewString("");
  365. }
  366. dmodule_directory = Copy(SWIG_output_directory());
  367. if (Len(package) > 0) {
  368. String *package_directory = Copy(package);
  369. Replaceall(package_directory, ".", SWIG_FILE_DELIMITER);
  370. Printv(dmodule_directory, package_directory, NIL);
  371. Delete(package_directory);
  372. }
  373. // Make the wrap and proxy D module names.
  374. // The wrap module name can be set in the module directive.
  375. if (!im_dmodule_name) {
  376. im_dmodule_name = NewStringf("%s_im", Getattr(n, "name"));
  377. }
  378. im_dmodule_fq_name = NewStringf("%s%s", package, im_dmodule_name);
  379. proxy_dmodule_name = Copy(Getattr(n, "name"));
  380. proxy_dmodule_fq_name = NewStringf("%s%s", package, proxy_dmodule_name);
  381. im_dmodule_code = NewString("");
  382. proxy_class_imports = NewString("");
  383. proxy_class_enums_code = NewString("");
  384. proxy_class_body_code = NewString("");
  385. proxy_class_epilogue_code = NewString("");
  386. proxy_class_code = NewString("");
  387. destructor_call = NewString("");
  388. proxy_dmodule_code = NewString("");
  389. proxy_dmodule_imports = NewString("");
  390. nspace_proxy_dmodules = NewHash();
  391. im_dmodule_imports = NewString("");
  392. upcasts_code = NewString("");
  393. global_proxy_imports = NewString("");
  394. wrapper_loader_code = NewString("");
  395. wrapper_loader_bind_command = NewString("");
  396. wrapper_loader_bind_code = NewString("");
  397. dmethods_seq = NewList();
  398. dmethods_table = NewHash();
  399. n_dmethods = 0;
  400. // By default, expect the dynamically loaded wrapper library to be named
  401. // [lib]<module>_wrap[.so/.dll].
  402. if (!wrap_library_name)
  403. wrap_library_name = NewStringf("%s_wrap", Getattr(n, "name"));
  404. Swig_banner(f_begin);
  405. Printf(f_runtime, "\n");
  406. Printf(f_runtime, "#define SWIGD\n");
  407. if (directorsEnabled()) {
  408. Printf(f_runtime, "#define SWIG_DIRECTORS\n");
  409. /* Emit initial director header and director code: */
  410. Swig_banner(f_directors_h);
  411. Printf(f_directors_h, "\n");
  412. Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", proxy_dmodule_name);
  413. Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", proxy_dmodule_name);
  414. Printf(f_directors, "\n\n");
  415. Printf(f_directors, "/* ---------------------------------------------------\n");
  416. Printf(f_directors, " * C++ director class methods\n");
  417. Printf(f_directors, " * --------------------------------------------------- */\n\n");
  418. if (outfile_h)
  419. Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
  420. }
  421. Printf(f_runtime, "\n");
  422. Swig_name_register("wrapper", "D_%f");
  423. Printf(f_wrappers, "\n#ifdef __cplusplus\n");
  424. Printf(f_wrappers, "extern \"C\" {\n");
  425. Printf(f_wrappers, "#endif\n\n");
  426. // Emit all the wrapper code.
  427. Language::top(n);
  428. if (directorsEnabled()) {
  429. // Insert director runtime into the f_runtime file (before %header section).
  430. Swig_insert_file("director.swg", f_runtime);
  431. }
  432. // Generate the wrap D module.
  433. // TODO: Add support for ťstaticŤ linking.
  434. {
  435. String *filen = NewStringf("%s%s.d", dmodule_directory, im_dmodule_name);
  436. File *im_d_file = NewFile(filen, "w", SWIG_output_files());
  437. if (!im_d_file) {
  438. FileErrorDisplay(filen);
  439. SWIG_exit(EXIT_FAILURE);
  440. }
  441. Append(filenames_list, Copy(filen));
  442. Delete(filen);
  443. filen = NULL;
  444. // Start writing out the intermediary class file.
  445. emitBanner(im_d_file);
  446. Printf(im_d_file, "module %s;\n", im_dmodule_fq_name);
  447. Printv(im_d_file, im_dmodule_imports, "\n", NIL);
  448. Replaceall(wrapper_loader_code, "$wraplibrary", wrap_library_name);
  449. Replaceall(wrapper_loader_code, "$wrapperloaderbindcode", wrapper_loader_bind_code);
  450. Replaceall(wrapper_loader_code, "$module", proxy_dmodule_name);
  451. Printf(im_d_file, "%s\n", wrapper_loader_code);
  452. // Add the wrapper function declarations.
  453. replaceModuleVariables(im_dmodule_code);
  454. Printv(im_d_file, im_dmodule_code, NIL);
  455. Close(im_d_file);
  456. }
  457. // Generate the main D proxy module.
  458. {
  459. String *filen = NewStringf("%s%s.d", dmodule_directory, proxy_dmodule_name);
  460. File *proxy_d_file = NewFile(filen, "w", SWIG_output_files());
  461. if (!proxy_d_file) {
  462. FileErrorDisplay(filen);
  463. SWIG_exit(EXIT_FAILURE);
  464. }
  465. Append(filenames_list, Copy(filen));
  466. Delete(filen);
  467. filen = NULL;
  468. emitBanner(proxy_d_file);
  469. Printf(proxy_d_file, "module %s;\n", proxy_dmodule_fq_name);
  470. Printf(proxy_d_file, "\nstatic import %s;\n", im_dmodule_fq_name);
  471. Printv(proxy_d_file, global_proxy_imports, NIL);
  472. Printv(proxy_d_file, proxy_dmodule_imports, NIL);
  473. Printv(proxy_d_file, "\n", NIL);
  474. // Write a D type wrapper class for each SWIG type to the proxy module code.
  475. for (Iterator swig_type = First(unknown_types); swig_type.key; swig_type = Next(swig_type)) {
  476. writeTypeWrapperClass(swig_type.key, swig_type.item);
  477. }
  478. // Add the proxy functions (and classes, if they are not written to a
  479. // seperate file).
  480. replaceModuleVariables(proxy_dmodule_code);
  481. Printv(proxy_d_file, proxy_dmodule_code, NIL);
  482. Close(proxy_d_file);
  483. }
  484. // Generate the additional proxy modules for nspace support.
  485. for (Iterator it = First(nspace_proxy_dmodules); it.key; it = Next(it)) {
  486. String *module_name = createLastNamespaceName(it.key);
  487. String *filename = NewStringf("%s%s.d", outputDirectory(it.key), module_name);
  488. File *file = NewFile(filename, "w", SWIG_output_files());
  489. if (!file) {
  490. FileErrorDisplay(filename);
  491. SWIG_exit(EXIT_FAILURE);
  492. }
  493. Delete(filename);
  494. emitBanner(file);
  495. Printf(file, "module %s%s.%s;\n", package, it.key, module_name);
  496. Printf(file, "\nstatic import %s;\n", im_dmodule_fq_name);
  497. Printv(file, global_proxy_imports, NIL);
  498. Printv(file, Getattr(it.item, "imports"), NIL);
  499. Printv(file, "\n", NIL);
  500. String *code = Getattr(it.item, "code");
  501. replaceModuleVariables(code);
  502. Printv(file, code, NIL);
  503. Close(file);
  504. Delete(module_name);
  505. }
  506. if (upcasts_code)
  507. Printv(f_wrappers, upcasts_code, NIL);
  508. Printf(f_wrappers, "#ifdef __cplusplus\n");
  509. Printf(f_wrappers, "}\n");
  510. Printf(f_wrappers, "#endif\n");
  511. // Check for overwriting file problems on filesystems that are case insensitive
  512. Iterator it1;
  513. Iterator it2;
  514. for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
  515. String *item1_lower = Swig_string_lower(it1.item);
  516. for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
  517. String *item2_lower = Swig_string_lower(it2.item);
  518. if (it1.item && it2.item) {
  519. if (Strcmp(item1_lower, item2_lower) == 0) {
  520. Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
  521. "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
  522. "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
  523. }
  524. }
  525. Delete(item2_lower);
  526. }
  527. Delete(item1_lower);
  528. }
  529. Delete(unknown_types);
  530. unknown_types = NULL;
  531. Delete(filenames_list);
  532. filenames_list = NULL;
  533. Delete(im_dmodule_name);
  534. im_dmodule_name = NULL;
  535. Delete(im_dmodule_fq_name);
  536. im_dmodule_fq_name = NULL;
  537. Delete(im_dmodule_code);
  538. im_dmodule_code = NULL;
  539. Delete(proxy_class_imports);
  540. proxy_class_imports = NULL;
  541. Delete(proxy_class_enums_code);
  542. proxy_class_enums_code = NULL;
  543. Delete(proxy_class_body_code);
  544. proxy_class_body_code = NULL;
  545. Delete(proxy_class_epilogue_code);
  546. proxy_class_epilogue_code = NULL;
  547. Delete(proxy_class_code);
  548. proxy_class_code = NULL;
  549. Delete(destructor_call);
  550. destructor_call = NULL;
  551. Delete(proxy_dmodule_name);
  552. proxy_dmodule_name = NULL;
  553. Delete(proxy_dmodule_fq_name);
  554. proxy_dmodule_fq_name = NULL;
  555. Delete(proxy_dmodule_code);
  556. proxy_dmodule_code = NULL;
  557. Delete(proxy_dmodule_imports);
  558. proxy_dmodule_imports = NULL;
  559. Delete(nspace_proxy_dmodules);
  560. nspace_proxy_dmodules = NULL;
  561. Delete(im_dmodule_imports);
  562. im_dmodule_imports = NULL;
  563. Delete(upcasts_code);
  564. upcasts_code = NULL;
  565. Delete(global_proxy_imports);
  566. global_proxy_imports = NULL;
  567. Delete(wrapper_loader_code);
  568. wrapper_loader_code = NULL;
  569. Delete(wrapper_loader_bind_code);
  570. wrapper_loader_bind_code = NULL;
  571. Delete(wrapper_loader_bind_command);
  572. wrapper_loader_bind_command = NULL;
  573. Delete(dmethods_seq);
  574. dmethods_seq = NULL;
  575. Delete(dmethods_table);
  576. dmethods_table = NULL;
  577. Delete(package);
  578. package = NULL;
  579. Delete(dmodule_directory);
  580. dmodule_directory = NULL;
  581. n_dmethods = 0;
  582. // Merge all the generated C/C++ code and close the output files.
  583. Dump(f_runtime, f_begin);
  584. Dump(f_header, f_begin);
  585. if (directorsEnabled()) {
  586. Dump(f_directors, f_begin);
  587. Dump(f_directors_h, f_runtime_h);
  588. Printf(f_runtime_h, "\n");
  589. Printf(f_runtime_h, "#endif\n");
  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. Dump(f_wrappers, f_begin);
  599. Wrapper_pretty_print(f_init, f_begin);
  600. Delete(f_header);
  601. Delete(f_wrappers);
  602. Delete(f_init);
  603. Close(f_begin);
  604. Delete(f_runtime);
  605. Delete(f_begin);
  606. return SWIG_OK;
  607. }
  608. /* ---------------------------------------------------------------------------
  609. * D::insertDirective()
  610. * --------------------------------------------------------------------------- */
  611. virtual int insertDirective(Node *n) {
  612. String *code = Getattr(n, "code");
  613. replaceModuleVariables(code);
  614. return Language::insertDirective(n);
  615. }
  616. /* ---------------------------------------------------------------------------
  617. * D::pragmaDirective()
  618. *
  619. * Valid Pragmas:
  620. * imdmodulecode - text (D code) is copied verbatim to the wrap module
  621. * imdmoduleimports - import statements for the im D module
  622. *
  623. * proxydmodulecode - text (D code) is copied verbatim to the proxy module
  624. * (the main proxy module if in split proxy mode).
  625. * globalproxyimports - import statements inserted into _all_ proxy modules.
  626. *
  627. * wrapperloadercode - D code for loading the wrapper library (is copied to
  628. * the im D module).
  629. * wrapperloaderbindcommand - D code for binding a symbol from the wrapper
  630. * library to the declaration in the im D module.
  631. * --------------------------------------------------------------------------- */
  632. virtual int pragmaDirective(Node *n) {
  633. if (!ImportMode) {
  634. String *lang = Getattr(n, "lang");
  635. String *code = Getattr(n, "name");
  636. String *value = Getattr(n, "value");
  637. if (Strcmp(lang, "d") == 0) {
  638. String *strvalue = NewString(value);
  639. Replaceall(strvalue, "\\\"", "\"");
  640. if (Strcmp(code, "imdmodulecode") == 0) {
  641. Printf(im_dmodule_code, "%s\n", strvalue);
  642. } else if (Strcmp(code, "imdmoduleimports") == 0) {
  643. replaceImportTypeMacros(strvalue);
  644. Chop(strvalue);
  645. Printf(im_dmodule_imports, "%s\n", strvalue);
  646. } else if (Strcmp(code, "proxydmodulecode") == 0) {
  647. Printf(proxyCodeBuffer(0), "%s\n", strvalue);
  648. } else if (Strcmp(code, "globalproxyimports") == 0) {
  649. replaceImportTypeMacros(strvalue);
  650. Chop(strvalue);
  651. Printf(global_proxy_imports, "%s\n", strvalue);
  652. } else if (Strcmp(code, "wrapperloadercode") == 0) {
  653. Delete(wrapper_loader_code);
  654. wrapper_loader_code = Copy(strvalue);
  655. } else if (Strcmp(code, "wrapperloaderbindcommand") == 0) {
  656. Delete(wrapper_loader_bind_command);
  657. wrapper_loader_bind_command = Copy(strvalue);
  658. } else {
  659. Swig_error(input_file, line_number, "Unrecognized pragma.\n");
  660. }
  661. Delete(strvalue);
  662. }
  663. }
  664. return Language::pragmaDirective(n);
  665. }
  666. /* ---------------------------------------------------------------------------
  667. * D::enumDeclaration()
  668. *
  669. * Wraps C/C++ enums as D enums.
  670. * --------------------------------------------------------------------------- */
  671. virtual int enumDeclaration(Node *n) {
  672. if (ImportMode)
  673. return SWIG_OK;
  674. if (getCurrentClass() && (cplus_mode != PUBLIC))
  675. return SWIG_NOWRAP;
  676. proxy_enum_code = NewString("");
  677. String *symname = Getattr(n, "sym:name");
  678. String *typemap_lookup_type = Getattr(n, "name");
  679. // Emit the enum declaration.
  680. if (typemap_lookup_type) {
  681. const String *enummodifiers = lookupCodeTypemap(n, "dclassmodifiers", typemap_lookup_type, WARN_D_TYPEMAP_CLASSMOD_UNDEF);
  682. Printv(proxy_enum_code, "\n", enummodifiers, " ", symname, " {\n", NIL);
  683. } else {
  684. // Handle anonymous enums.
  685. Printv(proxy_enum_code, "\nenum {\n", NIL);
  686. }
  687. // Emit each enum item.
  688. Language::enumDeclaration(n);
  689. if (!GetFlag(n, "nonempty")) {
  690. // Do not wrap empty enums; the resulting D code would be illegal.
  691. Delete(proxy_enum_code);
  692. return SWIG_NOWRAP;
  693. }
  694. // Finish the enum.
  695. if (typemap_lookup_type) {
  696. Printv(proxy_enum_code,
  697. lookupCodeTypemap(n, "dcode", typemap_lookup_type, WARN_NONE), // Extra D code
  698. "\n}\n", NIL);
  699. } else {
  700. // Handle anonymous enums.
  701. Printv(proxy_enum_code, "\n}\n", NIL);
  702. }
  703. Replaceall(proxy_enum_code, "$dclassname", symname);
  704. const String* imports =
  705. lookupCodeTypemap(n, "dimports", typemap_lookup_type, WARN_NONE);
  706. String* imports_trimmed;
  707. if (Len(imports) > 0) {
  708. imports_trimmed = Copy(imports);
  709. Chop(imports_trimmed);
  710. replaceImportTypeMacros(imports_trimmed);
  711. Printv(imports_trimmed, "\n", NIL);
  712. } else {
  713. imports_trimmed = NewString("");
  714. }
  715. if (is_wrapping_class()) {
  716. // Enums defined within the C++ class are written into the proxy
  717. // class.
  718. Printv(proxy_class_imports, imports_trimmed, NIL);
  719. Printv(proxy_class_enums_code, proxy_enum_code, NIL);
  720. } else {
  721. // Write non-anonymous enums to their own file if in split proxy module
  722. // mode.
  723. if (split_proxy_dmodule && typemap_lookup_type) {
  724. assertClassNameValidity(proxy_class_name);
  725. String *nspace = Getattr(n, "sym:nspace");
  726. String *output_directory = outputDirectory(nspace);
  727. String *filename = NewStringf("%s%s.d", output_directory, symname);
  728. Delete(output_directory);
  729. File *class_file = NewFile(filename, "w", SWIG_output_files());
  730. if (!class_file) {
  731. FileErrorDisplay(filename);
  732. SWIG_exit(EXIT_FAILURE);
  733. }
  734. Append(filenames_list, Copy(filename));
  735. Delete(filename);
  736. emitBanner(class_file);
  737. if (nspace) {
  738. Printf(class_file, "module %s%s.%s;\n", package, nspace, symname);
  739. } else {
  740. Printf(class_file, "module %s%s;\n", package, symname);
  741. }
  742. Printv(class_file, imports_trimmed, NIL);
  743. Printv(class_file, proxy_enum_code, NIL);
  744. Close(class_file);
  745. Delete(class_file);
  746. } else {
  747. String *nspace = Getattr(n, "sym:nspace");
  748. Printv(proxyImportsBuffer(nspace), imports, NIL);
  749. Printv(proxyCodeBuffer(nspace), proxy_enum_code, NIL);
  750. }
  751. }
  752. Delete(imports_trimmed);
  753. Delete(proxy_enum_code);
  754. proxy_enum_code = NULL;
  755. return SWIG_OK;
  756. }
  757. /* ---------------------------------------------------------------------------
  758. * D::enumvalueDeclaration()
  759. * --------------------------------------------------------------------------- */
  760. virtual int enumvalueDeclaration(Node *n) {
  761. if (getCurrentClass() && (cplus_mode != PUBLIC))
  762. return SWIG_NOWRAP;
  763. Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
  764. String *value = Getattr(n, "value");
  765. String *name = Getattr(n, "name");
  766. Node *parent = parentNode(n);
  767. String *tmpValue;
  768. // Strange hack from parent method.
  769. // RESEARCH: What is this doing?
  770. if (value)
  771. tmpValue = NewString(value);
  772. else
  773. tmpValue = NewString(name);
  774. // Note that this is used in enumValue() amongst other places
  775. Setattr(n, "value", tmpValue);
  776. // Deal with enum values that are not int
  777. int swigtype = SwigType_type(Getattr(n, "type"));
  778. if (swigtype == T_BOOL) {
  779. const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0";
  780. Setattr(n, "enumvalue", val);
  781. } else if (swigtype == T_CHAR) {
  782. String *val = NewStringf("'%s'", Getattr(n, "enumvalue"));
  783. Setattr(n, "enumvalue", val);
  784. Delete(val);
  785. }
  786. // Emit the enum item.
  787. {
  788. if (!GetFlag(n, "firstenumitem"))
  789. Printf(proxy_enum_code, ",\n");
  790. Printf(proxy_enum_code, " %s", Getattr(n, "sym:name"));
  791. // Check for the %dconstvalue feature
  792. String *value = Getattr(n, "feature:d:constvalue");
  793. // Note that in D, enum values must be compile-time constants. Thus,
  794. // %dmanifestconst(0) (getting the enum values at runtime) is not supported.
  795. value = value ? value : Getattr(n, "enumvalue");
  796. if (value) {
  797. Printf(proxy_enum_code, " = %s", value);
  798. }
  799. // Keep track that the currently processed enum has at least one value.
  800. SetFlag(parent, "nonempty");
  801. }
  802. Delete(tmpValue);
  803. Swig_restore(n);
  804. return SWIG_OK;
  805. }
  806. /* ---------------------------------------------------------------------------
  807. * D::memberfunctionHandler()
  808. * --------------------------------------------------------------------------- */
  809. virtual int memberfunctionHandler(Node *n) {
  810. Language::memberfunctionHandler(n);
  811. String *overloaded_name = getOverloadedName(n);
  812. String *intermediary_function_name =
  813. Swig_name_member(getNSpace(), proxy_class_name, overloaded_name);
  814. Setattr(n, "imfuncname", intermediary_function_name);
  815. String *proxy_func_name = Getattr(n, "sym:name");
  816. Setattr(n, "proxyfuncname", proxy_func_name);
  817. if (split_proxy_dmodule &&
  818. Len(Getattr(n, "parms")) == 0 &&
  819. Strncmp(proxy_func_name, package, Len(proxy_func_name)) == 0) {
  820. // If we are in split proxy mode and the function is named like the
  821. // target package, the D compiler is unable to resolve the ambiguity
  822. // between the package name and an argument-less function call.
  823. // TODO: This might occur with nspace as well, augment the check.
  824. Swig_warning(WARN_D_NAME_COLLISION, input_file, line_number,
  825. "%s::%s might collide with the package name, consider using %%rename to resolve the ambiguity.\n",
  826. proxy_class_name, proxy_func_name);
  827. }
  828. writeProxyClassFunction(n);
  829. Delete(overloaded_name);
  830. // For each function, look if we have to alias in the parent class function
  831. // for the overload resolution process to work as expected from C++
  832. // (http://www.digitalmars.com/d/2.0/function.html#function-inheritance).
  833. // For multiple overloads, only emit the alias directive once (for the
  834. // last method, ťsym:nextSiblingŤ is null then).
  835. // Smart pointer classes do not mirror the inheritance hierarchy of the
  836. // underlying types, so aliasing the base class methods in is not required
  837. // for them.
  838. // DMD BUG: We have to emit the alias after the last function becasue
  839. // taking a delegate in the overload checking code fails otherwise
  840. // (http://d.puremagic.com/issues/show_bug.cgi?id=4860).
  841. if (!Getattr(n, "sym:nextSibling") && !is_smart_pointer() &&
  842. !areAllOverloadsOverridden(n)) {
  843. String *name = Getattr(n, "sym:name");
  844. Printf(proxy_class_body_code, "\nalias $dbaseclass.%s %s;\n", name, name);
  845. }
  846. return SWIG_OK;
  847. }
  848. /* ---------------------------------------------------------------------------
  849. * D::staticmemberfunctionHandler()
  850. * --------------------------------------------------------------------------- */
  851. virtual int staticmemberfunctionHandler(Node *n) {
  852. static_flag = true;
  853. Language::staticmemberfunctionHandler(n);
  854. String *overloaded_name = getOverloadedName(n);
  855. String *intermediary_function_name =
  856. Swig_name_member(getNSpace(), proxy_class_name, overloaded_name);
  857. Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
  858. Setattr(n, "imfuncname", intermediary_function_name);
  859. writeProxyClassFunction(n);
  860. Delete(overloaded_name);
  861. static_flag = false;
  862. return SWIG_OK;
  863. }
  864. /* ---------------------------------------------------------------------------
  865. * D::globalvariableHandler()
  866. * --------------------------------------------------------------------------- */
  867. virtual int globalvariableHandler(Node *n) {
  868. variable_name = Getattr(n, "sym:name");
  869. global_variable_flag = true;
  870. int ret = Language::globalvariableHandler(n);
  871. global_variable_flag = false;
  872. return ret;
  873. }
  874. /* ---------------------------------------------------------------------------
  875. * D::membervariableHandler()
  876. * --------------------------------------------------------------------------- */
  877. virtual int membervariableHandler(Node *n) {
  878. variable_name = Getattr(n, "sym:name");
  879. wrapping_member_flag = true;
  880. variable_wrapper_flag = true;
  881. Language::membervariableHandler(n);
  882. wrapping_member_flag = false;
  883. variable_wrapper_flag = false;
  884. return SWIG_OK;
  885. }
  886. /* ---------------------------------------------------------------------------
  887. * D::staticmembervariableHandler()
  888. * --------------------------------------------------------------------------- */
  889. virtual int staticmembervariableHandler(Node *n) {
  890. if (GetFlag(n, "feature:d:manifestconst") != 1) {
  891. Delattr(n, "value");
  892. }
  893. variable_name = Getattr(n, "sym:name");
  894. wrapping_member_flag = true;
  895. static_flag = true;
  896. Language::staticmembervariableHandler(n);
  897. wrapping_member_flag = false;
  898. static_flag = false;
  899. return SWIG_OK;
  900. }
  901. /* ---------------------------------------------------------------------------
  902. * D::memberconstantHandler()
  903. * --------------------------------------------------------------------------- */
  904. virtual int memberconstantHandler(Node *n) {
  905. variable_name = Getattr(n, "sym:name");
  906. wrapping_member_flag = true;
  907. Language::memberconstantHandler(n);
  908. wrapping_member_flag = false;
  909. return SWIG_OK;
  910. }
  911. /* ---------------------------------------------------------------------------
  912. * D::constructorHandler()
  913. * --------------------------------------------------------------------------- */
  914. virtual int constructorHandler(Node *n) {
  915. Language::constructorHandler(n);
  916. // Wrappers not wanted for some methods where the parameters cannot be overloadedprocess in D.
  917. if (Getattr(n, "overload:ignore")) {
  918. return SWIG_OK;
  919. }
  920. ParmList *l = Getattr(n, "parms");
  921. String *tm;
  922. String *proxy_constructor_code = NewString("");
  923. int i;
  924. // Holds code for the constructor helper method generated only when the din
  925. // typemap has code in the pre or post attributes.
  926. String *helper_code = NewString("");
  927. String *helper_args = NewString("");
  928. String *pre_code = NewString("");
  929. String *post_code = NewString("");
  930. String *terminator_code = NewString("");
  931. NewString("");
  932. String *overloaded_name = getOverloadedName(n);
  933. String *mangled_overname = Swig_name_construct(getNSpace(), overloaded_name);
  934. String *imcall = NewString("");
  935. const String *methodmods = Getattr(n, "feature:d:methodmodifiers");
  936. methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
  937. // Typemaps were attached earlier to the node, get the return type of the
  938. // call to the C++ constructor wrapper.
  939. const String *wrapper_return_type = lookupDTypemap(n, "imtype", true);
  940. String *imtypeout = Getattr(n, "tmap:imtype:out");
  941. if (imtypeout) {
  942. // The type in the imtype typemap's out attribute overrides the type in
  943. // the typemap itself.
  944. wrapper_return_type = imtypeout;
  945. }
  946. Printf(proxy_constructor_code, "\n%s this(", methodmods);
  947. Printf(helper_code, "static private %s SwigConstruct%s(",
  948. wrapper_return_type, proxy_class_name);
  949. Printv(imcall, im_dmodule_fq_name, ".", mangled_overname, "(", NIL);
  950. /* Attach the non-standard typemaps to the parameter list */
  951. Swig_typemap_attach_parms("in", l, NULL);
  952. Swig_typemap_attach_parms("dtype", l, NULL);
  953. Swig_typemap_attach_parms("din", l, NULL);
  954. emit_mark_varargs(l);
  955. int gencomma = 0;
  956. /* Output each parameter */
  957. Parm *p = l;
  958. for (i = 0; p; i++) {
  959. if (checkAttribute(p, "varargs:ignore", "1")) {
  960. // Skip ignored varargs.
  961. p = nextSibling(p);
  962. continue;
  963. }
  964. if (checkAttribute(p, "tmap:in:numinputs", "0")) {
  965. // Skip ignored parameters.
  966. p = Getattr(p, "tmap:in:next");
  967. continue;
  968. }
  969. SwigType *pt = Getattr(p, "type");
  970. String *param_type = NewString("");
  971. // Get the D parameter type.
  972. if ((tm = lookupDTypemap(p, "dtype", true))) {
  973. const String *inattributes = Getattr(p, "tmap:dtype:inattributes");
  974. Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
  975. } else {
  976. Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
  977. "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
  978. }
  979. if (gencomma)
  980. Printf(imcall, ", ");
  981. String *arg = makeParameterName(n, p, i, false);
  982. String *parmtype = 0;
  983. // Get the D code to convert the parameter value to the type used in the
  984. // intermediary D module.
  985. if ((tm = lookupDTypemap(p, "din"))) {
  986. Replaceall(tm, "$dinput", arg);
  987. String *pre = Getattr(p, "tmap:din:pre");
  988. if (pre) {
  989. replaceClassname(pre, pt);
  990. Replaceall(pre, "$dinput", arg);
  991. if (Len(pre_code) > 0)
  992. Printf(pre_code, "\n");
  993. Printv(pre_code, pre, NIL);
  994. }
  995. String *post = Getattr(p, "tmap:din:post");
  996. if (post) {
  997. replaceClassname(post, pt);
  998. Replaceall(post, "$dinput", arg);
  999. if (Len(post_code) > 0)
  1000. Printf(post_code, "\n");
  1001. Printv(post_code, post, NIL);
  1002. }
  1003. String *terminator = Getattr(p, "tmap:din:terminator");
  1004. if (terminator) {
  1005. replaceClassname(terminator, pt);
  1006. Replaceall(terminator, "$dinput", arg);
  1007. if (Len(terminator_code) > 0)
  1008. Insert(terminator_code, 0, "\n");
  1009. Insert(terminator_code, 0, terminator);
  1010. }
  1011. parmtype = Getattr(p, "tmap:din:parmtype");
  1012. if (parmtype)
  1013. Replaceall(parmtype, "$dinput", arg);
  1014. Printv(imcall, tm, NIL);
  1015. } else {
  1016. Swig_warning(WARN_D_TYPEMAP_DIN_UNDEF, input_file, line_number,
  1017. "No din typemap defined for %s\n", SwigType_str(pt, 0));
  1018. }
  1019. /* Add parameter to proxy function */
  1020. if (gencomma) {
  1021. Printf(proxy_constructor_code, ", ");
  1022. Printf(helper_code, ", ");
  1023. Printf(helper_args, ", ");
  1024. }
  1025. Printf(proxy_constructor_code, "%s %s", param_type, arg);
  1026. Printf(helper_code, "%s %s", param_type, arg);
  1027. Printf(helper_args, "%s", parmtype ? parmtype : arg);
  1028. ++gencomma;
  1029. Delete(parmtype);
  1030. Delete(arg);
  1031. Delete(param_type);
  1032. p = Getattr(p, "tmap:in:next");
  1033. }
  1034. Printf(imcall, ")");
  1035. Printf(proxy_constructor_code, ")");
  1036. Printf(helper_code, ")");
  1037. // Insert the dconstructor typemap (replacing $directorconnect as needed).
  1038. Hash *attributes = NewHash();
  1039. String *construct_tm = Copy(lookupCodeTypemap(n, "dconstructor",
  1040. Getattr(n, "name"), WARN_D_TYPEMAP_DCONSTRUCTOR_UNDEF, attributes));
  1041. if (construct_tm) {
  1042. const bool use_director = (parentNode(n) && Swig_directorclass(n));
  1043. if (!use_director) {
  1044. Replaceall(construct_tm, "$directorconnect", "");
  1045. } else {
  1046. String *connect_attr = Getattr(attributes, "tmap:dconstructor:directorconnect");
  1047. if (connect_attr) {
  1048. Replaceall(construct_tm, "$directorconnect", connect_attr);
  1049. } else {
  1050. Swig_warning(WARN_D_NO_DIRECTORCONNECT_ATTR, input_file, line_number,
  1051. "\"directorconnect\" attribute missing in %s \"dconstructor\" typemap.\n",
  1052. Getattr(n, "name"));
  1053. Replaceall(construct_tm, "$directorconnect", "");
  1054. }
  1055. }
  1056. Printv(proxy_constructor_code, " ", construct_tm, NIL);
  1057. }
  1058. replaceExcode(n, proxy_constructor_code, "dconstructor", attributes);
  1059. bool is_pre_code = Len(pre_code) > 0;
  1060. bool is_post_code = Len(post_code) > 0;
  1061. bool is_terminator_code = Len(terminator_code) > 0;
  1062. if (is_pre_code || is_post_code || is_terminator_code) {
  1063. Printf(helper_code, " {\n");
  1064. if (is_pre_code) {
  1065. Printv(helper_code, pre_code, "\n", NIL);
  1066. }
  1067. if (is_post_code) {
  1068. Printf(helper_code, " try {\n");
  1069. Printv(helper_code, " return ", imcall, ";\n", NIL);
  1070. Printv(helper_code, " } finally {\n", post_code, "\n }", NIL);
  1071. } else {
  1072. Printv(helper_code, " return ", imcall, ";", NIL);
  1073. }
  1074. if (is_terminator_code) {
  1075. Printv(helper_code, "\n", terminator_code, NIL);
  1076. }
  1077. Printf(helper_code, "\n}\n");
  1078. String *helper_name = NewStringf("%s.SwigConstruct%s(%s)",
  1079. proxy_class_name, proxy_class_name, helper_args);
  1080. Replaceall(proxy_constructor_code, "$imcall", helper_name);
  1081. Delete(helper_name);
  1082. } else {
  1083. Replaceall(proxy_constructor_code, "$imcall", imcall);
  1084. }
  1085. Printv(proxy_class_body_code, proxy_constructor_code, "\n", NIL);
  1086. Delete(helper_args);
  1087. Delete(pre_code);
  1088. Delete(post_code);
  1089. Delete(terminator_code);
  1090. Delete(construct_tm);
  1091. Delete(attributes);
  1092. Delete(overloaded_name);
  1093. Delete(imcall);
  1094. return SWIG_OK;
  1095. }
  1096. /* ---------------------------------------------------------------------------
  1097. * D::destructorHandler()
  1098. * --------------------------------------------------------------------------- */
  1099. virtual int destructorHandler(Node *n) {
  1100. Language::destructorHandler(n);
  1101. String *symname = Getattr(n, "sym:name");
  1102. Printv(destructor_call, im_dmodule_fq_name, ".", Swig_name_destroy(getNSpace(),symname), "(cast(void*)swigCPtr)", NIL);
  1103. return SWIG_OK;
  1104. }
  1105. /* ---------------------------------------------------------------------------
  1106. * D::classHandler()
  1107. * --------------------------------------------------------------------------- */
  1108. virtual int classHandler(Node *n) {
  1109. String *nspace = getNSpace();
  1110. File *class_file = NULL;
  1111. proxy_class_name = Copy(Getattr(n, "sym:name"));
  1112. if (nspace) {
  1113. proxy_class_qname = NewStringf("%s.%s", nspace, proxy_class_name);
  1114. } else {
  1115. proxy_class_qname = Copy(proxy_class_name);
  1116. }
  1117. if (!addSymbol(proxy_class_name, n, nspace)) {
  1118. return SWIG_ERROR;
  1119. }
  1120. assertClassNameValidity(proxy_class_name);
  1121. if (split_proxy_dmodule) {
  1122. String *output_directory = outputDirectory(nspace);
  1123. String *filename = NewStringf("%s%s.d", output_directory, proxy_class_name);
  1124. class_file = NewFile(filename, "w", SWIG_output_files());
  1125. Delete(output_directory);
  1126. if (!class_file) {
  1127. FileErrorDisplay(filename);
  1128. SWIG_exit(EXIT_FAILURE);
  1129. }
  1130. Append(filenames_list, Copy(filename));
  1131. Delete(filename);
  1132. emitBanner(class_file);
  1133. if (nspace) {
  1134. Printf(class_file, "module %s%s.%s;\n", package, nspace, proxy_class_name);
  1135. } else {
  1136. Printf(class_file, "module %s%s;\n", package, proxy_class_name);
  1137. }
  1138. Printf(class_file, "\nstatic import %s;\n", im_dmodule_fq_name);
  1139. }
  1140. Clear(proxy_class_imports);
  1141. Clear(proxy_class_enums_code);
  1142. Clear(proxy_class_body_code);
  1143. Clear(proxy_class_epilogue_code);
  1144. Clear(proxy_class_code);
  1145. Clear(destructor_call);
  1146. // Traverse the tree for this class, using the *Handler()s to generate code
  1147. // to the proxy_class_* variables.
  1148. Language::classHandler(n);
  1149. writeProxyClassAndUpcasts(n);
  1150. writeDirectorConnectWrapper(n);
  1151. Replaceall(proxy_class_code, "$dclassname", proxy_class_name);
  1152. String *dclazzname = Swig_name_member(getNSpace(), proxy_class_name, "");
  1153. Replaceall(proxy_class_code, "$dclazzname", dclazzname);
  1154. Delete(dclazzname);
  1155. if (split_proxy_dmodule) {
  1156. Printv(class_file, global_proxy_imports, NIL);
  1157. Printv(class_file, proxy_class_imports, NIL);
  1158. replaceModuleVariables(proxy_class_code);
  1159. Printv(class_file, proxy_class_code, NIL);
  1160. Close(class_file);
  1161. Delete(class_file);
  1162. } else {
  1163. Printv(proxyImportsBuffer(getNSpace()), proxy_class_imports, NIL);
  1164. Printv(proxyCodeBuffer(getNSpace()), proxy_class_code, NIL);
  1165. }
  1166. Delete(proxy_class_qname);
  1167. proxy_class_qname = NULL;
  1168. Delete(proxy_class_name);
  1169. proxy_class_name = NULL;
  1170. return SWIG_OK;
  1171. }
  1172. /* ---------------------------------------------------------------------------
  1173. * D::constantWrapper()
  1174. *
  1175. * Used for wrapping constants declared by #define or %constant and also for
  1176. * (primitive) static member constants initialised inline.
  1177. *
  1178. * If the %dmanifestconst feature is used, the C/C++ constant value is used to
  1179. * initialize a D ťconstŤ. If not, a ťgetterŤ method is generated which
  1180. * retrieves the value via a call to the C wrapper. However, if there is a
  1181. * %dconstvalue specified, it overrides all other settings.
  1182. * --------------------------------------------------------------------------- */
  1183. virtual int constantWrapper(Node *n) {
  1184. String *symname = Getattr(n, "sym:name");
  1185. if (!addSymbol(symname, n))
  1186. return SWIG_ERROR;
  1187. // The %dmanifestconst feature determines if a D manifest constant
  1188. // (const/enum) or a getter function is created.
  1189. if (GetFlag(n, "feature:d:manifestconst") != 1) {
  1190. // Default constant handling will work with any type of C constant. It
  1191. // generates a getter function (which is the same as a read only property
  1192. // in D) which retrieves the value via by calling the C wrapper.
  1193. // Note that this is only called for global constants, static member
  1194. // constants are already handeled in staticmemberfunctionHandler().
  1195. Swig_save("constantWrapper", n, "value", NIL);
  1196. Swig_save("constantWrapper", n, "tmap:ctype:out", "tmap:imtype:out", "tmap:dtype:out", "tmap:out:null", "tmap:imtype:outattributes", "tmap:dtype:outattributes", NIL);
  1197. // Add the stripped quotes back in.
  1198. String *old_value = Getattr(n, "value");
  1199. SwigType *t = Getattr(n, "type");
  1200. if (SwigType_type(t) == T_STRING) {
  1201. Setattr(n, "value", NewStringf("\"%s\"", old_value));
  1202. Delete(old_value);
  1203. } else if (SwigType_type(t) == T_CHAR) {
  1204. Setattr(n, "value", NewStringf("\'%s\'", old_value));
  1205. Delete(old_value);
  1206. }
  1207. SetFlag(n, "feature:immutable");
  1208. int result = globalvariableHandler(n);
  1209. Swig_restore(n);
  1210. return result;
  1211. }
  1212. String *constants_code = NewString("");
  1213. SwigType *t = Getattr(n, "type");
  1214. ParmList *l = Getattr(n, "parms");
  1215. // Attach the non-standard typemaps to the parameter list.
  1216. Swig_typemap_attach_parms("dtype", l, NULL);
  1217. // Get D return type.
  1218. String *return_type = NewString("");
  1219. String *tm;
  1220. if ((tm = lookupDTypemap(n, "dtype"))) {
  1221. String *dtypeout = Getattr(n, "tmap:dtype:out");
  1222. if (dtypeout) {
  1223. // The type in the out attribute of the typemap overrides the type
  1224. // in the dtype typemap.
  1225. tm = dtypeout;
  1226. replaceClassname(tm, t);
  1227. }
  1228. Printf(return_type, "%s", tm);
  1229. } else {
  1230. Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
  1231. "No dtype typemap defined for %s\n", SwigType_str(t, 0));
  1232. }
  1233. const String *itemname = wrapping_member_flag ? variable_name : symname;
  1234. String *attributes = Getattr(n, "feature:d:methodmodifiers");
  1235. if (attributes) {
  1236. attributes = Copy(attributes);
  1237. } else {
  1238. attributes = Copy(is_public(n) ? public_string : protected_string);
  1239. }
  1240. if (d_version == 1) {
  1241. if (static_flag) {
  1242. Printv(attributes, " static", NIL);
  1243. }
  1244. Printf(constants_code, "\n%s const %s %s = ", attributes, return_type, itemname);
  1245. } else {
  1246. Printf(constants_code, "\n%s enum %s %s = ", attributes, return_type, itemname);
  1247. }
  1248. Delete(attributes);
  1249. // Retrive the override value set via %dconstvalue, if any.
  1250. String *override_value = Getattr(n, "feature:d:constvalue");
  1251. if (override_value) {
  1252. Printf(constants_code, "%s;\n", override_value);
  1253. } else {
  1254. // Just take the value from the C definition and hope it compiles in D.
  1255. String* value = Getattr(n, "wrappedasconstant") ?
  1256. Getattr(n, "staticmembervariableHandler:value") : Getattr(n, "value");
  1257. // Add the stripped quotes back in.
  1258. if (SwigType_type(t) == T_STRING) {
  1259. Printf(constants_code, "\"%s\";\n", value);
  1260. } else if (SwigType_type(t) == T_CHAR) {
  1261. Printf(constants_code, "\'%s\';\n", value);
  1262. } else {
  1263. Printf(constants_code, "%s;\n", value);
  1264. }
  1265. }
  1266. // Emit the generated code to appropriate place.
  1267. if (wrapping_member_flag) {
  1268. Printv(proxy_class_body_code, constants_code, NIL);
  1269. } else {
  1270. Printv(proxyCodeBuffer(getNSpace()), constants_code, NIL);
  1271. }
  1272. // Cleanup.
  1273. Delete(return_type);
  1274. Delete(constants_code);
  1275. return SWIG_OK;
  1276. }
  1277. /* ---------------------------------------------------------------------------
  1278. * D::functionWrapper()
  1279. *
  1280. * Generates the C wrapper code for a function and the corresponding
  1281. * declaration in the wrap D module.
  1282. * --------------------------------------------------------------------------- */
  1283. virtual int functionWrapper(Node *n) {
  1284. String *symname = Getattr(n, "sym:name");
  1285. SwigType *t = Getattr(n, "type");
  1286. ParmList *l = Getattr(n, "parms");
  1287. String *tm;
  1288. Parm *p;
  1289. int i;
  1290. String *c_return_type = NewString("");
  1291. String *im_return_type = NewString("");
  1292. String *cleanup = NewString("");
  1293. String *outarg = NewString("");
  1294. String *body = NewString("");
  1295. int num_arguments = 0;
  1296. bool is_void_return;
  1297. String *overloaded_name = getOverloadedName(n);
  1298. if (!Getattr(n, "sym:overloaded")) {
  1299. if (!addSymbol(Getattr(n, "sym:name"), n))
  1300. return SWIG_ERROR;
  1301. }
  1302. // A new wrapper function object
  1303. Wrapper *f = NewWrapper();
  1304. // Make a wrapper name for this function
  1305. String *wname = Swig_name_wrapper(overloaded_name);
  1306. /* Attach the non-standard typemaps to the parameter list. */
  1307. Swig_typemap_attach_parms("ctype", l, f);
  1308. Swig_typemap_attach_parms("imtype", l, f);
  1309. /* Get return types */
  1310. if ((tm = lookupDTypemap(n, "ctype"))) {
  1311. String *ctypeout = Getattr(n, "tmap:ctype:out");
  1312. if (ctypeout) {
  1313. // The type in the ctype typemap's out attribute overrides the type in
  1314. // the typemap itself.
  1315. tm = ctypeout;
  1316. }
  1317. Printf(c_return_type, "%s", tm);
  1318. } else {
  1319. Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
  1320. "No ctype typemap defined for %s\n", SwigType_str(t, 0));
  1321. }
  1322. if ((tm = lookupDTypemap(n, "imtype"))) {
  1323. String *imtypeout = Getattr(n, "tmap:imtype:out");
  1324. if (imtypeout) {
  1325. // The type in the imtype typemap's out attribute overrides the type in
  1326. // the typemap itself.
  1327. tm = imtypeout;
  1328. }
  1329. Printf(im_return_type, "%s", tm);
  1330. } else {
  1331. Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(t, 0));
  1332. }
  1333. is_void_return = (Cmp(c_return_type, "void") == 0);
  1334. if (!is_void_return)
  1335. Wrapper_add_localv(f, "jresult", c_return_type, "jresult", NIL);
  1336. Printv(f->def, " SWIGEXPORT ", c_return_type, " ", wname, "(", NIL);
  1337. // Emit all of the local variables for holding arguments.
  1338. emit_parameter_variables(l, f);
  1339. /* Attach the standard typemaps */
  1340. emit_attach_parmmaps(l, f);
  1341. // Parameter overloading
  1342. Setattr(n, "wrap:parms", l);
  1343. Setattr(n, "wrap:name", wname);
  1344. // Wrappers not wanted for some methods where the parameters cannot be overloaded in D
  1345. if (Getattr(n, "sym:overloaded")) {
  1346. // Emit warnings for the few cases that can't be overloaded in D and give up on generating wrapper
  1347. Swig_overload_check(n);
  1348. if (Getattr(n, "overload:ignore"))
  1349. return SWIG_OK;
  1350. }
  1351. // Collect the parameter list for the intermediary D module declaration of
  1352. // the generated wrapper function.
  1353. String *im_dmodule_parameters = NewString("(");
  1354. /* Get number of required and total arguments */
  1355. num_arguments = emit_num_arguments(l);
  1356. int gencomma = 0;
  1357. // Now walk the function parameter list and generate code to get arguments
  1358. for (i = 0, p = l; i < num_arguments; i++) {
  1359. while (checkAttribute(p, "tmap:in:numinputs", "0")) {
  1360. p = Getattr(p, "tmap:in:next");
  1361. }
  1362. SwigType *pt = Getattr(p, "type");
  1363. String *ln = Getattr(p, "lname");
  1364. String *im_param_type = NewString("");
  1365. String *c_param_type = NewString("");
  1366. String *arg = NewString("");
  1367. Printf(arg, "j%s", ln);
  1368. /* Get the ctype types of the parameter */
  1369. if ((tm = lookupDTypemap(p, "ctype", true))) {
  1370. Printv(c_param_type, tm, NIL);
  1371. } else {
  1372. Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0));
  1373. }
  1374. /* Get the intermediary class parameter types of the parameter */
  1375. if ((tm = lookupDTypemap(p, "imtype", true))) {
  1376. const String *inattributes = Getattr(p, "tmap:imtype:inattributes");
  1377. Printf(im_param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
  1378. } else {
  1379. Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0));
  1380. }
  1381. /* Add parameter to intermediary class method */
  1382. if (gencomma)
  1383. Printf(im_dmodule_parameters, ", ");
  1384. Printf(im_dmodule_parameters, "%s %s", im_param_type, arg);
  1385. // Add parameter to C function
  1386. Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
  1387. gencomma = 1;
  1388. // Get typemap for this argument
  1389. if ((tm = Getattr(p, "tmap:in"))) {
  1390. canThrow(n, "in", p);
  1391. Replaceall(tm, "$input", arg);
  1392. Setattr(p, "emit:input", arg);
  1393. Printf(f->code, "%s\n", tm);
  1394. p = Getattr(p, "tmap:in:next");
  1395. } else {
  1396. Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
  1397. p = nextSibling(p);
  1398. }
  1399. Delete(im_param_type);
  1400. Delete(c_param_type);
  1401. Delete(arg);
  1402. }
  1403. /* Insert constraint checking code */
  1404. for (p = l; p;) {
  1405. if ((tm = Getattr(p, "tmap:check"))) {
  1406. canThrow(n, "check", p);
  1407. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  1408. Printv(f->code, tm, "\n", NIL);
  1409. p = Getattr(p, "tmap:check:next");
  1410. } else {
  1411. p = nextSibling(p);
  1412. }
  1413. }
  1414. /* Insert cleanup code */
  1415. for (p = l; p;) {
  1416. if ((tm = Getattr(p, "tmap:freearg"))) {
  1417. canThrow(n, "freearg", p);
  1418. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  1419. Printv(cleanup, tm, "\n", NIL);
  1420. p = Getattr(p, "tmap:freearg:next");
  1421. } else {
  1422. p = nextSibling(p);
  1423. }
  1424. }
  1425. /* Insert argument output code */
  1426. for (p = l; p;) {
  1427. if ((tm = Getattr(p, "tmap:argout"))) {
  1428. canThrow(n, "argout", p);
  1429. Replaceall(tm, "$result", "jresult");
  1430. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  1431. Printv(outarg, tm, "\n", NIL);
  1432. p = Getattr(p, "tmap:argout:next");
  1433. } else {
  1434. p = nextSibling(p);
  1435. }
  1436. }
  1437. // Look for usage of throws typemap and the canthrow flag
  1438. ParmList *throw_parm_list = NULL;
  1439. if ((throw_parm_list = Getattr(n, "catchlist"))) {
  1440. Swig_typemap_attach_parms("throws", throw_parm_list, f);
  1441. for (p = throw_parm_list; p; p = nextSibling(p)) {
  1442. if ((tm = Getattr(p, "tmap:throws"))) {
  1443. canThrow(n, "throws", p);
  1444. }
  1445. }
  1446. }
  1447. String *null_attribute = 0;
  1448. // Now write code to make the function call
  1449. if (!native_function_flag) {
  1450. if (Cmp(nodeType(n), "constant") == 0) {
  1451. // Wrapping a constant hack
  1452. Swig_save("functionWrapper", n, "wrap:action", NIL);
  1453. // below based on Swig_VargetToFunction()
  1454. SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
  1455. Setattr(n, "wrap:action", NewStringf("%s = (%s) %s;", Swig_cresult_name(), SwigType_lstr(ty, 0), Getattr(n, "value")));
  1456. }
  1457. Swig_director_emit_dynamic_cast(n, f);
  1458. String *actioncode = emit_action(n);
  1459. if (Cmp(nodeType(n), "constant") == 0)
  1460. Swig_restore(n);
  1461. /* Return value if necessary */
  1462. if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
  1463. canThrow(n, "out", n);
  1464. Replaceall(tm, "$result", "jresult");
  1465. if (GetFlag(n, "feature:new"))
  1466. Replaceall(tm, "$owner", "1");
  1467. else
  1468. Replaceall(tm, "$owner", "0");
  1469. Printf(f->code, "%s", tm);
  1470. null_attribute = Getattr(n, "tmap:out:null");
  1471. if (Len(tm))
  1472. Printf(f->code, "\n");
  1473. } else {
  1474. 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"));
  1475. }
  1476. emit_return_variable(n, t, f);
  1477. }
  1478. /* Output argument output code */
  1479. Printv(f->code, outarg, NIL);
  1480. /* Output cleanup code */
  1481. Printv(f->code, cleanup, NIL);
  1482. /* Look to see if there is any newfree cleanup code */
  1483. if (GetFlag(n, "feature:new")) {
  1484. if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
  1485. canThrow(n, "newfree", n);
  1486. Printf(f->code, "%s\n", tm);
  1487. }
  1488. }
  1489. /* See if there is any return cleanup code */
  1490. if (!native_function_flag) {
  1491. if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
  1492. canThrow(n, "ret", n);
  1493. Printf(f->code, "%s\n", tm);
  1494. }
  1495. }
  1496. // Complete D im parameter list and emit the declaration/binding code.
  1497. Printv(im_dmodule_parameters, ")", NIL);
  1498. writeImDModuleFunction(overloaded_name, im_return_type,
  1499. im_dmodule_parameters, wname);
  1500. Delete(im_dmodule_parameters);
  1501. // Finish C function header.
  1502. Printf(f->def, ") {");
  1503. if (!is_void_return)
  1504. Printv(f->code, " return jresult;\n", NIL);
  1505. Printf(f->code, "}\n");
  1506. /* Substitute the cleanup code */
  1507. Replaceall(f->code, "$cleanup", cleanup);
  1508. /* Substitute the function name */
  1509. Replaceall(f->code, "$symname", symname);
  1510. /* Contract macro modification */
  1511. if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) {
  1512. Setattr(n, "d:canthrow", "1");
  1513. }
  1514. if (!null_attribute)
  1515. Replaceall(f->code, "$null", "0");
  1516. else
  1517. Replaceall(f->code, "$null", null_attribute);
  1518. /* Dump the function out */
  1519. if (!native_function_flag) {
  1520. Wrapper_print(f, f_wrappers);
  1521. // Handle %exception which sets the canthrow attribute.
  1522. if (Getattr(n, "feature:except:canthrow")) {
  1523. Setattr(n, "d:canthrow", "1");
  1524. }
  1525. // A very simple check (it is not foolproof) to assist typemap writers
  1526. // with setting the correct features when the want to throw D exceptions
  1527. // from C++ code. It checks for the common methods which set
  1528. // a pending D exception and issues a warning if one of them has been found
  1529. // in the typemap, but the ťcanthrowŤ attribute/feature is not set.
  1530. if (!Getattr(n, "d:canthrow")) {
  1531. if (Strstr(f->code, "SWIG_exception")) {
  1532. Swig_warning(WARN_D_CANTHROW_MISSING, input_file, line_number,
  1533. "C code contains a call to SWIG_exception and D code does not handle pending exceptions via the canthrow attribute.\n");
  1534. } else if (Strstr(f->code, "SWIG_DSetPendingException")) {
  1535. Swig_warning(WARN_D_CANTHROW_MISSING, input_file, line_number,
  1536. "C code contains a call to a SWIG_DSetPendingException method and D code does not handle pending exceptions via the canthrow attribute.\n");
  1537. }
  1538. }
  1539. }
  1540. // If we are not processing an enum or constant, and we were not generating
  1541. // a wrapper function which will be accessed via a proxy class, write a
  1542. // function to the proxy D module.
  1543. if (!is_wrapping_class()) {
  1544. writeProxyDModuleFunction(n);
  1545. }
  1546. // If we are processing a public member variable, write the property-style
  1547. // member function to the proxy class.
  1548. if (wrapping_member_flag) {
  1549. Setattr(n, "proxyfuncname", variable_name);
  1550. Setattr(n, "imfuncname", symname);
  1551. writeProxyClassFunction(n);
  1552. }
  1553. Delete(c_return_type);
  1554. Delete(im_return_type);
  1555. Delete(cleanup);
  1556. Delete(outarg);
  1557. Delete(body);
  1558. Delete(overloaded_name);
  1559. DelWrapper(f);
  1560. return SWIG_OK;
  1561. }
  1562. /* ---------------------------------------------------------------------------
  1563. * D::nativeWrapper()
  1564. * --------------------------------------------------------------------------- */
  1565. virtual int nativeWrapper(Node *n) {
  1566. String *wrapname = Getattr(n, "wrap:name");
  1567. if (!addSymbol(wrapname, n))
  1568. return SWIG_ERROR;
  1569. if (Getattr(n, "type")) {
  1570. Swig_save("nativeWrapper", n, "name", NIL);
  1571. Setattr(n, "name", wrapname);
  1572. native_function_flag = true;
  1573. functionWrapper(n);
  1574. Swig_restore(n);
  1575. native_function_flag = false;
  1576. } else {
  1577. Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
  1578. }
  1579. return SWIG_OK;
  1580. }
  1581. /* ---------------------------------------------------------------------------
  1582. * D::classDirector()
  1583. * --------------------------------------------------------------------------- */
  1584. virtual int classDirector(Node *n) {
  1585. String *nspace = Getattr(n, "sym:nspace");
  1586. proxy_class_name = NewString(Getattr(n, "sym:name"));
  1587. if (nspace) {
  1588. proxy_class_qname = NewStringf("%s.%s", nspace, proxy_class_name);
  1589. } else {
  1590. proxy_class_qname = Copy(proxy_class_name);
  1591. }
  1592. int success = Language::classDirector(n);
  1593. Delete(proxy_class_qname);
  1594. proxy_class_qname = NULL;
  1595. Delete(proxy_class_name);
  1596. proxy_class_name = NULL;
  1597. return success;
  1598. }
  1599. /* ---------------------------------------------------------------------------
  1600. * D::classDirectorInit()
  1601. * --------------------------------------------------------------------------- */
  1602. virtual int classDirectorInit(Node *n) {
  1603. Delete(director_ctor_code);
  1604. director_ctor_code = NewString("$director_new");
  1605. // Write C++ director class declaration, for example:
  1606. // class SwigDirector_myclass : public myclass, public Swig::Director {
  1607. String *classname = Swig_class_name(n);
  1608. String *directorname = NewStringf("SwigDirector_%s", classname);
  1609. String *declaration = Swig_class_declaration(n, directorname);
  1610. const String *base = Getattr(n, "classtype");
  1611. Printf(f_directors_h,
  1612. "%s : public %s, public Swig::Director {\n", declaration, base);
  1613. Printf(f_directors_h, "\npublic:\n");
  1614. Delete(declaration);
  1615. Delete(directorname);
  1616. Delete(classname);
  1617. // Stash for later.
  1618. Setattr(n, "director:ctor", NewString("Swig::Director()"));
  1619. // Keep track of the director methods for this class.
  1620. first_class_dmethod = curr_class_dmethod = n_dmethods;
  1621. director_callback_typedefs = NewString("");
  1622. director_callback_pointers = NewString("");
  1623. director_dcallbacks_code = NewString("");
  1624. return Language::classDirectorInit(n);
  1625. }
  1626. /* ---------------------------------------------------------------------------
  1627. * D::classDirectorMethod()
  1628. *
  1629. * Emit a virtual director method to pass a method call on to the
  1630. * underlying D object.
  1631. * --------------------------------------------------------------------------- */
  1632. virtual int classDirectorMethod(Node *n, Node *parent, String *super) {
  1633. String *empty_str = NewString("");
  1634. String *classname = Getattr(parent, "sym:name");
  1635. String *c_classname = Getattr(parent, "name");
  1636. String *name = Getattr(n, "name");
  1637. String *symname = Getattr(n, "sym:name");
  1638. SwigType *type = Getattr(n, "type");
  1639. SwigType *returntype = Getattr(n, "returntype");
  1640. String *overloaded_name = getOverloadedName(n);
  1641. String *storage = Getattr(n, "st