PageRenderTime 107ms CodeModel.GetById 13ms app.highlight 82ms RepoModel.GetById 1ms app.codeStats 1ms

/trunk/Source/Modules/d.cxx

#
C++ | 1938 lines | 1269 code | 297 blank | 372 comment | 238 complexity | 10b1678babbe738037ae5bbff7e705ee MD5 | raw file

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

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

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