| /* ----------------------------------------------------------------------------- | |
| * 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 https://www.swig.org/legal.html. | |
| * | |
| * java.cxx | |
| * | |
| * Java language module for SWIG. | |
| * ----------------------------------------------------------------------------- */ | |
| #include "swigmod.h" | |
| #include "cparse.h" | |
| #include <errno.h> | |
| #include <limits.h> // for INT_MAX | |
| #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 *common_begin_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 *constants_modifiers; // access modifiers for constants interface 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), | |
| common_begin_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), | |
| constants_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; | |
| directorLanguage(); | |
| } | |
| ~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", | |
| SwigType_namestr(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], "-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], "-help") == 0) { | |
| Printf(stdout, "%s", usage); | |
| } | |
| } | |
| } | |
| if (doxygen) | |
| doxygenTranslator = new JavaDocConverter(doxygen_translator_flags); | |
| // Add a symbol to the parser for conditional compilation | |
| Preprocessor_define("SWIGJAVA 1", 0); | |
| 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 *module = Getattr(n, "module"); | |
| Node *optionsnode = Getattr(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")); | |
| common_begin_code = Getattr(optionsnode, "javabegin"); | |
| if (common_begin_code) | |
| Printf(common_begin_code, "\n"); | |
| } | |
| /* 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"); | |
| Exit(EXIT_FAILURE); | |
| } | |
| f_begin = NewFile(outfile, "w", SWIG_output_files()); | |
| if (!f_begin) { | |
| FileErrorDisplay(outfile); | |
| Exit(EXIT_FAILURE); | |
| } | |
| if (Swig_directors_enabled()) { | |
| if (!outfile_h) { | |
| Printf(stderr, "Unable to determine outfile_h\n"); | |
| Exit(EXIT_FAILURE); | |
| } | |
| f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files()); | |
| if (!f_runtime_h) { | |
| FileErrorDisplay(outfile_h); | |
| 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, module)) | |
| return SWIG_ERROR; | |
| if (!addSymbol(module_class_name, module)) | |
| 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(""); | |
| constants_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); | |
| Swig_obligatory_macros(f_runtime, "JAVA"); | |
| if (Swig_directors_enabled()) { | |
| 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 (Swig_directors_enabled()) { | |
| // 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); | |
| 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); | |
| 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, 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); | |
| 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); | |
| if (Len(constants_modifiers) > 0) | |
| Printf(f_module, "%s ", constants_modifiers); | |
| Printf(f_module, "%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(constants_modifiers); | |
| constants_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 (Swig_directors_enabled()) { | |
| 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"); | |
| Printv(f, common_begin_code, NIL); | |
| } | |
| /*----------------------------------------------------------------------- | |
| * 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 *returntype = 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(returntype, 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(returntype, 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_parm_typemaps(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++) { | |
| p = emit_ignored_in_typemaps(p, nondir_args); | |
| 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, "$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); | |
| } | |
| p = emit_ignored_in_typemaps(p, nondir_args); | |
| 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, "$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, "$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, "$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, 0); | |
| 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) { | |
| if (Swig_director_emit_dynamic_cast(n, f)) { | |
| /* Add protection */ | |
| Append(f->code, "if (!darg) {\n"); | |
| Append(f->code, " if (!jenv->ExceptionCheck()) {\n"); | |
| Append(f->code, " SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, \"'self' is not a director\");\n"); | |
| Append(f->code, " }\n"); | |
| if (is_void_return) | |
| Append(f->code, " return;\n"); | |
| else | |
| Append(f->code, " return jresult;\n"); | |
| Append(f->code, "}\n"); | |
| } | |
| 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, "$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(returntype, 0), Getattr(n, "name")); | |
| } | |
| emit_return_variable(n, returntype, 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); | |
| 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); | |
| 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); | |
| emit_isvoid_special_variables(n, f->code, is_void_return); | |
| /* 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 | |
| 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, 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 the comment for the enum itself if flagged. There is no equivalent Java declaration for the enum for a javadoc | |
| // comment to attach to for simple enums, only the constants below, so emit it as a plain comment rather than a javadoc comment. | |
| if (doxygen && doxygenTranslator->hasDocumentation(n)) { | |
| String *doxygen_comments = doxygenTranslator->getDocumentation(n, " "); | |
| Replace(doxygen_comments, "/**", "/*", DOH_REPLACE_FIRST); | |
| if (comment_creation_chatter) | |
| Printf(constants_code, "/* This was generated from enumDeclaration() */\n"); | |
| Printv(constants_code, doxygen_comments, NIL); | |
| Delete(doxygen_comments); | |
| } | |
| } | |
| if (proxy_flag && !is_wrapping_class()) { | |
| // Global enums / enums in a namespace | |
| assert(!full_imclass_name); | |
| constructIntermediateClassName(n); | |
| } | |
| // Emit each enum item | |
| Language::enumDeclaration(n); | |
| if (proxy_flag && !is_wrapping_class()) { | |
| Delete(full_imclass_name); | |
| full_imclass_name = 0; | |
| } | |
| 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"); | |
| 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); | |
| 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; | |
| } | |
| 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); | |
| // Convert a character literal, including a wide one, or an integer or boolean literal value into a Java literal | |
| String *enumstringval = Getattr(n, "enumstringval"); | |
| if (enumstringval) { | |
| String *val = NewStringf("'%(escape)s'", enumstringval); | |
| Setattr(n, "enumvalue", val); | |
| Delete(val); | |
| } else { | |
| String *numval = Getattr(n, "enumnumval"); | |
| if (numval) { | |
| const char *p = Char(numval); | |
| if (isdigit(p[0])) { | |
| char *e; | |
| errno = 0; | |
| // long long is not in C++98, but every compiler we support provides it as an | |
| // extension and it is needed here for enum values which don't fit in 32 bits. | |
| #if defined(__GNUC__) | |
| #pragma GCC diagnostic push | |
| #pragma GCC diagnostic ignored "-Wlong-long" | |
| #endif | |
| unsigned long long value = strtoull(p, &e, 0); | |
| #if defined(__GNUC__) | |
| #pragma GCC diagnostic pop | |
| #endif | |
| if (errno != ERANGE && *e == '\0' && value >= 0x80000000) { | |
| // Use hex for larger unsigned integer constants in Java code since | |
| // Java allows implicit conversion to a signed integer value. | |
| String *hexval = NewStringf("0x%llx", value); | |
| Setattr(n, "enumvalue", hexval); | |
| Delete(hexval); | |
| } else { | |
| Setattr(n, "enumvalue", numval); | |
| } | |
| } else { | |
| // Emit negative values as-is. | |
| Setattr(n, "enumvalue", numval); | |
| } | |
| } | |
| } | |
| { | |
| 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, 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"); | |
| ParmList *l = Getattr(n, "parms"); | |
| String *tm; | |
| String *return_type = NewString(""); | |
| String *constants_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(constants_code, "/* This was generated from constantWrapper() */\n"); | |
| Printv(constants_code, 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)); | |
| } | |
| // A literal cannot initialise a constant wrapped as a class, such as a wide string without typemaps for wchar_t * | |
| String *stringval = Getattr(n, "stringval"); | |
| if (stringval && classname_substituted_flag) | |
| const_feature_flag = 0; | |
| 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 | |
| int type = SwigType_type(t); | |
| if (stringval && (type == T_STRING || type == T_WSTRING)) { | |
| // Decoded from UTF-8, as JNI decodes a char * string. A wide string has no L prefix in Java | |
| Printf(constants_code, "\"%(javaunicodeescape)s\";\n", stringval); | |
| } else if (stringval && type == T_WCHAR) { | |
| Printf(constants_code, "'%(javaunicodeescape)s';\n", stringval); | |
| } else if (Getattr(n, "wrappedasconstant")) { | |
| 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(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 | |
| * | |
| * constantsmodifiers - access modifiers for the constants interface | |
| * ----------------------------------------------------------------------------- */ | |
| 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, "constantsmodifiers") == 0) { | |
| Delete(constants_modifiers); | |
| constants_modifiers = Copy(strvalue); | |
| } 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, List *base_list, SwigType *c_classname) { | |
| for (Iterator it = First(base_list); it.item; it = Next(it)) { | |
| Node *base = it.item; | |
| SwigType *c_baseclassname = Getattr(base, "name"); | |
| String *interface_name = Getattr(base, "interface:name"); | |
| String *qualified_interface_name = getQualifiedInterfaceName(base); | |
| SwigType *bsmart = Getattr(base, "smart"); | |
| if (Len(interface_list)) | |
| Append(interface_list, ", "); | |
| Append(interface_list, qualified_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); | |
| Replaceall(interface_code, "$javainterfacename", qualified_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, bsmart, upcast_method_name, c_classname, c_baseclassname); | |
| Delete(upcast_method_name); | |
| Delete(cptr_method_name); | |
| Delete(interface_code); | |
| } | |
| } | |
| /* ----------------------------------------------------------------------------- | |
| * upcastsCode() | |
| * | |
| * Add code for C++ casting to base class | |
| * ----------------------------------------------------------------------------- */ | |
| void upcastsCode(SwigType *smart, SwigType *bsmart, 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); | |
| if (smart) { | |
| if (bsmart) { | |
| String *smartnamestr = SwigType_namestr(smart); | |
| String *bsmartnamestr = SwigType_namestr(bsmart); | |
| 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(bsmartnamestr); | |
| Delete(smartnamestr); | |
| } | |
| } else { | |
| String *classname = SwigType_namestr(c_classname); | |
| String *baseclassname = SwigType_namestr(c_baseclassname); | |
| 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 = Getattr(n, "smart"); | |
| SwigType *bsmart = 0; | |
| // 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") || GetFlag(base.item, "feature:interface"))) { | |
| SwigType *baseclassname = Getattr(base.item, "name"); | |
| if (!c_baseclassname) { | |
| String *name = getProxyName(baseclassname); | |
| if (name) { | |
| c_baseclassname = baseclassname; | |
| baseclass = name; | |
| bsmart = Getattr(base.item, "smart"); | |
| } | |
| } 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); | |
| } | |
| } | |
| } | |
| List *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, 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, bsmart, upcast_method_name, c_classname, c_baseclassname); | |
| Delete(upcast_method_name); | |
| } | |
| } | |
| /* ---------------------------------------------------------------------- | |
| * 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); | |
| if (doxygen && doxygenTranslator->hasDocumentation(n)) { | |
| String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0); | |
| Printv(f_interface, doxygen_comments, NIL); | |
| Delete(doxygen_comments); | |
| } | |
| Printv(f_interface, typemapLookup(n, "javainterfacemodifiers", Getattr(n, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACEMODIFIERS_UNDEF), NIL); | |
| Printf(f_interface, " %s", interface_name); | |
| String *additional = Getattr(n, "feature:interface:additional"); | |
| String *bases = additional ? Copy(additional) : 0; | |
| if (List *baselist = Getattr(n, "bases")) { | |
| for (Iterator base = First(baselist); base.item; base = Next(base)) { | |
| if (GetFlag(base.item, "feature:ignore") || !GetFlag(base.item, "feature:interface")) | |
| continue; // TODO: warn about skipped non-interface bases | |
| String *base_iname = getQualifiedInterfaceName(base.item); | |
| 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); | |
| 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); | |
| 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 = GetFlag(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); | |
| 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 (GetFlag(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); | |
| 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 = | |
| GetFlag(parentNode(n), "feature:interface") && !checkAttribute(n, "kind", "variable") && !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, doxygen_comments, NIL); | |
| if (is_interface) | |
| Printv(interface_class_code, "\n", 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, "$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(""); | |
| #if 0 | |
| // TODO: add full support for Java annotations - implementation should be same as C# attributes | |
| const String *annotations = Getattr(n, "feature:java:annotations"); | |
| #else | |
| const String *annotations = NULL; | |
| #endif | |
| // Default annotation for director constructors is a warning suppression | |
| static const String *suppress_warning_this_escape = NewString("@SuppressWarnings(\"this-escape\")"); | |
| if (!annotations && feature_director) | |
| annotations = suppress_warning_this_escape; | |
| if (annotations) { | |
| Printf(function_code, " %s\n", annotations); | |
| Printf(helper_code, " %s\n", annotations); | |
| } | |
| 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, 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 = Copy(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, "$imfuncname", overloaded_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)); | |
| } | |
| 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); | |
| 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); | |
| 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); | |
| SwigType *smart = Getattr(n, "smart"); | |
| String *smartptr = smart ? SwigType_namestr(smart) : 0; | |
| 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 (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 = 0; | |
| 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 = 0; | |
| 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?) | |
| if (!ignored_method) { | |
| overloaded_name = getOverloadedName(n); | |
| imclass_dmethod = 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); | |
| } | |
| } | |
| } | |
| if (!ignored_method) { | |
| /* 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", ""); | |
| } | |
| emit_isvoid_special_variables(0, w->code, is_void); | |
| 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) { | |
| /* Need to prepend 'jenv' to the director constructor's argument list */ | |
| String *jenv_type = NewString("JNIEnv"); | |
| SwigType_add_pointer(jenv_type); | |
| Parm *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); | |
| Printf(w->def, "void %s::swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global) {", director_classname); | |
| Printf(w->def, "static jclass baseclass = swig_new_global_ref(jenv, \"%s\");\n", internal_classname); | |
| Printf(w->def, "if (!baseclass) return;\n"); | |
| Printf(w->code, "if (swig_set_self(jenv, jself, swig_mem_own, weak_global)) {\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); | |
| // 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->def, "static SwigDirectorMethod methods[] = {\n"); | |
| for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) { | |
| UpcallData *udata = Getitem(dmethods_seq, i); | |
| Printf(w->def, "SwigDirectorMethod(jenv, baseclass, \"%s\", \"%s\")", Getattr(udata, "method"), Getattr(udata, "fdesc")); | |
| if (i != curr_class_dmethod - 1) | |
| Putc(',', w->def); | |
| Putc('\n', w->def); | |
| } | |
| Printf(w->def, "};"); | |
| Printf(w->code, " swig_override[i] = false;\n"); | |
| Printf(w->code, " if (derived) {\n"); | |
| Printf(w->code, " jmethodID methid = jenv->GetMethodID(jcls, methods[i].name, methods[i].desc);\n"); | |
| Printf(w->code, " swig_override[i] = methods[i].methid && (methid != methods[i].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"; |