diff options
| author | say <[email protected]> | 2023-02-14 17:24:43 +0300 | 
|---|---|---|
| committer | say <[email protected]> | 2023-02-14 17:24:43 +0300 | 
| commit | e0094c4ad6964e11564777bc0d859c68d8aa9de2 (patch) | |
| tree | 5d2ad1a4df88da1f74385888891a2a5f9fbbc3ef /contrib/tools/swig/Source/Modules/java.cxx | |
| parent | 65a08c9fdece8dba50da8beb4d7c81447211dd45 (diff) | |
Migrate black linter on custom_lint pipeline
Diffstat (limited to 'contrib/tools/swig/Source/Modules/java.cxx')
| -rw-r--r-- | contrib/tools/swig/Source/Modules/java.cxx | 5002 | 
1 files changed, 5002 insertions, 0 deletions
diff --git a/contrib/tools/swig/Source/Modules/java.cxx b/contrib/tools/swig/Source/Modules/java.cxx new file mode 100644 index 00000000000..7734c64714d --- /dev/null +++ b/contrib/tools/swig/Source/Modules/java.cxx @@ -0,0 +1,5002 @@ +/* ----------------------------------------------------------------------------- + * This file is part of SWIG, which is licensed as a whole under version 3  + * (or any later version) of the GNU General Public License. Some additional + * terms also apply to certain portions of SWIG. The full details of the SWIG + * license and copyrights can be found in the LICENSE and COPYRIGHT files + * included with the SWIG source code as distributed by the SWIG developers + * and at http://www.swig.org/legal.html. + * + * java.cxx + * + * Java language module for SWIG. + * ----------------------------------------------------------------------------- */ + +#include "swigmod.h" +#include <limits.h>		// for INT_MAX +#include "cparse.h" +#include <ctype.h> +#include "javadoc.h" + +/* Hash type used for upcalls from C/C++ */ +typedef DOH UpcallData; + +class JAVA:public Language { +  static const char *usage; +  const String *empty_string; +  const String *public_string; +  const String *protected_string; + +  Hash *swig_types_hash; +  File *f_begin; +  File *f_runtime; +  File *f_runtime_h; +  File *f_header; +  File *f_wrappers; +  File *f_init; +  File *f_directors; +  File *f_directors_h; +  List *filenames_list; + +  bool proxy_flag;		// Flag for generating proxy classes +  bool nopgcpp_flag;		// Flag for suppressing the premature garbage collection prevention parameter +  bool native_function_flag;	// Flag for when wrapping a native function +  bool enum_constant_flag;	// Flag for when wrapping an enum or constant +  bool static_flag;		// Flag for when wrapping a static functions or member variables +  bool variable_wrapper_flag;	// Flag for when wrapping a nonstatic member variable +  bool wrapping_member_flag;	// Flag for when wrapping a member variable/enum/const +  bool global_variable_flag;	// Flag for when wrapping a global variable +  bool old_variable_names;	// Flag for old style variable names in the intermediary class +  bool member_func_flag;	// flag set when wrapping a member function +  bool doxygen;			//flag for converting found doxygen to javadoc +  bool comment_creation_chatter; //flag for getting information about where comments were created in java.cxx +   +  String *imclass_name;		// intermediary class name +  String *module_class_name;	// module class name +  String *constants_interface_name;	// constants interface name +  String *imclass_class_code;	// intermediary class code +  String *proxy_class_def; +  String *proxy_class_code; +  String *interface_class_code; // if %feature("interface") was declared for a class, here goes the interface declaration +  String *module_class_code; +  String *proxy_class_name;	// proxy class name +  String *full_proxy_class_name;// fully qualified proxy class name when using nspace feature, otherwise same as proxy_class_name +  String *full_imclass_name;	// fully qualified intermediary class name when using nspace feature, otherwise same as imclass_name +  String *variable_name;	//Name of a variable being wrapped +  String *proxy_class_constants_code; +  String *module_class_constants_code; +  String *enum_code; +  String *package;		// Optional package name +  String *jnipackage;		// Package name used in the JNI code +  String *package_path;		// Package name used internally by JNI (slashes) +  String *imclass_imports;	//intermediary class imports from %pragma +  String *module_imports;	//module imports from %pragma +  String *imclass_baseclass;	//inheritance for intermediary class class from %pragma +  String *imclass_package;	//package in which to generate the intermediary class +  String *module_baseclass;	//inheritance for module class from %pragma +  String *imclass_interfaces;	//interfaces for intermediary class class from %pragma +  String *module_interfaces;	//interfaces for module class from %pragma +  String *imclass_class_modifiers;	//class modifiers for intermediary class overridden by %pragma +  String *module_class_modifiers;	//class modifiers for module class overridden by %pragma +  String *upcasts_code;		//C++ casts for inheritance hierarchies C++ code +  String *imclass_cppcasts_code;	//C++ casts up inheritance hierarchies intermediary class code +  String *imclass_directors;	// Intermediate class director code +  String *destructor_call;	//C++ destructor call if any +  String *destructor_throws_clause;	//C++ destructor throws clause if any + +  // Director method stuff: +  List *dmethods_seq; +  Hash *dmethods_table; +  int n_dmethods; +  int n_directors; +  int first_class_dmethod; +  int curr_class_dmethod; +  int nesting_depth; + +  enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum }; + +public: + +  /* ----------------------------------------------------------------------------- +   * JAVA() +   * ----------------------------------------------------------------------------- */ + +   JAVA():empty_string(NewString("")), +      public_string(NewString("public")), +      protected_string(NewString("protected")), +      swig_types_hash(NULL), +      f_begin(NULL), +      f_runtime(NULL), +      f_runtime_h(NULL), +      f_header(NULL), +      f_wrappers(NULL), +      f_init(NULL), +      f_directors(NULL), +      f_directors_h(NULL), +      filenames_list(NULL), +      proxy_flag(true), +      nopgcpp_flag(false), +      native_function_flag(false), +      enum_constant_flag(false), +      static_flag(false), +      variable_wrapper_flag(false), +      wrapping_member_flag(false), +      global_variable_flag(false), +      old_variable_names(false), +      member_func_flag(false), +      doxygen(false), +      comment_creation_chatter(false), +      imclass_name(NULL), +      module_class_name(NULL), +      constants_interface_name(NULL), +      imclass_class_code(NULL), +      proxy_class_def(NULL), +      proxy_class_code(NULL), +      interface_class_code(NULL), +      module_class_code(NULL), +      proxy_class_name(NULL), +      full_proxy_class_name(NULL), +      full_imclass_name(NULL), +      variable_name(NULL), +      proxy_class_constants_code(NULL), +      module_class_constants_code(NULL), +      enum_code(NULL), +      package(NULL), +      jnipackage(NULL), +      package_path(NULL), +      imclass_imports(NULL), +      module_imports(NULL), +      imclass_baseclass(NULL), +      imclass_package(NULL), +      module_baseclass(NULL), +      imclass_interfaces(NULL), +      module_interfaces(NULL), +      imclass_class_modifiers(NULL), +      module_class_modifiers(NULL), +      upcasts_code(NULL), +      imclass_cppcasts_code(NULL), +      imclass_directors(NULL), +      destructor_call(NULL), +      destructor_throws_clause(NULL), +      dmethods_seq(NULL), +      dmethods_table(NULL), +      n_dmethods(0), +      n_directors(0), +      first_class_dmethod(0), +      curr_class_dmethod(0), +      nesting_depth(0){ +    /* for now, multiple inheritance in directors is disabled, this +       should be easy to implement though */ +    director_multiple_inheritance = 0; +    director_language = 1; +  } +   +  ~JAVA() { +    delete doxygenTranslator; +  } + +  /* ----------------------------------------------------------------------------- +   * constructIntermediateClassName() +   * +   * Construct the fully qualified name of the intermediate class and set +   * the full_imclass_name attribute accordingly. +   * ----------------------------------------------------------------------------- */ +  void constructIntermediateClassName(Node *n) { +    String *nspace = Getattr(n, "sym:nspace"); + +    if (imclass_package && package) +      full_imclass_name = NewStringf("%s.%s.%s", package, imclass_package, imclass_name); +    else if (package && nspace) +      full_imclass_name = NewStringf("%s.%s", package, imclass_name); +    else if (imclass_package) +      full_imclass_name = NewStringf("%s.%s", imclass_package, imclass_name); +    else +      full_imclass_name = NewStringf("%s", imclass_name); + +    if (nspace && !package) { +      String *name = Getattr(n, "name") ? Getattr(n, "name") : NewString("<unnamed>"); +      Swig_warning(WARN_JAVA_NSPACE_WITHOUT_PACKAGE, Getfile(n), Getline(n), +	  "The nspace feature is used on '%s' without -package. " +	  "The generated code may not compile as Java does not support types declared in a named package accessing types declared in an unnamed package.\n", name); +    } +  } + +  /* ----------------------------------------------------------------------------- +   * getProxyName() +   * +   * Test to see if a type corresponds to something wrapped with a proxy class. +   * Return NULL if not otherwise the proxy class name, fully qualified with +   * package name if the nspace feature is used, unless jnidescriptor is true as +   * the package name is handled differently (unfortunately for legacy reasons). +   * ----------------------------------------------------------------------------- */ +   +   String *getProxyName(SwigType *t, bool jnidescriptor = false) { +     String *proxyname = NULL; +     if (proxy_flag) { +       Node *n = classLookup(t); +       if (n) { +	 proxyname = Getattr(n, "proxyname"); +	 if (!proxyname || jnidescriptor) { +	   String *nspace = Getattr(n, "sym:nspace"); +	   String *symname = Copy(Getattr(n, "sym:name")); +	   if (symname && !GetFlag(n, "feature:flatnested")) { +             for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) { +               if (String* name = Getattr(outer_class, "sym:name")) { +                 Push(symname, jnidescriptor ? "$" : "."); +                 Push(symname, name); +               } +               else +                 return NULL; +             } +	   } +	   if (nspace) { +	     if (package && !jnidescriptor) +	       proxyname = NewStringf("%s.%s.%s", package, nspace, symname); +	     else +	       proxyname = NewStringf("%s.%s", nspace, symname); +	   } else { +	     proxyname = Copy(symname); +	   } +	   if (!jnidescriptor) { +	     Setattr(n, "proxyname", proxyname); // Cache it +	     Delete(proxyname); +	   } +	   Delete(symname); +	 } +       } +     } +     return proxyname; +   } + +  /* ----------------------------------------------------------------------------- +   * makeValidJniName() +   * ----------------------------------------------------------------------------- */ + +  String *makeValidJniName(const String *name) { +    String *valid_jni_name = NewString(name); +    Replaceall(valid_jni_name, "_", "_1"); +    return valid_jni_name; +  } + +  /* ------------------------------------------------------------ +   * main() +   * ------------------------------------------------------------ */ + +  virtual void main(int argc, char *argv[]) { + +    SWIG_library_directory("java"); + +    int doxygen_translator_flags = 0; + +    // Look for certain command line options +    for (int i = 1; i < argc; i++) { +      if (argv[i]) { +	if (strcmp(argv[i], "-package") == 0) { +	  if (argv[i + 1]) { +	    package = NewString(""); +	    Printf(package, argv[i + 1]); +	    if (Len(package) == 0) { +	      Delete(package); +	      package = 0; +	    } +	    Swig_mark_arg(i); +	    Swig_mark_arg(i + 1); +	    i++; +	  } else { +	    Swig_arg_error(); +	  } +	} else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) { +	  Printf(stderr, "Deprecated command line option: %s. Proxy classes are now generated by default.\n", argv[i]); +	  Swig_mark_arg(i); +	  proxy_flag = true; +	} else if ((strcmp(argv[i], "-doxygen") == 0)) { +	  Swig_mark_arg(i); +	  doxygen = true; +	  scan_doxygen_comments = true; +	} else if ((strcmp(argv[i], "-debug-doxygen-translator") == 0)) { +	  Swig_mark_arg(i); +	  doxygen_translator_flags |= DoxygenTranslator::debug_translator; +	} else if ((strcmp(argv[i], "-debug-doxygen-parser") == 0)) { +	  Swig_mark_arg(i); +	  doxygen_translator_flags |= DoxygenTranslator::debug_parser; +	} else if ((strcmp(argv[i], "-noproxy") == 0)) { +	  Swig_mark_arg(i); +	  proxy_flag = false; +	} else if (strcmp(argv[i], "-nopgcpp") == 0) { +	  Swig_mark_arg(i); +	  nopgcpp_flag = true; +	} else if (strcmp(argv[i], "-oldvarnames") == 0) { +	  Swig_mark_arg(i); +	  old_variable_names = true; +	} else if (strcmp(argv[i], "-jnic") == 0) { +	  Swig_mark_arg(i); +	  Printf(stderr, "Deprecated command line option: -jnic. C JNI calling convention now used when -c++ not specified.\n"); +	} else if (strcmp(argv[i], "-nofinalize") == 0) { +	  Swig_mark_arg(i); +	  Printf(stderr, "Deprecated command line option: -nofinalize. Use the new javafinalize typemap instead.\n"); +	} else if (strcmp(argv[i], "-jnicpp") == 0) { +	  Swig_mark_arg(i); +	  Printf(stderr, "Deprecated command line option: -jnicpp. C++ JNI calling convention now used when -c++ specified.\n"); +	} else if (strcmp(argv[i], "-help") == 0) { +	  Printf(stdout, "%s\n", usage); +	} +      } +    } +     +    if (doxygen) +      doxygenTranslator = new JavaDocConverter(doxygen_translator_flags); + +    // Add a symbol to the parser for conditional compilation +    Preprocessor_define("SWIGJAVA 1", 0); + +    // Add typemap definitions +    SWIG_typemap_lang("java"); +    SWIG_config_file("java.swg"); + +    allow_overloading(); +    Swig_interface_feature_enable(); +  } + +  /* --------------------------------------------------------------------- +   * top() +   * --------------------------------------------------------------------- */ + +  virtual int top(Node *n) { + +    // Get any options set in the module directive +    Node *optionsnode = Getattr(Getattr(n, "module"), "options"); + +    if (optionsnode) { +      if (Getattr(optionsnode, "jniclassname")) +	imclass_name = Copy(Getattr(optionsnode, "jniclassname")); +      /* check if directors are enabled for this module.  note: this  +       * is a "master" switch, without which no director code will be +       * emitted.  %feature("director") statements are also required +       * to enable directors for individual classes or methods. +       * +       * use %module(directors="1") modulename at the start of the  +       * interface file to enable director generation. +       */ +      if (Getattr(optionsnode, "directors")) { +	allow_directors(); +      } +      if (Getattr(optionsnode, "dirprot")) { +	allow_dirprot(); +      } +      allow_allprotected(GetFlag(optionsnode, "allprotected")); +    } + +    /* Initialize all of the output files */ +    String *outfile = Getattr(n, "outfile"); +    String *outfile_h = Getattr(n, "outfile_h"); + +    if (!outfile) { +      Printf(stderr, "Unable to determine outfile\n"); +      SWIG_exit(EXIT_FAILURE); +    } + +    f_begin = NewFile(outfile, "w", SWIG_output_files()); +    if (!f_begin) { +      FileErrorDisplay(outfile); +      SWIG_exit(EXIT_FAILURE); +    } + +    if (directorsEnabled()) { +      if (!outfile_h) { +        Printf(stderr, "Unable to determine outfile_h\n"); +        SWIG_exit(EXIT_FAILURE); +      } +      f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files()); +      if (!f_runtime_h) { +	FileErrorDisplay(outfile_h); +	SWIG_exit(EXIT_FAILURE); +      } +    } + +    f_runtime = NewString(""); +    f_init = NewString(""); +    f_header = NewString(""); +    f_wrappers = NewString(""); +    f_directors_h = NewString(""); +    f_directors = NewString(""); + +    /* Register file targets with the SWIG file handler */ +    Swig_register_filebyname("begin", f_begin); +    Swig_register_filebyname("header", f_header); +    Swig_register_filebyname("wrapper", f_wrappers); +    Swig_register_filebyname("runtime", f_runtime); +    Swig_register_filebyname("init", f_init); +    Swig_register_filebyname("director", f_directors); +    Swig_register_filebyname("director_h", f_directors_h); + +    swig_types_hash = NewHash(); +    filenames_list = NewList(); + +    // Make the intermediary class and module class names. The intermediary class name can be set in the module directive. +    if (!imclass_name) { +      imclass_name = NewStringf("%sJNI", Getattr(n, "name")); +      module_class_name = Copy(Getattr(n, "name")); +    } else { +      // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution +      if (Cmp(imclass_name, Getattr(n, "name")) == 0) +	module_class_name = NewStringf("%sModule", Getattr(n, "name")); +      else +	module_class_name = Copy(Getattr(n, "name")); +    } +    constants_interface_name = NewStringf("%sConstants", module_class_name); + +    // module class and intermediary classes are always created +    if (!addSymbol(imclass_name, n)) +      return SWIG_ERROR; +    if (!addSymbol(module_class_name, n)) +      return SWIG_ERROR; + +    imclass_class_code = NewString(""); +    proxy_class_def = NewString(""); +    proxy_class_code = NewString(""); +    module_class_constants_code = NewString(""); +    imclass_baseclass = NewString(""); +    imclass_package = NULL; +    imclass_interfaces = NewString(""); +    imclass_class_modifiers = NewString(""); +    module_class_code = NewString(""); +    module_baseclass = NewString(""); +    module_interfaces = NewString(""); +    module_imports = NewString(""); +    module_class_modifiers = NewString(""); +    imclass_imports = NewString(""); +    imclass_cppcasts_code = NewString(""); +    imclass_directors = NewString(""); +    upcasts_code = NewString(""); +    dmethods_seq = NewList(); +    dmethods_table = NewHash(); +    n_dmethods = 0; +    n_directors = 0; +    jnipackage = NewString(""); +    package_path = NewString(""); + +    Swig_banner(f_begin); + +    Printf(f_runtime, "\n\n#ifndef SWIGJAVA\n#define SWIGJAVA\n#endif\n\n"); + +    if (directorsEnabled()) { +      Printf(f_runtime, "#define SWIG_DIRECTORS\n"); + +      /* Emit initial director header and director code: */ +      Swig_banner(f_directors_h); +      Printf(f_directors_h, "\n"); +      Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name); +      Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name); + +      Printf(f_directors, "\n\n"); +      Printf(f_directors, "/* ---------------------------------------------------\n"); +      Printf(f_directors, " * C++ director class methods\n"); +      Printf(f_directors, " * --------------------------------------------------- */\n\n"); +      if (outfile_h) { +	String *filename = Swig_file_filename(outfile_h); +	Printf(f_directors, "#include \"%s\"\n\n", filename); +	Delete(filename); +      } +    } + +    Printf(f_runtime, "\n"); + +    String *wrapper_name = NewString(""); + +    if (package) { +      String *jniname = makeValidJniName(package); +      Printv(jnipackage, jniname, NIL); +      Delete(jniname); +      Replaceall(jnipackage, ".", "_"); +      Append(jnipackage, "_"); +      Printv(package_path, package, NIL); +      Replaceall(package_path, ".", "/"); +    } +    String *jniname = makeValidJniName(imclass_name); +    Printf(wrapper_name, "Java_%s%s_%%f", jnipackage, jniname); +    Delete(jniname); + +    Swig_name_register("wrapper", Char(wrapper_name)); +    if (old_variable_names) { +      Swig_name_register("set", "set_%n%v"); +      Swig_name_register("get", "get_%n%v"); +    } + +    Delete(wrapper_name); + +    Printf(f_wrappers, "\n#ifdef __cplusplus\n"); +    Printf(f_wrappers, "extern \"C\" {\n"); +    Printf(f_wrappers, "#endif\n\n"); + +    /* Emit code */ +    Language::top(n); + +    if (directorsEnabled()) { +      // Insert director runtime into the f_runtime file (make it occur before %header section) +      Swig_insert_file("director_common.swg", f_runtime); +      Swig_insert_file("director.swg", f_runtime); +    } +    // Generate the intermediary class +    { +      String *filen = NewStringf("%s%s.java", outputDirectory(imclass_package), imclass_name); +      File *f_im = NewFile(filen, "w", SWIG_output_files()); +      if (!f_im) { +	FileErrorDisplay(filen); +	SWIG_exit(EXIT_FAILURE); +      } +      Append(filenames_list, Copy(filen)); +      Delete(filen); +      filen = NULL; + +      // Start writing out the intermediary class file +      emitBanner(f_im); + +      if (imclass_package && package) +        Printf(f_im, "package %s.%s;", package, imclass_package); +      else if (imclass_package) +        Printf(f_im, "package %s;", imclass_package); +      else if (package) +        Printf(f_im, "package %s;\n", package); + +      if (imclass_imports) +	Printf(f_im, "%s\n", imclass_imports); + +      if (Len(imclass_class_modifiers) > 0) +	Printf(f_im, "%s ", imclass_class_modifiers); +      Printf(f_im, "%s ", imclass_name); + +      if (imclass_baseclass && *Char(imclass_baseclass)) +	Printf(f_im, "extends %s ", imclass_baseclass); +      if (Len(imclass_interfaces) > 0) +	Printv(f_im, "implements ", imclass_interfaces, " ", NIL); +      Printf(f_im, "{\n"); + +      // Add the intermediary class methods +      Replaceall(imclass_class_code, "$module", module_class_name); +      Replaceall(imclass_class_code, "$imclassname", imclass_name); +      Printv(f_im, imclass_class_code, NIL); +      Printv(f_im, imclass_cppcasts_code, NIL); +      if (Len(imclass_directors) > 0) +	Printv(f_im, "\n", imclass_directors, NIL); + +      if (n_dmethods > 0) { +	Putc('\n', f_im); +	Printf(f_im, "  private final static native void swig_module_init();\n"); +	Printf(f_im, "  static {\n"); +	Printf(f_im, "    swig_module_init();\n"); +	Printf(f_im, "  }\n"); +      } +      // Finish off the class +      Printf(f_im, "}\n"); +      Delete(f_im); +    } + +    // Generate the Java module class +    { +      String *filen = NewStringf("%s%s.java", SWIG_output_directory(), module_class_name); +      File *f_module = NewFile(filen, "w", SWIG_output_files()); +      if (!f_module) { +	FileErrorDisplay(filen); +	SWIG_exit(EXIT_FAILURE); +      } +      Append(filenames_list, Copy(filen)); +      Delete(filen); +      filen = NULL; + +      // Start writing out the module class file +      emitBanner(f_module); + +      if (package) +	Printf(f_module, "package %s;\n", package); + +      if (module_imports) +	Printf(f_module, "%s\n", module_imports); + +      if (doxygen && doxygenTranslator->hasDocumentation(n)) { +	String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0); +	if (comment_creation_chatter) +	  Printf(f_module, "/* This was generated from top() */\n"); +	Printv(f_module, Char(doxygen_comments), NIL); +	Delete(doxygen_comments); +      } +      if (Len(module_class_modifiers) > 0) +	Printf(f_module, "%s ", module_class_modifiers); +      Printf(f_module, "%s ", module_class_name); + +      if (module_baseclass && *Char(module_baseclass)) +	Printf(f_module, "extends %s ", module_baseclass); +      if (Len(module_interfaces) > 0) { +	if (Len(module_class_constants_code) != 0) +	  Printv(f_module, "implements ", constants_interface_name, ", ", module_interfaces, " ", NIL); +	else +	  Printv(f_module, "implements ", module_interfaces, " ", NIL); +      } else { +	if (Len(module_class_constants_code) != 0) +	  Printv(f_module, "implements ", constants_interface_name, " ", NIL); +      } +      Printf(f_module, "{\n"); + +      Replaceall(module_class_code, "$module", module_class_name); +      Replaceall(module_class_constants_code, "$module", module_class_name); + +      Replaceall(module_class_code, "$imclassname", imclass_name); +      Replaceall(module_class_constants_code, "$imclassname", imclass_name); + +      // Add the wrapper methods +      Printv(f_module, module_class_code, NIL); + +      // Finish off the class +      Printf(f_module, "}\n"); +      Delete(f_module); +    } + +    // Generate the Java constants interface +    if (Len(module_class_constants_code) != 0) { +      String *filen = NewStringf("%s%s.java", SWIG_output_directory(), constants_interface_name); +      File *f_module = NewFile(filen, "w", SWIG_output_files()); +      if (!f_module) { +	FileErrorDisplay(filen); +	SWIG_exit(EXIT_FAILURE); +      } +      Append(filenames_list, Copy(filen)); +      Delete(filen); +      filen = NULL; + +      // Start writing out the Java constants interface file +      emitBanner(f_module); + +      if (package) +	Printf(f_module, "package %s;\n", package); + +      if (module_imports) +	Printf(f_module, "%s\n", module_imports); + +      Printf(f_module, "public interface %s {\n", constants_interface_name); + +      // Write out all the global constants +      Printv(f_module, module_class_constants_code, NIL); + +      // Finish off the Java interface +      Printf(f_module, "}\n"); +      Delete(f_module); +    } + +    if (upcasts_code) +      Printv(f_wrappers, upcasts_code, NIL); + +    emitDirectorUpcalls(); + +    Printf(f_wrappers, "#ifdef __cplusplus\n"); +    Printf(f_wrappers, "}\n"); +    Printf(f_wrappers, "#endif\n"); + +    // Output a Java type wrapper class for each SWIG type +    for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) { +      emitTypeWrapperClass(swig_type.key, swig_type.item); +    } + +    // Check for overwriting file problems on filesystems that are case insensitive +    Iterator it1; +    Iterator it2; +    for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) { +      String *item1_lower = Swig_string_lower(it1.item); +      for (it2 = Next(it1); it2.item; it2 = Next(it2)) { +	String *item2_lower = Swig_string_lower(it2.item); +	if (it1.item && it2.item) { +	  if (Strcmp(item1_lower, item2_lower) == 0) { +	    Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number, +			 "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as " +			 "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item); +	  } +	} +	Delete(item2_lower); +      } +      Delete(item1_lower); +    } + +    Delete(swig_types_hash); +    swig_types_hash = NULL; +    Delete(filenames_list); +    filenames_list = NULL; +    Delete(imclass_name); +    imclass_name = NULL; +    Delete(imclass_class_code); +    imclass_class_code = NULL; +    Delete(proxy_class_def); +    proxy_class_def = NULL; +    Delete(proxy_class_code); +    proxy_class_code = NULL; +    Delete(module_class_constants_code); +    module_class_constants_code = NULL; +    Delete(imclass_baseclass); +    imclass_baseclass = NULL; +    Delete(imclass_package); +    imclass_package = NULL; +    Delete(imclass_interfaces); +    imclass_interfaces = NULL; +    Delete(imclass_class_modifiers); +    imclass_class_modifiers = NULL; +    Delete(module_class_name); +    module_class_name = NULL; +    Delete(constants_interface_name); +    constants_interface_name = NULL; +    Delete(module_class_code); +    module_class_code = NULL; +    Delete(module_baseclass); +    module_baseclass = NULL; +    Delete(module_interfaces); +    module_interfaces = NULL; +    Delete(module_imports); +    module_imports = NULL; +    Delete(module_class_modifiers); +    module_class_modifiers = NULL; +    Delete(imclass_imports); +    imclass_imports = NULL; +    Delete(imclass_cppcasts_code); +    imclass_cppcasts_code = NULL; +    Delete(imclass_directors); +    imclass_directors = NULL; +    Delete(upcasts_code); +    upcasts_code = NULL; +    Delete(package); +    package = NULL; +    Delete(jnipackage); +    jnipackage = NULL; +    Delete(package_path); +    package_path = NULL; +    Delete(dmethods_seq); +    dmethods_seq = NULL; +    Delete(dmethods_table); +    dmethods_table = NULL; +    n_dmethods = 0; + +    /* Close all of the files */ +    Dump(f_header, f_runtime); + +    if (directorsEnabled()) { +      Dump(f_directors, f_runtime); +      Dump(f_directors_h, f_runtime_h); + +      Printf(f_runtime_h, "\n"); +      Printf(f_runtime_h, "#endif\n"); + +      Delete(f_runtime_h); +      f_runtime_h = NULL; +      Delete(f_directors); +      f_directors = NULL; +      Delete(f_directors_h); +      f_directors_h = NULL; +    } + +    Dump(f_wrappers, f_runtime); +    Wrapper_pretty_print(f_init, f_runtime); +    Delete(f_header); +    Delete(f_wrappers); +    Delete(f_init); +    Dump(f_runtime, f_begin); +    Delete(f_runtime); +    Delete(f_begin); +    return SWIG_OK; +  } + +  /* ----------------------------------------------------------------------------- +   * emitBanner() +   * ----------------------------------------------------------------------------- */ + +  void emitBanner(File *f) { +    Printf(f, "/* ----------------------------------------------------------------------------\n"); +    Swig_banner_target_lang(f, " *"); +    Printf(f, " * ----------------------------------------------------------------------------- */\n\n"); +  } + +  /*----------------------------------------------------------------------- +   * Add new director upcall signature +   *----------------------------------------------------------------------*/ + +  UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *imclass_desc, String *class_desc, String *decl) { +    String *key = NewStringf("%s|%s", imclass_method, decl); + +    ++curr_class_dmethod; + +    String *imclass_methodidx = NewStringf("%d", n_dmethods); +    String *class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod); +    n_dmethods++; + +    Hash *new_udata = NewHash(); +    Append(dmethods_seq, new_udata); +    Setattr(dmethods_table, key, new_udata); + +    Setattr(new_udata, "method", Copy(class_method)); +    Setattr(new_udata, "fdesc", Copy(class_desc)); +    Setattr(new_udata, "imclass_method", Copy(imclass_method)); +    Setattr(new_udata, "imclass_fdesc", Copy(imclass_desc)); +    Setattr(new_udata, "imclass_methodidx", imclass_methodidx); +    Setattr(new_udata, "class_methodidx", class_methodidx); +    Setattr(new_udata, "decl", Copy(decl)); + +    Delete(key); +    return new_udata; +  } + +  /*----------------------------------------------------------------------- +   * Get director upcall signature +   *----------------------------------------------------------------------*/ + +  UpcallData *getUpcallMethodData(String *director_class, String *decl) { +    String *key = NewStringf("%s|%s", director_class, decl); +    UpcallData *udata = Getattr(dmethods_table, key); + +    Delete(key); +    return udata; +  } + +  /* ---------------------------------------------------------------------- +   * nativeWrapper() +   * ---------------------------------------------------------------------- */ + +  virtual int nativeWrapper(Node *n) { +    String *wrapname = Getattr(n, "wrap:name"); + +    if (!addSymbol(wrapname, n, imclass_name)) +      return SWIG_ERROR; + +    if (Getattr(n, "type")) { +      Swig_save("nativeWrapper", n, "name", NIL); +      Setattr(n, "name", wrapname); +      native_function_flag = true; +      functionWrapper(n); +      Swig_restore(n); +      native_function_flag = false; +    } else { +      Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name")); +    } + +    return SWIG_OK; +  } + +  /* ---------------------------------------------------------------------- +   * functionWrapper() +   * ---------------------------------------------------------------------- */ + +  virtual int functionWrapper(Node *n) { +    String *symname = Getattr(n, "sym:name"); +    SwigType *t = Getattr(n, "type"); +    ParmList *l = Getattr(n, "parms"); +    String *tm; +    Parm *p; +    int i; +    String *c_return_type = NewString(""); +    String *im_return_type = NewString(""); +    String *cleanup = NewString(""); +    String *outarg = NewString(""); +    String *body = NewString(""); +    int num_arguments = 0; +    int gencomma = 0; +    bool is_void_return; +    String *overloaded_name = getOverloadedName(n); +    String *nondir_args = NewString(""); +    bool is_destructor = (Cmp(Getattr(n, "nodeType"), "destructor") == 0); + +    if (!Getattr(n, "sym:overloaded")) { +      if (!addSymbol(symname, n, imclass_name)) +	return SWIG_ERROR; +    } + +    /* +       The rest of this function deals with generating the intermediary class wrapper function (that wraps +       a c/c++ function) and generating the JNI c code. Each Java wrapper function has a  +       matching JNI c function call. +     */ + +    // A new wrapper function object +    Wrapper *f = NewWrapper(); + +    // Make a wrapper name for this function +    String *jniname = makeValidJniName(overloaded_name); +    String *wname = Swig_name_wrapper(jniname); + +    Delete(jniname); + +    /* Attach the non-standard typemaps to the parameter list. */ +    Swig_typemap_attach_parms("jni", l, f); +    Swig_typemap_attach_parms("jtype", l, f); +    Swig_typemap_attach_parms("jstype", l, f); + +    /* Get return types */ +    if ((tm = Swig_typemap_lookup("jni", n, "", 0))) { +      Printf(c_return_type, "%s", tm); +    } else { +      Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(t, 0)); +    } + +    if ((tm = Swig_typemap_lookup("jtype", n, "", 0))) { +      Printf(im_return_type, "%s", tm); +    } else { +      Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(t, 0)); +    } + +    is_void_return = (Cmp(c_return_type, "void") == 0); +    if (!is_void_return) +      Wrapper_add_localv(f, "jresult", c_return_type, "jresult = 0", NIL); + +    Printv(f->def, "SWIGEXPORT ", c_return_type, " JNICALL ", wname, "(JNIEnv *jenv, jclass jcls", NIL); + +    // Usually these function parameters are unused - The code below ensures +    // that compilers do not issue such a warning if configured to do so. + +    Printv(f->code, "    (void)jenv;\n", NIL); +    Printv(f->code, "    (void)jcls;\n", NIL); + +    // Emit all of the local variables for holding arguments. +    emit_parameter_variables(l, f); + +    /* Attach the standard typemaps */ +    emit_attach_parmmaps(l, f); + +    // Parameter overloading +    Setattr(n, "wrap:parms", l); +    Setattr(n, "wrap:name", wname); + +    // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java +    if (Getattr(n, "sym:overloaded")) { +      // Emit warnings for the few cases that can't be overloaded in Java and give up on generating wrapper +      Swig_overload_check(n); +      if (Getattr(n, "overload:ignore")) { +	DelWrapper(f); +	return SWIG_OK; +      } +    } + +    Printf(imclass_class_code, "  public final static native %s %s(", im_return_type, overloaded_name); + +    num_arguments = emit_num_arguments(l); + +    // Now walk the function parameter list and generate code to get arguments +    for (i = 0, p = l; i < num_arguments; i++) { + +      while (checkAttribute(p, "tmap:in:numinputs", "0")) { +	p = Getattr(p, "tmap:in:next"); +      } + +      SwigType *pt = Getattr(p, "type"); +      String *ln = Getattr(p, "lname"); +      String *im_param_type = NewString(""); +      String *c_param_type = NewString(""); +      String *arg = NewString(""); + +      Printf(arg, "j%s", ln); + +      /* Get the JNI C types of the parameter */ +      if ((tm = Getattr(p, "tmap:jni"))) { +	Printv(c_param_type, tm, NIL); +      } else { +	Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(pt, 0)); +      } + +      /* Get the intermediary class parameter types of the parameter */ +      if ((tm = Getattr(p, "tmap:jtype"))) { +	Printv(im_param_type, tm, NIL); +      } else { +	Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(pt, 0)); +      } + +      /* Add parameter to intermediary class method */ +      if (gencomma) +	Printf(imclass_class_code, ", "); +      Printf(imclass_class_code, "%s %s", im_param_type, arg); + +      // Add parameter to C function +      Printv(f->def, ", ", c_param_type, " ", arg, NIL); + +      ++gencomma; + +      // Premature garbage collection prevention parameter +      if (!is_destructor) { +	String *pgc_parameter = prematureGarbageCollectionPreventionParameter(pt, p); +	if (pgc_parameter) { +	  Printf(imclass_class_code, ", %s %s_", pgc_parameter, arg); +	  Printf(f->def, ", jobject %s_", arg); +	  Printf(f->code, "    (void)%s_;\n", arg); +	} +      } +      // Get typemap for this argument +      if ((tm = Getattr(p, "tmap:in"))) { +	addThrows(n, "tmap:in", p); +	Replaceall(tm, "$source", arg);	/* deprecated */ +	Replaceall(tm, "$target", ln);	/* deprecated */ +	Replaceall(tm, "$arg", arg);	/* deprecated? */ +	Replaceall(tm, "$input", arg); +	Setattr(p, "emit:input", arg); + +	Printf(nondir_args, "%s\n", tm); + +	p = Getattr(p, "tmap:in:next"); +      } else { +	Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0)); +	p = nextSibling(p); +      } + +      Delete(im_param_type); +      Delete(c_param_type); +      Delete(arg); +    } + +    Printv(f->code, nondir_args, NIL); +    Delete(nondir_args); + +    /* Insert constraint checking code */ +    for (p = l; p;) { +      if ((tm = Getattr(p, "tmap:check"))) { +	addThrows(n, "tmap:check", p); +	Replaceall(tm, "$target", Getattr(p, "lname"));	/* deprecated */ +	Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */ +	Replaceall(tm, "$input", Getattr(p, "emit:input")); +	Printv(f->code, tm, "\n", NIL); +	p = Getattr(p, "tmap:check:next"); +      } else { +	p = nextSibling(p); +      } +    } + +    /* Insert cleanup code */ +    for (p = l; p;) { +      if ((tm = Getattr(p, "tmap:freearg"))) { +	addThrows(n, "tmap:freearg", p); +	Replaceall(tm, "$source", Getattr(p, "emit:input"));	/* deprecated */ +	Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */ +	Replaceall(tm, "$input", Getattr(p, "emit:input")); +	Printv(cleanup, tm, "\n", NIL); +	p = Getattr(p, "tmap:freearg:next"); +      } else { +	p = nextSibling(p); +      } +    } + +    /* Insert argument output code */ +    for (p = l; p;) { +      if ((tm = Getattr(p, "tmap:argout"))) { +	addThrows(n, "tmap:argout", p); +	Replaceall(tm, "$source", Getattr(p, "emit:input"));	/* deprecated */ +	Replaceall(tm, "$target", Getattr(p, "lname"));	/* deprecated */ +	Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */ +	Replaceall(tm, "$result", "jresult"); +	Replaceall(tm, "$input", Getattr(p, "emit:input")); +	Printv(outarg, tm, "\n", NIL); +	p = Getattr(p, "tmap:argout:next"); +      } else { +	p = nextSibling(p); +      } +    } + +    // Get any Java exception classes in the throws typemap +    ParmList *throw_parm_list = NULL; +    if ((throw_parm_list = Getattr(n, "catchlist"))) { +      Swig_typemap_attach_parms("throws", throw_parm_list, f); +      for (p = throw_parm_list; p; p = nextSibling(p)) { +	if (Getattr(p, "tmap:throws")) { +	  addThrows(n, "tmap:throws", p); +	} +      } +    } + +    // Now write code to make the function call +    if (!native_function_flag) { + +      Swig_director_emit_dynamic_cast(n, f); +      String *actioncode = emit_action(n); + +      // Handle exception classes specified in the "except" feature's "throws" attribute +      addThrows(n, "feature:except", n); + +      /* Return value if necessary  */ +      if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) { +	addThrows(n, "tmap:out", n); +	Replaceall(tm, "$source", Swig_cresult_name());	/* deprecated */ +	Replaceall(tm, "$target", "jresult");	/* deprecated */ +	Replaceall(tm, "$result", "jresult"); + +        if (GetFlag(n, "feature:new")) +          Replaceall(tm, "$owner", "1"); +        else +          Replaceall(tm, "$owner", "0"); + +	Printf(f->code, "%s", tm); +	if (Len(tm)) +	  Printf(f->code, "\n"); +      } else { +	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")); +      } +      emit_return_variable(n, t, f); +    } + +    /* Output argument output code */ +    Printv(f->code, outarg, NIL); + +    /* Output cleanup code */ +    Printv(f->code, cleanup, NIL); + +    /* Look to see if there is any newfree cleanup code */ +    if (GetFlag(n, "feature:new")) { +      if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) { +	addThrows(n, "tmap:newfree", n); +	Replaceall(tm, "$source", Swig_cresult_name());	/* deprecated */ +	Printf(f->code, "%s\n", tm); +      } +    } + +    /* See if there is any return cleanup code */ +    if (!native_function_flag) { +      if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) { +	addThrows(n, "tmap:ret", n); +	Replaceall(tm, "$source", Swig_cresult_name());	/* deprecated */ +	Printf(f->code, "%s\n", tm); +      } +    } + +    /* Finish C function and intermediary class function definitions */ +    Printf(imclass_class_code, ")"); +    generateThrowsClause(n, imclass_class_code); +    Printf(imclass_class_code, ";\n"); + +    Printf(f->def, ") {"); + +    if (!is_void_return) +      Printv(f->code, "    return jresult;\n", NIL); +    Printf(f->code, "}\n"); + +    /* Substitute the cleanup code */ +    Replaceall(f->code, "$cleanup", cleanup); + +    /* Substitute the function name */ +    Replaceall(f->code, "$symname", symname); + +    /* Contract macro modification */ +    Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, "); + +    if (!is_void_return) +      Replaceall(f->code, "$null", "0"); +    else +      Replaceall(f->code, "$null", ""); + +    /* Dump the function out */ +    if (!native_function_flag) +      Wrapper_print(f, f_wrappers); + +    if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) { +      moduleClassFunctionHandler(n); +    } + +    /*  +     * Generate the proxy class getters/setters for public member variables. +     * Not for enums and constants. +     */ +    if (proxy_flag && wrapping_member_flag && !enum_constant_flag) { +      // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name +      bool getter_flag = Cmp(symname, Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) != 0; + +      String *getter_setter_name = NewString(""); +      if (!getter_flag) +	Printf(getter_setter_name, "set"); +      else +	Printf(getter_setter_name, "get"); +      Putc(toupper((int) *Char(variable_name)), getter_setter_name); +      Printf(getter_setter_name, "%s", Char(variable_name) + 1); + +      Setattr(n, "proxyfuncname", getter_setter_name); +      Setattr(n, "imfuncname", symname); + +      proxyClassFunctionHandler(n); +      Delete(getter_setter_name); +    } + +    Delete(c_return_type); +    Delete(im_return_type); +    Delete(cleanup); +    Delete(outarg); +    Delete(body); +    Delete(overloaded_name); +    DelWrapper(f); +    return SWIG_OK; +  } + +  /* ----------------------------------------------------------------------- +   * variableWrapper() +   * ----------------------------------------------------------------------- */ + +  virtual int variableWrapper(Node *n) { +    variable_wrapper_flag = true; +    Language::variableWrapper(n);	/* Default to functions */ +    variable_wrapper_flag = false; +    return SWIG_OK; +  } + +  /* ----------------------------------------------------------------------- +   * globalvariableHandler() +   * ------------------------------------------------------------------------ */ + +  virtual int globalvariableHandler(Node *n) { + +    variable_name = Getattr(n, "sym:name"); +    global_variable_flag = true; +    int ret = Language::globalvariableHandler(n); +    global_variable_flag = false; +    return ret; +  } + +  String *getCurrentScopeName(String *nspace) { +    String *scope = 0; +    if (nspace || getCurrentClass()) { +      scope = NewString(""); +      if (nspace) +	Printf(scope, "%s", nspace); +      if (Node* cls = getCurrentClass()) { +	if (Node *outer = Getattr(cls, "nested:outer")) { +	  String *outerClassesPrefix = Copy(Getattr(outer, "sym:name")); +	  for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) { +	    Push(outerClassesPrefix, "."); +	    Push(outerClassesPrefix, Getattr(outer, "sym:name")); +	  } +	  Printv(scope, nspace ? "." : "", outerClassesPrefix, ".", proxy_class_name, NIL); +	  Delete(outerClassesPrefix); +	} else +	  Printv(scope, nspace ? "." : "", proxy_class_name, NIL); +      } +    } +    return scope; +  } + +  /* ---------------------------------------------------------------------- +   * enumDeclaration() +   * +   * C/C++ enums can be mapped in one of 4 ways, depending on the java:enum feature specified: +   * 1) Simple enums - simple constant within the proxy class or module class +   * 2) Typeunsafe enums - simple constant in a Java class (class named after the c++ enum name) +   * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name) +   * 4) Proper enums - proper Java enum +   * Anonymous enums always default to 1) +   * ---------------------------------------------------------------------- */ + +  virtual int enumDeclaration(Node *n) { + +    if (!ImportMode) { +      if (getCurrentClass() && (cplus_mode != PUBLIC)) +	return SWIG_NOWRAP; + +      String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call +      if (proxy_flag && !is_wrapping_class()) { +	// Global enums / enums in a namespace +	assert(!full_imclass_name); +	constructIntermediateClassName(n); +      } + +      enum_code = NewString(""); +      String *symname = Getattr(n, "sym:name"); +      String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code; +      EnumFeature enum_feature = decodeEnumFeature(n); +      String *typemap_lookup_type = Getattr(n, "name"); + +      if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) { +	// Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum + +	if (doxygen && doxygenTranslator->hasDocumentation(n)) { +	  String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0); +	  if (comment_creation_chatter) +	    Printf(enum_code, "/* This was generated from enumDeclaration() */\n"); +	  Printv(enum_code, Char(doxygen_comments), NIL); +	  Delete(doxygen_comments); +	} + +	String *scope = getCurrentScopeName(nspace); +	if (!addSymbol(symname, n, scope)) +	  return SWIG_ERROR; + +	// Pure Java baseclass and interfaces +	const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE); +	const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE); + +	// Emit the enum +	Printv(enum_code, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF),	// Class modifiers (enum modifiers really) +	       " ", symname, *Char(pure_baseclass) ?	// Bases +	       " extends " : "", pure_baseclass, *Char(pure_interfaces) ?	// Interfaces +	       " implements " : "", pure_interfaces, " {\n", NIL); +	if (proxy_flag && is_wrapping_class()) +	  Replaceall(enum_code, "$static ", "static "); +	else +	  Replaceall(enum_code, "$static ", ""); +	Delete(scope); +      } else { +	if (symname && !Getattr(n, "unnamedinstance")) +	  Printf(constants_code, "  // %s \n", symname); +	// Translate and write javadoc comment for the enum itself if flagged +	if (doxygen && doxygenTranslator->hasDocumentation(n)) { +	  String *doxygen_comments = doxygenTranslator->getDocumentation(n, "  "); +	  if (comment_creation_chatter) +	    Printf(constants_code, "/* This was generated from enumDeclaration() */\n"); +	  Printf(constants_code, Char(doxygen_comments)); +	  Printf(constants_code, "\n"); +	  Delete(doxygen_comments); +	} +      } + +      // Emit each enum item +      Language::enumDeclaration(n); + +      if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) { +	// Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum +	// Finish the enum declaration +	// Typemaps are used to generate the enum definition in a similar manner to proxy classes. +	Printv(enum_code, (enum_feature == ProperEnum) ? ";\n" : "", typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF),	// main body of class +	       typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE),	// extra Java code +	       "}", NIL); + +	Replaceall(enum_code, "$javaclassname", symname); + +	// Substitute $enumvalues - intended usage is for typesafe enums +	if (Getattr(n, "enumvalues")) +	  Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues")); +	else +	  Replaceall(enum_code, "$enumvalues", ""); + +	if (proxy_flag && is_wrapping_class()) { +	  // Enums defined within the C++ class are defined within the proxy class + +	  // Add extra indentation +	  Replaceall(enum_code, "\n", "\n  "); +	  Replaceall(enum_code, "  \n", "\n"); +	  if (GetFlag(getCurrentClass(), "feature:interface")) +	    Printv(interface_class_code, "  ", enum_code, "\n\n", NIL); +	  else +	    Printv(proxy_class_constants_code, "  ", enum_code, "\n\n", NIL); +	} else { +	  // Global enums are defined in their own file +	  String *output_directory = outputDirectory(nspace); +	  String *filen = NewStringf("%s%s.java", output_directory, symname); +	  File *f_enum = NewFile(filen, "w", SWIG_output_files()); +	  if (!f_enum) { +	    FileErrorDisplay(filen); +	    SWIG_exit(EXIT_FAILURE); +	  } +	  Append(filenames_list, Copy(filen)); +	  Delete(filen); +	  filen = NULL; + +	  // Start writing out the enum file +	  emitBanner(f_enum); + +	  if (package || nspace) { +	    Printf(f_enum, "package "); +	    if (package) +	      Printv(f_enum, package, nspace ? "." : "", NIL); +	    if (nspace) +	      Printv(f_enum, nspace, NIL); +	    Printf(f_enum, ";\n"); +	  } + +	  Printv(f_enum, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements +		 "\n", enum_code, "\n", NIL); + +	  Printf(f_enum, "\n"); +	  Delete(f_enum); +	  Delete(output_directory); +	} +      } else { +	// Wrap C++ enum with simple constant +	Printf(enum_code, "\n"); +	if (proxy_flag && is_wrapping_class()) +	  Printv(proxy_class_constants_code, enum_code, NIL); +	else +	  Printv(module_class_constants_code, enum_code, NIL); +      } + +      Delete(enum_code); +      enum_code = NULL; + +      if (proxy_flag && !is_wrapping_class()) { +	Delete(full_imclass_name); +	full_imclass_name = 0; +      } +    } +    return SWIG_OK; +  } + +  /* ---------------------------------------------------------------------- +   * enumvalueDeclaration() +   * ---------------------------------------------------------------------- */ + +  virtual int enumvalueDeclaration(Node *n) { +    if (getCurrentClass() && (cplus_mode != PUBLIC)) +      return SWIG_NOWRAP; + +    Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL); +    String *symname = Getattr(n, "sym:name"); +    String *value = Getattr(n, "value"); +    String *name = Getattr(n, "name"); +    Node *parent = parentNode(n); +    int unnamedinstance = GetFlag(parent, "unnamedinstance"); +    String *parent_name = Getattr(parent, "name"); +    String *nspace = getNSpace(); +    String *newsymname = 0; +    String *tmpValue; + +    // Strange hack from parent method +    if (value) +      tmpValue = NewString(value); +    else +      tmpValue = NewString(name); +    // Note that this is used in enumValue() amongst other places +    Setattr(n, "value", tmpValue); + +    // Deal with enum values that are not int +    int swigtype = SwigType_type(Getattr(n, "type")); +    if (swigtype == T_BOOL) { +      const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0"; +      Setattr(n, "enumvalue", val); +    } else if (swigtype == T_CHAR) { +      String *val = NewStringf("'%(escape)s'", Getattr(n, "enumvalue")); +      Setattr(n, "enumvalue", val); +      Delete(val); +    } + +    { +      EnumFeature enum_feature = decodeEnumFeature(parent); + +      if ((enum_feature == SimpleEnum) && GetFlag(parent, "scopedenum")) { +	newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname); +	symname = newsymname; +      } + +      // Add to language symbol table +      String *scope = 0; +      if (unnamedinstance || !parent_name || enum_feature == SimpleEnum) { +	String *enumClassPrefix = getEnumClassPrefix(); +	if (enumClassPrefix) { +	  scope = NewString(""); +	  if (nspace) +	    Printf(scope, "%s.", nspace); +	  Printf(scope, "%s", enumClassPrefix); +	} else { +	  scope = Copy(constants_interface_name); +	} +      } else { +	scope = getCurrentScopeName(nspace); +	if (!scope) +	  scope = Copy(Getattr(parent, "sym:name")); +	else +	  Printf(scope, ".%s", Getattr(parent, "sym:name")); +      } +      if (!addSymbol(symname, n, scope)) +	return SWIG_ERROR; +       +      if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) { +	if (!GetFlag(n, "firstenumitem")) +	  Printf(enum_code, ",\n"); +      } + +      // Translate and write javadoc comment if flagged +      if (doxygen && doxygenTranslator->hasDocumentation(n)) { +	String *doxygen_comments = doxygenTranslator->getDocumentation(n, "  "); +	if (comment_creation_chatter) +	  Printf(enum_code, "/* This was generated from enumvalueDeclaration() */\n"); +	Printv(enum_code, Char(doxygen_comments), NIL); +	Delete(doxygen_comments); +      } + +      if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) { +	// Wrap (non-anonymous) C/C++ enum with a proper Java enum +	// Emit the enum item. +	Printf(enum_code, "  %s", symname); +	if (Getattr(n, "enumvalue")) { +	  String *value = enumValue(n); +	  Printf(enum_code, "(%s)", value); +	  Delete(value); +	} +      } else { +	// Wrap C/C++ enums with constant integers or use the typesafe enum pattern +	SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum "); +	Setattr(n, "type", typemap_lookup_type); +	const String *tm = typemapLookup(n, "jstype", typemap_lookup_type, WARN_JAVA_TYPEMAP_JSTYPE_UNDEF); + +	String *return_type = Copy(tm); +	substituteClassname(typemap_lookup_type, return_type); +        const String *methodmods = Getattr(n, "feature:java:methodmodifiers"); +        methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); + +	if ((enum_feature == TypesafeEnum) && parent_name && !unnamedinstance) { +	  // Wrap (non-anonymous) enum using the typesafe enum pattern +	  if (Getattr(n, "enumvalue")) { +	    String *value = enumValue(n); +	    Printf(enum_code, "  %s final static %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value); +	    Delete(value); +	  } else { +	    Printf(enum_code, "  %s final static %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname); +	  } +	} else { +	  // Simple integer constants +	  // Note these are always generated for anonymous enums, no matter what enum_feature is specified +	  // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later +	  String *value = enumValue(n); +	  Printf(enum_code, "  %s final static %s %s = %s;\n", methodmods, return_type, symname, value); +	  Delete(value); +	} +	Delete(return_type); +      } + +      // Add the enum value to the comma separated list being constructed in the enum declaration. +      String *enumvalues = Getattr(parent, "enumvalues"); +      if (!enumvalues) +	Setattr(parent, "enumvalues", Copy(symname)); +      else +	Printv(enumvalues, ", ", symname, NIL); +      Delete(scope); +    } + +    Delete(newsymname); +    Delete(tmpValue); +    Swig_restore(n); +    return SWIG_OK; +  } + +  /* ----------------------------------------------------------------------- +   * constantWrapper() +   * Used for wrapping constants - #define or %constant. +   * Also for inline initialised const static primitive type member variables (short, int, double, enums etc). +   * Java static final variables are generated for these. +   * If the %javaconst(1) feature is used then the C constant value is used to initialise the Java final variable. +   * If not, a JNI method is generated to get the C constant value for initialisation of the Java final variable. +   * However, if the %javaconstvalue feature is used, it overrides all other ways to generate the initialisation. +   * Also note that this method might be called for wrapping enum items (when the enum is using %javaconst(0)). +   * ------------------------------------------------------------------------ */ + +  virtual int constantWrapper(Node *n) { +    String *symname = Getattr(n, "sym:name"); +    SwigType *t = Getattr(n, "type"); +    SwigType *valuetype = Getattr(n, "valuetype"); +    ParmList *l = Getattr(n, "parms"); +    String *tm; +    String *return_type = NewString(""); +    String *constants_code = NewString(""); +    Swig_save("constantWrapper", n, "value", NIL); + +    // Translate and write javadoc comment if flagged +    if (doxygen && doxygenTranslator->hasDocumentation(n)) { +      String *doxygen_comments = doxygenTranslator->getDocumentation(n, "  "); +      if (comment_creation_chatter) +	Printf(constants_code, "/* This was generated from constantWrapper() */\n"); +      Printv(constants_code, Char(doxygen_comments), NIL); +      Delete(doxygen_comments); +    } +     +    bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0); + +    const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname; +    if (!is_enum_item) { +      String *scope = 0; +      if (proxy_class_name) { +	String *nspace = getNSpace(); +	scope = NewString(""); +	if (nspace) +	  Printf(scope, "%s.", nspace); +	Printf(scope, "%s", proxy_class_name); +      } else { +	scope = Copy(constants_interface_name); +      } +      if (!addSymbol(itemname, n, scope)) +	return SWIG_ERROR; +      Delete(scope); +    } + +    // The %javaconst feature determines how the constant value is obtained +    int const_feature_flag = GetFlag(n, "feature:java:const"); + +    /* Adjust the enum type for the Swig_typemap_lookup. +     * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */ +    if (is_enum_item) { +      t = Getattr(parentNode(n), "enumtype"); +      Setattr(n, "type", t); +    } + +    /* Attach the non-standard typemaps to the parameter list. */ +    Swig_typemap_attach_parms("jstype", l, NULL); + +    /* Get Java return types */ +    bool classname_substituted_flag = false; + +    if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) { +      classname_substituted_flag = substituteClassname(t, tm); +      Printf(return_type, "%s", tm); +    } else { +      Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0)); +    } + +    // Add the stripped quotes back in +    String *new_value = NewString(""); +    if (SwigType_type(t) == T_STRING) { +      Printf(new_value, "\"%s\"", Copy(Getattr(n, "value"))); +      Setattr(n, "value", new_value); +    } else if (SwigType_type(t) == T_CHAR) { +      Printf(new_value, "\'%s\'", Copy(Getattr(n, "value"))); +      Setattr(n, "value", new_value); +    } + +    const String *methodmods = Getattr(n, "feature:java:methodmodifiers"); +    methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); + +    Printf(constants_code, "  %s final static %s %s = ", methodmods, return_type, itemname); + +    // Check for the %javaconstvalue feature +    String *value = Getattr(n, "feature:java:constvalue"); + +    if (value) { +      Printf(constants_code, "%s;\n", value); +    } else if (!const_feature_flag) { +      // Default enum and constant handling will work with any type of C constant and initialises the Java variable from C through a JNI call. + +      if (classname_substituted_flag) { +	if (SwigType_isenum(t)) { +	  // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on) +	  Printf(constants_code, "%s.swigToEnum(%s.%s());\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname)); +	} else { +	  // This handles function pointers using the %constant directive +	  Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname)); +	} +      } else { +	Printf(constants_code, "%s.%s();\n", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname)); +      } + +      // Each constant and enum value is wrapped with a separate JNI function call +      SetFlag(n, "feature:immutable"); +      enum_constant_flag = true; +      variableWrapper(n); +      enum_constant_flag = false; +    } else { +      // Alternative constant handling will use the C syntax to make a true Java constant and hope that it compiles as Java code +      if (Getattr(n, "wrappedasconstant")) { +	if (SwigType_type(valuetype) == T_CHAR) +          Printf(constants_code, "\'%(escape)s\';\n", Getattr(n, "staticmembervariableHandler:value")); +	else +          Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value")); +      } else { +        Printf(constants_code, "%s;\n", Getattr(n, "value")); +      } +    } + +    // Emit the generated code to appropriate place +    // Enums only emit the intermediate and JNI methods, so no proxy or module class wrapper methods needed +    if (!is_enum_item) { +      if (proxy_flag && wrapping_member_flag) +	Printv(proxy_class_constants_code, constants_code, NIL); +      else +	Printv(module_class_constants_code, constants_code, NIL); +    } +    // Cleanup +    Swig_restore(n); +    Delete(new_value); +    Delete(return_type); +    Delete(constants_code); +    return SWIG_OK; +  } + +  /* ----------------------------------------------------------------------------- +   * insertDirective() +   * ----------------------------------------------------------------------------- */ + +  virtual int insertDirective(Node *n) { +    int ret = SWIG_OK; +    String *code = Getattr(n, "code"); +    String *section = Getattr(n, "section"); +    Replaceall(code, "$module", module_class_name); +    Replaceall(code, "$imclassname", imclass_name); + +    if (!ImportMode && (Cmp(section, "proxycode") == 0)) { +      if (proxy_class_code) { +	Swig_typemap_replace_embedded_typemap(code, n); +	int offset = Len(code) > 0 && *Char(code) == '\n' ? 1 : 0; +	Printv(proxy_class_code, Char(code) + offset, "\n", NIL); +      } +    } else { +      ret = Language::insertDirective(n); +    } +    return ret; +  } + +  /* ----------------------------------------------------------------------------- +   * pragmaDirective() +   * +   * Valid Pragmas: +   * jniclassbase            - base (extends) for the intermediary class +   * jniclasspackage         - package in which to generate the intermediary class +   * jniclassclassmodifiers  - class modifiers for the intermediary class +   * jniclasscode            - text (java code) is copied verbatim to the intermediary class +   * jniclassimports         - import statements for the intermediary class +   * jniclassinterfaces      - interface (implements) for the intermediary class +   * +   * modulebase              - base (extends) for the module class +   * moduleclassmodifiers    - class modifiers for the module class +   * modulecode              - text (java code) is copied verbatim to the module class +   * moduleimports           - import statements for the module class +   * moduleinterfaces        - interface (implements) for the module class +   * +   * ----------------------------------------------------------------------------- */ + +  virtual int pragmaDirective(Node *n) { +    if (!ImportMode) { +      String *lang = Getattr(n, "lang"); +      String *code = Getattr(n, "name"); +      String *value = Getattr(n, "value"); + +      if (Strcmp(lang, "java") == 0) { + +	String *strvalue = NewString(value); +	Replaceall(strvalue, "\\\"", "\""); + +	if (Strcmp(code, "jniclassbase") == 0) { +	  Delete(imclass_baseclass); +	  imclass_baseclass = Copy(strvalue); +	} else if (Strcmp(code, "jniclasspackage") == 0) { +	  Delete(imclass_package); +	  imclass_package = Copy(strvalue); +	  String *imclass_class_package_jniname = makeValidJniName(imclass_package); +	  Printv(jnipackage, imclass_class_package_jniname, NIL); +	  Delete(imclass_class_package_jniname); +	  Replaceall(jnipackage, NSPACE_SEPARATOR, "_"); +	  Append(jnipackage, "_"); + +	  String *wrapper_name = NewString(""); +	  String *imclass_class_jniname = makeValidJniName(imclass_name); +	  Printf(wrapper_name, "Java_%s%s_%%f", jnipackage, imclass_class_jniname); +	  Delete(imclass_class_jniname); + +	  Swig_name_unregister("wrapper"); +	  Swig_name_register("wrapper", Char(wrapper_name)); + +	  Delete(wrapper_name); +	} else if (Strcmp(code, "jniclassclassmodifiers") == 0) { +	  Delete(imclass_class_modifiers); +	  imclass_class_modifiers = Copy(strvalue); +	} else if (Strcmp(code, "jniclasscode") == 0) { +	  Printf(imclass_class_code, "%s\n", strvalue); +	} else if (Strcmp(code, "jniclassimports") == 0) { +	  Delete(imclass_imports); +	  imclass_imports = Copy(strvalue); +	} else if (Strcmp(code, "jniclassinterfaces") == 0) { +	  Delete(imclass_interfaces); +	  imclass_interfaces = Copy(strvalue); +	} else if (Strcmp(code, "modulebase") == 0) { +	  Delete(module_baseclass); +	  module_baseclass = Copy(strvalue); +	} else if (Strcmp(code, "moduleclassmodifiers") == 0) { +	  Delete(module_class_modifiers); +	  module_class_modifiers = Copy(strvalue); +	} else if (Strcmp(code, "modulecode") == 0) { +	  Printf(module_class_code, "%s\n", strvalue); +	} else if (Strcmp(code, "moduleimports") == 0) { +	  Delete(module_imports); +	  module_imports = Copy(strvalue); +	} else if (Strcmp(code, "moduleinterfaces") == 0) { +	  Delete(module_interfaces); +	  module_interfaces = Copy(strvalue); +	} else if (Strcmp(code, "moduleimport") == 0) { +	  Swig_error(input_file, line_number, "Deprecated pragma. Please use the moduleimports pragma.\n"); +	} else if (Strcmp(code, "moduleinterface") == 0) { +	  Swig_error(input_file, line_number, "Deprecated pragma. Please use the moduleinterfaces pragma.\n"); +	} else if (Strcmp(code, "modulemethodmodifiers") == 0) { +	  Swig_error(input_file, line_number, "Deprecated pragma. Please use %%javamethodmodifiers.\n"); +	} else if (Strcmp(code, "allshadowimport") == 0) { +	  Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaimports).\n"); +	} else if (Strcmp(code, "allshadowcode") == 0) { +	  Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javacode).\n"); +	} else if (Strcmp(code, "allshadowbase") == 0) { +	  Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javabase).\n"); +	} else if (Strcmp(code, "allshadowinterface") == 0) { +	  Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javainterfaces).\n"); +	} else if (Strcmp(code, "allshadowclassmodifiers") == 0) { +	  Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n"); +	} else if (proxy_flag) { +	  if (Strcmp(code, "shadowcode") == 0) { +	    Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javacode).\n"); +	  } else if (Strcmp(code, "shadowimport") == 0) { +	    Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaimports).\n"); +	  } else if (Strcmp(code, "shadowbase") == 0) { +	    Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javabase).\n"); +	  } else if (Strcmp(code, "shadowinterface") == 0) { +	    Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javainterfaces).\n"); +	  } else if (Strcmp(code, "shadowclassmodifiers") == 0) { +	    Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n"); +	  } else { +	    Swig_error(input_file, line_number, "Unrecognized pragma.\n"); +	  } +	} else { +	  Swig_error(input_file, line_number, "Unrecognized pragma.\n"); +	} +	Delete(strvalue); +      } +    } +    return Language::pragmaDirective(n); +  } + +  /* ----------------------------------------------------------------------------- +   * getQualifiedInterfaceName() +   * ----------------------------------------------------------------------------- */ + +  String *getQualifiedInterfaceName(Node *n) { +    String *ret = Getattr(n, "interface:qname"); +    if (!ret) { +      String *nspace = Getattr(n, "sym:nspace"); +      String *symname = Getattr(n, "interface:name"); +      if (nspace) { +	if (package) +	  ret = NewStringf("%s.%s.%s", package, nspace, symname); +	else +	  ret = NewStringf("%s.%s", nspace, symname); +      } else { +	ret = Copy(symname); +      } +      Setattr(n, "interface:qname", ret); +    } +    return ret; +  } + +  /* ----------------------------------------------------------------------------- +   * getInterfaceName() +   * ----------------------------------------------------------------------------- */ + +  String *getInterfaceName(SwigType *t, bool qualified) { +    String *interface_name = NULL; +    if (proxy_flag) { +      Node *n = classLookup(t); +      if (n && Getattr(n, "interface:name")) +	interface_name = qualified ? getQualifiedInterfaceName(n) : Getattr(n, "interface:name"); +    } +    return interface_name; +  } + +  /* ----------------------------------------------------------------------------- +   * addInterfaceNameAndUpcasts() +   * ----------------------------------------------------------------------------- */ + +  void addInterfaceNameAndUpcasts(SwigType *smart, String *interface_list, String *interface_upcasts, Hash *base_list, SwigType *c_classname) { +    List *keys = Keys(base_list); +    for (Iterator it = First(keys); it.item; it = Next(it)) { +      Node *base = Getattr(base_list, it.item); +      SwigType *c_baseclassname = Getattr(base, "name"); +      String *interface_name = Getattr(base, "interface:name"); +      if (Len(interface_list)) +	Append(interface_list, ", "); +      Append(interface_list, interface_name); + +      Node *attributes = NewHash(); +      String *interface_code = Copy(typemapLookup(base, "javainterfacecode", Getattr(base, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF, attributes)); +      String *cptr_method_name = 0; +      if (interface_code) { +        Replaceall(interface_code, "$interfacename", interface_name); +	Printv(interface_upcasts, interface_code, NIL); +	cptr_method_name = Copy(Getattr(attributes, "tmap:javainterfacecode:cptrmethod")); +      } +      if (!cptr_method_name) +	cptr_method_name = NewStringf("%s_GetInterfaceCPtr", interface_name); +      Replaceall(cptr_method_name, ".", "_"); +      Replaceall(cptr_method_name, "$interfacename", interface_name); + +      String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name); +      upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname); + +      Delete(upcast_method_name); +      Delete(cptr_method_name); +      Delete(interface_code); +    } +    Delete(keys); +  } + +  /* ----------------------------------------------------------------------------- +   * upcastsCode() +   * +   * Add code for C++ casting to base class +   * ----------------------------------------------------------------------------- */ + +  void upcastsCode(SwigType *smart, String *upcast_method_name, SwigType *c_classname, SwigType *c_baseclassname) { +    String *jniname = makeValidJniName(upcast_method_name); +    String *wname = Swig_name_wrapper(jniname); + +    Printf(imclass_cppcasts_code, "  public final static native long %s(long jarg1);\n", upcast_method_name); + +    String *classname = SwigType_namestr(c_classname); +    String *baseclassname = SwigType_namestr(c_baseclassname); +    if (smart) { +      String *smartnamestr = SwigType_namestr(smart); +      String *bsmartnamestr = SwigType_namestr(smart); + +      // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates +      SwigType *rclassname = SwigType_typedef_resolve_all(classname); +      SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname); +      Replaceall(bsmartnamestr, rclassname, rbaseclassname); + +      Printv(upcasts_code, +	  "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", +	  "    jlong baseptr = 0;\n" +	  "    ", smartnamestr, " *argp1;\n" +	  "    (void)jenv;\n" +	  "    (void)jcls;\n" +	  "    argp1 = *(", smartnamestr, " **)&jarg1;\n" +	  "    *(", bsmartnamestr, " **)&baseptr = argp1 ? new ", bsmartnamestr, "(*argp1) : 0;\n" +	  "    return baseptr;\n" +	  "}\n", "\n", NIL); + +      Delete(rbaseclassname); +      Delete(rclassname); +      Delete(bsmartnamestr); +      Delete(smartnamestr); +    } else { +      Printv(upcasts_code, +	  "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n", +	  "    jlong baseptr = 0;\n" +	  "    (void)jenv;\n" +	  "    (void)jcls;\n" +	  "    *(", baseclassname, " **)&baseptr = *(", classname, " **)&jarg1;\n" +	  "    return baseptr;\n" +	  "}\n", "\n", NIL); +    } + +    Delete(baseclassname); +    Delete(classname); +    Delete(wname); +    Delete(jniname); +  } + +  /* ----------------------------------------------------------------------------- +   * emitProxyClassDefAndCPPCasts() +   * ----------------------------------------------------------------------------- */ + +  void emitProxyClassDefAndCPPCasts(Node *n) { +    SwigType *c_classname = Getattr(n, "name"); +    SwigType *c_baseclassname = NULL; +    String *baseclass = NULL; +    String *interface_list = NewStringEmpty(); +    String *interface_upcasts = NewStringEmpty(); +    SwigType *typemap_lookup_type = Getattr(n, "classtypeobj"); +    bool feature_director = Swig_directorclass(n) ? true : false; +    bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested"); +    SwigType *smart = Swig_cparse_smartptr(n); + +    // Inheritance from pure Java classes +    Node *attributes = NewHash(); +    const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE, attributes); +    bool purebase_replace = GetFlag(attributes, "tmap:javabase:replace") ? true : false; +    bool purebase_notderived = GetFlag(attributes, "tmap:javabase:notderived") ? true : false; +    Delete(attributes); + +    // C++ inheritance +    if (!purebase_replace) { +      List *baselist = Getattr(n, "bases"); +      if (baselist) { +	Iterator base = First(baselist); +	while (base.item) { +	  if (!(GetFlag(base.item, "feature:ignore") || Getattr(base.item, "feature:interface"))) { +	    SwigType *baseclassname = Getattr(base.item, "name"); +	    if (!c_baseclassname) { +	      String *name = getProxyName(baseclassname); +	      if (name) { +		c_baseclassname = baseclassname; +		baseclass = name; +	      } +	    } else { +	      /* Warn about multiple inheritance for additional base class(es) */ +	      String *proxyclassname = Getattr(n, "classtypeobj"); +	      Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n), +		  "Warning for %s, base %s ignored. Multiple inheritance is not supported in Java.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname)); +	    } +	  } +	  base = Next(base); +	} +      } +    } + +    Hash *interface_bases = Getattr(n, "interface:bases"); +    if (interface_bases) +      addInterfaceNameAndUpcasts(smart, interface_list, interface_upcasts, interface_bases, c_classname); + +    bool derived = baseclass != 0; +    if (derived && purebase_notderived) +      pure_baseclass = empty_string; +    const String *wanted_base = baseclass ? baseclass : pure_baseclass; + +    if (purebase_replace) { +      wanted_base = pure_baseclass; +      derived = false; +      baseclass = NULL; +      if (purebase_notderived) +        Swig_error(Getfile(n), Getline(n), "The javabase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type); +    } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) { +      Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n), +		   "Warning for %s, base %s ignored. Multiple inheritance is not supported in Java. " +		   "Perhaps you need one of the 'replace' or 'notderived' attributes in the javabase typemap?\n", typemap_lookup_type, pure_baseclass); +    } + +    // Pure Java interfaces +    const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE); + +    if (*Char(interface_list) && *Char(pure_interfaces)) +      Append(interface_list, ", "); +    Append(interface_list, pure_interfaces); +    // Start writing the proxy class +    if (!has_outerclass) // Import statements +      Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE),"\n", NIL); + +    // Translate and write javadoc comment if flagged +    if (doxygen && doxygenTranslator->hasDocumentation(n)) { +      String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0); +      if (comment_creation_chatter) +	Printf(proxy_class_def, "/* This was generated from emitProxyClassDefAndCPPCasts() */\n"); +      Printv(proxy_class_def, Char(doxygen_comments), NIL); +      Delete(doxygen_comments); +    } + +    if (has_outerclass) +      Printv(proxy_class_def, "static ", NIL); // C++ nested classes correspond to static java classes +    Printv(proxy_class_def, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF),	// Class modifiers +	   " $javaclassname",	// Class name and bases +	   (*Char(wanted_base)) ? " extends " : "", wanted_base, *Char(interface_list) ?	// Pure Java interfaces +	   " implements " : "", interface_list, " {", derived ? typemapLookup(n, "javabody_derived", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) :	// main body of class +	   typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF),	// main body of class +	   NIL); + +    // C++ destructor is wrapped by the delete method +    // Note that the method name is specified in a typemap attribute called methodname +    String *destruct = NewString(""); +    const String *tm = NULL; +    attributes = NewHash(); +    const String *destruct_methodname = NULL; +    const String *destruct_methodmodifiers = NULL; +    const String *destruct_parameters = NULL; +    if (derived) { +      tm = typemapLookup(n, "javadestruct_derived", typemap_lookup_type, WARN_NONE, attributes); +      destruct_methodname = Getattr(attributes, "tmap:javadestruct_derived:methodname"); +      destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct_derived:methodmodifiers"); +      destruct_parameters = Getattr(attributes, "tmap:javadestruct_derived:parameters"); +    } else { +      tm = typemapLookup(n, "javadestruct", typemap_lookup_type, WARN_NONE, attributes); +      destruct_methodname = Getattr(attributes, "tmap:javadestruct:methodname"); +      destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct:methodmodifiers"); +      destruct_parameters = Getattr(attributes, "tmap:javadestruct:parameters"); +    } +    if (tm && *Char(tm)) { +      if (!destruct_methodname) { +	Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in javadestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name); +      } +      if (!destruct_methodmodifiers) { +	Swig_error(Getfile(n), Getline(n), "No methodmodifiers attribute defined in javadestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name); +      } +      if (!destruct_parameters) +	destruct_parameters = empty_string; +    } +    // Emit the finalize and delete methods +    if (tm) { +      // Finalize method +      if (*Char(destructor_call)) { +	Printv(proxy_class_def, typemapLookup(n, "javafinalize", typemap_lookup_type, WARN_NONE), NIL); +      } +      // delete method +      Printv(destruct, tm, NIL); +      if (*Char(destructor_call)) +	Replaceall(destruct, "$jnicall", destructor_call); +      else +	Replaceall(destruct, "$jnicall", "throw new UnsupportedOperationException(\"C++ destructor does not have public access\")"); +      if (*Char(destruct)) { +	Printv(proxy_class_def, "\n  ", NIL); +	const String *methodmods = Getattr(n, "destructmethodmodifiers"); +	if (methodmods) +	  Printv(proxy_class_def, methodmods, NIL); +	else +	  Printv(proxy_class_def, destruct_methodmodifiers, NIL); +	Printv(proxy_class_def, " void ", destruct_methodname, "(", destruct_parameters, ")", destructor_throws_clause, " ", destruct, "\n", NIL); +      } +    } +    if (*Char(interface_upcasts)) +      Printv(proxy_class_def, interface_upcasts, NIL); + +    /* Insert directordisconnect typemap, if this class has directors enabled */ +    /* Also insert the swigTakeOwnership and swigReleaseOwnership methods */ +    if (feature_director) { +      String *destruct_jnicall, *release_jnicall, *take_jnicall; +      String *changeown_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "change_ownership"); + +      destruct_jnicall = NewStringf("%s()", destruct_methodname); +      release_jnicall = NewStringf("%s.%s(this, swigCPtr, false)", full_imclass_name, changeown_method_name); +      take_jnicall = NewStringf("%s.%s(this, swigCPtr, true)", full_imclass_name, changeown_method_name); + +      emitCodeTypemap(n, false, typemap_lookup_type, "directordisconnect", "methodname", destruct_jnicall); +      emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_release", "methodname", release_jnicall); +      emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_take", "methodname", take_jnicall); + +      Delete(destruct_jnicall); +      Delete(changeown_method_name); +      Delete(release_jnicall); +      Delete(take_jnicall); +    } + +    Delete(interface_upcasts); +    Delete(interface_list); +    Delete(attributes); +    Delete(destruct); + +    // Emit extra user code +    Printv(proxy_class_def, typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE),	// extra Java code +	   "\n", NIL); + +    if (derived) { +      String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast"); +      upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname); +      Delete(upcast_method_name); +    } + +    Delete(smart); +  } + +  /* ---------------------------------------------------------------------- +   * emitInterfaceDeclaration() +   * ---------------------------------------------------------------------- */ + +  void emitInterfaceDeclaration(Node *n, String *interface_name, File *f_interface, String *nspace) { +    if (package || nspace) { +      Printf(f_interface, "package "); +      if (package) +	Printv(f_interface, package, nspace ? "." : "", NIL); +      if (nspace) +	Printv(f_interface, nspace, NIL); +      Printf(f_interface, ";\n"); +    } + +    Printv(f_interface, typemapLookup(n, "javaimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL); +    Printf(f_interface, "public interface %s", interface_name); +    if (List *baselist = Getattr(n, "bases")) { +      String *bases = 0; +      for (Iterator base = First(baselist); base.item; base = Next(base)) { +	if (GetFlag(base.item, "feature:ignore") || !Getattr(base.item, "feature:interface")) +	  continue; // TODO: warn about skipped non-interface bases +	String *base_iname = Getattr(base.item, "interface:name"); +	if (!bases) +	  bases = Copy(base_iname); +	else { +	  Append(bases, ", "); +	  Append(bases, base_iname); +	} +      } +      if (bases) { +	Printv(f_interface, " extends ", bases, NIL); +	Delete(bases); +      } +    } +    Printf(f_interface, " {\n"); + +    Node *attributes = NewHash(); +    String *interface_code = Copy(typemapLookup(n, "javainterfacecode", Getattr(n, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF, attributes)); +    if (interface_code) { +      String *interface_declaration = Copy(Getattr(attributes, "tmap:javainterfacecode:declaration")); +      if (interface_declaration) { +        Replaceall(interface_declaration, "$interfacename", interface_name); +	Printv(f_interface, interface_declaration, NIL); +	Delete(interface_declaration); +      } +      Delete(interface_code); +    } +  } + +  /* ---------------------------------------------------------------------- +  * classDeclaration() +  * ---------------------------------------------------------------------- */ + +  int classDeclaration(Node *n) { +    return Language::classDeclaration(n); +  } + +  /* ---------------------------------------------------------------------- +  * classHandler() +  * ---------------------------------------------------------------------- */ + +  virtual int classHandler(Node *n) { +    File *f_proxy = NULL; +    File *f_interface = NULL; +    String *old_proxy_class_name = proxy_class_name; +    String *old_full_proxy_class_name = full_proxy_class_name; +    String *old_full_imclass_name = full_imclass_name; +    String *old_destructor_call = destructor_call; +    String *old_destructor_throws_clause = destructor_throws_clause; +    String *old_proxy_class_constants_code = proxy_class_constants_code; +    String *old_proxy_class_def = proxy_class_def; +    String *old_proxy_class_code = proxy_class_code; +    bool has_outerclass = Getattr(n, "nested:outer") && !GetFlag(n, "feature:flatnested"); +    String *old_interface_class_code = interface_class_code; +    interface_class_code = 0; + +    if (proxy_flag) { +      proxy_class_name = NewString(Getattr(n, "sym:name")); +      String *nspace = getNSpace(); +      constructIntermediateClassName(n); + +      String *outerClassesPrefix = 0; +      if (Node *outer = Getattr(n, "nested:outer")) { +	outerClassesPrefix = Copy(Getattr(outer, "sym:name")); +	for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) { +	  Push(outerClassesPrefix, "."); +	  Push(outerClassesPrefix, Getattr(outer, "sym:name")); +	} +      } +      if (!nspace) { +	full_proxy_class_name = outerClassesPrefix ? NewStringf("%s.%s", outerClassesPrefix, proxy_class_name) : NewStringf("%s", proxy_class_name); + +	if (Cmp(proxy_class_name, imclass_name) == 0) { +	  Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name); +	  SWIG_exit(EXIT_FAILURE); +	} + +	if (Cmp(proxy_class_name, module_class_name) == 0) { +	  Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name); +	  SWIG_exit(EXIT_FAILURE); +	} +      } else { +	if (outerClassesPrefix) { +	  if (package) +	    full_proxy_class_name = NewStringf("%s.%s.%s.%s", package, nspace, outerClassesPrefix, proxy_class_name); +	  else +	    full_proxy_class_name = NewStringf("%s.%s.%s", nspace, outerClassesPrefix, proxy_class_name); +	} else { +	  if (package) +	    full_proxy_class_name = NewStringf("%s.%s.%s", package, nspace, proxy_class_name); +	  else +	    full_proxy_class_name = NewStringf("%s.%s", nspace, proxy_class_name); +	} +      } + +      String *interface_name = Getattr(n, "feature:interface") ? Getattr(n, "interface:name") : 0; +      if (outerClassesPrefix) { +	String *fnspace = nspace ? NewStringf("%s.%s", nspace, outerClassesPrefix) : outerClassesPrefix; +	if (!addSymbol(proxy_class_name, n, fnspace)) +	  return SWIG_ERROR; +	if (interface_name && !addInterfaceSymbol(interface_name, n, fnspace)) +	  return SWIG_ERROR; +	if (nspace) +	  Delete(fnspace); +	Delete(outerClassesPrefix); +      } else { +	if (!addSymbol(proxy_class_name, n, nspace)) +	  return SWIG_ERROR; +	if (interface_name && !addInterfaceSymbol(interface_name, n, nspace)) +	  return SWIG_ERROR; +      } + +      // Each outer proxy class goes into a separate file +      if (!has_outerclass) { +	String *output_directory = outputDirectory(nspace); +	String *filen = NewStringf("%s%s.java", output_directory, proxy_class_name); +	f_proxy = NewFile(filen, "w", SWIG_output_files()); +	if (!f_proxy) { +	  FileErrorDisplay(filen); +	  SWIG_exit(EXIT_FAILURE); +	} +	Append(filenames_list, Copy(filen)); +	Delete(filen); +	Delete(output_directory); + +	// Start writing out the proxy class file +	emitBanner(f_proxy); + +	if (package || nspace) { +	  Printf(f_proxy, "package "); +	  if (package) +	    Printv(f_proxy, package, nspace ? "." : "", NIL); +	  if (nspace) +	    Printv(f_proxy, nspace, NIL); +	  Printf(f_proxy, ";\n"); +	} +      } +      else +	++nesting_depth; + +      proxy_class_def = NewString(""); +      proxy_class_code = NewString(""); +      destructor_call = NewString(""); +      destructor_throws_clause = NewString(""); +      proxy_class_constants_code = NewString(""); + +      if (Getattr(n, "feature:interface")) { +        interface_class_code = NewString(""); +	String *output_directory = outputDirectory(nspace); +	String *filen = NewStringf("%s%s.java", output_directory, interface_name); +	f_interface = NewFile(filen, "w", SWIG_output_files()); +	if (!f_interface) { +	  FileErrorDisplay(filen); +	  SWIG_exit(EXIT_FAILURE); +	} +	Append(filenames_list, filen); // file name ownership goes to the list +	emitBanner(f_interface); +	emitInterfaceDeclaration(n, interface_name, interface_class_code, nspace); +	Delete(filen); +	Delete(output_directory); +      } +    } + +    Language::classHandler(n); + +    if (proxy_flag) { +      emitProxyClassDefAndCPPCasts(n); + +      String *javaclazzname = Swig_name_member(getNSpace(), getClassPrefix(), ""); // mangled full proxy class name + +      Replaceall(proxy_class_def, "$javaclassname", proxy_class_name); +      Replaceall(proxy_class_code, "$javaclassname", proxy_class_name); +      Replaceall(proxy_class_constants_code, "$javaclassname", proxy_class_name); +      Replaceall(interface_class_code, "$javaclassname", proxy_class_name); + +      Replaceall(proxy_class_def, "$javaclazzname", javaclazzname); +      Replaceall(proxy_class_code, "$javaclazzname", javaclazzname); +      Replaceall(proxy_class_constants_code, "$javaclazzname", javaclazzname); +      Replaceall(interface_class_code, "$javaclazzname", javaclazzname); + +      Replaceall(proxy_class_def, "$module", module_class_name); +      Replaceall(proxy_class_code, "$module", module_class_name); +      Replaceall(proxy_class_constants_code, "$module", module_class_name); +      Replaceall(interface_class_code, "$module", module_class_name); + +      Replaceall(proxy_class_def, "$imclassname", full_imclass_name); +      Replaceall(proxy_class_code, "$imclassname", full_imclass_name); +      Replaceall(proxy_class_constants_code, "$imclassname", full_imclass_name); +      Replaceall(interface_class_code, "$imclassname", full_imclass_name); + +      if (!has_outerclass) +	Printv(f_proxy, proxy_class_def, proxy_class_code, NIL); +      else { +	Swig_offset_string(proxy_class_def, nesting_depth); +	Append(old_proxy_class_code, proxy_class_def); +	Swig_offset_string(proxy_class_code, nesting_depth); +	Append(old_proxy_class_code, proxy_class_code); +      } + +      // Write out all the constants +      if (Len(proxy_class_constants_code) != 0) { +	if (!has_outerclass) +	  Printv(f_proxy, proxy_class_constants_code, NIL); +	else { +	  Swig_offset_string(proxy_class_constants_code, nesting_depth); +	  Append(old_proxy_class_code, proxy_class_constants_code); +	} +      } + +      if (!has_outerclass) { +	Printf(f_proxy, "}\n"); +        Delete(f_proxy); +        f_proxy = NULL; +      } else { +	for (int i = 0; i < nesting_depth; ++i) +	  Append(old_proxy_class_code, "  "); +	Append(old_proxy_class_code, "}\n\n"); +	--nesting_depth; +      } + +      if (f_interface) { +	Printv(f_interface, interface_class_code, "}\n", NIL); +	Delete(f_interface); +	f_interface = 0; +      } + +      emitDirectorExtraMethods(n); + +      Delete(interface_class_code); +      interface_class_code = old_interface_class_code; +      Delete(javaclazzname); +      Delete(proxy_class_name); +      proxy_class_name = old_proxy_class_name; +      Delete(full_proxy_class_name); +      full_proxy_class_name = old_full_proxy_class_name; +      Delete(full_imclass_name); +      full_imclass_name = old_full_imclass_name; +      Delete(destructor_call); +      destructor_call = old_destructor_call; +      Delete(destructor_throws_clause); +      destructor_throws_clause = old_destructor_throws_clause; +      Delete(proxy_class_constants_code); +      proxy_class_constants_code = old_proxy_class_constants_code; +      Delete(proxy_class_def); +      proxy_class_def = old_proxy_class_def; +      Delete(proxy_class_code); +      proxy_class_code = old_proxy_class_code; +    } + +    return SWIG_OK; +  } + +  /* ---------------------------------------------------------------------- +   * memberfunctionHandler() +   * ---------------------------------------------------------------------- */ + +  virtual int memberfunctionHandler(Node *n) { +    member_func_flag = true; +    Language::memberfunctionHandler(n); + +    if (proxy_flag) { +      String *overloaded_name = getOverloadedName(n); +      String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name); +      Setattr(n, "proxyfuncname", Getattr(n, "sym:name")); +      Setattr(n, "imfuncname", intermediary_function_name); +      proxyClassFunctionHandler(n); +      Delete(overloaded_name); +    } +    member_func_flag = false; +    return SWIG_OK; +  } + +  /* ---------------------------------------------------------------------- +   * staticmemberfunctionHandler() +   * ---------------------------------------------------------------------- */ + +  virtual int staticmemberfunctionHandler(Node *n) { + +    static_flag = true; +    member_func_flag = true; +    Language::staticmemberfunctionHandler(n); + +    if (proxy_flag) { +      String *overloaded_name = getOverloadedName(n); +      String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name); +      Setattr(n, "proxyfuncname", Getattr(n, "sym:name")); +      Setattr(n, "imfuncname", intermediary_function_name); +      proxyClassFunctionHandler(n); +      Delete(overloaded_name); +    } +    static_flag = false; +    member_func_flag = false; + +    return SWIG_OK; +  } + +  /* ----------------------------------------------------------------------------- +   * proxyClassFunctionHandler() +   * +   * Function called for creating a Java wrapper function around a c++ function in the  +   * proxy class. Used for both static and non-static C++ class functions. +   * C++ class static functions map to Java static functions. +   * Two extra attributes in the Node must be available. These are "proxyfuncname" -  +   * the name of the Java class proxy function, which in turn will call "imfuncname" -  +   * the intermediary (JNI) function name in the intermediary class. +   * ----------------------------------------------------------------------------- */ + +  void proxyClassFunctionHandler(Node *n) { +    SwigType *t = Getattr(n, "type"); +    ParmList *l = Getattr(n, "parms"); +    String *intermediary_function_name = Getattr(n, "imfuncname"); +    String *proxy_function_name = Getattr(n, "proxyfuncname"); +    String *tm; +    Parm *p; +    int i; +    String *imcall = NewString(""); +    String *return_type = NewString(""); +    String *function_code = NewString(""); +    bool setter_flag = false; +    String *pre_code = NewString(""); +    String *post_code = NewString(""); +    bool is_interface = Getattr(parentNode(n), "feature:interface") != 0  +      && !static_flag && Getattr(n, "interface:owner") == 0; + +    if (!proxy_flag) +      return; + +    // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java +    if (Getattr(n, "overload:ignore")) +      return; + +    // Don't generate proxy method for additional explicitcall method used in directors +    if (GetFlag(n, "explicitcall")) +      return; + +    if (l) { +      if (SwigType_type(Getattr(l, "type")) == T_VOID) { +	l = nextSibling(l); +      } +    } + +    /* Attach the non-standard typemaps to the parameter list */ +    Swig_typemap_attach_parms("in", l, NULL); +    Swig_typemap_attach_parms("jtype", l, NULL); +    Swig_typemap_attach_parms("jstype", l, NULL); +    Swig_typemap_attach_parms("javain", l, NULL); + +    /* Get return types */ +    if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) { +      // Note that in the case of polymorphic (covariant) return types, the method's return type is changed to be the base of the C++ return type +      SwigType *covariant = Getattr(n, "covariant"); +      substituteClassname(covariant ? covariant : t, tm); +      Printf(return_type, "%s", tm); +      if (covariant) +	Swig_warning(WARN_JAVA_COVARIANT_RET, input_file, line_number, +		     "Covariant return types not supported in Java. Proxy method will return %s.\n", SwigType_str(covariant, 0)); +    } else { +      Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0)); +    } + +    if (wrapping_member_flag && !enum_constant_flag) { +      // For wrapping member variables (Javabean setter) +      setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) == 0); +    } + +    // Translate and write javadoc comment if flagged +    if (doxygen && doxygenTranslator->hasDocumentation(n)) { +      String *doxygen_comments = doxygenTranslator->getDocumentation(n, "  "); +      if (comment_creation_chatter) +	Printf(function_code, "/* This was generated from proxyclassfunctionhandler() */\n"); +      Printv(function_code, Char(doxygen_comments), NIL); +      Delete(doxygen_comments); +    } + +    /* Start generating the proxy function */ +    const String *methodmods = Getattr(n, "feature:java:methodmodifiers"); +    methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); +    Printf(function_code, "  %s ", methodmods); +    if (static_flag) +      Printf(function_code, "static "); +    Printf(function_code, "%s %s(", return_type, proxy_function_name); + +    if (is_interface) +      Printf(interface_class_code, "  %s %s(", return_type, proxy_function_name); + +    Printv(imcall, full_imclass_name, ".$imfuncname(", NIL); +    if (!static_flag) { +      Printf(imcall, "swigCPtr"); + +      String *this_type = Copy(getClassType()); +      String *name = NewString("jself"); +      String *qualifier = Getattr(n, "qualifier"); +      if (qualifier) +	SwigType_push(this_type, qualifier); +      SwigType_add_pointer(this_type); +      Parm *this_parm = NewParm(this_type, name, n); +      Swig_typemap_attach_parms("jtype", this_parm, NULL); +      Swig_typemap_attach_parms("jstype", this_parm, NULL); + +      if (prematureGarbageCollectionPreventionParameter(this_type, this_parm)) +	Printf(imcall, ", this"); + +      Delete(this_parm); +      Delete(name); +      Delete(this_type); +    } + +    emit_mark_varargs(l); + +    int gencomma = !static_flag; + +    /* Output each parameter */ +    for (i = 0, p = l; p; i++) { + +      /* Ignored varargs */ +      if (checkAttribute(p, "varargs:ignore", "1")) { +	p = nextSibling(p); +	continue; +      } + +      /* Ignored parameters */ +      if (checkAttribute(p, "tmap:in:numinputs", "0")) { +	p = Getattr(p, "tmap:in:next"); +	continue; +      } + +      /* Ignore the 'this' argument for variable wrappers */ +      if (!(variable_wrapper_flag && i == 0) || static_flag) { +	SwigType *pt = Getattr(p, "type"); +	String *param_type = NewString(""); + +	/* Get the Java parameter type */ +	if ((tm = Getattr(p, "tmap:jstype"))) { +	  substituteClassname(pt, tm); +	  Printf(param_type, "%s", tm); +	} else { +	  Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0)); +	} + +	if (gencomma) +	  Printf(imcall, ", "); + +	String *arg = makeParameterName(n, p, i, setter_flag); + +	// Use typemaps to transform type used in Java proxy wrapper (in proxy class) to type used in JNI function (in intermediary class) +	if ((tm = Getattr(p, "tmap:javain"))) { +	  addThrows(n, "tmap:javain", p); +	  substituteClassname(pt, tm); +	  Replaceall(tm, "$javainput", arg); +          String *pre = Getattr(p, "tmap:javain:pre"); +          if (pre) { +            substituteClassname(pt, pre); +            Replaceall(pre, "$javainput", arg); +            if (Len(pre_code) > 0) +              Printf(pre_code, "\n"); +            Printv(pre_code, pre, NIL); +          } +          String *post = Getattr(p, "tmap:javain:post"); +          if (post) { +            substituteClassname(pt, post); +            Replaceall(post, "$javainput", arg); +            if (Len(post_code) > 0) +              Printf(post_code, "\n"); +            Printv(post_code, post, NIL); +          } +	  Printv(imcall, tm, NIL); +	} else { +	  Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0)); +	} + +	/* Add parameter to proxy function */ +	if (gencomma >= 2) { +	  Printf(function_code, ", "); +	  if (is_interface) +	    Printf(interface_class_code, ", "); +	} +	gencomma = 2; +	Printf(function_code, "%s %s", param_type, arg); +	if (is_interface) +	  Printf(interface_class_code, "%s %s", param_type, arg); + +	if (prematureGarbageCollectionPreventionParameter(pt, p)) { +          String *pgcppname = Getattr(p, "tmap:javain:pgcppname"); +          if (pgcppname) { +            String *argname = Copy(pgcppname); +            Replaceall(argname, "$javainput", arg); +            Printf(imcall, ", %s", argname); +            Delete(argname); +          } else { +            Printf(imcall, ", %s", arg); +          } +        } + +	Delete(arg); +	Delete(param_type); +      } +      p = Getattr(p, "tmap:in:next"); +    } + +    Printf(imcall, ")"); +    Printf(function_code, ")"); + +    // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in proxy class) +    if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) { +      addThrows(n, "tmap:javaout", n); +      bool is_pre_code = Len(pre_code) > 0; +      bool is_post_code = Len(post_code) > 0; +      if (is_pre_code || is_post_code) { +        Replaceall(tm, "\n ", "\n   "); // add extra indentation to code in typemap +        if (is_post_code) { +          Insert(tm, 0, "\n    try "); +          Printv(tm, " finally {\n", post_code, "\n    }", NIL); +        } else { +          Insert(tm, 0, "\n    "); +        } +        if (is_pre_code) { +          Insert(tm, 0, pre_code); +          Insert(tm, 0, "\n"); +        } +	Insert(tm, 0, "{"); +	Printf(tm, "\n  }"); +      } +      if (GetFlag(n, "feature:new")) +	Replaceall(tm, "$owner", "true"); +      else +	Replaceall(tm, "$owner", "false"); +      substituteClassname(t, tm); + +      // For director methods: generate code to selectively make a normal polymorphic call or  +      // an explicit method call - needed to prevent infinite recursion calls in director methods. +      Node *explicit_n = Getattr(n, "explicitcallnode"); +      if (explicit_n) { +	String *ex_overloaded_name = getOverloadedName(explicit_n); +	String *ex_intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), ex_overloaded_name); + +	String *ex_imcall = Copy(imcall); +	Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name); +	Replaceall(imcall, "$imfuncname", intermediary_function_name); + +	String *excode = NewString(""); +	if (!Cmp(return_type, "void")) +	  Printf(excode, "if (getClass() == %s.class) %s; else %s", proxy_class_name, imcall, ex_imcall); +	else +	  Printf(excode, "(getClass() == %s.class) ? %s : %s", proxy_class_name, imcall, ex_imcall); + +	Clear(imcall); +	Printv(imcall, excode, NIL); +	Delete(ex_overloaded_name); +	Delete(excode); +      } else { +	Replaceall(imcall, "$imfuncname", intermediary_function_name); +      } + +      Replaceall(tm, "$jnicall", imcall); +    } else { +      Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0)); +    } + +    if (is_interface) { +      Printf(interface_class_code, ")"); +      generateThrowsClause(n, interface_class_code); +      Printf(interface_class_code, ";\n"); +    } +    generateThrowsClause(n, function_code); +    Printf(function_code, " %s\n\n", tm ? tm : empty_string); +    Printv(proxy_class_code, function_code, NIL); + +    Delete(pre_code); +    Delete(post_code); +    Delete(function_code); +    Delete(return_type); +    Delete(imcall); +  } + +  /* ---------------------------------------------------------------------- +   * constructorHandler() +   * ---------------------------------------------------------------------- */ + +  virtual int constructorHandler(Node *n) { + +    ParmList *l = Getattr(n, "parms"); +    String *tm; +    Parm *p; +    int i; +    String *function_code = NewString(""); +    String *helper_code = NewString(""); // Holds code for the constructor helper method generated only when the javain typemap has code in the pre or post attributes +    String *helper_args = NewString(""); +    String *pre_code = NewString(""); +    String *post_code = NewString(""); +    String *im_return_type = NewString(""); +    bool feature_director = (parentNode(n) && Swig_directorclass(n)); + +    Language::constructorHandler(n); + +    // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java +    if (Getattr(n, "overload:ignore")) +      return SWIG_OK; + +    if (proxy_flag) { +      String *overloaded_name = getOverloadedName(n); +      String *mangled_overname = Swig_name_construct(getNSpace(), overloaded_name); +      String *imcall = NewString(""); + +      const String *methodmods = Getattr(n, "feature:java:methodmodifiers"); +      methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); + +      tm = Getattr(n, "tmap:jtype"); // typemaps were attached earlier to the node +      Printf(im_return_type, "%s", tm); + +      // Translate and write javadoc comment if flagged +      if (doxygen && doxygenTranslator->hasDocumentation(n)) { +	String *doxygen_comments = doxygenTranslator->getDocumentation(n, "  "); +	if (comment_creation_chatter) +	  Printf(function_code, "/* This was generated from constructionhandler() */\n"); +	Printv(function_code, Char(doxygen_comments), NIL); +	Delete(doxygen_comments); +      } + +      Printf(function_code, "  %s %s(", methodmods, proxy_class_name); +      Printf(helper_code, "  static private %s SwigConstruct%s(", im_return_type, proxy_class_name); + +      Printv(imcall, full_imclass_name, ".", mangled_overname, "(", NIL); + +      /* Attach the non-standard typemaps to the parameter list */ +      Swig_typemap_attach_parms("in", l, NULL); +      Swig_typemap_attach_parms("jtype", l, NULL); +      Swig_typemap_attach_parms("jstype", l, NULL); +      Swig_typemap_attach_parms("javain", l, NULL); + +      emit_mark_varargs(l); + +      int gencomma = 0; + +      /* Output each parameter */ +      for (i = 0, p = l; p; i++) { + +	/* Ignored varargs */ +	if (checkAttribute(p, "varargs:ignore", "1")) { +	  p = nextSibling(p); +	  continue; +	} + +	/* Ignored parameters */ +	if (checkAttribute(p, "tmap:in:numinputs", "0")) { +	  p = Getattr(p, "tmap:in:next"); +	  continue; +	} + +	SwigType *pt = Getattr(p, "type"); +	String *param_type = NewString(""); + +	/* Get the Java parameter type */ +	if ((tm = Getattr(p, "tmap:jstype"))) { +	  substituteClassname(pt, tm); +	  Printf(param_type, "%s", tm); +	} else { +	  Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0)); +	} + +	if (gencomma) +	  Printf(imcall, ", "); + +	String *arg = makeParameterName(n, p, i, false); + +	// Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class) +	if ((tm = Getattr(p, "tmap:javain"))) { +	  addThrows(n, "tmap:javain", p); +	  substituteClassname(pt, tm); +	  Replaceall(tm, "$javainput", arg); +          String *pre = Getattr(p, "tmap:javain:pre"); +          if (pre) { +            substituteClassname(pt, pre); +            Replaceall(pre, "$javainput", arg); +            if (Len(pre_code) > 0) +              Printf(pre_code, "\n"); +            Printv(pre_code, pre, NIL); +          } +          String *post = Getattr(p, "tmap:javain:post"); +          if (post) { +            substituteClassname(pt, post); +            Replaceall(post, "$javainput", arg); +            if (Len(post_code) > 0) +              Printf(post_code, "\n"); +            Printv(post_code, post, NIL); +          } +	  Printv(imcall, tm, NIL); +	} else { +	  Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0)); +	} + +	/* Add parameter to proxy function */ +	if (gencomma) { +	  Printf(function_code, ", "); +	  Printf(helper_code, ", "); +	  Printf(helper_args, ", "); +        } +	Printf(function_code, "%s %s", param_type, arg); +	Printf(helper_code, "%s %s", param_type, arg); +	Printf(helper_args, "%s", arg); +	++gencomma; + +	if (prematureGarbageCollectionPreventionParameter(pt, p)) { +          String *pgcppname = Getattr(p, "tmap:javain:pgcppname"); +          if (pgcppname) { +            String *argname = Copy(pgcppname); +            Replaceall(argname, "$javainput", arg); +            Printf(imcall, ", %s", argname); +            Delete(argname); +          } else { +            Printf(imcall, ", %s", arg); +          } +        } + +	Delete(arg); +	Delete(param_type); +	p = Getattr(p, "tmap:in:next"); +      } + +      Printf(imcall, ")"); + +      Printf(function_code, ")"); +      Printf(helper_code, ")"); +      generateThrowsClause(n, function_code); + +      /* Insert the javaconstruct typemap, doing the replacement for $directorconnect, as needed */ +      Hash *attributes = NewHash(); +      String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj"); +      String *construct_tm = Copy(typemapLookup(n, "javaconstruct", typemap_lookup_type, +						WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF, attributes)); +      if (construct_tm) { +	if (!feature_director) { +	  Replaceall(construct_tm, "$directorconnect", ""); +	} else { +	  String *connect_attr = Getattr(attributes, "tmap:javaconstruct:directorconnect"); + +	  if (connect_attr) { +	    Replaceall(construct_tm, "$directorconnect", connect_attr); +	  } else { +	    Swig_warning(WARN_JAVA_NO_DIRECTORCONNECT_ATTR, input_file, line_number, "\"directorconnect\" attribute missing in %s \"javaconstruct\" typemap.\n", +			 Getattr(n, "name")); +	    Replaceall(construct_tm, "$directorconnect", ""); +	  } +	} + +	Printv(function_code, " ", construct_tm, "\n", NIL); +      } + +      bool is_pre_code = Len(pre_code) > 0; +      bool is_post_code = Len(post_code) > 0; +      if (is_pre_code || is_post_code) { +        generateThrowsClause(n, helper_code); +        Printf(helper_code, " {\n"); +        if (is_pre_code) { +          Printv(helper_code, pre_code, "\n", NIL); +        } +        if (is_post_code) { +          Printf(helper_code, "    try {\n"); +          Printv(helper_code, "      return ", imcall, ";\n", NIL); +          Printv(helper_code, "    } finally {\n", post_code, "\n    }", NIL); +        } else { +          Printv(helper_code, "    return ", imcall, ";", NIL); +        } +        Printf(helper_code, "\n  }\n"); +        String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args); +        Printv(proxy_class_code, helper_code, "\n", NIL); +        Replaceall(function_code, "$imcall", helper_name); +        Delete(helper_name); +      } else { +        Replaceall(function_code, "$imcall", imcall); +      } + +      Printv(proxy_class_code, function_code, "\n", NIL); + +      Delete(helper_args); +      Delete(im_return_type); +      Delete(pre_code); +      Delete(post_code); +      Delete(construct_tm); +      Delete(attributes); +      Delete(overloaded_name); +      Delete(imcall); +    } + +    return SWIG_OK; +  } + +  /* ---------------------------------------------------------------------- +   * destructorHandler() +   * ---------------------------------------------------------------------- */ + +  virtual int destructorHandler(Node *n) { +    Language::destructorHandler(n); +    String *symname = Getattr(n, "sym:name"); + +    if (proxy_flag) { +      Printv(destructor_call, full_imclass_name, ".", Swig_name_destroy(getNSpace(), symname), "(swigCPtr)", NIL); +      generateThrowsClause(n, destructor_throws_clause); +      const String *methodmods = Getattr(n, "feature:java:methodmodifiers"); +      if (methodmods) +	Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods); +    } +    return SWIG_OK; +  } + +  /* ---------------------------------------------------------------------- +   * membervariableHandler() +   * ---------------------------------------------------------------------- */ + +  virtual int membervariableHandler(Node *n) { +    variable_name = Getattr(n, "sym:name"); +    wrapping_member_flag = true; +    variable_wrapper_flag = true; +    Language::membervariableHandler(n); +    wrapping_member_flag = false; +    variable_wrapper_flag = false; +    return SWIG_OK; +  } + +  /* ---------------------------------------------------------------------- +   * staticmembervariableHandler() +   * ---------------------------------------------------------------------- */ + +  virtual int staticmembervariableHandler(Node *n) { +    variable_name = Getattr(n, "sym:name"); +    wrapping_member_flag = true; +    static_flag = true; +    Language::staticmembervariableHandler(n); +    wrapping_member_flag = false; +    static_flag = false; +    return SWIG_OK; +  } + +  /* ---------------------------------------------------------------------- +   * memberconstantHandler() +   * ---------------------------------------------------------------------- */ + +  virtual int memberconstantHandler(Node *n) { +    variable_name = Getattr(n, "sym:name"); +    wrapping_member_flag = true; +    Language::memberconstantHandler(n); +    wrapping_member_flag = false; +    return SWIG_OK; +  } + +  /* ----------------------------------------------------------------------------- +   * getOverloadedName() +   * ----------------------------------------------------------------------------- */ + +  String *getOverloadedName(Node *n) { + +    /* Although JNI functions are designed to handle overloaded Java functions, +     * a Java long is used for all classes in the SWIG intermediary class. +     * The intermediary class methods are thus mangled when overloaded to give +     * a unique name. */ +    String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name")); + +    if (Getattr(n, "sym:overloaded")) { +      Printv(overloaded_name, Getattr(n, "sym:overname"), NIL); +    } + +    return overloaded_name; +  } + +  /* ----------------------------------------------------------------------------- +   * moduleClassFunctionHandler() +   * ----------------------------------------------------------------------------- */ + +  void moduleClassFunctionHandler(Node *n) { +    SwigType *t = Getattr(n, "type"); +    ParmList *l = Getattr(n, "parms"); +    String *tm; +    Parm *p; +    int i; +    String *imcall = NewString(""); +    String *return_type = NewString(""); +    String *function_code = NewString(""); +    int num_arguments = 0; +    String *overloaded_name = getOverloadedName(n); +    String *func_name = NULL; +    bool setter_flag = false; +    String *pre_code = NewString(""); +    String *post_code = NewString(""); + +    // Translate and write javadoc comment if flagged +    if (doxygen && doxygenTranslator->hasDocumentation(n)) { +      String *doxygen_comments = doxygenTranslator->getDocumentation(n, "  "); +      if (comment_creation_chatter) +	Printf(function_code, "/* This was generated from moduleClassFunctionHandler() */\n"); +      Printv(function_code, doxygen_comments, NIL); +      Delete(doxygen_comments); +    } + +    if (l) { +      if (SwigType_type(Getattr(l, "type")) == T_VOID) { +	l = nextSibling(l); +      } +    } + +    /* Attach the non-standard typemaps to the parameter list */ +    Swig_typemap_attach_parms("jstype", l, NULL); +    Swig_typemap_attach_parms("javain", l, NULL); + +    /* Get return types */ +    if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) { +      substituteClassname(t, tm); +      Printf(return_type, "%s", tm); +    } else { +      Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0)); +    } + +    /* Change function name for global variables */ +    if (proxy_flag && global_variable_flag) { +      // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name +      func_name = NewString(""); +      setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), variable_name)) == 0); +      if (setter_flag) +	Printf(func_name, "set"); +      else +	Printf(func_name, "get"); +      Putc(toupper((int) *Char(variable_name)), func_name); +      Printf(func_name, "%s", Char(variable_name) + 1); +    } else { +      func_name = Copy(Getattr(n, "sym:name")); +    } + +    /* Start generating the function */ +    const String *methodmods = Getattr(n, "feature:java:methodmodifiers"); +    methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string); +    Printf(function_code, "  %s static %s %s(", methodmods, return_type, func_name); +    Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL); + +    /* Get number of required and total arguments */ +    num_arguments = emit_num_arguments(l); + +    bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag); +    int gencomma = 0; + +    /* Output each parameter */ +    for (i = 0, p = l; i < num_arguments; i++) { + +      /* Ignored parameters */ +      while (checkAttribute(p, "tmap:in:numinputs", "0")) { +	p = Getattr(p, "tmap:in:next"); +      } + +      SwigType *pt = Getattr(p, "type"); +      String *param_type = NewString(""); + +      /* Get the Java parameter type */ +      if ((tm = Getattr(p, "tmap:jstype"))) { +	substituteClassname(pt, tm); +	Printf(param_type, "%s", tm); +      } else { +	Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0)); +      } + +      if (gencomma) +	Printf(imcall, ", "); + +      String *arg = makeParameterName(n, p, i, global_or_member_variable); + +      // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class) +      if ((tm = Getattr(p, "tmap:javain"))) { +	addThrows(n, "tmap:javain", p); +	substituteClassname(pt, tm); +	Replaceall(tm, "$javainput", arg); +	String *pre = Getattr(p, "tmap:javain:pre"); +	if (pre) { +	  substituteClassname(pt, pre); +	  Replaceall(pre, "$javainput", arg); +          if (Len(pre_code) > 0) +            Printf(pre_code, "\n"); +	  Printv(pre_code, pre, NIL); +	} +	String *post = Getattr(p, "tmap:javain:post"); +	if (post) { +	  substituteClassname(pt, post); +	  Replaceall(post, "$javainput", arg); +          if (Len(post_code) > 0) +            Printf(post_code, "\n"); +	  Printv(post_code, post, NIL); +	} +	Printv(imcall, tm, NIL); +      } else { +	Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0)); +      } + +      /* Add parameter to module class function */ +      if (gencomma >= 2) +	Printf(function_code, ", "); +      gencomma = 2; +      Printf(function_code, "%s %s", param_type, arg); + +      if (prematureGarbageCollectionPreventionParameter(pt, p)) { +        String *pgcppname = Getattr(p, "tmap:javain:pgcppname"); +        if (pgcppname) { +          String *argname = Copy(pgcppname); +          Replaceall(argname, "$javainput", arg); +          Printf(imcall, ", %s", argname); +          Delete(argname); +        } else { +          Printf(imcall, ", %s", arg); +        } +      } + +      p = Getattr(p, "tmap:in:next"); +      Delete(arg); +      Delete(param_type); +    } + +    Printf(imcall, ")"); +    Printf(function_code, ")"); + +    // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in module class) +    if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) { +      addThrows(n, "tmap:javaout", n); +      bool is_pre_code = Len(pre_code) > 0; +      bool is_post_code = Len(post_code) > 0; +      if (is_pre_code || is_post_code) { +        Replaceall(tm, "\n ", "\n   "); // add extra indentation to code in typemap +        if (is_post_code) { +          Insert(tm, 0, "\n    try "); +          Printv(tm, " finally {\n", post_code, "\n    }", NIL); +        } else { +          Insert(tm, 0, "\n    "); +        } +        if (is_pre_code) { +          Insert(tm, 0, pre_code); +          Insert(tm, 0, "\n"); +        } +	Insert(tm, 0, "{"); +	Printf(tm, "\n  }"); +      } +      if (GetFlag(n, "feature:new")) +	Replaceall(tm, "$owner", "true"); +      else +	Replaceall(tm, "$owner", "false"); +      substituteClassname(t, tm); +      Replaceall(tm, "$jnicall", imcall); +    } else { +      Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0)); +    } + +    generateThrowsClause(n, function_code); +    Printf(function_code, " %s\n\n", tm ? tm : empty_string); +    Printv(module_class_code, function_code, NIL); + +    Delete(pre_code); +    Delete(post_code); +    Delete(function_code); +    Delete(return_type); +    Delete(imcall); +    Delete(func_name); +  } + +  /*---------------------------------------------------------------------- +   * replaceSpecialVariables() +   *--------------------------------------------------------------------*/ + +  virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) { +    (void)method; +    SwigType *type = Getattr(parm, "type"); +    substituteClassname(type, tm); +  } + +  /*---------------------------------------------------------------------- +   * decodeEnumFeature() +   * Decode the possible enum features, which are one of: +   *   %javaenum(simple) +   *   %javaenum(typeunsafe) - default +   *   %javaenum(typesafe) +   *   %javaenum(proper) +   *--------------------------------------------------------------------*/ + +  EnumFeature decodeEnumFeature(Node *n) { +    EnumFeature enum_feature = TypeunsafeEnum; +    String *feature = Getattr(n, "feature:java:enum"); +    if (feature) { +      if (Cmp(feature, "simple") == 0) +	enum_feature = SimpleEnum; +      else if (Cmp(feature, "typesafe") == 0) +	enum_feature = TypesafeEnum; +      else if (Cmp(feature, "proper") == 0) +	enum_feature = ProperEnum; +    } +    return enum_feature; +  } + +  /* ----------------------------------------------------------------------- +   * enumValue() +   * This method will return a string with an enum value to use in Java generated +   * code. If the %javaconst feature is not used, the string will contain the intermediary +   * class call to obtain the enum value. The intermediary class and JNI methods to obtain +   * the enum value will be generated. Otherwise the C/C++ enum value will be used if there +   * is one and hopefully it will compile as Java code - e.g. 20 as in: enum E{e=20}; +   * The %javaconstvalue feature overrides all other ways to generate the constant value. +   * The caller must delete memory allocated for the returned string. +   * ------------------------------------------------------------------------ */ + +  String *enumValue(Node *n) { +    String *symname = Getattr(n, "sym:name"); + +    // Check for the %javaconstvalue feature +    String *value = Getattr(n, "feature:java:constvalue"); + +    if (!value) { +      // The %javaconst feature determines how the constant value is obtained +      int const_feature_flag = GetFlag(n, "feature:java:const"); + +      if (const_feature_flag) { +	// Use the C syntax to make a true Java constant and hope that it compiles as Java code +	value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex")); +      } else { +	String *newsymname = 0; +	if (!getCurrentClass() || !proxy_flag) { +	  String *enumClassPrefix = getEnumClassPrefix(); +	  if (enumClassPrefix) { +	    // A global scoped enum +	    newsymname = Swig_name_member(0, enumClassPrefix, symname); +	    symname = newsymname; +	  } +	} + +	// Get the enumvalue from a JNI call +	if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) { +	  // Strange hack to change the name +	  Setattr(n, "name", Getattr(n, "value"));	/* for wrapping of enums in a namespace when emit_action is used */ +	  constantWrapper(n); +	  value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname)); +	} else { +	  memberconstantHandler(n); +	  value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), Swig_name_member(0, getEnumClassPrefix(), symname))); +	} +	Delete(newsymname); +      } +    } +    return value; +  } + +  /* ----------------------------------------------------------------------------- +   * getEnumName() +   * +   * If jnidescriptor is set, inner class names are separated with '$' otherwise a '.' +   * and the package is also not added to the name. +   * ----------------------------------------------------------------------------- */ + +  String *getEnumName(SwigType *t, bool jnidescriptor) { +    Node *enumname = NULL; +    Node *n = enumLookup(t); +    if (n) { +      enumname = Getattr(n, "enumname"); +      if (!enumname || jnidescriptor) { +	String *symname = Getattr(n, "sym:name"); +	if (symname) { +	  // Add in class scope when referencing enum if not a global enum +	  String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name")); +	  String *proxyname = 0; +	  if (scopename_prefix) { +	    proxyname = getProxyName(scopename_prefix, jnidescriptor); +	  } +	  if (proxyname) { +	    const char *class_separator = jnidescriptor ? "$" : "."; +	    enumname = NewStringf("%s%s%s", proxyname, class_separator, symname); +	  } else { +	    // global enum or enum in a namespace +	    String *nspace = Getattr(n, "sym:nspace"); +	    if (nspace) { +	      if (package && !jnidescriptor) +		enumname = NewStringf("%s.%s.%s", package, nspace, symname); +	      else +		enumname = NewStringf("%s.%s", nspace, symname); +	    } else { +	      enumname = Copy(symname); +	    } +	  } +	  if (!jnidescriptor) { +	    Setattr(n, "enumname", enumname); // Cache it +	    Delete(enumname); +	  } +	  Delete(scopename_prefix); +	} +      } +    } + +    return enumname; +  } + +  /* ----------------------------------------------------------------------------- +   * substituteClassname() +   * +   * Substitute the special variable $javaclassname with the proxy class name for classes/structs/unions  +   * that SWIG knows about. Also substitutes enums with enum name. +   * Otherwise use the $descriptor name for the Java class name. Note that the $&javaclassname substitution +   * is the same as a $&descriptor substitution, ie one pointer added to descriptor name. +   * Note that the path separator is a '.' unless jnidescriptor is set. +   * Inputs: +   *   pt - parameter type +   *   tm - typemap contents that might contain the special variable to be replaced +   *   jnidescriptor - if set, inner class names are separated with '$' otherwise a '/' is used for the path separator +   * Outputs: +   *   tm - typemap contents complete with the special variable substitution +   * Return: +   *   substitution_performed - flag indicating if a substitution was performed +   * ----------------------------------------------------------------------------- */ + +  bool substituteClassname(SwigType *pt, String *tm, bool jnidescriptor = false) { +    bool substitution_performed = false; +    SwigType *type = Copy(SwigType_typedef_resolve_all(pt)); +    SwigType *strippedtype = SwigType_strip_qualifiers(type); + +    if (Strstr(tm, "$javaclassname")) { +      SwigType *classnametype = Copy(strippedtype); +      substituteClassnameSpecialVariable(classnametype, tm, "$javaclassname", jnidescriptor); +      substitution_performed = true; +      Delete(classnametype); +    } +    if (Strstr(tm, "$*javaclassname")) { +      SwigType *classnametype = Copy(strippedtype); +      Delete(SwigType_pop(classnametype)); +      if (Len(classnametype) > 0) { +	substituteClassnameSpecialVariable(classnametype, tm, "$*javaclassname", jnidescriptor); +	substitution_performed = true; +      } +      Delete(classnametype); +    } +    if (Strstr(tm, "$&javaclassname")) { +      SwigType *classnametype = Copy(strippedtype); +      SwigType_add_pointer(classnametype); +      substituteClassnameSpecialVariable(classnametype, tm, "$&javaclassname", jnidescriptor); +      substitution_performed = true; +      Delete(classnametype); +    } +    if (Strstr(tm, "$javainterfacename")) { +      SwigType *interfacenametype = Copy(strippedtype); +      substituteInterfacenameSpecialVariable(interfacenametype, tm, "$javainterfacename", jnidescriptor, true); +      substitution_performed = true; +      Delete(interfacenametype); +    } +    if (Strstr(tm, "$*javainterfacename")) { +      SwigType *interfacenametype = Copy(strippedtype); +      Delete(SwigType_pop(interfacenametype)); +      if (Len(interfacenametype) > 0) { +	substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*javainterfacename", jnidescriptor, true); +	substitution_performed = true; +      } +      Delete(interfacenametype); +    } +    if (Strstr(tm, "$&javainterfacename")) { +      SwigType *interfacenametype = Copy(strippedtype); +      SwigType_add_pointer(interfacenametype); +      substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&javainterfacename", jnidescriptor, true); +      substitution_performed = true; +      Delete(interfacenametype); +    } +    if (Strstr(tm, "$interfacename")) { +      SwigType *interfacenametype = Copy(strippedtype); +      substituteInterfacenameSpecialVariable(interfacenametype, tm, "$interfacename", jnidescriptor, false); +      substitution_performed = true; +      Delete(interfacenametype); +    } +    if (Strstr(tm, "$*interfacename")) { +      SwigType *interfacenametype = Copy(strippedtype); +      Delete(SwigType_pop(interfacenametype)); +      if (Len(interfacenametype) > 0) { +	substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*interfacename", jnidescriptor, false); +	substitution_performed = true; +      } +      Delete(interfacenametype); +    } +    if (Strstr(tm, "$&interfacename")) { +      SwigType *interfacenametype = Copy(strippedtype); +      SwigType_add_pointer(interfacenametype); +      substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&interfacename", jnidescriptor, false); +      substitution_performed = true; +      Delete(interfacenametype); +    } + +    Delete(strippedtype); +    Delete(type); + +    return substitution_performed; +  } + +  /* ----------------------------------------------------------------------------- +   * substituteClassnameSpecialVariable() +   * ----------------------------------------------------------------------------- */ + +  void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable, bool jnidescriptor) { +    String *replacementname; + +    if (SwigType_isenum(classnametype)) { +      String *enumname = getEnumName(classnametype, jnidescriptor); +      if (enumname) { +	replacementname = Copy(enumname); +      } else { +        bool anonymous_enum = (Cmp(classnametype, "enum ") == 0); +	if (anonymous_enum) { +	  replacementname = NewString("int"); +	} else { +	  // An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition) or an ignored enum +	  replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype)); +	  Replace(replacementname, "enum ", "", DOH_REPLACE_ANY); +	  Setattr(swig_types_hash, replacementname, classnametype); +	} +      } +    } else { +      String *classname = getProxyName(classnametype, jnidescriptor); // getProxyName() works for pointers to classes too +      if (classname) { +	replacementname = Copy(classname); +      } else { +	// use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved. +	replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype)); + +	// Add to hash table so that the type wrapper classes can be created later +	Setattr(swig_types_hash, replacementname, classnametype); +      } +    } +    if (jnidescriptor) +      Replaceall(replacementname,".","/"); +    Replaceall(tm, classnamespecialvariable, replacementname); + +    Delete(replacementname); +  } + +  /* ----------------------------------------------------------------------------- +   * substituteInterfacenameSpecialVariable() +   * ----------------------------------------------------------------------------- */ + +  void substituteInterfacenameSpecialVariable(SwigType *interfacenametype, String *tm, const char *interfacenamespecialvariable, bool jnidescriptor, bool qualified) { + +    String *interfacename = getInterfaceName(interfacenametype/*, jnidescriptor*/, qualified); +    if (interfacename) { +      String *replacementname = Copy(interfacename); + +      if (jnidescriptor) +	Replaceall(replacementname,".","/"); +      Replaceall(tm, interfacenamespecialvariable, replacementname); + +      Delete(replacementname); +    } +  } + +  /* ----------------------------------------------------------------------------- +   * emitTypeWrapperClass() +   * ----------------------------------------------------------------------------- */ + +  void emitTypeWrapperClass(String *classname, SwigType *type) { +    Node *n = NewHash(); +    Setfile(n, input_file); +    Setline(n, line_number); + +    String *swigtype = NewString(""); +    String *filen = NewStringf("%s%s.java", SWIG_output_directory(), classname); +    File *f_swigtype = NewFile(filen, "w", SWIG_output_files()); +    if (!f_swigtype) { +      FileErrorDisplay(filen); +      SWIG_exit(EXIT_FAILURE); +    } +    Append(filenames_list, Copy(filen)); +    Delete(filen); +    filen = NULL; + +    // Start writing out the type wrapper class file +    emitBanner(f_swigtype); + +    if (package) +      Printf(f_swigtype, "package %s;\n", package); + +    // Pure Java baseclass and interfaces +    const String *pure_baseclass = typemapLookup(n, "javabase", type, WARN_NONE); +    const String *pure_interfaces = typemapLookup(n, "javainterfaces", type, WARN_NONE); + +    // Emit the class +    Printv(swigtype, typemapLookup(n, "javaimports", type, WARN_NONE),	// Import statements +	   "\n", typemapLookup(n, "javaclassmodifiers", type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF),	// Class modifiers +	   " $javaclassname",	// Class name and bases +	   *Char(pure_baseclass) ? " extends " : "", pure_baseclass, *Char(pure_interfaces) ?	// Interfaces +	   " implements " : "", pure_interfaces, " {", typemapLookup(n, "javabody", type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF),	// main body of class +	   typemapLookup(n, "javacode", type, WARN_NONE),	// extra Java code +	   "}\n", "\n", NIL); + +    Replaceall(swigtype, "$javaclassname", classname); +    Replaceall(swigtype, "$module", module_class_name); +    Replaceall(swigtype, "$imclassname", imclass_name); + +    // For unknown enums +    Replaceall(swigtype, "$static ", ""); +    Replaceall(swigtype, "$enumvalues", ""); + +    Printv(f_swigtype, swigtype, NIL); + +    Delete(f_swigtype); +    Delete(swigtype); +    Delete(n); +  } + +  /* ----------------------------------------------------------------------------- +   * typemapLookup() +   * n - for input only and must contain info for Getfile(n) and Getline(n) to work +   * tmap_method - typemap method name +   * type - typemap type to lookup +   * warning - warning number to issue if no typemaps found +   * typemap_attributes - the typemap attributes are attached to this node and will  +   *   also be used for temporary storage if non null +   * return is never NULL, unlike Swig_typemap_lookup() +   * ----------------------------------------------------------------------------- */ + +  const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) { +    Node *node = !typemap_attributes ? NewHash() : typemap_attributes; +    Setattr(node, "type", type); +    Setfile(node, Getfile(n)); +    Setline(node, Getline(n)); +    const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0); +    if (!tm) { +      tm = empty_string; +      if (warning != WARN_NONE) +	Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0)); +    } +    if (!typemap_attributes) +      Delete(node); +    return tm; +  } + +  /* ----------------------------------------------------------------------------- +   * addThrows() +   * +   * Adds exception classes to a throws list. The throws list is the list of classes +   * that will form the Java throws clause. Mainly for checked exceptions. +   * ----------------------------------------------------------------------------- */ + +  void addThrows(Node *n, const String *attribute, Node *parameter) { +    // Get the comma separated exception classes for the throws clause - held in typemap/feature's "throws" attribute +    String *throws_attribute = NewStringf("%s:throws", attribute); +    String *throws = Getattr(parameter, throws_attribute); + +    if (throws && Len(throws) > 0) { +      String *throws_list = Getattr(n, "java:throwslist"); +      if (!throws_list) { +	throws_list = NewList(); +	Setattr(n, "java:throwslist", throws_list); +      } +      // Put the exception classes in the throws clause into a temporary List +      List *temp_classes_list = Split(throws, ',', INT_MAX); + +      // Add the exception classes to the node throws list, but don't duplicate if already in list +      if (temp_classes_list && Len(temp_classes_list) > 0) { +	for (Iterator cls = First(temp_classes_list); cls.item; cls = Next(cls)) { +	  String *exception_class = NewString(cls.item); +	  Replaceall(exception_class, " ", "");	// remove spaces +	  Replaceall(exception_class, "\t", "");	// remove tabs +	  if (Len(exception_class) > 0) { +	    // $javaclassname substitution +	    SwigType *pt = Getattr(parameter, "type"); +	    substituteClassname(pt, exception_class); + +	    // Don't duplicate the Java exception class in the throws clause +	    bool found_flag = false; +	    for (Iterator item = First(throws_list); item.item; item = Next(item)) { +	      if (Strcmp(item.item, exception_class) == 0) +		found_flag = true; +	    } +	    if (!found_flag) +	      Append(throws_list, exception_class); +	  } +	  Delete(exception_class); +	} +      } +      Delete(temp_classes_list); +    } +    Delete(throws_attribute); +  } + +  /* ----------------------------------------------------------------------------- +   * generateThrowsClause() +   * +   * Generates throws clause for checked exception +   * ----------------------------------------------------------------------------- */ + +  void generateThrowsClause(Node *n, String *code) { +    // Add the throws clause into code +    List *throws_list = Getattr(n, "java:throwslist"); +    if (throws_list) { +      Iterator cls = First(throws_list); +      Printf(code, " throws %s", cls.item); +      while ((cls = Next(cls)).item) +	Printf(code, ", %s", cls.item); +    } +  } + +  /* ----------------------------------------------------------------------------- +   * prematureGarbageCollectionPreventionParameter() +   * +   * Get the proxy class name for use in an additional generated parameter. The +   * additional parameter is added to a native method call purely to prevent  +   * premature garbage collection of proxy classes which pass their C++ class pointer +   * in a Java long to the JNI layer. +   * ----------------------------------------------------------------------------- */ + +  String *prematureGarbageCollectionPreventionParameter(SwigType *t, Parm *p) { +    String *pgcpp_java_type = 0; +    String *jtype = NewString(Getattr(p, "tmap:jtype")); + +    // Strip C comments +    String *stripped_jtype = Swig_strip_c_comments(jtype); +    if (stripped_jtype) { +      Delete(jtype); +      jtype = stripped_jtype; +    } + +    // Remove whitespace +    Replaceall(jtype, " ", ""); +    Replaceall(jtype, "\t", ""); + +    if (Cmp(jtype, "long") == 0) { +      if (proxy_flag) { +	if (!GetFlag(p, "tmap:jtype:nopgcpp") && !nopgcpp_flag) { +	  String *interface_name = getInterfaceName(t, true); +          pgcpp_java_type = interface_name ? interface_name : getProxyName(t); +          if (!pgcpp_java_type) { +            // Look for proxy class parameters passed to C++ layer using non-default typemaps, ie not one of above types +            String *jstype = NewString(Getattr(p, "tmap:jstype")); +            if (jstype) { +              Hash *classes = getClassHash(); +              if (classes) { +                // Strip C comments +                String *stripped_jstype = Swig_strip_c_comments(jstype); +                if (stripped_jstype) { +                  Delete(jstype); +                  jstype = stripped_jstype; +                } +                // Remove whitespace +                Replaceall(jstype, " ", ""); +                Replaceall(jstype, "\t", ""); + +                Iterator ki; +                for (ki = First(classes); ki.key; ki = Next(ki)) { +                  Node *cls = ki.item; +                  if (cls && !Getattr(cls, "feature:ignore")) { +                    String *symname = Getattr(cls, "sym:name"); +                    if (symname && Strcmp(symname, jstype) == 0) { +                      pgcpp_java_type = symname; +                    } +                  } +                } +              } +            } +            Delete(jstype); +          } +	} +      } +    } +    Delete(jtype); +    return pgcpp_java_type; +  } + +  /* ----------------------------------------------------------------------------- +   * outputDirectory() +   * +   * Return the directory to use for generating Java classes/enums and create the +   * subdirectory (does not create if language specific outdir does not exist). +   * ----------------------------------------------------------------------------- */ + +  String *outputDirectory(String *nspace) { +    String *output_directory = Copy(SWIG_output_directory()); +    if (nspace) { +      String *nspace_subdirectory = Copy(nspace); +      Replaceall(nspace_subdirectory, ".", SWIG_FILE_DELIMITER); +      String *newdir_error = Swig_new_subdirectory(output_directory, nspace_subdirectory); +      if (newdir_error) { +	Printf(stderr, "%s\n", newdir_error); +	Delete(newdir_error); +	SWIG_exit(EXIT_FAILURE); +      } +      Printv(output_directory, nspace_subdirectory, SWIG_FILE_DELIMITER, 0); +      Delete(nspace_subdirectory); +    } +    return output_directory; +  } + +  /*---------------------------------------------------------------------- +   * Start of director methods +   *--------------------------------------------------------------------*/ + +  /*---------------------------------------------------------------------- +   * getUpcallJNIMethod() +   *--------------------------------------------------------------------*/ + +  String *getUpcallJNIMethod(String *descrip) { +    static struct { +      char code; +      const char *method; +    } upcall_methods[] = { +      { +      'B', "CallStaticByteMethod"}, { +      'C', "CallStaticCharMethod"}, { +      'D', "CallStaticDoubleMethod"}, { +      'F', "CallStaticFloatMethod"}, { +      'I', "CallStaticIntMethod"}, { +      'J', "CallStaticLongMethod"}, { +      'L', "CallStaticObjectMethod"}, { +      'S', "CallStaticShortMethod"}, { +      'V', "CallStaticVoidMethod"}, { +      'Z', "CallStaticBooleanMethod"}, { +      '[', "CallStaticObjectMethod"} +    }; + +    char code; +    int i; + +    code = *Char(descrip); +    for (i = 0; i < (int) (sizeof(upcall_methods) / sizeof(upcall_methods[0])); ++i) +      if (code == upcall_methods[i].code) +	return NewString(upcall_methods[i].method); +    return NULL; +  } + +  /*---------------------------------------------------------------------- +   * emitDirectorUpcalls() +   *--------------------------------------------------------------------*/ + +  void emitDirectorUpcalls() { +    if (n_dmethods) { +      Wrapper *w = NewWrapper(); +      String *jni_imclass_name = makeValidJniName(imclass_name); +      String *swig_module_init = NewString("swig_module_init"); +      String *swig_module_init_jni = makeValidJniName(swig_module_init); +      String *dmethod_data = NewString(""); +      int n_methods = 0; +      Iterator udata_iter; + +      udata_iter = First(dmethods_seq); +      while (udata_iter.item) { +	UpcallData *udata = udata_iter.item; +	Printf(dmethod_data, "  { \"%s\", \"%s\" }", Getattr(udata, "imclass_method"), Getattr(udata, "imclass_fdesc")); +	++n_methods; + +	udata_iter = Next(udata_iter); + +	if (udata_iter.item) +	  Putc(',', dmethod_data); +	Putc('\n', dmethod_data); +      } + +      Printf(f_runtime, "namespace Swig {\n"); +      Printf(f_runtime, "  namespace {\n"); +      Printf(f_runtime, "    jclass jclass_%s = NULL;\n", imclass_name); +      Printf(f_runtime, "    jmethodID director_method_ids[%d];\n", n_methods); +      Printf(f_runtime, "  }\n"); +      Printf(f_runtime, "}\n"); + +      Printf(w->def, "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls) {", jnipackage, jni_imclass_name, swig_module_init_jni); +      Printf(w->code, "static struct {\n"); +      Printf(w->code, "  const char *method;\n"); +      Printf(w->code, "  const char *signature;\n"); +      Printf(w->code, "} methods[%d] = {\n", n_methods); +      Printv(w->code, dmethod_data, NIL); +      Printf(w->code, "};\n"); + +      Wrapper_add_local(w, "i", "int i"); + +      Printf(w->code, "Swig::jclass_%s = (jclass) jenv->NewGlobalRef(jcls);\n", imclass_name); +      Printf(w->code, "if (!Swig::jclass_%s) return;\n", imclass_name); +      Printf(w->code, "for (i = 0; i < (int) (sizeof(methods)/sizeof(methods[0])); ++i) {\n"); +      Printf(w->code, "  Swig::director_method_ids[i] = jenv->GetStaticMethodID(jcls, methods[i].method, methods[i].signature);\n"); +      Printf(w->code, "  if (!Swig::director_method_ids[i]) return;\n"); +      Printf(w->code, "}\n"); + +      Printf(w->code, "}\n"); + +      Wrapper_print(w, f_wrappers); +      Delete(dmethod_data); +      Delete(swig_module_init_jni); +      Delete(swig_module_init); +      Delete(jni_imclass_name); +      DelWrapper(w); +    } +  } + +  /*---------------------------------------------------------------------- +   * emitDirectorExtraMethods() +   * +   * This is where the director connect method is generated. +   *--------------------------------------------------------------------*/ +  void emitDirectorExtraMethods(Node *n) { +    if (!Swig_directorclass(n)) +      return; + +    // Output the director connect method: +    String *jni_imclass_name = makeValidJniName(imclass_name); +    String *norm_name = SwigType_namestr(Getattr(n, "name")); +    String *swig_director_connect = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect"); +    String *swig_director_connect_jni = makeValidJniName(swig_director_connect); +    String *smartptr = Getattr(n, "feature:smartptr"); +    String *dirClassName = directorClassName(n); +    Wrapper *code_wrap; + +    Printf(imclass_class_code, "  public final static native void %s(%s obj, long cptr, boolean mem_own, boolean weak_global);\n", +	   swig_director_connect, full_proxy_class_name); + +    code_wrap = NewWrapper(); +    Printf(code_wrap->def, +	   "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jswig_mem_own, " +	   "jboolean jweak_global) {\n", jnipackage, jni_imclass_name, swig_director_connect_jni); + +    if (smartptr) { +      Printf(code_wrap->code, "  %s *obj = *((%s **)&objarg);\n", smartptr, smartptr); +      Printf(code_wrap->code, "  (void)jcls;\n"); +      Printf(code_wrap->code, "  // Keep a local instance of the smart pointer around while we are using the raw pointer\n"); +      Printf(code_wrap->code, "  // Avoids using smart pointer specific API.\n"); +      Printf(code_wrap->code, "  %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); +    } +    else { +      Printf(code_wrap->code, "  %s *obj = *((%s **)&objarg);\n", norm_name, norm_name); +      Printf(code_wrap->code, "  (void)jcls;\n"); +      Printf(code_wrap->code, "  %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);  +    } + +    Printf(code_wrap->code, "  director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), " +	   "(jswig_mem_own == JNI_TRUE), (jweak_global == JNI_TRUE));\n"); +    Printf(code_wrap->code, "}\n"); + +    Wrapper_print(code_wrap, f_wrappers); +    DelWrapper(code_wrap); + +    Delete(swig_director_connect_jni); +    Delete(swig_director_connect); + +    // Output the swigReleaseOwnership, swigTakeOwnership methods: +    String *changeown_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "change_ownership"); +    String *changeown_jnimethod_name = makeValidJniName(changeown_method_name); + +    Printf(imclass_class_code, "  public final static native void %s(%s obj, long cptr, boolean take_or_release);\n", changeown_method_name, full_proxy_class_name); + +    code_wrap = NewWrapper(); +    Printf(code_wrap->def, +	   "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jtake_or_release) {\n", +	   jnipackage, jni_imclass_name, changeown_jnimethod_name); + +    if (Len(smartptr)) { +        Printf(code_wrap->code, "  %s *obj = *((%s **)&objarg);\n", smartptr, smartptr); +        Printf(code_wrap->code, "  // Keep a local instance of the smart pointer around while we are using the raw pointer\n"); +        Printf(code_wrap->code, "  // Avoids using smart pointer specific API.\n"); +        Printf(code_wrap->code, "  %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName); +    } else { +        Printf(code_wrap->code, "  %s *obj = *((%s **)&objarg);\n", norm_name, norm_name); +        Printf(code_wrap->code, "  %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName); +    } + +    Printf(code_wrap->code, "  (void)jcls;\n"); +    Printf(code_wrap->code, "  if (director) {\n"); +    Printf(code_wrap->code, "    director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n"); +    Printf(code_wrap->code, "  }\n"); +    Printf(code_wrap->code, "}\n"); + +    Wrapper_print(code_wrap, f_wrappers); +    DelWrapper(code_wrap); + +    Delete(changeown_method_name); +    Delete(changeown_jnimethod_name); +    Delete(norm_name); +    Delete(dirClassName); +    Delete(jni_imclass_name); +  } + +  /*---------------------------------------------------------------------- +   * emitCodeTypemap() +   * +   * Output a code typemap that uses $methodname and $jnicall, as used +   * in the directordisconnect, director_release and director_take +   * typemaps. +   *--------------------------------------------------------------------*/ + +  void emitCodeTypemap(Node *n, bool derived, SwigType *lookup_type, const String *typemap, const String *methodname, const String *jnicall) { +    const String *tm = NULL; +    Node *tmattrs = NewHash(); +    String *lookup_tmname = NewString(typemap); +    String *method_attr_name; +    String *method_attr; + +    if (derived) { +      Append(lookup_tmname, "_derived"); +    } + +    tm = typemapLookup(n, lookup_tmname, lookup_type, WARN_NONE, tmattrs); +    method_attr_name = NewStringf("tmap:%s:%s", lookup_tmname, methodname); +    method_attr = Getattr(tmattrs, method_attr_name); + +    if (*Char(tm)) { +      if (method_attr) { +	String *codebody = Copy(tm); +	Replaceall(codebody, "$methodname", method_attr); +	Replaceall(codebody, "$jnicall", jnicall); +	Append(proxy_class_def, codebody); +	Delete(codebody); +      } else { +	Swig_error(input_file, line_number, "No %s method name attribute for %s\n", lookup_tmname, proxy_class_name); +      } +    } else { +      Swig_error(input_file, line_number, "No %s typemap for %s\n", lookup_tmname, proxy_class_name); +    } + +    Delete(tmattrs); +    Delete(lookup_tmname); +    // Delete(method_attr); +  } + +  /* ----------------------------------------------------------------------------- +   * substitutePackagePath() +   * +   * Replace $packagepath using the javapackage typemap associated with passed +   * parm or global package if p is 0. "$packagepath/" is replaced with "" if +   * no package is set. Note that the path separator is a '/'. +   * ----------------------------------------------------------------------------- */ + +  void substitutePackagePath(String *text, Parm *p) { +    String *pkg_path= 0; + +    if (p) +      pkg_path = Swig_typemap_lookup("javapackage", p, "", 0); +    if (!pkg_path || Len(pkg_path) == 0) +      pkg_path = Copy(package_path); + +    if (Len(pkg_path) > 0) { +      Replaceall(pkg_path, ".", "/"); +      Replaceall(text, "$packagepath", pkg_path); +    } else { +      Replaceall(text, "$packagepath/", empty_string); +      Replaceall(text, "$packagepath", empty_string); +    } +    Delete(pkg_path); +  } + +  /* --------------------------------------------------------------- +   * Canonicalize the JNI field descriptor +   * +   * Replace the $packagepath and $javaclassname family of special +   * variables with the desired package and Java proxy name as  +   * required in the JNI field descriptors. +   *  +   * !!SFM!! If $packagepath occurs in the field descriptor, but +   * package_path isn't set (length == 0), then strip it and the +   * optional trailing '/' from the resulting name. +   *  +   * --------------------------------------------------------------- */ + +  String *canonicalizeJNIDescriptor(String *descriptor_in, Parm *p) { +    SwigType *type = Getattr(p, "type"); +    String *descriptor_out = Copy(descriptor_in); + +    substituteClassname(type, descriptor_out, true); +    substitutePackagePath(descriptor_out, p); + +    return descriptor_out; +  } + +  /* --------------------------------------------------------------- +   * classDirectorMethod() +   * +   * Emit a virtual director method to pass a method call on to the  +   * underlying Java object. +   * +   * --------------------------------------------------------------- */ + +  int classDirectorMethod(Node *n, Node *parent, String *super) { +    String *c_classname = Getattr(parent, "name"); +    String *name = Getattr(n, "name"); +    String *symname = Getattr(n, "sym:name"); +    SwigType *returntype = Getattr(n, "type"); +    String *overloaded_name = getOverloadedName(n); +    String *storage = Getattr(n, "storage"); +    String *value = Getattr(n, "value"); +    String *decl = Getattr(n, "decl"); +    String *declaration = NewString(""); +    String *tm; +    Parm *p; +    int i; +    Wrapper *w = NewWrapper(); +    ParmList *l = Getattr(n, "parms"); +    bool is_void = !(Cmp(returntype, "void")); +    String *qualified_return = 0; +    bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0"))); +    int status = SWIG_OK; +    bool output_director = true; +    String *dirclassname = directorClassName(parent); +    String *qualified_name = NewStringf("%s::%s", dirclassname, name); +    String *jnidesc = NewString(""); +    String *classdesc = NewString(""); +    String *jniret_desc = NewString(""); +    String *classret_desc = NewString(""); +    SwigType *c_ret_type = NULL; +    String *jupcall_args = NewString("swigjobj"); +    String *imclass_dmethod; +    String *callback_def = NewString(""); +    String *callback_code = NewString(""); +    String *imcall_args = NewString(""); +    int classmeth_off = curr_class_dmethod - first_class_dmethod; +    bool ignored_method = GetFlag(n, "feature:ignore") ? true : false; +    String *qualified_classname = getProxyName(getClassName()); + +    // Kludge Alert: functionWrapper sets sym:overload properly, but it +    // isn't at this point, so we have to manufacture it ourselves. At least +    // we're consistent with the sym:overload name in functionWrapper. (?? when +    // does the overloaded method name get set?) + +    imclass_dmethod = NewStringf("%s", Swig_name_member(getNSpace(), dirclassname, overloaded_name)); + +    qualified_return = SwigType_rcaststr(returntype, "c_result"); + +    if (!is_void && (!ignored_method || pure_virtual)) { +      if (!SwigType_isclass(returntype)) { +	if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) { +	  String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0)); +	  Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL); +	  Delete(construct_result); +	} else { +	  String *base_typename = SwigType_base(returntype); +	  String *resolved_typename = SwigType_typedef_resolve_all(base_typename); +	  Symtab *symtab = Getattr(n, "sym:symtab"); +	  Node *typenode = Swig_symbol_clookup(resolved_typename, symtab); + +	  if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstracts"))) { +	    /* initialize pointers to something sane. Same for abstract +	       classes when a reference is returned. */ +	    Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL); +	  } else { +	    /* If returning a reference, initialize the pointer to a sane +	       default - if a Java exception occurs, then the pointer returns +	       something other than a NULL-initialized reference. */ +	    SwigType *noref_type = SwigType_del_reference(Copy(returntype)); +	    String *noref_ltype = SwigType_lstr(noref_type, 0); +	    String *return_ltype = SwigType_lstr(returntype, 0); + +	    Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL); +	    Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL); +	    Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype); +	    Printf(w->code, "c_result = &result_default;\n"); +	    Delete(return_ltype); +	    Delete(noref_ltype); +	    Delete(noref_type); +	  } + +	  Delete(base_typename); +	  Delete(resolved_typename); +	} +      } else { +	SwigType *vt; + +	vt = cplus_value_type(returntype); +	if (!vt) { +	  Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL); +	} else { +	  Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL); +	  Delete(vt); +	} +      } +    } + +    /* Create the intermediate class wrapper */ +    tm = Swig_typemap_lookup("jtype", n, "", 0); +    if (tm) { +      Printf(callback_def, "  public static %s %s(%s jself", tm, imclass_dmethod, qualified_classname); +    } else { +      Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(returntype, 0)); +    } + +    String *cdesc = NULL; +    SwigType *covariant = Getattr(n, "covariant"); +    SwigType *adjustedreturntype = covariant ? covariant : returntype; +    Parm *adjustedreturntypeparm = NewParmNode(adjustedreturntype, n); + +    if (Swig_typemap_lookup("directorin", adjustedreturntypeparm, "", 0) +	&& (cdesc = Getattr(adjustedreturntypeparm, "tmap:directorin:descriptor"))) { + +      // Note that in the case of polymorphic (covariant) return types, the +      // method's return type is changed to be the base of the C++ return +      // type +      String *jnidesc_canon = canonicalizeJNIDescriptor(cdesc, adjustedreturntypeparm); +      Append(classret_desc, jnidesc_canon); +      Delete(jnidesc_canon); +    } else { +      Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",  +	  SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); +      output_director = false; +    } + +    /* Get the JNI field descriptor for this return type, add the JNI field descriptor +       to jniret_desc */ +    if ((c_ret_type = Swig_typemap_lookup("jni", n, "", 0))) { +      Parm *tp = NewParmNode(c_ret_type, n); + +      if (!is_void && !ignored_method) { +	String *jretval_decl = NewStringf("%s jresult", c_ret_type); +	Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL); +	Delete(jretval_decl); +      } + +      String *jdesc = NULL; +      if (Swig_typemap_lookup("directorin", tp, "", 0) +	  && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) { + +	// Objects marshalled passing a Java class across JNI boundary use jobject - the nouse flag indicates this +	// We need the specific Java class name instead of the generic 'Ljava/lang/Object;' +	if (GetFlag(tp, "tmap:directorin:nouse")) +	  jdesc = cdesc; +	String *jnidesc_canon = canonicalizeJNIDescriptor(jdesc, tp); +	Append(jniret_desc, jnidesc_canon); +	Delete(jnidesc_canon); +      } else { +	Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, +		     "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",  +		     SwigType_str(c_ret_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); +	output_director = false; +      } + +      Delete(tp); +    } else { +      Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n",  +	  SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); +      output_director = false; +    } + +    Delete(adjustedreturntypeparm); + +    Swig_director_parms_fixup(l); + +    /* Attach the standard typemaps */ +    Swig_typemap_attach_parms("out", l, 0); +    Swig_typemap_attach_parms("jni", l, 0); +    Swig_typemap_attach_parms("jtype", l, 0); +    Swig_typemap_attach_parms("directorin", l, w); +    Swig_typemap_attach_parms("javadirectorin", l, 0); +    Swig_typemap_attach_parms("directorargout", l, w); + +    if (!ignored_method) { +      /* Add Java environment pointer to wrapper */ +      String *jenvstr = NewString("jenv"); +      String *jobjstr = NewString("swigjobj"); + +      Wrapper_add_localv(w, "swigjnienv", "JNIEnvWrapper", "swigjnienv(this)", NIL, NIL); +      Wrapper_add_localv(w, jenvstr, "JNIEnv *", jenvstr, "= swigjnienv.getJNIEnv()", NIL); +      Wrapper_add_localv(w, jobjstr, "jobject", jobjstr, "= (jobject) NULL", NIL); +      Delete(jenvstr); +      Delete(jobjstr); + +      /* Preamble code */ +      Printf(w->code, "if (!swig_override[%d]) {\n", classmeth_off); +    } + +    if (!pure_virtual) { +      String *super_call = Swig_method_call(super, l); +      if (is_void) { +	Printf(w->code, "%s;\n", super_call); +	if (!ignored_method) +	  Printf(w->code, "return;\n"); +      } else { +	Printf(w->code, "return %s;\n", super_call); +      } +      Delete(super_call); +    } else { +      Printf(w->code, "SWIG_JavaThrowException(JNIEnvWrapper(this).getJNIEnv(), SWIG_JavaDirectorPureVirtual, "); +      Printf(w->code, "\"Attempted to invoke pure virtual method %s::%s.\");\n", SwigType_namestr(c_classname), SwigType_namestr(name)); + +      /* Make sure that we return something in the case of a pure +       * virtual method call for syntactical reasons. */ +      if (!is_void) +	Printf(w->code, "return %s;", qualified_return); +      else if (!ignored_method) +	Printf(w->code, "return;\n"); +    } + +    if (!ignored_method) { +      Printf(w->code, "}\n"); +      Printf(w->code, "swigjobj = swig_get_self(jenv);\n"); +      Printf(w->code, "if (swigjobj && jenv->IsSameObject(swigjobj, NULL) == JNI_FALSE) {\n"); +    } + +    /* Start the Java field descriptor for the intermediate class's upcall (insert jself object) */ +    Parm *tp = NewParmNode(c_classname, n); +    String *jdesc; + +    if ((tm = Swig_typemap_lookup("directorin", tp, "", 0)) +	&& (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) { +      String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp); +      Append(jnidesc, jni_canon); +      Delete(jni_canon); +      Delete(tm); +    } else { +      Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number, +		   "No or improper directorin typemap for type %s  for use in %s::%s (skipping director method)\n",  +		   SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); +      output_director = false; +    } + +    Delete(tp); + +    /* Go through argument list, convert from native to Java */ +    for (i = 0, p = l; p; ++i) { +      /* Is this superfluous? */ +      while (checkAttribute(p, "tmap:directorin:numinputs", "0")) { +	p = Getattr(p, "tmap:directorin:next"); +      } + +      SwigType *pt = Getattr(p, "type"); +      String *ln = makeParameterName(n, p, i, false); +      String *c_param_type = NULL; +      String *c_decl = NewString(""); +      String *arg = NewString(""); + +      Printf(arg, "j%s", ln); + +      /* Add various typemap's 'throws' clauses */ +      addThrows(n, "tmap:directorin", p); +      addThrows(n, "tmap:out", p); + +      /* And add to the upcall args */ +      Printf(jupcall_args, ", %s", arg); + +      /* Get parameter's intermediary C type */ +      if ((c_param_type = Getattr(p, "tmap:jni"))) { +	Parm *tp = NewParm(c_param_type, Getattr(p, "name"), n); +	String *desc_tm = NULL, *jdesc = NULL, *cdesc = NULL; + +	/* Add to local variables */ +	Printf(c_decl, "%s %s", c_param_type, arg); +	if (!ignored_method) +	  Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL); + +	/* Add input marshalling code and update JNI field descriptor */ +	if ((desc_tm = Swig_typemap_lookup("directorin", tp, "", 0)) +	    && (jdesc = Getattr(tp, "tmap:directorin:descriptor")) +	    && (tm = Getattr(p, "tmap:directorin")) +	    && (cdesc = Getattr(p, "tmap:directorin:descriptor"))) { + +	  // Objects marshalled by passing a Java class across the JNI boundary use jobject as the JNI type -  +	  // the nouse flag indicates this. We need the specific Java class name instead of the generic 'Ljava/lang/Object;' +	  if (GetFlag(tp, "tmap:directorin:nouse")) +	    jdesc = cdesc; +	  String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp); +	  Append(jnidesc, jni_canon); +	  Delete(jni_canon); + +	  Setattr(p, "emit:directorinput", arg); +	  Replaceall(tm, "$input", arg); +	  Replaceall(tm, "$owner", "0"); + +	  if (Len(tm)) +	    if (!ignored_method) +	      Printf(w->code, "%s\n", tm); + +	  /* Add parameter to the intermediate class code if generating the +	   * intermediate's upcall code */ +	  if ((tm = Getattr(p, "tmap:jtype"))) { +	    String *din = Copy(Getattr(p, "tmap:javadirectorin")); +            addThrows(n, "tmap:javadirectorin", p); + +	    if (din) { +	      Replaceall(din, "$module", module_class_name); +	      Replaceall(din, "$imclassname", imclass_name); +	      substituteClassname(pt, din); +	      Replaceall(din, "$jniinput", ln); + +	      if (i > 0) +		Printf(imcall_args, ", "); +	      Printf(callback_def, ", %s %s", tm, ln); + +	      if (Cmp(din, ln)) { +		Printv(imcall_args, din, NIL); +	      } else +		Printv(imcall_args, ln, NIL); + +	      jni_canon = canonicalizeJNIDescriptor(cdesc, p); +	      Append(classdesc, jni_canon); +	      Delete(jni_canon); +	    } else { +	      Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number, "No javadirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",  +		  SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); +	      output_director = false; +	    } +	  } else { +	    Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s for use in %s::%s (skipping director method)\n",  +		SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); +	    output_director = false; +	  } + +	  p = Getattr(p, "tmap:directorin:next"); + +	  Delete(desc_tm); +	} else { +	  if (!desc_tm) { +	    Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number, +			 "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",  +			 SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); +	    p = nextSibling(p); +	  } else if (!jdesc) { +	    Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number, +			 "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n",  +			 SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); +	    p = Getattr(p, "tmap:directorin:next"); +	  } else if (!tm) { +	    Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number, +			 "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",  +			 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); +	    p = nextSibling(p); +	  } else if (!cdesc) { +	    Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number, +			 "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n",  +			 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); +	    p = Getattr(p, "tmap:directorin:next"); +	  } + +	  output_director = false; +	} + +      } else { +	Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s for use in %s::%s (skipping director method)\n",  +	    SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); +	output_director = false; +	p = nextSibling(p); +      } + +      Delete(arg); +      Delete(c_decl); +      Delete(ln); +    } + +    /* header declaration, start wrapper definition */ +    String *target; +    SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type"); +    target = Swig_method_decl(rtype, decl, qualified_name, l, 0); +    Printf(w->def, "%s", target); +    Delete(qualified_name); +    Delete(target); +    target = Swig_method_decl(rtype, decl, name, l, 1); +    Printf(declaration, "    virtual %s", target); +    Delete(target); + +    // Add any exception specifications to the methods in the director class +    // Get any Java exception classes in the throws typemap +    ParmList *throw_parm_list = NULL; + +    // May need to add Java throws clause to director methods if %catches defined +    // Get any Java exception classes in the throws typemap +    ParmList *catches_list = Getattr(n, "catchlist"); +    if (catches_list) { +      Swig_typemap_attach_parms("throws", catches_list, 0); +      Swig_typemap_attach_parms("directorthrows", catches_list, 0); +      for (p = catches_list; p; p = nextSibling(p)) { +	addThrows(n, "tmap:throws", p); +      } +    } + +    if (Getattr(n, "noexcept")) { +      Append(w->def, " noexcept"); +      Append(declaration, " noexcept"); +    } +    if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) { +      int gencomma = 0; + +      Append(w->def, " throw("); +      Append(declaration, " throw("); + +      if (throw_parm_list) { +	Swig_typemap_attach_parms("throws", throw_parm_list, 0); +	Swig_typemap_attach_parms("directorthrows", throw_parm_list, 0); +      } +      for (p = throw_parm_list; p; p = nextSibling(p)) { +	if (Getattr(p, "tmap:throws")) { +	  // %catches replaces the specified exception specification +	  if (!catches_list) { +	    addThrows(n, "tmap:throws", p); +	  } + +	  if (gencomma++) { +	    Append(w->def, ", "); +	    Append(declaration, ", "); +	  } + +	  Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0)); +	  Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0)); +	} +      } + +      Append(w->def, ")"); +      Append(declaration, ")"); +    } + +    Append(w->def, " {"); +    Append(declaration, ";\n"); + +    /* Emit the intermediate class's upcall to the actual class */ + +    String *upcall = NewStringf("jself.%s(%s)", symname, imcall_args); + +    // Handle exception classes specified in the "except" feature's "throws" attribute +    addThrows(n, "feature:except", n); + +    if (!is_void) { +      if ((tm = Swig_typemap_lookup("javadirectorout", n, "", 0))) { +        addThrows(n, "tmap:javadirectorout", n); +	substituteClassname(returntype, tm); +	Replaceall(tm, "$javacall", upcall); + +	Printf(callback_code, "    return %s;\n", tm); +      } + +      if ((tm = Swig_typemap_lookup("out", n, "", 0))) +        addThrows(n, "tmap:out", n); + +      Delete(tm); +    } else +      Printf(callback_code, "    %s;\n", upcall); + +    Printf(callback_code, "  }\n"); +    Delete(upcall); + +    /* Finish off the inherited upcall's definition */ +    Putc(')', callback_def); +    generateThrowsClause(n, callback_def); +    Printf(callback_def, " {\n"); + +    if (!ignored_method) { +      /* Emit the actual upcall through */ +      String *imclass_desc = NewStringf("(%s)%s", jnidesc, jniret_desc); +      String *class_desc = NewStringf("(%s)%s", classdesc, classret_desc); +      UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, imclass_desc, class_desc, decl); +      String *methid = Getattr(udata, "imclass_methodidx"); +      String *methop = getUpcallJNIMethod(jniret_desc); + +      if (!is_void) +	Printf(w->code, "jresult = (%s) ", c_ret_type); + +      Printf(w->code, "jenv->%s(Swig::jclass_%s, Swig::director_method_ids[%s], %s);\n", methop, imclass_name, methid, jupcall_args); + +      // Generate code to handle any Java exception thrown by director delegation +      directorExceptHandler(n, catches_list ? catches_list : throw_parm_list, w); + +      if (!is_void) { +	String *jresult_str = NewString("jresult"); +	String *result_str = NewString("c_result"); + +	/* Copy jresult into c_result... */ +	if ((tm = Swig_typemap_lookup("directorout", n, result_str, w))) { +	  addThrows(n, "tmap:directorout", n); +	  Replaceall(tm, "$input", jresult_str); +	  Replaceall(tm, "$result", result_str); +	  Printf(w->code, "%s\n", tm); +	} else { +	  Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number, +		       "Unable to use return type %s used in %s::%s (skipping director method)\n",  +		       SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name)); +	  output_director = false; +	} + +	Delete(jresult_str); +	Delete(result_str); +      } + +      /* Marshal outputs */ +      for (p = l; p;) { +	if ((tm = Getattr(p, "tmap:directorargout"))) { +	  addThrows(n, "tmap:directorargout", p); +	  Replaceall(tm, "$result", makeParameterName(n, p, i, false)); +	  Replaceall(tm, "$input", Getattr(p, "emit:directorinput")); +	  Printv(w->code, tm, "\n", NIL); +	  p = Getattr(p, "tmap:directorargout:next"); +	} else { +	  p = nextSibling(p); +	} +      } + +      Delete(imclass_desc); +      Delete(class_desc); + +      /* Terminate wrapper code */ +      Printf(w->code, "} else {\n"); +      Printf(w->code, "SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, \"null upcall object in %s::%s \");\n", +	     SwigType_namestr(c_classname), SwigType_namestr(name)); +      Printf(w->code, "}\n"); + +      Printf(w->code, "if (swigjobj) jenv->DeleteLocalRef(swigjobj);\n"); + +      if (!is_void) +	Printf(w->code, "return %s;", qualified_return); +    } + +    Printf(w->code, "}"); + +    // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method +    String *inline_extra_method = NewString(""); +    if (dirprot_mode() && !is_public(n) && !pure_virtual) { +      Printv(inline_extra_method, declaration, NIL); +      String *extra_method_name = NewStringf("%sSwigPublic", name); +      Replaceall(inline_extra_method, name, extra_method_name); +      Replaceall(inline_extra_method, ";\n", " {\n      "); +      if (!is_void) +	Printf(inline_extra_method, "return "); +      String *methodcall = Swig_method_call(super, l); +      Printv(inline_extra_method, methodcall, ";\n    }\n", NIL); +      Delete(methodcall); +      Delete(extra_method_name); +    } + +    /* emit the director method */ +    if (status == SWIG_OK && output_director) { +      if (!is_void) { +	Replaceall(w->code, "$null", qualified_return); +      } else { +	Replaceall(w->code, "$null", ""); +      } +      if (!GetFlag(n, "feature:ignore")) +	Printv(imclass_directors, callback_def, callback_code, NIL); +      if (!Getattr(n, "defaultargs")) { +	Replaceall(w->code, "$symname", symname); +	Wrapper_print(w, f_directors); +	Printv(f_directors_h, declaration, NIL); +	Printv(f_directors_h, inline_extra_method, NIL); +      } +    } + +    Delete(inline_extra_method); +    Delete(qualified_return); +    Delete(jnidesc); +    Delete(c_ret_type); +    Delete(jniret_desc); +    Delete(declaration); +    Delete(callback_def); +    Delete(callback_code); +    DelWrapper(w); + +    return status; +  } + +  /* ------------------------------------------------------------ +   * directorExceptHandler() +   * +   * Emit code to map Java exceptions back to C++ exceptions when +   * feature("director:except") is applied to a method node. +   * This is generated after the Java method upcall. +   * ------------------------------------------------------------ */ + +  void directorExceptHandler(Node *n, ParmList *throw_parm_list, Wrapper *w) { + +    String *directorexcept = Getattr(n, "feature:director:except"); +    if (!directorexcept) { +      directorexcept = NewString(""); +      Printf(directorexcept, "jthrowable $error = jenv->ExceptionOccurred();\n"); +      Printf(directorexcept, "if ($error) {"); +      Printf(directorexcept, "$directorthrowshandlers\n"); +      Printf(directorexcept, "  Swig::DirectorException::raise(jenv, $error);\n"); +      Printf(directorexcept, "}\n"); +    } else { +      directorexcept = Copy(directorexcept); +    } + +    // Can explicitly disable director:except by setting to "" or "0" +    if (Len(directorexcept) > 0 && Cmp(directorexcept, "0") != 0) { + +      // Replace $packagepath +      substitutePackagePath(directorexcept, 0); + +      // Replace $directorthrowshandlers with any defined typemap handlers (or nothing) +      if (Strstr(directorexcept, "$directorthrowshandlers")) { +	String *directorthrowshandlers_code = NewString(""); + +	for (Parm *p = throw_parm_list; p; p = nextSibling(p)) { +	  String *tm = Getattr(p, "tmap:directorthrows"); + +	  if (tm) { +	    // replace $packagepath/$javaclassname +	    String *directorthrows = canonicalizeJNIDescriptor(tm, p); +	    Printv(directorthrowshandlers_code, directorthrows, NIL); +	    Delete(directorthrows); +	  } else { +	    String *t = Getattr(p,"type"); +	    Swig_warning(WARN_TYPEMAP_DIRECTORTHROWS_UNDEF, Getfile(n), Getline(n), "No directorthrows typemap defined for %s\n", SwigType_str(t, 0)); +	  } +	} +	Replaceall(directorexcept, "$directorthrowshandlers", directorthrowshandlers_code); +	Delete(directorthrowshandlers_code); +      } + +      Replaceall(directorexcept, "$error", "swigerror"); +      Printf(w->code, "    %s\n", directorexcept); +    } +    Delete(directorexcept); +  } + +  /* ------------------------------------------------------------ +   * directorPrefixArgs() +   * ------------------------------------------------------------ */ + +  void directorPrefixArgs(Node *n) { +    Parm *p; + +    /* Need to prepend 'jenv' to the director constructor's argument list */ + +    String *jenv_type = NewString("JNIEnv"); + +    SwigType_add_pointer(jenv_type); + +    p = NewParm(jenv_type, NewString("jenv"), n); +    Setattr(p, "arg:byname", "1"); +    set_nextSibling(p, NULL); + +    Setattr(n, "director:prefix_args", p); +  } + +  /* ------------------------------------------------------------ +   * classDirectorConstructor() +   * ------------------------------------------------------------ */ + +  int classDirectorConstructor(Node *n) { +    Node *parent = parentNode(n); +    String *decl = Getattr(n, "decl"); +    String *supername = Swig_class_name(parent); +    String *dirclassname = directorClassName(parent); +    String *sub = NewString(""); +    Parm *p; +    ParmList *superparms = Getattr(n, "parms"); +    ParmList *parms; +    int argidx = 0; + +    /* Assign arguments to superclass's parameters, if not already done */ +    for (p = superparms; p; p = nextSibling(p)) { +      String *pname = Getattr(p, "name"); + +      if (!pname) { +	pname = NewStringf("arg%d", argidx++); +	Setattr(p, "name", pname); +      } +    } + +    /* insert jenv prefix argument */ +    parms = CopyParmList(superparms); + +    String *jenv_type = NewString("JNIEnv"); +    SwigType_add_pointer(jenv_type); +    p = NewParm(jenv_type, NewString("jenv"), n); +    set_nextSibling(p, parms); +    parms = p; + +    directorPrefixArgs(n); + +    if (!Getattr(n, "defaultargs")) { +      /* constructor */ +      { +	String *basetype = Getattr(parent, "classtype"); +	String *target = Swig_method_decl(0, decl, dirclassname, parms, 0); +	String *call = Swig_csuperclass_call(0, basetype, superparms); +	String *classtype = SwigType_namestr(Getattr(n, "name")); + +	Printf(f_directors, "%s::%s : %s, %s {\n", dirclassname, target, call, Getattr(parent, "director:ctor")); +	Printf(f_directors, "}\n\n"); + +	Delete(classtype); +	Delete(target); +	Delete(call); +      } + +      /* constructor header */ +      { +	String *target = Swig_method_decl(0, decl, dirclassname, parms, 1); +	Printf(f_directors_h, "    %s;\n", target); +	Delete(target); +      } +    } + +    Delete(sub); +    Delete(supername); +    Delete(jenv_type); +    Delete(parms); +    Delete(dirclassname); +    return Language::classDirectorConstructor(n); +  } + +  /* ------------------------------------------------------------ +   * classDirectorDefaultConstructor() +   * ------------------------------------------------------------ */ + +  int classDirectorDefaultConstructor(Node *n) { +    String *classname = Swig_class_name(n); +    String *classtype = SwigType_namestr(Getattr(n, "name")); +    String *dirClassName = directorClassName(n); +    Wrapper *w = NewWrapper(); + +    Printf(w->def, "%s::%s(JNIEnv *jenv) : %s {", dirClassName, dirClassName, Getattr(n, "director:ctor")); +    Printf(w->code, "}\n"); +    Wrapper_print(w, f_directors); + +    Printf(f_directors_h, "    %s(JNIEnv *jenv);\n", dirClassName); +    DelWrapper(w); +    Delete(classtype); +    Delete(classname); +    Delete(dirClassName); +    directorPrefixArgs(n); +    return Language::classDirectorDefaultConstructor(n); +  } + + +  /* ------------------------------------------------------------ +   * classDirectorInit() +   * ------------------------------------------------------------ */ + +  int classDirectorInit(Node *n) { +    Delete(none_comparison); +    none_comparison = NewString("");	// not used + +    Delete(director_ctor_code); +    director_ctor_code = NewString("$director_new"); + +    directorDeclaration(n); + +    Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl")); +    Printf(f_directors_h, "\npublic:\n"); +    Printf(f_directors_h, "    void swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global);\n"); + +    /* Keep track of the director methods for this class */ +    first_class_dmethod = curr_class_dmethod = n_dmethods; + +    return Language::classDirectorInit(n); +  } + +  /* ---------------------------------------------------------------------- +   * classDirectorDestructor() +   * ---------------------------------------------------------------------- */ + +  int classDirectorDestructor(Node *n) { +    Node *current_class = getCurrentClass(); +    String *full_classname = Getattr(current_class, "name"); +    String *classname = Swig_class_name(current_class); +    String *dirClassName = directorClassName(current_class); +    Wrapper *w = NewWrapper(); + +    if (Getattr(n, "noexcept")) { +      Printf(f_directors_h, "    virtual ~%s() noexcept;\n", dirClassName); +      Printf(w->def, "%s::~%s() noexcept {\n", dirClassName, dirClassName); +    } else if (Getattr(n, "throw")) { +      Printf(f_directors_h, "    virtual ~%s() throw();\n", dirClassName); +      Printf(w->def, "%s::~%s() throw() {\n", dirClassName, dirClassName); +    } else { +      Printf(f_directors_h, "    virtual ~%s();\n", dirClassName); +      Printf(w->def, "%s::~%s() {\n", dirClassName, dirClassName); +    } + +    /* Ensure that correct directordisconnect typemap's method name is called +     * here: */ + +    Node *disconn_attr = NewHash(); +    String *disconn_methodname = NULL; + +    typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr); +    disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname"); + +    Printv(w->code, "  swig_disconnect_director_self(\"", disconn_methodname, "\");\n", "}\n", NIL); + +    Wrapper_print(w, f_directors); + +    DelWrapper(w); +    Delete(disconn_attr); +    Delete(classname); +    Delete(dirClassName); +    return SWIG_OK; +  } + +  /* ------------------------------------------------------------ +   * classDirectorEnd() +   * ------------------------------------------------------------ */ + +  int classDirectorEnd(Node *n) { +    String *full_classname = Getattr(n, "name"); +    String *classname = getProxyName(full_classname, true); +    String *director_classname = directorClassName(n); +    String *internal_classname; + +    Wrapper *w = NewWrapper(); + +    if (Len(package_path) > 0) +      internal_classname = NewStringf("%s/%s", package_path, classname); +    else +      internal_classname = NewStringf("%s", classname); + +    // If the namespace is multiple levels, the result of getNSpace() will have inserted +    // .'s to delimit namespaces, so we need to replace those with /'s +    Replace(internal_classname, NSPACE_SEPARATOR, "/", DOH_REPLACE_ANY); + +    Wrapper_add_localv(w, "baseclass", "static jclass baseclass", "= 0", NIL); +    Printf(w->def, "void %s::swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global) {", director_classname); + +    if (first_class_dmethod != curr_class_dmethod) { +      Printf(w->def, "static struct {\n"); +      Printf(w->def, "const char *mname;\n"); +      Printf(w->def, "const char *mdesc;\n"); +      Printf(w->def, "jmethodID base_methid;\n"); +      Printf(w->def, "} methods[] = {\n"); + +      for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) { +	UpcallData *udata = Getitem(dmethods_seq, i); + +	Printf(w->def, "{ \"%s\", \"%s\", NULL }", Getattr(udata, "method"), Getattr(udata, "fdesc")); +	if (i != curr_class_dmethod - 1) +	  Putc(',', w->def); +	Putc('\n', w->def); +      } + +      Printf(w->def, "};\n"); +    } + +    Printf(w->code, "if (swig_set_self(jenv, jself, swig_mem_own, weak_global)) {\n"); +    Printf(w->code, "if (!baseclass) {\n"); +    Printf(w->code, "baseclass = jenv->FindClass(\"%s\");\n", internal_classname); +    Printf(w->code, "if (!baseclass) return;\n"); +    Printf(w->code, "baseclass = (jclass) jenv->NewGlobalRef(baseclass);\n"); +    Printf(w->code, "}\n"); + +    int n_methods = curr_class_dmethod - first_class_dmethod; + +    if (n_methods) { +      /* Emit the swig_overrides() method and the swig_override array */ +      Printf(f_directors_h, "public:\n"); +      Printf(f_directors_h, "    bool swig_overrides(int n) {\n"); +      Printf(f_directors_h, "      return (n < %d ? swig_override[n] : false);\n", n_methods); +      Printf(f_directors_h, "    }\n"); +      Printf(f_directors_h, "protected:\n"); +      Printf(f_directors_h, "    Swig::BoolArray<%d> swig_override;\n", n_methods); + +      /* Emit the code to look up the class's methods, initialize the override array */ + +      Printf(w->code, "bool derived = (jenv->IsSameObject(baseclass, jcls) ? false : true);\n"); +      Printf(w->code, "for (int i = 0; i < %d; ++i) {\n", n_methods); +      Printf(w->code, "  if (!methods[i].base_methid) {\n"); +      Printf(w->code, "    methods[i].base_methid = jenv->GetMethodID(baseclass, methods[i].mname, methods[i].mdesc);\n"); +      Printf(w->code, "    if (!methods[i].base_methid) return;\n"); +      Printf(w->code, "  }\n"); +      // Generally, derived classes have a mix of overridden and +      // non-overridden methods and it is worth making a GetMethodID +      // check during initialization to determine if each method is +      // overridden, thus avoiding unnecessary calls into Java. +      // +      // On the other hand, when derived classes are +      // expected to override all director methods then the +      // GetMethodID calls are inefficient, and it is better to let +      // the director unconditionally call up into Java.  The resulting code +      // will still behave correctly (though less efficiently) when Java +      // code doesn't override a given method. +      // +      // The assumeoverride feature on a director controls whether or not +      // overrides are assumed. +      if (GetFlag(n, "feature:director:assumeoverride")) { +        Printf(w->code, "  swig_override[i] = derived;\n"); +      } else { +        Printf(w->code, "  swig_override[i] = false;\n"); +        Printf(w->code, "  if (derived) {\n"); +        Printf(w->code, "    jmethodID methid = jenv->GetMethodID(jcls, methods[i].mname, methods[i].mdesc);\n"); +        Printf(w->code, "    swig_override[i] = (methid != methods[i].base_methid);\n"); +        Printf(w->code, "    jenv->ExceptionClear();\n"); +        Printf(w->code, "  }\n"); +      } +      Printf(w->code, "}\n"); +    } else { +      Printf(f_directors_h, "public:\n"); +      Printf(f_directors_h, "    bool swig_overrides(int n) {\n"); +      Printf(f_directors_h, "      return false;\n"); +      Printf(f_directors_h, "    }\n"); +    } + +    Printf(f_directors_h, "};\n\n"); +    Printf(w->code, "}\n"); +    Printf(w->code, "}\n"); + +    Wrapper_print(w, f_directors); + +    DelWrapper(w); +    Delete(internal_classname); + +    return Language::classDirectorEnd(n); +  } + +  /* -------------------------------------------------------------------- +   * classDirectorDisown() +   * ------------------------------------------------------------------*/ + +  virtual int classDirectorDisown(Node *n) { +    (void) n; +    return SWIG_OK; +  } + +  /*---------------------------------------------------------------------- +   * extraDirectorProtectedCPPMethodsRequired() +   *--------------------------------------------------------------------*/ + +  bool extraDirectorProtectedCPPMethodsRequired() const { +    return false; +  } + +  /*---------------------------------------------------------------------- +   * directorDeclaration() +   * +   * Generate the director class's declaration +   * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {" +   *--------------------------------------------------------------------*/ + +  void directorDeclaration(Node *n) { +    String *base = Getattr(n, "classtype"); +    String *class_ctor = NewString("Swig::Director(jenv)"); + +    String *directorname = directorClassName(n); +    String *declaration = Swig_class_declaration(n, directorname); + +    Printf(declaration, " : public %s, public Swig::Director", base); + +    // Stash stuff for later. +    Setattr(n, "director:decl", declaration); +    Setattr(n, "director:ctor", class_ctor); +  } + +  /*---------------------------------------------------------------------- +   * nestedClassesSupport() +   *--------------------------------------------------------------------*/ + +  NestedClassSupport nestedClassesSupport() const { +    return NCS_Full; +  } +};				/* class JAVA */ + +/* ----------------------------------------------------------------------------- + * swig_java()    - Instantiate module + * ----------------------------------------------------------------------------- */ + +static Language *new_swig_java() { +  return new JAVA(); +} +extern "C" Language *swig_java(void) { +  return new_swig_java(); +} + +/* ----------------------------------------------------------------------------- + * Static member variables + * ----------------------------------------------------------------------------- */ + +const char *JAVA::usage = "\ +Java Options (available with -java)\n\ +     -doxygen        - Convert C++ doxygen comments to JavaDoc comments in proxy classes\n\ +     -debug-doxygen-parser     - Display doxygen parser module debugging information\n\ +     -debug-doxygen-translator - Display doxygen translator module debugging information\n\ +     -nopgcpp        - Suppress premature garbage collection prevention parameter\n\ +     -noproxy        - Generate the low-level functional interface instead\n\ +                       of proxy classes\n\ +     -oldvarnames    - Old intermediary method names for variable wrappers\n\ +     -package <name> - Set name of the Java package to <name>\n\ +\n";  | 
