1 /* -----------------------------------------------------------------------------
2  * This file is part of SWIG, which is licensed as a whole under version 3
3  * (or any later version) of the GNU General Public License. Some additional
4  * terms also apply to certain portions of SWIG. The full details of the SWIG
5  * license and copyrights can be found in the LICENSE and COPYRIGHT files
6  * included with the SWIG source code as distributed by the SWIG developers
7  * and at http://www.swig.org/legal.html.
8  *
9  * java.cxx
10  *
11  * Java language module for SWIG.
12  * ----------------------------------------------------------------------------- */
13 
14 #include "swigmod.h"
15 #include <limits.h>		// for INT_MAX
16 #include "cparse.h"
17 #include <ctype.h>
18 #include "javadoc.h"
19 
20 /* Hash type used for upcalls from C/C++ */
21 typedef DOH UpcallData;
22 
23 class JAVA:public Language {
24   static const char *usage;
25   const String *empty_string;
26   const String *public_string;
27   const String *protected_string;
28 
29   Hash *swig_types_hash;
30   File *f_begin;
31   File *f_runtime;
32   File *f_runtime_h;
33   File *f_header;
34   File *f_wrappers;
35   File *f_init;
36   File *f_directors;
37   File *f_directors_h;
38   List *filenames_list;
39 
40   bool proxy_flag;		// Flag for generating proxy classes
41   bool nopgcpp_flag;		// Flag for suppressing the premature garbage collection prevention parameter
42   bool native_function_flag;	// Flag for when wrapping a native function
43   bool enum_constant_flag;	// Flag for when wrapping an enum or constant
44   bool static_flag;		// Flag for when wrapping a static functions or member variables
45   bool variable_wrapper_flag;	// Flag for when wrapping a nonstatic member variable
46   bool wrapping_member_flag;	// Flag for when wrapping a member variable/enum/const
47   bool global_variable_flag;	// Flag for when wrapping a global variable
48   bool old_variable_names;	// Flag for old style variable names in the intermediary class
49   bool member_func_flag;	// flag set when wrapping a member function
50   bool doxygen;			//flag for converting found doxygen to javadoc
51   bool comment_creation_chatter; //flag for getting information about where comments were created in java.cxx
52 
53   String *imclass_name;		// intermediary class name
54   String *module_class_name;	// module class name
55   String *constants_interface_name;	// constants interface name
56   String *imclass_class_code;	// intermediary class code
57   String *proxy_class_def;
58   String *proxy_class_code;
59   String *interface_class_code; // if %feature("interface") was declared for a class, here goes the interface declaration
60   String *module_class_code;
61   String *proxy_class_name;	// proxy class name
62   String *full_proxy_class_name;// fully qualified proxy class name when using nspace feature, otherwise same as proxy_class_name
63   String *full_imclass_name;	// fully qualified intermediary class name when using nspace feature, otherwise same as imclass_name
64   String *variable_name;	//Name of a variable being wrapped
65   String *proxy_class_constants_code;
66   String *module_class_constants_code;
67   String *enum_code;
68   String *package;		// Optional package name
69   String *jnipackage;		// Package name used in the JNI code
70   String *package_path;		// Package name used internally by JNI (slashes)
71   String *imclass_imports;	//intermediary class imports from %pragma
72   String *module_imports;	//module imports from %pragma
73   String *imclass_baseclass;	//inheritance for intermediary class class from %pragma
74   String *imclass_package;	//package in which to generate the intermediary class
75   String *module_baseclass;	//inheritance for module class from %pragma
76   String *imclass_interfaces;	//interfaces for intermediary class class from %pragma
77   String *module_interfaces;	//interfaces for module class from %pragma
78   String *imclass_class_modifiers;	//class modifiers for intermediary class overridden by %pragma
79   String *module_class_modifiers;	//class modifiers for module class overridden by %pragma
80   String *upcasts_code;		//C++ casts for inheritance hierarchies C++ code
81   String *imclass_cppcasts_code;	//C++ casts up inheritance hierarchies intermediary class code
82   String *imclass_directors;	// Intermediate class director code
83   String *destructor_call;	//C++ destructor call if any
84   String *destructor_throws_clause;	//C++ destructor throws clause if any
85 
86   // Director method stuff:
87   List *dmethods_seq;
88   Hash *dmethods_table;
89   int n_dmethods;
90   int n_directors;
91   int first_class_dmethod;
92   int curr_class_dmethod;
93   int nesting_depth;
94 
95   enum EnumFeature { SimpleEnum, TypeunsafeEnum, TypesafeEnum, ProperEnum };
96 
97 public:
98 
99   /* -----------------------------------------------------------------------------
100    * JAVA()
101    * ----------------------------------------------------------------------------- */
102 
JAVA()103    JAVA():empty_string(NewString("")),
104       public_string(NewString("public")),
105       protected_string(NewString("protected")),
106       swig_types_hash(NULL),
107       f_begin(NULL),
108       f_runtime(NULL),
109       f_runtime_h(NULL),
110       f_header(NULL),
111       f_wrappers(NULL),
112       f_init(NULL),
113       f_directors(NULL),
114       f_directors_h(NULL),
115       filenames_list(NULL),
116       proxy_flag(true),
117       nopgcpp_flag(false),
118       native_function_flag(false),
119       enum_constant_flag(false),
120       static_flag(false),
121       variable_wrapper_flag(false),
122       wrapping_member_flag(false),
123       global_variable_flag(false),
124       old_variable_names(false),
125       member_func_flag(false),
126       doxygen(false),
127       comment_creation_chatter(false),
128       imclass_name(NULL),
129       module_class_name(NULL),
130       constants_interface_name(NULL),
131       imclass_class_code(NULL),
132       proxy_class_def(NULL),
133       proxy_class_code(NULL),
134       interface_class_code(NULL),
135       module_class_code(NULL),
136       proxy_class_name(NULL),
137       full_proxy_class_name(NULL),
138       full_imclass_name(NULL),
139       variable_name(NULL),
140       proxy_class_constants_code(NULL),
141       module_class_constants_code(NULL),
142       enum_code(NULL),
143       package(NULL),
144       jnipackage(NULL),
145       package_path(NULL),
146       imclass_imports(NULL),
147       module_imports(NULL),
148       imclass_baseclass(NULL),
149       imclass_package(NULL),
150       module_baseclass(NULL),
151       imclass_interfaces(NULL),
152       module_interfaces(NULL),
153       imclass_class_modifiers(NULL),
154       module_class_modifiers(NULL),
155       upcasts_code(NULL),
156       imclass_cppcasts_code(NULL),
157       imclass_directors(NULL),
158       destructor_call(NULL),
159       destructor_throws_clause(NULL),
160       dmethods_seq(NULL),
161       dmethods_table(NULL),
162       n_dmethods(0),
163       n_directors(0),
164       first_class_dmethod(0),
165       curr_class_dmethod(0),
166       nesting_depth(0){
167     /* for now, multiple inheritance in directors is disabled, this
168        should be easy to implement though */
169     director_multiple_inheritance = 0;
170     director_language = 1;
171   }
172 
~JAVA()173   ~JAVA() {
174     delete doxygenTranslator;
175   }
176 
177   /* -----------------------------------------------------------------------------
178    * constructIntermediateClassName()
179    *
180    * Construct the fully qualified name of the intermediate class and set
181    * the full_imclass_name attribute accordingly.
182    * ----------------------------------------------------------------------------- */
constructIntermediateClassName(Node * n)183   void constructIntermediateClassName(Node *n) {
184     String *nspace = Getattr(n, "sym:nspace");
185 
186     if (imclass_package && package)
187       full_imclass_name = NewStringf("%s.%s.%s", package, imclass_package, imclass_name);
188     else if (package && nspace)
189       full_imclass_name = NewStringf("%s.%s", package, imclass_name);
190     else if (imclass_package)
191       full_imclass_name = NewStringf("%s.%s", imclass_package, imclass_name);
192     else
193       full_imclass_name = NewStringf("%s", imclass_name);
194 
195     if (nspace && !package) {
196       String *name = Getattr(n, "name") ? Getattr(n, "name") : NewString("<unnamed>");
197       Swig_warning(WARN_JAVA_NSPACE_WITHOUT_PACKAGE, Getfile(n), Getline(n),
198 	  "The nspace feature is used on '%s' without -package. "
199 	  "The generated code may not compile as Java does not support types declared in a named package accessing types declared in an unnamed package.\n", name);
200     }
201   }
202 
203   /* -----------------------------------------------------------------------------
204    * getProxyName()
205    *
206    * Test to see if a type corresponds to something wrapped with a proxy class.
207    * Return NULL if not otherwise the proxy class name, fully qualified with
208    * package name if the nspace feature is used, unless jnidescriptor is true as
209    * the package name is handled differently (unfortunately for legacy reasons).
210    * ----------------------------------------------------------------------------- */
211 
getProxyName(SwigType * t,bool jnidescriptor=false)212    String *getProxyName(SwigType *t, bool jnidescriptor = false) {
213      String *proxyname = NULL;
214      if (proxy_flag) {
215        Node *n = classLookup(t);
216        if (n) {
217 	 proxyname = Getattr(n, "proxyname");
218 	 if (!proxyname || jnidescriptor) {
219 	   String *nspace = Getattr(n, "sym:nspace");
220 	   String *symname = Copy(Getattr(n, "sym:name"));
221 	   if (symname && !GetFlag(n, "feature:flatnested")) {
222              for (Node *outer_class = Getattr(n, "nested:outer"); outer_class; outer_class = Getattr(outer_class, "nested:outer")) {
223                if (String* name = Getattr(outer_class, "sym:name")) {
224                  Push(symname, jnidescriptor ? "$" : ".");
225                  Push(symname, name);
226                }
227                else
228                  return NULL;
229              }
230 	   }
231 	   if (nspace) {
232 	     if (package && !jnidescriptor)
233 	       proxyname = NewStringf("%s.%s.%s", package, nspace, symname);
234 	     else
235 	       proxyname = NewStringf("%s.%s", nspace, symname);
236 	   } else {
237 	     proxyname = Copy(symname);
238 	   }
239 	   if (!jnidescriptor) {
240 	     Setattr(n, "proxyname", proxyname); // Cache it
241 	     Delete(proxyname);
242 	   }
243 	   Delete(symname);
244 	 }
245        }
246      }
247      return proxyname;
248    }
249 
250   /* -----------------------------------------------------------------------------
251    * makeValidJniName()
252    * ----------------------------------------------------------------------------- */
253 
makeValidJniName(const String * name)254   String *makeValidJniName(const String *name) {
255     String *valid_jni_name = NewString(name);
256     Replaceall(valid_jni_name, "_", "_1");
257     return valid_jni_name;
258   }
259 
260   /* ------------------------------------------------------------
261    * main()
262    * ------------------------------------------------------------ */
263 
main(int argc,char * argv[])264   virtual void main(int argc, char *argv[]) {
265 
266     SWIG_library_directory("java");
267 
268     int doxygen_translator_flags = 0;
269 
270     // Look for certain command line options
271     for (int i = 1; i < argc; i++) {
272       if (argv[i]) {
273 	if (strcmp(argv[i], "-package") == 0) {
274 	  if (argv[i + 1]) {
275 	    package = NewString("");
276 	    Printf(package, argv[i + 1]);
277 	    if (Len(package) == 0) {
278 	      Delete(package);
279 	      package = 0;
280 	    }
281 	    Swig_mark_arg(i);
282 	    Swig_mark_arg(i + 1);
283 	    i++;
284 	  } else {
285 	    Swig_arg_error();
286 	  }
287 	} else if ((strcmp(argv[i], "-shadow") == 0) || ((strcmp(argv[i], "-proxy") == 0))) {
288 	  Printf(stderr, "Deprecated command line option: %s. Proxy classes are now generated by default.\n", argv[i]);
289 	  Swig_mark_arg(i);
290 	  proxy_flag = true;
291 	} else if ((strcmp(argv[i], "-doxygen") == 0)) {
292 	  Swig_mark_arg(i);
293 	  doxygen = true;
294 	  scan_doxygen_comments = true;
295 	} else if ((strcmp(argv[i], "-debug-doxygen-translator") == 0)) {
296 	  Swig_mark_arg(i);
297 	  doxygen_translator_flags |= DoxygenTranslator::debug_translator;
298 	} else if ((strcmp(argv[i], "-debug-doxygen-parser") == 0)) {
299 	  Swig_mark_arg(i);
300 	  doxygen_translator_flags |= DoxygenTranslator::debug_parser;
301 	} else if ((strcmp(argv[i], "-noproxy") == 0)) {
302 	  Swig_mark_arg(i);
303 	  proxy_flag = false;
304 	} else if (strcmp(argv[i], "-nopgcpp") == 0) {
305 	  Swig_mark_arg(i);
306 	  nopgcpp_flag = true;
307 	} else if (strcmp(argv[i], "-oldvarnames") == 0) {
308 	  Swig_mark_arg(i);
309 	  old_variable_names = true;
310 	} else if (strcmp(argv[i], "-jnic") == 0) {
311 	  Swig_mark_arg(i);
312 	  Printf(stderr, "Deprecated command line option: -jnic. C JNI calling convention now used when -c++ not specified.\n");
313 	} else if (strcmp(argv[i], "-nofinalize") == 0) {
314 	  Swig_mark_arg(i);
315 	  Printf(stderr, "Deprecated command line option: -nofinalize. Use the new javafinalize typemap instead.\n");
316 	} else if (strcmp(argv[i], "-jnicpp") == 0) {
317 	  Swig_mark_arg(i);
318 	  Printf(stderr, "Deprecated command line option: -jnicpp. C++ JNI calling convention now used when -c++ specified.\n");
319 	} else if (strcmp(argv[i], "-help") == 0) {
320 	  Printf(stdout, "%s\n", usage);
321 	}
322       }
323     }
324 
325     if (doxygen)
326       doxygenTranslator = new JavaDocConverter(doxygen_translator_flags);
327 
328     // Add a symbol to the parser for conditional compilation
329     Preprocessor_define("SWIGJAVA 1", 0);
330 
331     // Add typemap definitions
332     SWIG_typemap_lang("java");
333     SWIG_config_file("java.swg");
334 
335     allow_overloading();
336     Swig_interface_feature_enable();
337   }
338 
339   /* ---------------------------------------------------------------------
340    * top()
341    * --------------------------------------------------------------------- */
342 
top(Node * n)343   virtual int top(Node *n) {
344 
345     // Get any options set in the module directive
346     Node *optionsnode = Getattr(Getattr(n, "module"), "options");
347 
348     if (optionsnode) {
349       if (Getattr(optionsnode, "jniclassname"))
350 	imclass_name = Copy(Getattr(optionsnode, "jniclassname"));
351       /* check if directors are enabled for this module.  note: this
352        * is a "master" switch, without which no director code will be
353        * emitted.  %feature("director") statements are also required
354        * to enable directors for individual classes or methods.
355        *
356        * use %module(directors="1") modulename at the start of the
357        * interface file to enable director generation.
358        */
359       if (Getattr(optionsnode, "directors")) {
360 	allow_directors();
361       }
362       if (Getattr(optionsnode, "dirprot")) {
363 	allow_dirprot();
364       }
365       allow_allprotected(GetFlag(optionsnode, "allprotected"));
366     }
367 
368     /* Initialize all of the output files */
369     String *outfile = Getattr(n, "outfile");
370     String *outfile_h = Getattr(n, "outfile_h");
371 
372     if (!outfile) {
373       Printf(stderr, "Unable to determine outfile\n");
374       SWIG_exit(EXIT_FAILURE);
375     }
376 
377     f_begin = NewFile(outfile, "w", SWIG_output_files());
378     if (!f_begin) {
379       FileErrorDisplay(outfile);
380       SWIG_exit(EXIT_FAILURE);
381     }
382 
383     if (directorsEnabled()) {
384       if (!outfile_h) {
385         Printf(stderr, "Unable to determine outfile_h\n");
386         SWIG_exit(EXIT_FAILURE);
387       }
388       f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
389       if (!f_runtime_h) {
390 	FileErrorDisplay(outfile_h);
391 	SWIG_exit(EXIT_FAILURE);
392       }
393     }
394 
395     f_runtime = NewString("");
396     f_init = NewString("");
397     f_header = NewString("");
398     f_wrappers = NewString("");
399     f_directors_h = NewString("");
400     f_directors = NewString("");
401 
402     /* Register file targets with the SWIG file handler */
403     Swig_register_filebyname("begin", f_begin);
404     Swig_register_filebyname("header", f_header);
405     Swig_register_filebyname("wrapper", f_wrappers);
406     Swig_register_filebyname("runtime", f_runtime);
407     Swig_register_filebyname("init", f_init);
408     Swig_register_filebyname("director", f_directors);
409     Swig_register_filebyname("director_h", f_directors_h);
410 
411     swig_types_hash = NewHash();
412     filenames_list = NewList();
413 
414     // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
415     if (!imclass_name) {
416       imclass_name = NewStringf("%sJNI", Getattr(n, "name"));
417       module_class_name = Copy(Getattr(n, "name"));
418     } else {
419       // Rename the module name if it is the same as intermediary class name - a backwards compatibility solution
420       if (Cmp(imclass_name, Getattr(n, "name")) == 0)
421 	module_class_name = NewStringf("%sModule", Getattr(n, "name"));
422       else
423 	module_class_name = Copy(Getattr(n, "name"));
424     }
425     constants_interface_name = NewStringf("%sConstants", module_class_name);
426 
427     // module class and intermediary classes are always created
428     if (!addSymbol(imclass_name, n))
429       return SWIG_ERROR;
430     if (!addSymbol(module_class_name, n))
431       return SWIG_ERROR;
432 
433     imclass_class_code = NewString("");
434     proxy_class_def = NewString("");
435     proxy_class_code = NewString("");
436     module_class_constants_code = NewString("");
437     imclass_baseclass = NewString("");
438     imclass_package = NULL;
439     imclass_interfaces = NewString("");
440     imclass_class_modifiers = NewString("");
441     module_class_code = NewString("");
442     module_baseclass = NewString("");
443     module_interfaces = NewString("");
444     module_imports = NewString("");
445     module_class_modifiers = NewString("");
446     imclass_imports = NewString("");
447     imclass_cppcasts_code = NewString("");
448     imclass_directors = NewString("");
449     upcasts_code = NewString("");
450     dmethods_seq = NewList();
451     dmethods_table = NewHash();
452     n_dmethods = 0;
453     n_directors = 0;
454     jnipackage = NewString("");
455     package_path = NewString("");
456 
457     Swig_banner(f_begin);
458 
459     Printf(f_runtime, "\n\n#ifndef SWIGJAVA\n#define SWIGJAVA\n#endif\n\n");
460 
461     if (directorsEnabled()) {
462       Printf(f_runtime, "#define SWIG_DIRECTORS\n");
463 
464       /* Emit initial director header and director code: */
465       Swig_banner(f_directors_h);
466       Printf(f_directors_h, "\n");
467       Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_class_name);
468       Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_class_name);
469 
470       Printf(f_directors, "\n\n");
471       Printf(f_directors, "/* ---------------------------------------------------\n");
472       Printf(f_directors, " * C++ director class methods\n");
473       Printf(f_directors, " * --------------------------------------------------- */\n\n");
474       if (outfile_h) {
475 	String *filename = Swig_file_filename(outfile_h);
476 	Printf(f_directors, "#include \"%s\"\n\n", filename);
477 	Delete(filename);
478       }
479     }
480 
481     Printf(f_runtime, "\n");
482 
483     String *wrapper_name = NewString("");
484 
485     if (package) {
486       String *jniname = makeValidJniName(package);
487       Printv(jnipackage, jniname, NIL);
488       Delete(jniname);
489       Replaceall(jnipackage, ".", "_");
490       Append(jnipackage, "_");
491       Printv(package_path, package, NIL);
492       Replaceall(package_path, ".", "/");
493     }
494     String *jniname = makeValidJniName(imclass_name);
495     Printf(wrapper_name, "Java_%s%s_%%f", jnipackage, jniname);
496     Delete(jniname);
497 
498     Swig_name_register("wrapper", Char(wrapper_name));
499     if (old_variable_names) {
500       Swig_name_register("set", "set_%n%v");
501       Swig_name_register("get", "get_%n%v");
502     }
503 
504     Delete(wrapper_name);
505 
506     Printf(f_wrappers, "\n#ifdef __cplusplus\n");
507     Printf(f_wrappers, "extern \"C\" {\n");
508     Printf(f_wrappers, "#endif\n\n");
509 
510     /* Emit code */
511     Language::top(n);
512 
513     if (directorsEnabled()) {
514       // Insert director runtime into the f_runtime file (make it occur before %header section)
515       Swig_insert_file("director_common.swg", f_runtime);
516       Swig_insert_file("director.swg", f_runtime);
517     }
518     // Generate the intermediary class
519     {
520       String *filen = NewStringf("%s%s.java", outputDirectory(imclass_package), imclass_name);
521       File *f_im = NewFile(filen, "w", SWIG_output_files());
522       if (!f_im) {
523 	FileErrorDisplay(filen);
524 	SWIG_exit(EXIT_FAILURE);
525       }
526       Append(filenames_list, Copy(filen));
527       Delete(filen);
528       filen = NULL;
529 
530       // Start writing out the intermediary class file
531       emitBanner(f_im);
532 
533       if (imclass_package && package)
534         Printf(f_im, "package %s.%s;", package, imclass_package);
535       else if (imclass_package)
536         Printf(f_im, "package %s;", imclass_package);
537       else if (package)
538         Printf(f_im, "package %s;\n", package);
539 
540       if (imclass_imports)
541 	Printf(f_im, "%s\n", imclass_imports);
542 
543       if (Len(imclass_class_modifiers) > 0)
544 	Printf(f_im, "%s ", imclass_class_modifiers);
545       Printf(f_im, "%s ", imclass_name);
546 
547       if (imclass_baseclass && *Char(imclass_baseclass))
548 	Printf(f_im, "extends %s ", imclass_baseclass);
549       if (Len(imclass_interfaces) > 0)
550 	Printv(f_im, "implements ", imclass_interfaces, " ", NIL);
551       Printf(f_im, "{\n");
552 
553       // Add the intermediary class methods
554       Replaceall(imclass_class_code, "$module", module_class_name);
555       Replaceall(imclass_class_code, "$imclassname", imclass_name);
556       Printv(f_im, imclass_class_code, NIL);
557       Printv(f_im, imclass_cppcasts_code, NIL);
558       if (Len(imclass_directors) > 0)
559 	Printv(f_im, "\n", imclass_directors, NIL);
560 
561       if (n_dmethods > 0) {
562 	Putc('\n', f_im);
563 	Printf(f_im, "  private final static native void swig_module_init();\n");
564 	Printf(f_im, "  static {\n");
565 	Printf(f_im, "    swig_module_init();\n");
566 	Printf(f_im, "  }\n");
567       }
568       // Finish off the class
569       Printf(f_im, "}\n");
570       Delete(f_im);
571     }
572 
573     // Generate the Java module class
574     {
575       String *filen = NewStringf("%s%s.java", SWIG_output_directory(), module_class_name);
576       File *f_module = NewFile(filen, "w", SWIG_output_files());
577       if (!f_module) {
578 	FileErrorDisplay(filen);
579 	SWIG_exit(EXIT_FAILURE);
580       }
581       Append(filenames_list, Copy(filen));
582       Delete(filen);
583       filen = NULL;
584 
585       // Start writing out the module class file
586       emitBanner(f_module);
587 
588       if (package)
589 	Printf(f_module, "package %s;\n", package);
590 
591       if (module_imports)
592 	Printf(f_module, "%s\n", module_imports);
593 
594       if (doxygen && doxygenTranslator->hasDocumentation(n)) {
595 	String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
596 	if (comment_creation_chatter)
597 	  Printf(f_module, "/* This was generated from top() */\n");
598 	Printv(f_module, Char(doxygen_comments), NIL);
599 	Delete(doxygen_comments);
600       }
601       if (Len(module_class_modifiers) > 0)
602 	Printf(f_module, "%s ", module_class_modifiers);
603       Printf(f_module, "%s ", module_class_name);
604 
605       if (module_baseclass && *Char(module_baseclass))
606 	Printf(f_module, "extends %s ", module_baseclass);
607       if (Len(module_interfaces) > 0) {
608 	if (Len(module_class_constants_code) != 0)
609 	  Printv(f_module, "implements ", constants_interface_name, ", ", module_interfaces, " ", NIL);
610 	else
611 	  Printv(f_module, "implements ", module_interfaces, " ", NIL);
612       } else {
613 	if (Len(module_class_constants_code) != 0)
614 	  Printv(f_module, "implements ", constants_interface_name, " ", NIL);
615       }
616       Printf(f_module, "{\n");
617 
618       Replaceall(module_class_code, "$module", module_class_name);
619       Replaceall(module_class_constants_code, "$module", module_class_name);
620 
621       Replaceall(module_class_code, "$imclassname", imclass_name);
622       Replaceall(module_class_constants_code, "$imclassname", imclass_name);
623 
624       // Add the wrapper methods
625       Printv(f_module, module_class_code, NIL);
626 
627       // Finish off the class
628       Printf(f_module, "}\n");
629       Delete(f_module);
630     }
631 
632     // Generate the Java constants interface
633     if (Len(module_class_constants_code) != 0) {
634       String *filen = NewStringf("%s%s.java", SWIG_output_directory(), constants_interface_name);
635       File *f_module = NewFile(filen, "w", SWIG_output_files());
636       if (!f_module) {
637 	FileErrorDisplay(filen);
638 	SWIG_exit(EXIT_FAILURE);
639       }
640       Append(filenames_list, Copy(filen));
641       Delete(filen);
642       filen = NULL;
643 
644       // Start writing out the Java constants interface file
645       emitBanner(f_module);
646 
647       if (package)
648 	Printf(f_module, "package %s;\n", package);
649 
650       if (module_imports)
651 	Printf(f_module, "%s\n", module_imports);
652 
653       Printf(f_module, "public interface %s {\n", constants_interface_name);
654 
655       // Write out all the global constants
656       Printv(f_module, module_class_constants_code, NIL);
657 
658       // Finish off the Java interface
659       Printf(f_module, "}\n");
660       Delete(f_module);
661     }
662 
663     if (upcasts_code)
664       Printv(f_wrappers, upcasts_code, NIL);
665 
666     emitDirectorUpcalls();
667 
668     Printf(f_wrappers, "#ifdef __cplusplus\n");
669     Printf(f_wrappers, "}\n");
670     Printf(f_wrappers, "#endif\n");
671 
672     // Output a Java type wrapper class for each SWIG type
673     for (Iterator swig_type = First(swig_types_hash); swig_type.key; swig_type = Next(swig_type)) {
674       emitTypeWrapperClass(swig_type.key, swig_type.item);
675     }
676 
677     // Check for overwriting file problems on filesystems that are case insensitive
678     Iterator it1;
679     Iterator it2;
680     for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
681       String *item1_lower = Swig_string_lower(it1.item);
682       for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
683 	String *item2_lower = Swig_string_lower(it2.item);
684 	if (it1.item && it2.item) {
685 	  if (Strcmp(item1_lower, item2_lower) == 0) {
686 	    Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
687 			 "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
688 			 "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
689 	  }
690 	}
691 	Delete(item2_lower);
692       }
693       Delete(item1_lower);
694     }
695 
696     Delete(swig_types_hash);
697     swig_types_hash = NULL;
698     Delete(filenames_list);
699     filenames_list = NULL;
700     Delete(imclass_name);
701     imclass_name = NULL;
702     Delete(imclass_class_code);
703     imclass_class_code = NULL;
704     Delete(proxy_class_def);
705     proxy_class_def = NULL;
706     Delete(proxy_class_code);
707     proxy_class_code = NULL;
708     Delete(module_class_constants_code);
709     module_class_constants_code = NULL;
710     Delete(imclass_baseclass);
711     imclass_baseclass = NULL;
712     Delete(imclass_package);
713     imclass_package = NULL;
714     Delete(imclass_interfaces);
715     imclass_interfaces = NULL;
716     Delete(imclass_class_modifiers);
717     imclass_class_modifiers = NULL;
718     Delete(module_class_name);
719     module_class_name = NULL;
720     Delete(constants_interface_name);
721     constants_interface_name = NULL;
722     Delete(module_class_code);
723     module_class_code = NULL;
724     Delete(module_baseclass);
725     module_baseclass = NULL;
726     Delete(module_interfaces);
727     module_interfaces = NULL;
728     Delete(module_imports);
729     module_imports = NULL;
730     Delete(module_class_modifiers);
731     module_class_modifiers = NULL;
732     Delete(imclass_imports);
733     imclass_imports = NULL;
734     Delete(imclass_cppcasts_code);
735     imclass_cppcasts_code = NULL;
736     Delete(imclass_directors);
737     imclass_directors = NULL;
738     Delete(upcasts_code);
739     upcasts_code = NULL;
740     Delete(package);
741     package = NULL;
742     Delete(jnipackage);
743     jnipackage = NULL;
744     Delete(package_path);
745     package_path = NULL;
746     Delete(dmethods_seq);
747     dmethods_seq = NULL;
748     Delete(dmethods_table);
749     dmethods_table = NULL;
750     n_dmethods = 0;
751 
752     /* Close all of the files */
753     Dump(f_header, f_runtime);
754 
755     if (directorsEnabled()) {
756       Dump(f_directors, f_runtime);
757       Dump(f_directors_h, f_runtime_h);
758 
759       Printf(f_runtime_h, "\n");
760       Printf(f_runtime_h, "#endif\n");
761 
762       Delete(f_runtime_h);
763       f_runtime_h = NULL;
764       Delete(f_directors);
765       f_directors = NULL;
766       Delete(f_directors_h);
767       f_directors_h = NULL;
768     }
769 
770     Dump(f_wrappers, f_runtime);
771     Wrapper_pretty_print(f_init, f_runtime);
772     Delete(f_header);
773     Delete(f_wrappers);
774     Delete(f_init);
775     Dump(f_runtime, f_begin);
776     Delete(f_runtime);
777     Delete(f_begin);
778     return SWIG_OK;
779   }
780 
781   /* -----------------------------------------------------------------------------
782    * emitBanner()
783    * ----------------------------------------------------------------------------- */
784 
emitBanner(File * f)785   void emitBanner(File *f) {
786     Printf(f, "/* ----------------------------------------------------------------------------\n");
787     Swig_banner_target_lang(f, " *");
788     Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
789   }
790 
791   /*-----------------------------------------------------------------------
792    * Add new director upcall signature
793    *----------------------------------------------------------------------*/
794 
addUpcallMethod(String * imclass_method,String * class_method,String * imclass_desc,String * class_desc,String * decl)795   UpcallData *addUpcallMethod(String *imclass_method, String *class_method, String *imclass_desc, String *class_desc, String *decl) {
796     String *key = NewStringf("%s|%s", imclass_method, decl);
797 
798     ++curr_class_dmethod;
799 
800     String *imclass_methodidx = NewStringf("%d", n_dmethods);
801     String *class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
802     n_dmethods++;
803 
804     Hash *new_udata = NewHash();
805     Append(dmethods_seq, new_udata);
806     Setattr(dmethods_table, key, new_udata);
807 
808     Setattr(new_udata, "method", Copy(class_method));
809     Setattr(new_udata, "fdesc", Copy(class_desc));
810     Setattr(new_udata, "imclass_method", Copy(imclass_method));
811     Setattr(new_udata, "imclass_fdesc", Copy(imclass_desc));
812     Setattr(new_udata, "imclass_methodidx", imclass_methodidx);
813     Setattr(new_udata, "class_methodidx", class_methodidx);
814     Setattr(new_udata, "decl", Copy(decl));
815 
816     Delete(key);
817     return new_udata;
818   }
819 
820   /*-----------------------------------------------------------------------
821    * Get director upcall signature
822    *----------------------------------------------------------------------*/
823 
getUpcallMethodData(String * director_class,String * decl)824   UpcallData *getUpcallMethodData(String *director_class, String *decl) {
825     String *key = NewStringf("%s|%s", director_class, decl);
826     UpcallData *udata = Getattr(dmethods_table, key);
827 
828     Delete(key);
829     return udata;
830   }
831 
832   /* ----------------------------------------------------------------------
833    * nativeWrapper()
834    * ---------------------------------------------------------------------- */
835 
nativeWrapper(Node * n)836   virtual int nativeWrapper(Node *n) {
837     String *wrapname = Getattr(n, "wrap:name");
838 
839     if (!addSymbol(wrapname, n, imclass_name))
840       return SWIG_ERROR;
841 
842     if (Getattr(n, "type")) {
843       Swig_save("nativeWrapper", n, "name", NIL);
844       Setattr(n, "name", wrapname);
845       native_function_flag = true;
846       functionWrapper(n);
847       Swig_restore(n);
848       native_function_flag = false;
849     } else {
850       Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
851     }
852 
853     return SWIG_OK;
854   }
855 
856   /* ----------------------------------------------------------------------
857    * functionWrapper()
858    * ---------------------------------------------------------------------- */
859 
functionWrapper(Node * n)860   virtual int functionWrapper(Node *n) {
861     String *symname = Getattr(n, "sym:name");
862     SwigType *t = Getattr(n, "type");
863     ParmList *l = Getattr(n, "parms");
864     String *tm;
865     Parm *p;
866     int i;
867     String *c_return_type = NewString("");
868     String *im_return_type = NewString("");
869     String *cleanup = NewString("");
870     String *outarg = NewString("");
871     String *body = NewString("");
872     int num_arguments = 0;
873     int gencomma = 0;
874     bool is_void_return;
875     String *overloaded_name = getOverloadedName(n);
876     String *nondir_args = NewString("");
877     bool is_destructor = (Cmp(Getattr(n, "nodeType"), "destructor") == 0);
878 
879     if (!Getattr(n, "sym:overloaded")) {
880       if (!addSymbol(symname, n, imclass_name))
881 	return SWIG_ERROR;
882     }
883 
884     /*
885        The rest of this function deals with generating the intermediary class wrapper function (that wraps
886        a c/c++ function) and generating the JNI c code. Each Java wrapper function has a
887        matching JNI c function call.
888      */
889 
890     // A new wrapper function object
891     Wrapper *f = NewWrapper();
892 
893     // Make a wrapper name for this function
894     String *jniname = makeValidJniName(overloaded_name);
895     String *wname = Swig_name_wrapper(jniname);
896 
897     Delete(jniname);
898 
899     /* Attach the non-standard typemaps to the parameter list. */
900     Swig_typemap_attach_parms("jni", l, f);
901     Swig_typemap_attach_parms("jtype", l, f);
902     Swig_typemap_attach_parms("jstype", l, f);
903 
904     /* Get return types */
905     if ((tm = Swig_typemap_lookup("jni", n, "", 0))) {
906       Printf(c_return_type, "%s", tm);
907     } else {
908       Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(t, 0));
909     }
910 
911     if ((tm = Swig_typemap_lookup("jtype", n, "", 0))) {
912       Printf(im_return_type, "%s", tm);
913     } else {
914       Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(t, 0));
915     }
916 
917     is_void_return = (Cmp(c_return_type, "void") == 0);
918     if (!is_void_return)
919       Wrapper_add_localv(f, "jresult", c_return_type, "jresult = 0", NIL);
920 
921     Printv(f->def, "SWIGEXPORT ", c_return_type, " JNICALL ", wname, "(JNIEnv *jenv, jclass jcls", NIL);
922 
923     // Usually these function parameters are unused - The code below ensures
924     // that compilers do not issue such a warning if configured to do so.
925 
926     Printv(f->code, "    (void)jenv;\n", NIL);
927     Printv(f->code, "    (void)jcls;\n", NIL);
928 
929     // Emit all of the local variables for holding arguments.
930     emit_parameter_variables(l, f);
931 
932     /* Attach the standard typemaps */
933     emit_attach_parmmaps(l, f);
934 
935     // Parameter overloading
936     Setattr(n, "wrap:parms", l);
937     Setattr(n, "wrap:name", wname);
938 
939     // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
940     if (Getattr(n, "sym:overloaded")) {
941       // Emit warnings for the few cases that can't be overloaded in Java and give up on generating wrapper
942       Swig_overload_check(n);
943       if (Getattr(n, "overload:ignore")) {
944 	DelWrapper(f);
945 	return SWIG_OK;
946       }
947     }
948 
949     Printf(imclass_class_code, "  public final static native %s %s(", im_return_type, overloaded_name);
950 
951     num_arguments = emit_num_arguments(l);
952 
953     // Now walk the function parameter list and generate code to get arguments
954     for (i = 0, p = l; i < num_arguments; i++) {
955 
956       while (checkAttribute(p, "tmap:in:numinputs", "0")) {
957 	p = Getattr(p, "tmap:in:next");
958       }
959 
960       SwigType *pt = Getattr(p, "type");
961       String *ln = Getattr(p, "lname");
962       String *im_param_type = NewString("");
963       String *c_param_type = NewString("");
964       String *arg = NewString("");
965 
966       Printf(arg, "j%s", ln);
967 
968       /* Get the JNI C types of the parameter */
969       if ((tm = Getattr(p, "tmap:jni"))) {
970 	Printv(c_param_type, tm, NIL);
971       } else {
972 	Swig_warning(WARN_JAVA_TYPEMAP_JNI_UNDEF, input_file, line_number, "No jni typemap defined for %s\n", SwigType_str(pt, 0));
973       }
974 
975       /* Get the intermediary class parameter types of the parameter */
976       if ((tm = Getattr(p, "tmap:jtype"))) {
977 	Printv(im_param_type, tm, NIL);
978       } else {
979 	Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(pt, 0));
980       }
981 
982       /* Add parameter to intermediary class method */
983       if (gencomma)
984 	Printf(imclass_class_code, ", ");
985       Printf(imclass_class_code, "%s %s", im_param_type, arg);
986 
987       // Add parameter to C function
988       Printv(f->def, ", ", c_param_type, " ", arg, NIL);
989 
990       ++gencomma;
991 
992       // Premature garbage collection prevention parameter
993       if (!is_destructor) {
994 	String *pgc_parameter = prematureGarbageCollectionPreventionParameter(pt, p);
995 	if (pgc_parameter) {
996 	  Printf(imclass_class_code, ", %s %s_", pgc_parameter, arg);
997 	  Printf(f->def, ", jobject %s_", arg);
998 	  Printf(f->code, "    (void)%s_;\n", arg);
999 	}
1000       }
1001       // Get typemap for this argument
1002       if ((tm = Getattr(p, "tmap:in"))) {
1003 	addThrows(n, "tmap:in", p);
1004 	Replaceall(tm, "$source", arg);	/* deprecated */
1005 	Replaceall(tm, "$target", ln);	/* deprecated */
1006 	Replaceall(tm, "$arg", arg);	/* deprecated? */
1007 	Replaceall(tm, "$input", arg);
1008 	Setattr(p, "emit:input", arg);
1009 
1010 	Printf(nondir_args, "%s\n", tm);
1011 
1012 	p = Getattr(p, "tmap:in:next");
1013       } else {
1014 	Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
1015 	p = nextSibling(p);
1016       }
1017 
1018       Delete(im_param_type);
1019       Delete(c_param_type);
1020       Delete(arg);
1021     }
1022 
1023     Printv(f->code, nondir_args, NIL);
1024     Delete(nondir_args);
1025 
1026     /* Insert constraint checking code */
1027     for (p = l; p;) {
1028       if ((tm = Getattr(p, "tmap:check"))) {
1029 	addThrows(n, "tmap:check", p);
1030 	Replaceall(tm, "$target", Getattr(p, "lname"));	/* deprecated */
1031 	Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */
1032 	Replaceall(tm, "$input", Getattr(p, "emit:input"));
1033 	Printv(f->code, tm, "\n", NIL);
1034 	p = Getattr(p, "tmap:check:next");
1035       } else {
1036 	p = nextSibling(p);
1037       }
1038     }
1039 
1040     /* Insert cleanup code */
1041     for (p = l; p;) {
1042       if ((tm = Getattr(p, "tmap:freearg"))) {
1043 	addThrows(n, "tmap:freearg", p);
1044 	Replaceall(tm, "$source", Getattr(p, "emit:input"));	/* deprecated */
1045 	Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */
1046 	Replaceall(tm, "$input", Getattr(p, "emit:input"));
1047 	Printv(cleanup, tm, "\n", NIL);
1048 	p = Getattr(p, "tmap:freearg:next");
1049       } else {
1050 	p = nextSibling(p);
1051       }
1052     }
1053 
1054     /* Insert argument output code */
1055     for (p = l; p;) {
1056       if ((tm = Getattr(p, "tmap:argout"))) {
1057 	addThrows(n, "tmap:argout", p);
1058 	Replaceall(tm, "$source", Getattr(p, "emit:input"));	/* deprecated */
1059 	Replaceall(tm, "$target", Getattr(p, "lname"));	/* deprecated */
1060 	Replaceall(tm, "$arg", Getattr(p, "emit:input"));	/* deprecated? */
1061 	Replaceall(tm, "$result", "jresult");
1062 	Replaceall(tm, "$input", Getattr(p, "emit:input"));
1063 	Printv(outarg, tm, "\n", NIL);
1064 	p = Getattr(p, "tmap:argout:next");
1065       } else {
1066 	p = nextSibling(p);
1067       }
1068     }
1069 
1070     // Get any Java exception classes in the throws typemap
1071     ParmList *throw_parm_list = NULL;
1072     if ((throw_parm_list = Getattr(n, "catchlist"))) {
1073       Swig_typemap_attach_parms("throws", throw_parm_list, f);
1074       for (p = throw_parm_list; p; p = nextSibling(p)) {
1075 	if (Getattr(p, "tmap:throws")) {
1076 	  addThrows(n, "tmap:throws", p);
1077 	}
1078       }
1079     }
1080 
1081     // Now write code to make the function call
1082     if (!native_function_flag) {
1083 
1084       Swig_director_emit_dynamic_cast(n, f);
1085       String *actioncode = emit_action(n);
1086 
1087       // Handle exception classes specified in the "except" feature's "throws" attribute
1088       addThrows(n, "feature:except", n);
1089 
1090       /* Return value if necessary  */
1091       if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
1092 	addThrows(n, "tmap:out", n);
1093 	Replaceall(tm, "$source", Swig_cresult_name());	/* deprecated */
1094 	Replaceall(tm, "$target", "jresult");	/* deprecated */
1095 	Replaceall(tm, "$result", "jresult");
1096 
1097         if (GetFlag(n, "feature:new"))
1098           Replaceall(tm, "$owner", "1");
1099         else
1100           Replaceall(tm, "$owner", "0");
1101 
1102 	Printf(f->code, "%s", tm);
1103 	if (Len(tm))
1104 	  Printf(f->code, "\n");
1105       } else {
1106 	Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t, 0), Getattr(n, "name"));
1107       }
1108       emit_return_variable(n, t, f);
1109     }
1110 
1111     /* Output argument output code */
1112     Printv(f->code, outarg, NIL);
1113 
1114     /* Output cleanup code */
1115     Printv(f->code, cleanup, NIL);
1116 
1117     /* Look to see if there is any newfree cleanup code */
1118     if (GetFlag(n, "feature:new")) {
1119       if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
1120 	addThrows(n, "tmap:newfree", n);
1121 	Replaceall(tm, "$source", Swig_cresult_name());	/* deprecated */
1122 	Printf(f->code, "%s\n", tm);
1123       }
1124     }
1125 
1126     /* See if there is any return cleanup code */
1127     if (!native_function_flag) {
1128       if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
1129 	addThrows(n, "tmap:ret", n);
1130 	Replaceall(tm, "$source", Swig_cresult_name());	/* deprecated */
1131 	Printf(f->code, "%s\n", tm);
1132       }
1133     }
1134 
1135     /* Finish C function and intermediary class function definitions */
1136     Printf(imclass_class_code, ")");
1137     generateThrowsClause(n, imclass_class_code);
1138     Printf(imclass_class_code, ";\n");
1139 
1140     Printf(f->def, ") {");
1141 
1142     if (!is_void_return)
1143       Printv(f->code, "    return jresult;\n", NIL);
1144     Printf(f->code, "}\n");
1145 
1146     /* Substitute the cleanup code */
1147     Replaceall(f->code, "$cleanup", cleanup);
1148 
1149     /* Substitute the function name */
1150     Replaceall(f->code, "$symname", symname);
1151 
1152     /* Contract macro modification */
1153     Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ");
1154 
1155     if (!is_void_return)
1156       Replaceall(f->code, "$null", "0");
1157     else
1158       Replaceall(f->code, "$null", "");
1159 
1160     /* Dump the function out */
1161     if (!native_function_flag)
1162       Wrapper_print(f, f_wrappers);
1163 
1164     if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
1165       moduleClassFunctionHandler(n);
1166     }
1167 
1168     /*
1169      * Generate the proxy class getters/setters for public member variables.
1170      * Not for enums and constants.
1171      */
1172     if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
1173       // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name
1174       bool getter_flag = Cmp(symname, Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) != 0;
1175 
1176       String *getter_setter_name = NewString("");
1177       if (!getter_flag)
1178 	Printf(getter_setter_name, "set");
1179       else
1180 	Printf(getter_setter_name, "get");
1181       Putc(toupper((int) *Char(variable_name)), getter_setter_name);
1182       Printf(getter_setter_name, "%s", Char(variable_name) + 1);
1183 
1184       Setattr(n, "proxyfuncname", getter_setter_name);
1185       Setattr(n, "imfuncname", symname);
1186 
1187       proxyClassFunctionHandler(n);
1188       Delete(getter_setter_name);
1189     }
1190 
1191     Delete(c_return_type);
1192     Delete(im_return_type);
1193     Delete(cleanup);
1194     Delete(outarg);
1195     Delete(body);
1196     Delete(overloaded_name);
1197     DelWrapper(f);
1198     return SWIG_OK;
1199   }
1200 
1201   /* -----------------------------------------------------------------------
1202    * variableWrapper()
1203    * ----------------------------------------------------------------------- */
1204 
variableWrapper(Node * n)1205   virtual int variableWrapper(Node *n) {
1206     variable_wrapper_flag = true;
1207     Language::variableWrapper(n);	/* Default to functions */
1208     variable_wrapper_flag = false;
1209     return SWIG_OK;
1210   }
1211 
1212   /* -----------------------------------------------------------------------
1213    * globalvariableHandler()
1214    * ------------------------------------------------------------------------ */
1215 
globalvariableHandler(Node * n)1216   virtual int globalvariableHandler(Node *n) {
1217 
1218     variable_name = Getattr(n, "sym:name");
1219     global_variable_flag = true;
1220     int ret = Language::globalvariableHandler(n);
1221     global_variable_flag = false;
1222     return ret;
1223   }
1224 
getCurrentScopeName(String * nspace)1225   String *getCurrentScopeName(String *nspace) {
1226     String *scope = 0;
1227     if (nspace || getCurrentClass()) {
1228       scope = NewString("");
1229       if (nspace)
1230 	Printf(scope, "%s", nspace);
1231       if (Node* cls = getCurrentClass()) {
1232 	if (Node *outer = Getattr(cls, "nested:outer")) {
1233 	  String *outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
1234 	  for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
1235 	    Push(outerClassesPrefix, ".");
1236 	    Push(outerClassesPrefix, Getattr(outer, "sym:name"));
1237 	  }
1238 	  Printv(scope, nspace ? "." : "", outerClassesPrefix, ".", proxy_class_name, NIL);
1239 	  Delete(outerClassesPrefix);
1240 	} else
1241 	  Printv(scope, nspace ? "." : "", proxy_class_name, NIL);
1242       }
1243     }
1244     return scope;
1245   }
1246 
1247   /* ----------------------------------------------------------------------
1248    * enumDeclaration()
1249    *
1250    * C/C++ enums can be mapped in one of 4 ways, depending on the java:enum feature specified:
1251    * 1) Simple enums - simple constant within the proxy class or module class
1252    * 2) Typeunsafe enums - simple constant in a Java class (class named after the c++ enum name)
1253    * 3) Typesafe enum - typesafe enum pattern (class named after the c++ enum name)
1254    * 4) Proper enums - proper Java enum
1255    * Anonymous enums always default to 1)
1256    * ---------------------------------------------------------------------- */
1257 
enumDeclaration(Node * n)1258   virtual int enumDeclaration(Node *n) {
1259 
1260     if (!ImportMode) {
1261       if (getCurrentClass() && (cplus_mode != PUBLIC))
1262 	return SWIG_NOWRAP;
1263 
1264       String *nspace = Getattr(n, "sym:nspace"); // NSpace/getNSpace() only works during Language::enumDeclaration call
1265       if (proxy_flag && !is_wrapping_class()) {
1266 	// Global enums / enums in a namespace
1267 	assert(!full_imclass_name);
1268 	constructIntermediateClassName(n);
1269       }
1270 
1271       enum_code = NewString("");
1272       String *symname = Getattr(n, "sym:name");
1273       String *constants_code = (proxy_flag && is_wrapping_class())? proxy_class_constants_code : module_class_constants_code;
1274       EnumFeature enum_feature = decodeEnumFeature(n);
1275       String *typemap_lookup_type = Getattr(n, "name");
1276 
1277       if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
1278 	// Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
1279 
1280 	if (doxygen && doxygenTranslator->hasDocumentation(n)) {
1281 	  String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
1282 	  if (comment_creation_chatter)
1283 	    Printf(enum_code, "/* This was generated from enumDeclaration() */\n");
1284 	  Printv(enum_code, Char(doxygen_comments), NIL);
1285 	  Delete(doxygen_comments);
1286 	}
1287 
1288 	String *scope = getCurrentScopeName(nspace);
1289 	if (!addSymbol(symname, n, scope))
1290 	  return SWIG_ERROR;
1291 
1292 	// Pure Java baseclass and interfaces
1293 	const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE);
1294 	const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
1295 
1296 	// Emit the enum
1297 	Printv(enum_code, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF),	// Class modifiers (enum modifiers really)
1298 	       " ", symname, *Char(pure_baseclass) ?	// Bases
1299 	       " extends " : "", pure_baseclass, *Char(pure_interfaces) ?	// Interfaces
1300 	       " implements " : "", pure_interfaces, " {\n", NIL);
1301 	if (proxy_flag && is_wrapping_class())
1302 	  Replaceall(enum_code, "$static ", "static ");
1303 	else
1304 	  Replaceall(enum_code, "$static ", "");
1305 	Delete(scope);
1306       } else {
1307 	if (symname && !Getattr(n, "unnamedinstance"))
1308 	  Printf(constants_code, "  // %s \n", symname);
1309 	// Translate and write javadoc comment for the enum itself if flagged
1310 	if (doxygen && doxygenTranslator->hasDocumentation(n)) {
1311 	  String *doxygen_comments = doxygenTranslator->getDocumentation(n, "  ");
1312 	  if (comment_creation_chatter)
1313 	    Printf(constants_code, "/* This was generated from enumDeclaration() */\n");
1314 	  Printf(constants_code, Char(doxygen_comments));
1315 	  Printf(constants_code, "\n");
1316 	  Delete(doxygen_comments);
1317 	}
1318       }
1319 
1320       // Emit each enum item
1321       Language::enumDeclaration(n);
1322 
1323       if ((enum_feature != SimpleEnum) && symname && typemap_lookup_type) {
1324 	// Wrap (non-anonymous) C/C++ enum within a typesafe, typeunsafe or proper Java enum
1325 	// Finish the enum declaration
1326 	// Typemaps are used to generate the enum definition in a similar manner to proxy classes.
1327 	Printv(enum_code, (enum_feature == ProperEnum) ? ";\n" : "", typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF),	// main body of class
1328 	       typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE),	// extra Java code
1329 	       "}", NIL);
1330 
1331 	Replaceall(enum_code, "$javaclassname", symname);
1332 
1333 	// Substitute $enumvalues - intended usage is for typesafe enums
1334 	if (Getattr(n, "enumvalues"))
1335 	  Replaceall(enum_code, "$enumvalues", Getattr(n, "enumvalues"));
1336 	else
1337 	  Replaceall(enum_code, "$enumvalues", "");
1338 
1339 	if (proxy_flag && is_wrapping_class()) {
1340 	  // Enums defined within the C++ class are defined within the proxy class
1341 
1342 	  // Add extra indentation
1343 	  Replaceall(enum_code, "\n", "\n  ");
1344 	  Replaceall(enum_code, "  \n", "\n");
1345 	  if (GetFlag(getCurrentClass(), "feature:interface"))
1346 	    Printv(interface_class_code, "  ", enum_code, "\n\n", NIL);
1347 	  else
1348 	    Printv(proxy_class_constants_code, "  ", enum_code, "\n\n", NIL);
1349 	} else {
1350 	  // Global enums are defined in their own file
1351 	  String *output_directory = outputDirectory(nspace);
1352 	  String *filen = NewStringf("%s%s.java", output_directory, symname);
1353 	  File *f_enum = NewFile(filen, "w", SWIG_output_files());
1354 	  if (!f_enum) {
1355 	    FileErrorDisplay(filen);
1356 	    SWIG_exit(EXIT_FAILURE);
1357 	  }
1358 	  Append(filenames_list, Copy(filen));
1359 	  Delete(filen);
1360 	  filen = NULL;
1361 
1362 	  // Start writing out the enum file
1363 	  emitBanner(f_enum);
1364 
1365 	  if (package || nspace) {
1366 	    Printf(f_enum, "package ");
1367 	    if (package)
1368 	      Printv(f_enum, package, nspace ? "." : "", NIL);
1369 	    if (nspace)
1370 	      Printv(f_enum, nspace, NIL);
1371 	    Printf(f_enum, ";\n");
1372 	  }
1373 
1374 	  Printv(f_enum, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE), // Import statements
1375 		 "\n", enum_code, "\n", NIL);
1376 
1377 	  Printf(f_enum, "\n");
1378 	  Delete(f_enum);
1379 	  Delete(output_directory);
1380 	}
1381       } else {
1382 	// Wrap C++ enum with simple constant
1383 	Printf(enum_code, "\n");
1384 	if (proxy_flag && is_wrapping_class())
1385 	  Printv(proxy_class_constants_code, enum_code, NIL);
1386 	else
1387 	  Printv(module_class_constants_code, enum_code, NIL);
1388       }
1389 
1390       Delete(enum_code);
1391       enum_code = NULL;
1392 
1393       if (proxy_flag && !is_wrapping_class()) {
1394 	Delete(full_imclass_name);
1395 	full_imclass_name = 0;
1396       }
1397     }
1398     return SWIG_OK;
1399   }
1400 
1401   /* ----------------------------------------------------------------------
1402    * enumvalueDeclaration()
1403    * ---------------------------------------------------------------------- */
1404 
enumvalueDeclaration(Node * n)1405   virtual int enumvalueDeclaration(Node *n) {
1406     if (getCurrentClass() && (cplus_mode != PUBLIC))
1407       return SWIG_NOWRAP;
1408 
1409     Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
1410     String *symname = Getattr(n, "sym:name");
1411     String *value = Getattr(n, "value");
1412     String *name = Getattr(n, "name");
1413     Node *parent = parentNode(n);
1414     int unnamedinstance = GetFlag(parent, "unnamedinstance");
1415     String *parent_name = Getattr(parent, "name");
1416     String *nspace = getNSpace();
1417     String *newsymname = 0;
1418     String *tmpValue;
1419 
1420     // Strange hack from parent method
1421     if (value)
1422       tmpValue = NewString(value);
1423     else
1424       tmpValue = NewString(name);
1425     // Note that this is used in enumValue() amongst other places
1426     Setattr(n, "value", tmpValue);
1427 
1428     // Deal with enum values that are not int
1429     int swigtype = SwigType_type(Getattr(n, "type"));
1430     if (swigtype == T_BOOL) {
1431       const char *val = Equal(Getattr(n, "enumvalue"), "true") ? "1" : "0";
1432       Setattr(n, "enumvalue", val);
1433     } else if (swigtype == T_CHAR) {
1434       String *val = NewStringf("'%(escape)s'", Getattr(n, "enumvalue"));
1435       Setattr(n, "enumvalue", val);
1436       Delete(val);
1437     }
1438 
1439     {
1440       EnumFeature enum_feature = decodeEnumFeature(parent);
1441 
1442       if ((enum_feature == SimpleEnum) && GetFlag(parent, "scopedenum")) {
1443 	newsymname = Swig_name_member(0, Getattr(parent, "sym:name"), symname);
1444 	symname = newsymname;
1445       }
1446 
1447       // Add to language symbol table
1448       String *scope = 0;
1449       if (unnamedinstance || !parent_name || enum_feature == SimpleEnum) {
1450 	String *enumClassPrefix = getEnumClassPrefix();
1451 	if (enumClassPrefix) {
1452 	  scope = NewString("");
1453 	  if (nspace)
1454 	    Printf(scope, "%s.", nspace);
1455 	  Printf(scope, "%s", enumClassPrefix);
1456 	} else {
1457 	  scope = Copy(constants_interface_name);
1458 	}
1459       } else {
1460 	scope = getCurrentScopeName(nspace);
1461 	if (!scope)
1462 	  scope = Copy(Getattr(parent, "sym:name"));
1463 	else
1464 	  Printf(scope, ".%s", Getattr(parent, "sym:name"));
1465       }
1466       if (!addSymbol(symname, n, scope))
1467 	return SWIG_ERROR;
1468 
1469       if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
1470 	if (!GetFlag(n, "firstenumitem"))
1471 	  Printf(enum_code, ",\n");
1472       }
1473 
1474       // Translate and write javadoc comment if flagged
1475       if (doxygen && doxygenTranslator->hasDocumentation(n)) {
1476 	String *doxygen_comments = doxygenTranslator->getDocumentation(n, "  ");
1477 	if (comment_creation_chatter)
1478 	  Printf(enum_code, "/* This was generated from enumvalueDeclaration() */\n");
1479 	Printv(enum_code, Char(doxygen_comments), NIL);
1480 	Delete(doxygen_comments);
1481       }
1482 
1483       if ((enum_feature == ProperEnum) && parent_name && !unnamedinstance) {
1484 	// Wrap (non-anonymous) C/C++ enum with a proper Java enum
1485 	// Emit the enum item.
1486 	Printf(enum_code, "  %s", symname);
1487 	if (Getattr(n, "enumvalue")) {
1488 	  String *value = enumValue(n);
1489 	  Printf(enum_code, "(%s)", value);
1490 	  Delete(value);
1491 	}
1492       } else {
1493 	// Wrap C/C++ enums with constant integers or use the typesafe enum pattern
1494 	SwigType *typemap_lookup_type = parent_name ? parent_name : NewString("enum ");
1495 	Setattr(n, "type", typemap_lookup_type);
1496 	const String *tm = typemapLookup(n, "jstype", typemap_lookup_type, WARN_JAVA_TYPEMAP_JSTYPE_UNDEF);
1497 
1498 	String *return_type = Copy(tm);
1499 	substituteClassname(typemap_lookup_type, return_type);
1500         const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
1501         methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1502 
1503 	if ((enum_feature == TypesafeEnum) && parent_name && !unnamedinstance) {
1504 	  // Wrap (non-anonymous) enum using the typesafe enum pattern
1505 	  if (Getattr(n, "enumvalue")) {
1506 	    String *value = enumValue(n);
1507 	    Printf(enum_code, "  %s final static %s %s = new %s(\"%s\", %s);\n", methodmods, return_type, symname, return_type, symname, value);
1508 	    Delete(value);
1509 	  } else {
1510 	    Printf(enum_code, "  %s final static %s %s = new %s(\"%s\");\n", methodmods, return_type, symname, return_type, symname);
1511 	  }
1512 	} else {
1513 	  // Simple integer constants
1514 	  // Note these are always generated for anonymous enums, no matter what enum_feature is specified
1515 	  // Code generated is the same for SimpleEnum and TypeunsafeEnum -> the class it is generated into is determined later
1516 	  String *value = enumValue(n);
1517 	  Printf(enum_code, "  %s final static %s %s = %s;\n", methodmods, return_type, symname, value);
1518 	  Delete(value);
1519 	}
1520 	Delete(return_type);
1521       }
1522 
1523       // Add the enum value to the comma separated list being constructed in the enum declaration.
1524       String *enumvalues = Getattr(parent, "enumvalues");
1525       if (!enumvalues)
1526 	Setattr(parent, "enumvalues", Copy(symname));
1527       else
1528 	Printv(enumvalues, ", ", symname, NIL);
1529       Delete(scope);
1530     }
1531 
1532     Delete(newsymname);
1533     Delete(tmpValue);
1534     Swig_restore(n);
1535     return SWIG_OK;
1536   }
1537 
1538   /* -----------------------------------------------------------------------
1539    * constantWrapper()
1540    * Used for wrapping constants - #define or %constant.
1541    * Also for inline initialised const static primitive type member variables (short, int, double, enums etc).
1542    * Java static final variables are generated for these.
1543    * If the %javaconst(1) feature is used then the C constant value is used to initialise the Java final variable.
1544    * If not, a JNI method is generated to get the C constant value for initialisation of the Java final variable.
1545    * However, if the %javaconstvalue feature is used, it overrides all other ways to generate the initialisation.
1546    * Also note that this method might be called for wrapping enum items (when the enum is using %javaconst(0)).
1547    * ------------------------------------------------------------------------ */
1548 
constantWrapper(Node * n)1549   virtual int constantWrapper(Node *n) {
1550     String *symname = Getattr(n, "sym:name");
1551     SwigType *t = Getattr(n, "type");
1552     SwigType *valuetype = Getattr(n, "valuetype");
1553     ParmList *l = Getattr(n, "parms");
1554     String *tm;
1555     String *return_type = NewString("");
1556     String *constants_code = NewString("");
1557     Swig_save("constantWrapper", n, "value", NIL);
1558 
1559     // Translate and write javadoc comment if flagged
1560     if (doxygen && doxygenTranslator->hasDocumentation(n)) {
1561       String *doxygen_comments = doxygenTranslator->getDocumentation(n, "  ");
1562       if (comment_creation_chatter)
1563 	Printf(constants_code, "/* This was generated from constantWrapper() */\n");
1564       Printv(constants_code, Char(doxygen_comments), NIL);
1565       Delete(doxygen_comments);
1566     }
1567 
1568     bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
1569 
1570     const String *itemname = (proxy_flag && wrapping_member_flag) ? variable_name : symname;
1571     if (!is_enum_item) {
1572       String *scope = 0;
1573       if (proxy_class_name) {
1574 	String *nspace = getNSpace();
1575 	scope = NewString("");
1576 	if (nspace)
1577 	  Printf(scope, "%s.", nspace);
1578 	Printf(scope, "%s", proxy_class_name);
1579       } else {
1580 	scope = Copy(constants_interface_name);
1581       }
1582       if (!addSymbol(itemname, n, scope))
1583 	return SWIG_ERROR;
1584       Delete(scope);
1585     }
1586 
1587     // The %javaconst feature determines how the constant value is obtained
1588     int const_feature_flag = GetFlag(n, "feature:java:const");
1589 
1590     /* Adjust the enum type for the Swig_typemap_lookup.
1591      * We want the same jstype typemap for all the enum items so we use the enum type (parent node). */
1592     if (is_enum_item) {
1593       t = Getattr(parentNode(n), "enumtype");
1594       Setattr(n, "type", t);
1595     }
1596 
1597     /* Attach the non-standard typemaps to the parameter list. */
1598     Swig_typemap_attach_parms("jstype", l, NULL);
1599 
1600     /* Get Java return types */
1601     bool classname_substituted_flag = false;
1602 
1603     if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
1604       classname_substituted_flag = substituteClassname(t, tm);
1605       Printf(return_type, "%s", tm);
1606     } else {
1607       Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
1608     }
1609 
1610     // Add the stripped quotes back in
1611     String *new_value = NewString("");
1612     if (SwigType_type(t) == T_STRING) {
1613       Printf(new_value, "\"%s\"", Copy(Getattr(n, "value")));
1614       Setattr(n, "value", new_value);
1615     } else if (SwigType_type(t) == T_CHAR) {
1616       Printf(new_value, "\'%s\'", Copy(Getattr(n, "value")));
1617       Setattr(n, "value", new_value);
1618     }
1619 
1620     const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
1621     methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
1622 
1623     Printf(constants_code, "  %s final static %s %s = ", methodmods, return_type, itemname);
1624 
1625     // Check for the %javaconstvalue feature
1626     String *value = Getattr(n, "feature:java:constvalue");
1627 
1628     if (value) {
1629       Printf(constants_code, "%s;\n", value);
1630     } else if (!const_feature_flag) {
1631       // Default enum and constant handling will work with any type of C constant and initialises the Java variable from C through a JNI call.
1632 
1633       if (classname_substituted_flag) {
1634 	if (SwigType_isenum(t)) {
1635 	  // This handles wrapping of inline initialised const enum static member variables (not when wrapping enum items - ignored later on)
1636 	  Printf(constants_code, "%s.swigToEnum(%s.%s());\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
1637 	} else {
1638 	  // This handles function pointers using the %constant directive
1639 	  Printf(constants_code, "new %s(%s.%s(), false);\n", return_type, full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
1640 	}
1641       } else {
1642 	Printf(constants_code, "%s.%s();\n", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
1643       }
1644 
1645       // Each constant and enum value is wrapped with a separate JNI function call
1646       SetFlag(n, "feature:immutable");
1647       enum_constant_flag = true;
1648       variableWrapper(n);
1649       enum_constant_flag = false;
1650     } else {
1651       // Alternative constant handling will use the C syntax to make a true Java constant and hope that it compiles as Java code
1652       if (Getattr(n, "wrappedasconstant")) {
1653 	if (SwigType_type(valuetype) == T_CHAR)
1654           Printf(constants_code, "\'%(escape)s\';\n", Getattr(n, "staticmembervariableHandler:value"));
1655 	else
1656           Printf(constants_code, "%s;\n", Getattr(n, "staticmembervariableHandler:value"));
1657       } else {
1658         Printf(constants_code, "%s;\n", Getattr(n, "value"));
1659       }
1660     }
1661 
1662     // Emit the generated code to appropriate place
1663     // Enums only emit the intermediate and JNI methods, so no proxy or module class wrapper methods needed
1664     if (!is_enum_item) {
1665       if (proxy_flag && wrapping_member_flag)
1666 	Printv(proxy_class_constants_code, constants_code, NIL);
1667       else
1668 	Printv(module_class_constants_code, constants_code, NIL);
1669     }
1670     // Cleanup
1671     Swig_restore(n);
1672     Delete(new_value);
1673     Delete(return_type);
1674     Delete(constants_code);
1675     return SWIG_OK;
1676   }
1677 
1678   /* -----------------------------------------------------------------------------
1679    * insertDirective()
1680    * ----------------------------------------------------------------------------- */
1681 
insertDirective(Node * n)1682   virtual int insertDirective(Node *n) {
1683     int ret = SWIG_OK;
1684     String *code = Getattr(n, "code");
1685     String *section = Getattr(n, "section");
1686     Replaceall(code, "$module", module_class_name);
1687     Replaceall(code, "$imclassname", imclass_name);
1688 
1689     if (!ImportMode && (Cmp(section, "proxycode") == 0)) {
1690       if (proxy_class_code) {
1691 	Swig_typemap_replace_embedded_typemap(code, n);
1692 	int offset = Len(code) > 0 && *Char(code) == '\n' ? 1 : 0;
1693 	Printv(proxy_class_code, Char(code) + offset, "\n", NIL);
1694       }
1695     } else {
1696       ret = Language::insertDirective(n);
1697     }
1698     return ret;
1699   }
1700 
1701   /* -----------------------------------------------------------------------------
1702    * pragmaDirective()
1703    *
1704    * Valid Pragmas:
1705    * jniclassbase            - base (extends) for the intermediary class
1706    * jniclasspackage         - package in which to generate the intermediary class
1707    * jniclassclassmodifiers  - class modifiers for the intermediary class
1708    * jniclasscode            - text (java code) is copied verbatim to the intermediary class
1709    * jniclassimports         - import statements for the intermediary class
1710    * jniclassinterfaces      - interface (implements) for the intermediary class
1711    *
1712    * modulebase              - base (extends) for the module class
1713    * moduleclassmodifiers    - class modifiers for the module class
1714    * modulecode              - text (java code) is copied verbatim to the module class
1715    * moduleimports           - import statements for the module class
1716    * moduleinterfaces        - interface (implements) for the module class
1717    *
1718    * ----------------------------------------------------------------------------- */
1719 
pragmaDirective(Node * n)1720   virtual int pragmaDirective(Node *n) {
1721     if (!ImportMode) {
1722       String *lang = Getattr(n, "lang");
1723       String *code = Getattr(n, "name");
1724       String *value = Getattr(n, "value");
1725 
1726       if (Strcmp(lang, "java") == 0) {
1727 
1728 	String *strvalue = NewString(value);
1729 	Replaceall(strvalue, "\\\"", "\"");
1730 
1731 	if (Strcmp(code, "jniclassbase") == 0) {
1732 	  Delete(imclass_baseclass);
1733 	  imclass_baseclass = Copy(strvalue);
1734 	} else if (Strcmp(code, "jniclasspackage") == 0) {
1735 	  Delete(imclass_package);
1736 	  imclass_package = Copy(strvalue);
1737 	  String *imclass_class_package_jniname = makeValidJniName(imclass_package);
1738 	  Printv(jnipackage, imclass_class_package_jniname, NIL);
1739 	  Delete(imclass_class_package_jniname);
1740 	  Replaceall(jnipackage, NSPACE_SEPARATOR, "_");
1741 	  Append(jnipackage, "_");
1742 
1743 	  String *wrapper_name = NewString("");
1744 	  String *imclass_class_jniname = makeValidJniName(imclass_name);
1745 	  Printf(wrapper_name, "Java_%s%s_%%f", jnipackage, imclass_class_jniname);
1746 	  Delete(imclass_class_jniname);
1747 
1748 	  Swig_name_unregister("wrapper");
1749 	  Swig_name_register("wrapper", Char(wrapper_name));
1750 
1751 	  Delete(wrapper_name);
1752 	} else if (Strcmp(code, "jniclassclassmodifiers") == 0) {
1753 	  Delete(imclass_class_modifiers);
1754 	  imclass_class_modifiers = Copy(strvalue);
1755 	} else if (Strcmp(code, "jniclasscode") == 0) {
1756 	  Printf(imclass_class_code, "%s\n", strvalue);
1757 	} else if (Strcmp(code, "jniclassimports") == 0) {
1758 	  Delete(imclass_imports);
1759 	  imclass_imports = Copy(strvalue);
1760 	} else if (Strcmp(code, "jniclassinterfaces") == 0) {
1761 	  Delete(imclass_interfaces);
1762 	  imclass_interfaces = Copy(strvalue);
1763 	} else if (Strcmp(code, "modulebase") == 0) {
1764 	  Delete(module_baseclass);
1765 	  module_baseclass = Copy(strvalue);
1766 	} else if (Strcmp(code, "moduleclassmodifiers") == 0) {
1767 	  Delete(module_class_modifiers);
1768 	  module_class_modifiers = Copy(strvalue);
1769 	} else if (Strcmp(code, "modulecode") == 0) {
1770 	  Printf(module_class_code, "%s\n", strvalue);
1771 	} else if (Strcmp(code, "moduleimports") == 0) {
1772 	  Delete(module_imports);
1773 	  module_imports = Copy(strvalue);
1774 	} else if (Strcmp(code, "moduleinterfaces") == 0) {
1775 	  Delete(module_interfaces);
1776 	  module_interfaces = Copy(strvalue);
1777 	} else if (Strcmp(code, "moduleimport") == 0) {
1778 	  Swig_error(input_file, line_number, "Deprecated pragma. Please use the moduleimports pragma.\n");
1779 	} else if (Strcmp(code, "moduleinterface") == 0) {
1780 	  Swig_error(input_file, line_number, "Deprecated pragma. Please use the moduleinterfaces pragma.\n");
1781 	} else if (Strcmp(code, "modulemethodmodifiers") == 0) {
1782 	  Swig_error(input_file, line_number, "Deprecated pragma. Please use %%javamethodmodifiers.\n");
1783 	} else if (Strcmp(code, "allshadowimport") == 0) {
1784 	  Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaimports).\n");
1785 	} else if (Strcmp(code, "allshadowcode") == 0) {
1786 	  Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javacode).\n");
1787 	} else if (Strcmp(code, "allshadowbase") == 0) {
1788 	  Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javabase).\n");
1789 	} else if (Strcmp(code, "allshadowinterface") == 0) {
1790 	  Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javainterfaces).\n");
1791 	} else if (Strcmp(code, "allshadowclassmodifiers") == 0) {
1792 	  Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n");
1793 	} else if (proxy_flag) {
1794 	  if (Strcmp(code, "shadowcode") == 0) {
1795 	    Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javacode).\n");
1796 	  } else if (Strcmp(code, "shadowimport") == 0) {
1797 	    Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaimports).\n");
1798 	  } else if (Strcmp(code, "shadowbase") == 0) {
1799 	    Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javabase).\n");
1800 	  } else if (Strcmp(code, "shadowinterface") == 0) {
1801 	    Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javainterfaces).\n");
1802 	  } else if (Strcmp(code, "shadowclassmodifiers") == 0) {
1803 	    Swig_error(input_file, line_number, "Deprecated pragma. Please use %%typemap(javaclassmodifiers).\n");
1804 	  } else {
1805 	    Swig_error(input_file, line_number, "Unrecognized pragma.\n");
1806 	  }
1807 	} else {
1808 	  Swig_error(input_file, line_number, "Unrecognized pragma.\n");
1809 	}
1810 	Delete(strvalue);
1811       }
1812     }
1813     return Language::pragmaDirective(n);
1814   }
1815 
1816   /* -----------------------------------------------------------------------------
1817    * getQualifiedInterfaceName()
1818    * ----------------------------------------------------------------------------- */
1819 
getQualifiedInterfaceName(Node * n)1820   String *getQualifiedInterfaceName(Node *n) {
1821     String *ret = Getattr(n, "interface:qname");
1822     if (!ret) {
1823       String *nspace = Getattr(n, "sym:nspace");
1824       String *symname = Getattr(n, "interface:name");
1825       if (nspace) {
1826 	if (package)
1827 	  ret = NewStringf("%s.%s.%s", package, nspace, symname);
1828 	else
1829 	  ret = NewStringf("%s.%s", nspace, symname);
1830       } else {
1831 	ret = Copy(symname);
1832       }
1833       Setattr(n, "interface:qname", ret);
1834     }
1835     return ret;
1836   }
1837 
1838   /* -----------------------------------------------------------------------------
1839    * getInterfaceName()
1840    * ----------------------------------------------------------------------------- */
1841 
getInterfaceName(SwigType * t,bool qualified)1842   String *getInterfaceName(SwigType *t, bool qualified) {
1843     String *interface_name = NULL;
1844     if (proxy_flag) {
1845       Node *n = classLookup(t);
1846       if (n && Getattr(n, "interface:name"))
1847 	interface_name = qualified ? getQualifiedInterfaceName(n) : Getattr(n, "interface:name");
1848     }
1849     return interface_name;
1850   }
1851 
1852   /* -----------------------------------------------------------------------------
1853    * addInterfaceNameAndUpcasts()
1854    * ----------------------------------------------------------------------------- */
1855 
addInterfaceNameAndUpcasts(SwigType * smart,String * interface_list,String * interface_upcasts,Hash * base_list,SwigType * c_classname)1856   void addInterfaceNameAndUpcasts(SwigType *smart, String *interface_list, String *interface_upcasts, Hash *base_list, SwigType *c_classname) {
1857     List *keys = Keys(base_list);
1858     for (Iterator it = First(keys); it.item; it = Next(it)) {
1859       Node *base = Getattr(base_list, it.item);
1860       SwigType *c_baseclassname = Getattr(base, "name");
1861       String *interface_name = Getattr(base, "interface:name");
1862       if (Len(interface_list))
1863 	Append(interface_list, ", ");
1864       Append(interface_list, interface_name);
1865 
1866       Node *attributes = NewHash();
1867       String *interface_code = Copy(typemapLookup(base, "javainterfacecode", Getattr(base, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF, attributes));
1868       String *cptr_method_name = 0;
1869       if (interface_code) {
1870         Replaceall(interface_code, "$interfacename", interface_name);
1871 	Printv(interface_upcasts, interface_code, NIL);
1872 	cptr_method_name = Copy(Getattr(attributes, "tmap:javainterfacecode:cptrmethod"));
1873       }
1874       if (!cptr_method_name)
1875 	cptr_method_name = NewStringf("%s_GetInterfaceCPtr", interface_name);
1876       Replaceall(cptr_method_name, ".", "_");
1877       Replaceall(cptr_method_name, "$interfacename", interface_name);
1878 
1879       String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), cptr_method_name);
1880       upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname);
1881 
1882       Delete(upcast_method_name);
1883       Delete(cptr_method_name);
1884       Delete(interface_code);
1885     }
1886     Delete(keys);
1887   }
1888 
1889   /* -----------------------------------------------------------------------------
1890    * upcastsCode()
1891    *
1892    * Add code for C++ casting to base class
1893    * ----------------------------------------------------------------------------- */
1894 
upcastsCode(SwigType * smart,String * upcast_method_name,SwigType * c_classname,SwigType * c_baseclassname)1895   void upcastsCode(SwigType *smart, String *upcast_method_name, SwigType *c_classname, SwigType *c_baseclassname) {
1896     String *jniname = makeValidJniName(upcast_method_name);
1897     String *wname = Swig_name_wrapper(jniname);
1898 
1899     Printf(imclass_cppcasts_code, "  public final static native long %s(long jarg1);\n", upcast_method_name);
1900 
1901     String *classname = SwigType_namestr(c_classname);
1902     String *baseclassname = SwigType_namestr(c_baseclassname);
1903     if (smart) {
1904       String *smartnamestr = SwigType_namestr(smart);
1905       String *bsmartnamestr = SwigType_namestr(smart);
1906 
1907       // TODO: SwigType_typedef_resolve_all on a String instead of SwigType is incorrect for templates
1908       SwigType *rclassname = SwigType_typedef_resolve_all(classname);
1909       SwigType *rbaseclassname = SwigType_typedef_resolve_all(baseclassname);
1910       Replaceall(bsmartnamestr, rclassname, rbaseclassname);
1911 
1912       Printv(upcasts_code,
1913 	  "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
1914 	  "    jlong baseptr = 0;\n"
1915 	  "    ", smartnamestr, " *argp1;\n"
1916 	  "    (void)jenv;\n"
1917 	  "    (void)jcls;\n"
1918 	  "    argp1 = *(", smartnamestr, " **)&jarg1;\n"
1919 	  "    *(", bsmartnamestr, " **)&baseptr = argp1 ? new ", bsmartnamestr, "(*argp1) : 0;\n"
1920 	  "    return baseptr;\n"
1921 	  "}\n", "\n", NIL);
1922 
1923       Delete(rbaseclassname);
1924       Delete(rclassname);
1925       Delete(bsmartnamestr);
1926       Delete(smartnamestr);
1927     } else {
1928       Printv(upcasts_code,
1929 	  "SWIGEXPORT jlong JNICALL ", wname, "(JNIEnv *jenv, jclass jcls, jlong jarg1) {\n",
1930 	  "    jlong baseptr = 0;\n"
1931 	  "    (void)jenv;\n"
1932 	  "    (void)jcls;\n"
1933 	  "    *(", baseclassname, " **)&baseptr = *(", classname, " **)&jarg1;\n"
1934 	  "    return baseptr;\n"
1935 	  "}\n", "\n", NIL);
1936     }
1937 
1938     Delete(baseclassname);
1939     Delete(classname);
1940     Delete(wname);
1941     Delete(jniname);
1942   }
1943 
1944   /* -----------------------------------------------------------------------------
1945    * emitProxyClassDefAndCPPCasts()
1946    * ----------------------------------------------------------------------------- */
1947 
emitProxyClassDefAndCPPCasts(Node * n)1948   void emitProxyClassDefAndCPPCasts(Node *n) {
1949     SwigType *c_classname = Getattr(n, "name");
1950     SwigType *c_baseclassname = NULL;
1951     String *baseclass = NULL;
1952     String *interface_list = NewStringEmpty();
1953     String *interface_upcasts = NewStringEmpty();
1954     SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
1955     bool feature_director = Swig_directorclass(n) ? true : false;
1956     bool has_outerclass = Getattr(n, "nested:outer") != 0 && !GetFlag(n, "feature:flatnested");
1957     SwigType *smart = Swig_cparse_smartptr(n);
1958 
1959     // Inheritance from pure Java classes
1960     Node *attributes = NewHash();
1961     const String *pure_baseclass = typemapLookup(n, "javabase", typemap_lookup_type, WARN_NONE, attributes);
1962     bool purebase_replace = GetFlag(attributes, "tmap:javabase:replace") ? true : false;
1963     bool purebase_notderived = GetFlag(attributes, "tmap:javabase:notderived") ? true : false;
1964     Delete(attributes);
1965 
1966     // C++ inheritance
1967     if (!purebase_replace) {
1968       List *baselist = Getattr(n, "bases");
1969       if (baselist) {
1970 	Iterator base = First(baselist);
1971 	while (base.item) {
1972 	  if (!(GetFlag(base.item, "feature:ignore") || Getattr(base.item, "feature:interface"))) {
1973 	    SwigType *baseclassname = Getattr(base.item, "name");
1974 	    if (!c_baseclassname) {
1975 	      String *name = getProxyName(baseclassname);
1976 	      if (name) {
1977 		c_baseclassname = baseclassname;
1978 		baseclass = name;
1979 	      }
1980 	    } else {
1981 	      /* Warn about multiple inheritance for additional base class(es) */
1982 	      String *proxyclassname = Getattr(n, "classtypeobj");
1983 	      Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
1984 		  "Warning for %s, base %s ignored. Multiple inheritance is not supported in Java.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
1985 	    }
1986 	  }
1987 	  base = Next(base);
1988 	}
1989       }
1990     }
1991 
1992     Hash *interface_bases = Getattr(n, "interface:bases");
1993     if (interface_bases)
1994       addInterfaceNameAndUpcasts(smart, interface_list, interface_upcasts, interface_bases, c_classname);
1995 
1996     bool derived = baseclass != 0;
1997     if (derived && purebase_notderived)
1998       pure_baseclass = empty_string;
1999     const String *wanted_base = baseclass ? baseclass : pure_baseclass;
2000 
2001     if (purebase_replace) {
2002       wanted_base = pure_baseclass;
2003       derived = false;
2004       baseclass = NULL;
2005       if (purebase_notderived)
2006         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);
2007     } else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
2008       Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
2009 		   "Warning for %s, base %s ignored. Multiple inheritance is not supported in Java. "
2010 		   "Perhaps you need one of the 'replace' or 'notderived' attributes in the javabase typemap?\n", typemap_lookup_type, pure_baseclass);
2011     }
2012 
2013     // Pure Java interfaces
2014     const String *pure_interfaces = typemapLookup(n, "javainterfaces", typemap_lookup_type, WARN_NONE);
2015 
2016     if (*Char(interface_list) && *Char(pure_interfaces))
2017       Append(interface_list, ", ");
2018     Append(interface_list, pure_interfaces);
2019     // Start writing the proxy class
2020     if (!has_outerclass) // Import statements
2021       Printv(proxy_class_def, typemapLookup(n, "javaimports", typemap_lookup_type, WARN_NONE),"\n", NIL);
2022 
2023     // Translate and write javadoc comment if flagged
2024     if (doxygen && doxygenTranslator->hasDocumentation(n)) {
2025       String *doxygen_comments = doxygenTranslator->getDocumentation(n, 0);
2026       if (comment_creation_chatter)
2027 	Printf(proxy_class_def, "/* This was generated from emitProxyClassDefAndCPPCasts() */\n");
2028       Printv(proxy_class_def, Char(doxygen_comments), NIL);
2029       Delete(doxygen_comments);
2030     }
2031 
2032     if (has_outerclass)
2033       Printv(proxy_class_def, "static ", NIL); // C++ nested classes correspond to static java classes
2034     Printv(proxy_class_def, typemapLookup(n, "javaclassmodifiers", typemap_lookup_type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF),	// Class modifiers
2035 	   " $javaclassname",	// Class name and bases
2036 	   (*Char(wanted_base)) ? " extends " : "", wanted_base, *Char(interface_list) ?	// Pure Java interfaces
2037 	   " implements " : "", interface_list, " {", derived ? typemapLookup(n, "javabody_derived", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF) :	// main body of class
2038 	   typemapLookup(n, "javabody", typemap_lookup_type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF),	// main body of class
2039 	   NIL);
2040 
2041     // C++ destructor is wrapped by the delete method
2042     // Note that the method name is specified in a typemap attribute called methodname
2043     String *destruct = NewString("");
2044     const String *tm = NULL;
2045     attributes = NewHash();
2046     const String *destruct_methodname = NULL;
2047     const String *destruct_methodmodifiers = NULL;
2048     const String *destruct_parameters = NULL;
2049     if (derived) {
2050       tm = typemapLookup(n, "javadestruct_derived", typemap_lookup_type, WARN_NONE, attributes);
2051       destruct_methodname = Getattr(attributes, "tmap:javadestruct_derived:methodname");
2052       destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct_derived:methodmodifiers");
2053       destruct_parameters = Getattr(attributes, "tmap:javadestruct_derived:parameters");
2054     } else {
2055       tm = typemapLookup(n, "javadestruct", typemap_lookup_type, WARN_NONE, attributes);
2056       destruct_methodname = Getattr(attributes, "tmap:javadestruct:methodname");
2057       destruct_methodmodifiers = Getattr(attributes, "tmap:javadestruct:methodmodifiers");
2058       destruct_parameters = Getattr(attributes, "tmap:javadestruct:parameters");
2059     }
2060     if (tm && *Char(tm)) {
2061       if (!destruct_methodname) {
2062 	Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in javadestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
2063       }
2064       if (!destruct_methodmodifiers) {
2065 	Swig_error(Getfile(n), Getline(n), "No methodmodifiers attribute defined in javadestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
2066       }
2067       if (!destruct_parameters)
2068 	destruct_parameters = empty_string;
2069     }
2070     // Emit the finalize and delete methods
2071     if (tm) {
2072       // Finalize method
2073       if (*Char(destructor_call)) {
2074 	Printv(proxy_class_def, typemapLookup(n, "javafinalize", typemap_lookup_type, WARN_NONE), NIL);
2075       }
2076       // delete method
2077       Printv(destruct, tm, NIL);
2078       if (*Char(destructor_call))
2079 	Replaceall(destruct, "$jnicall", destructor_call);
2080       else
2081 	Replaceall(destruct, "$jnicall", "throw new UnsupportedOperationException(\"C++ destructor does not have public access\")");
2082       if (*Char(destruct)) {
2083 	Printv(proxy_class_def, "\n  ", NIL);
2084 	const String *methodmods = Getattr(n, "destructmethodmodifiers");
2085 	if (methodmods)
2086 	  Printv(proxy_class_def, methodmods, NIL);
2087 	else
2088 	  Printv(proxy_class_def, destruct_methodmodifiers, NIL);
2089 	Printv(proxy_class_def, " void ", destruct_methodname, "(", destruct_parameters, ")", destructor_throws_clause, " ", destruct, "\n", NIL);
2090       }
2091     }
2092     if (*Char(interface_upcasts))
2093       Printv(proxy_class_def, interface_upcasts, NIL);
2094 
2095     /* Insert directordisconnect typemap, if this class has directors enabled */
2096     /* Also insert the swigTakeOwnership and swigReleaseOwnership methods */
2097     if (feature_director) {
2098       String *destruct_jnicall, *release_jnicall, *take_jnicall;
2099       String *changeown_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "change_ownership");
2100 
2101       destruct_jnicall = NewStringf("%s()", destruct_methodname);
2102       release_jnicall = NewStringf("%s.%s(this, swigCPtr, false)", full_imclass_name, changeown_method_name);
2103       take_jnicall = NewStringf("%s.%s(this, swigCPtr, true)", full_imclass_name, changeown_method_name);
2104 
2105       emitCodeTypemap(n, false, typemap_lookup_type, "directordisconnect", "methodname", destruct_jnicall);
2106       emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_release", "methodname", release_jnicall);
2107       emitCodeTypemap(n, false, typemap_lookup_type, "directorowner_take", "methodname", take_jnicall);
2108 
2109       Delete(destruct_jnicall);
2110       Delete(changeown_method_name);
2111       Delete(release_jnicall);
2112       Delete(take_jnicall);
2113     }
2114 
2115     Delete(interface_upcasts);
2116     Delete(interface_list);
2117     Delete(attributes);
2118     Delete(destruct);
2119 
2120     // Emit extra user code
2121     Printv(proxy_class_def, typemapLookup(n, "javacode", typemap_lookup_type, WARN_NONE),	// extra Java code
2122 	   "\n", NIL);
2123 
2124     if (derived) {
2125       String *upcast_method_name = Swig_name_member(getNSpace(), getClassPrefix(), smart != 0 ? "SWIGSmartPtrUpcast" : "SWIGUpcast");
2126       upcastsCode(smart, upcast_method_name, c_classname, c_baseclassname);
2127       Delete(upcast_method_name);
2128     }
2129 
2130     Delete(smart);
2131   }
2132 
2133   /* ----------------------------------------------------------------------
2134    * emitInterfaceDeclaration()
2135    * ---------------------------------------------------------------------- */
2136 
emitInterfaceDeclaration(Node * n,String * interface_name,File * f_interface,String * nspace)2137   void emitInterfaceDeclaration(Node *n, String *interface_name, File *f_interface, String *nspace) {
2138     if (package || nspace) {
2139       Printf(f_interface, "package ");
2140       if (package)
2141 	Printv(f_interface, package, nspace ? "." : "", NIL);
2142       if (nspace)
2143 	Printv(f_interface, nspace, NIL);
2144       Printf(f_interface, ";\n");
2145     }
2146 
2147     Printv(f_interface, typemapLookup(n, "javaimports", Getattr(n, "classtypeobj"), WARN_NONE), "\n", NIL);
2148     Printf(f_interface, "public interface %s", interface_name);
2149     if (List *baselist = Getattr(n, "bases")) {
2150       String *bases = 0;
2151       for (Iterator base = First(baselist); base.item; base = Next(base)) {
2152 	if (GetFlag(base.item, "feature:ignore") || !Getattr(base.item, "feature:interface"))
2153 	  continue; // TODO: warn about skipped non-interface bases
2154 	String *base_iname = Getattr(base.item, "interface:name");
2155 	if (!bases)
2156 	  bases = Copy(base_iname);
2157 	else {
2158 	  Append(bases, ", ");
2159 	  Append(bases, base_iname);
2160 	}
2161       }
2162       if (bases) {
2163 	Printv(f_interface, " extends ", bases, NIL);
2164 	Delete(bases);
2165       }
2166     }
2167     Printf(f_interface, " {\n");
2168 
2169     Node *attributes = NewHash();
2170     String *interface_code = Copy(typemapLookup(n, "javainterfacecode", Getattr(n, "classtypeobj"), WARN_JAVA_TYPEMAP_INTERFACECODE_UNDEF, attributes));
2171     if (interface_code) {
2172       String *interface_declaration = Copy(Getattr(attributes, "tmap:javainterfacecode:declaration"));
2173       if (interface_declaration) {
2174         Replaceall(interface_declaration, "$interfacename", interface_name);
2175 	Printv(f_interface, interface_declaration, NIL);
2176 	Delete(interface_declaration);
2177       }
2178       Delete(interface_code);
2179     }
2180   }
2181 
2182   /* ----------------------------------------------------------------------
2183   * classDeclaration()
2184   * ---------------------------------------------------------------------- */
2185 
classDeclaration(Node * n)2186   int classDeclaration(Node *n) {
2187     return Language::classDeclaration(n);
2188   }
2189 
2190   /* ----------------------------------------------------------------------
2191   * classHandler()
2192   * ---------------------------------------------------------------------- */
2193 
classHandler(Node * n)2194   virtual int classHandler(Node *n) {
2195     File *f_proxy = NULL;
2196     File *f_interface = NULL;
2197     String *old_proxy_class_name = proxy_class_name;
2198     String *old_full_proxy_class_name = full_proxy_class_name;
2199     String *old_full_imclass_name = full_imclass_name;
2200     String *old_destructor_call = destructor_call;
2201     String *old_destructor_throws_clause = destructor_throws_clause;
2202     String *old_proxy_class_constants_code = proxy_class_constants_code;
2203     String *old_proxy_class_def = proxy_class_def;
2204     String *old_proxy_class_code = proxy_class_code;
2205     bool has_outerclass = Getattr(n, "nested:outer") && !GetFlag(n, "feature:flatnested");
2206     String *old_interface_class_code = interface_class_code;
2207     interface_class_code = 0;
2208 
2209     if (proxy_flag) {
2210       proxy_class_name = NewString(Getattr(n, "sym:name"));
2211       String *nspace = getNSpace();
2212       constructIntermediateClassName(n);
2213 
2214       String *outerClassesPrefix = 0;
2215       if (Node *outer = Getattr(n, "nested:outer")) {
2216 	outerClassesPrefix = Copy(Getattr(outer, "sym:name"));
2217 	for (outer = Getattr(outer, "nested:outer"); outer != 0; outer = Getattr(outer, "nested:outer")) {
2218 	  Push(outerClassesPrefix, ".");
2219 	  Push(outerClassesPrefix, Getattr(outer, "sym:name"));
2220 	}
2221       }
2222       if (!nspace) {
2223 	full_proxy_class_name = outerClassesPrefix ? NewStringf("%s.%s", outerClassesPrefix, proxy_class_name) : NewStringf("%s", proxy_class_name);
2224 
2225 	if (Cmp(proxy_class_name, imclass_name) == 0) {
2226 	  Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
2227 	  SWIG_exit(EXIT_FAILURE);
2228 	}
2229 
2230 	if (Cmp(proxy_class_name, module_class_name) == 0) {
2231 	  Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
2232 	  SWIG_exit(EXIT_FAILURE);
2233 	}
2234       } else {
2235 	if (outerClassesPrefix) {
2236 	  if (package)
2237 	    full_proxy_class_name = NewStringf("%s.%s.%s.%s", package, nspace, outerClassesPrefix, proxy_class_name);
2238 	  else
2239 	    full_proxy_class_name = NewStringf("%s.%s.%s", nspace, outerClassesPrefix, proxy_class_name);
2240 	} else {
2241 	  if (package)
2242 	    full_proxy_class_name = NewStringf("%s.%s.%s", package, nspace, proxy_class_name);
2243 	  else
2244 	    full_proxy_class_name = NewStringf("%s.%s", nspace, proxy_class_name);
2245 	}
2246       }
2247 
2248       String *interface_name = Getattr(n, "feature:interface") ? Getattr(n, "interface:name") : 0;
2249       if (outerClassesPrefix) {
2250 	String *fnspace = nspace ? NewStringf("%s.%s", nspace, outerClassesPrefix) : outerClassesPrefix;
2251 	if (!addSymbol(proxy_class_name, n, fnspace))
2252 	  return SWIG_ERROR;
2253 	if (interface_name && !addInterfaceSymbol(interface_name, n, fnspace))
2254 	  return SWIG_ERROR;
2255 	if (nspace)
2256 	  Delete(fnspace);
2257 	Delete(outerClassesPrefix);
2258       } else {
2259 	if (!addSymbol(proxy_class_name, n, nspace))
2260 	  return SWIG_ERROR;
2261 	if (interface_name && !addInterfaceSymbol(interface_name, n, nspace))
2262 	  return SWIG_ERROR;
2263       }
2264 
2265       // Each outer proxy class goes into a separate file
2266       if (!has_outerclass) {
2267 	String *output_directory = outputDirectory(nspace);
2268 	String *filen = NewStringf("%s%s.java", output_directory, proxy_class_name);
2269 	f_proxy = NewFile(filen, "w", SWIG_output_files());
2270 	if (!f_proxy) {
2271 	  FileErrorDisplay(filen);
2272 	  SWIG_exit(EXIT_FAILURE);
2273 	}
2274 	Append(filenames_list, Copy(filen));
2275 	Delete(filen);
2276 	Delete(output_directory);
2277 
2278 	// Start writing out the proxy class file
2279 	emitBanner(f_proxy);
2280 
2281 	if (package || nspace) {
2282 	  Printf(f_proxy, "package ");
2283 	  if (package)
2284 	    Printv(f_proxy, package, nspace ? "." : "", NIL);
2285 	  if (nspace)
2286 	    Printv(f_proxy, nspace, NIL);
2287 	  Printf(f_proxy, ";\n");
2288 	}
2289       }
2290       else
2291 	++nesting_depth;
2292 
2293       proxy_class_def = NewString("");
2294       proxy_class_code = NewString("");
2295       destructor_call = NewString("");
2296       destructor_throws_clause = NewString("");
2297       proxy_class_constants_code = NewString("");
2298 
2299       if (Getattr(n, "feature:interface")) {
2300         interface_class_code = NewString("");
2301 	String *output_directory = outputDirectory(nspace);
2302 	String *filen = NewStringf("%s%s.java", output_directory, interface_name);
2303 	f_interface = NewFile(filen, "w", SWIG_output_files());
2304 	if (!f_interface) {
2305 	  FileErrorDisplay(filen);
2306 	  SWIG_exit(EXIT_FAILURE);
2307 	}
2308 	Append(filenames_list, filen); // file name ownership goes to the list
2309 	emitBanner(f_interface);
2310 	emitInterfaceDeclaration(n, interface_name, interface_class_code, nspace);
2311 	Delete(filen);
2312 	Delete(output_directory);
2313       }
2314     }
2315 
2316     Language::classHandler(n);
2317 
2318     if (proxy_flag) {
2319       emitProxyClassDefAndCPPCasts(n);
2320 
2321       String *javaclazzname = Swig_name_member(getNSpace(), getClassPrefix(), ""); // mangled full proxy class name
2322 
2323       Replaceall(proxy_class_def, "$javaclassname", proxy_class_name);
2324       Replaceall(proxy_class_code, "$javaclassname", proxy_class_name);
2325       Replaceall(proxy_class_constants_code, "$javaclassname", proxy_class_name);
2326       Replaceall(interface_class_code, "$javaclassname", proxy_class_name);
2327 
2328       Replaceall(proxy_class_def, "$javaclazzname", javaclazzname);
2329       Replaceall(proxy_class_code, "$javaclazzname", javaclazzname);
2330       Replaceall(proxy_class_constants_code, "$javaclazzname", javaclazzname);
2331       Replaceall(interface_class_code, "$javaclazzname", javaclazzname);
2332 
2333       Replaceall(proxy_class_def, "$module", module_class_name);
2334       Replaceall(proxy_class_code, "$module", module_class_name);
2335       Replaceall(proxy_class_constants_code, "$module", module_class_name);
2336       Replaceall(interface_class_code, "$module", module_class_name);
2337 
2338       Replaceall(proxy_class_def, "$imclassname", full_imclass_name);
2339       Replaceall(proxy_class_code, "$imclassname", full_imclass_name);
2340       Replaceall(proxy_class_constants_code, "$imclassname", full_imclass_name);
2341       Replaceall(interface_class_code, "$imclassname", full_imclass_name);
2342 
2343       if (!has_outerclass)
2344 	Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
2345       else {
2346 	Swig_offset_string(proxy_class_def, nesting_depth);
2347 	Append(old_proxy_class_code, proxy_class_def);
2348 	Swig_offset_string(proxy_class_code, nesting_depth);
2349 	Append(old_proxy_class_code, proxy_class_code);
2350       }
2351 
2352       // Write out all the constants
2353       if (Len(proxy_class_constants_code) != 0) {
2354 	if (!has_outerclass)
2355 	  Printv(f_proxy, proxy_class_constants_code, NIL);
2356 	else {
2357 	  Swig_offset_string(proxy_class_constants_code, nesting_depth);
2358 	  Append(old_proxy_class_code, proxy_class_constants_code);
2359 	}
2360       }
2361 
2362       if (!has_outerclass) {
2363 	Printf(f_proxy, "}\n");
2364         Delete(f_proxy);
2365         f_proxy = NULL;
2366       } else {
2367 	for (int i = 0; i < nesting_depth; ++i)
2368 	  Append(old_proxy_class_code, "  ");
2369 	Append(old_proxy_class_code, "}\n\n");
2370 	--nesting_depth;
2371       }
2372 
2373       if (f_interface) {
2374 	Printv(f_interface, interface_class_code, "}\n", NIL);
2375 	Delete(f_interface);
2376 	f_interface = 0;
2377       }
2378 
2379       emitDirectorExtraMethods(n);
2380 
2381       Delete(interface_class_code);
2382       interface_class_code = old_interface_class_code;
2383       Delete(javaclazzname);
2384       Delete(proxy_class_name);
2385       proxy_class_name = old_proxy_class_name;
2386       Delete(full_proxy_class_name);
2387       full_proxy_class_name = old_full_proxy_class_name;
2388       Delete(full_imclass_name);
2389       full_imclass_name = old_full_imclass_name;
2390       Delete(destructor_call);
2391       destructor_call = old_destructor_call;
2392       Delete(destructor_throws_clause);
2393       destructor_throws_clause = old_destructor_throws_clause;
2394       Delete(proxy_class_constants_code);
2395       proxy_class_constants_code = old_proxy_class_constants_code;
2396       Delete(proxy_class_def);
2397       proxy_class_def = old_proxy_class_def;
2398       Delete(proxy_class_code);
2399       proxy_class_code = old_proxy_class_code;
2400     }
2401 
2402     return SWIG_OK;
2403   }
2404 
2405   /* ----------------------------------------------------------------------
2406    * memberfunctionHandler()
2407    * ---------------------------------------------------------------------- */
2408 
memberfunctionHandler(Node * n)2409   virtual int memberfunctionHandler(Node *n) {
2410     member_func_flag = true;
2411     Language::memberfunctionHandler(n);
2412 
2413     if (proxy_flag) {
2414       String *overloaded_name = getOverloadedName(n);
2415       String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
2416       Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
2417       Setattr(n, "imfuncname", intermediary_function_name);
2418       proxyClassFunctionHandler(n);
2419       Delete(overloaded_name);
2420     }
2421     member_func_flag = false;
2422     return SWIG_OK;
2423   }
2424 
2425   /* ----------------------------------------------------------------------
2426    * staticmemberfunctionHandler()
2427    * ---------------------------------------------------------------------- */
2428 
staticmemberfunctionHandler(Node * n)2429   virtual int staticmemberfunctionHandler(Node *n) {
2430 
2431     static_flag = true;
2432     member_func_flag = true;
2433     Language::staticmemberfunctionHandler(n);
2434 
2435     if (proxy_flag) {
2436       String *overloaded_name = getOverloadedName(n);
2437       String *intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), overloaded_name);
2438       Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
2439       Setattr(n, "imfuncname", intermediary_function_name);
2440       proxyClassFunctionHandler(n);
2441       Delete(overloaded_name);
2442     }
2443     static_flag = false;
2444     member_func_flag = false;
2445 
2446     return SWIG_OK;
2447   }
2448 
2449   /* -----------------------------------------------------------------------------
2450    * proxyClassFunctionHandler()
2451    *
2452    * Function called for creating a Java wrapper function around a c++ function in the
2453    * proxy class. Used for both static and non-static C++ class functions.
2454    * C++ class static functions map to Java static functions.
2455    * Two extra attributes in the Node must be available. These are "proxyfuncname" -
2456    * the name of the Java class proxy function, which in turn will call "imfuncname" -
2457    * the intermediary (JNI) function name in the intermediary class.
2458    * ----------------------------------------------------------------------------- */
2459 
proxyClassFunctionHandler(Node * n)2460   void proxyClassFunctionHandler(Node *n) {
2461     SwigType *t = Getattr(n, "type");
2462     ParmList *l = Getattr(n, "parms");
2463     String *intermediary_function_name = Getattr(n, "imfuncname");
2464     String *proxy_function_name = Getattr(n, "proxyfuncname");
2465     String *tm;
2466     Parm *p;
2467     int i;
2468     String *imcall = NewString("");
2469     String *return_type = NewString("");
2470     String *function_code = NewString("");
2471     bool setter_flag = false;
2472     String *pre_code = NewString("");
2473     String *post_code = NewString("");
2474     bool is_interface = Getattr(parentNode(n), "feature:interface") != 0
2475       && !static_flag && Getattr(n, "interface:owner") == 0;
2476 
2477     if (!proxy_flag)
2478       return;
2479 
2480     // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
2481     if (Getattr(n, "overload:ignore"))
2482       return;
2483 
2484     // Don't generate proxy method for additional explicitcall method used in directors
2485     if (GetFlag(n, "explicitcall"))
2486       return;
2487 
2488     if (l) {
2489       if (SwigType_type(Getattr(l, "type")) == T_VOID) {
2490 	l = nextSibling(l);
2491       }
2492     }
2493 
2494     /* Attach the non-standard typemaps to the parameter list */
2495     Swig_typemap_attach_parms("in", l, NULL);
2496     Swig_typemap_attach_parms("jtype", l, NULL);
2497     Swig_typemap_attach_parms("jstype", l, NULL);
2498     Swig_typemap_attach_parms("javain", l, NULL);
2499 
2500     /* Get return types */
2501     if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
2502       // 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
2503       SwigType *covariant = Getattr(n, "covariant");
2504       substituteClassname(covariant ? covariant : t, tm);
2505       Printf(return_type, "%s", tm);
2506       if (covariant)
2507 	Swig_warning(WARN_JAVA_COVARIANT_RET, input_file, line_number,
2508 		     "Covariant return types not supported in Java. Proxy method will return %s.\n", SwigType_str(covariant, 0));
2509     } else {
2510       Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
2511     }
2512 
2513     if (wrapping_member_flag && !enum_constant_flag) {
2514       // For wrapping member variables (Javabean setter)
2515       setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), Swig_name_member(0, getClassPrefix(), variable_name))) == 0);
2516     }
2517 
2518     // Translate and write javadoc comment if flagged
2519     if (doxygen && doxygenTranslator->hasDocumentation(n)) {
2520       String *doxygen_comments = doxygenTranslator->getDocumentation(n, "  ");
2521       if (comment_creation_chatter)
2522 	Printf(function_code, "/* This was generated from proxyclassfunctionhandler() */\n");
2523       Printv(function_code, Char(doxygen_comments), NIL);
2524       Delete(doxygen_comments);
2525     }
2526 
2527     /* Start generating the proxy function */
2528     const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
2529     methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
2530     Printf(function_code, "  %s ", methodmods);
2531     if (static_flag)
2532       Printf(function_code, "static ");
2533     Printf(function_code, "%s %s(", return_type, proxy_function_name);
2534 
2535     if (is_interface)
2536       Printf(interface_class_code, "  %s %s(", return_type, proxy_function_name);
2537 
2538     Printv(imcall, full_imclass_name, ".$imfuncname(", NIL);
2539     if (!static_flag) {
2540       Printf(imcall, "swigCPtr");
2541 
2542       String *this_type = Copy(getClassType());
2543       String *name = NewString("jself");
2544       String *qualifier = Getattr(n, "qualifier");
2545       if (qualifier)
2546 	SwigType_push(this_type, qualifier);
2547       SwigType_add_pointer(this_type);
2548       Parm *this_parm = NewParm(this_type, name, n);
2549       Swig_typemap_attach_parms("jtype", this_parm, NULL);
2550       Swig_typemap_attach_parms("jstype", this_parm, NULL);
2551 
2552       if (prematureGarbageCollectionPreventionParameter(this_type, this_parm))
2553 	Printf(imcall, ", this");
2554 
2555       Delete(this_parm);
2556       Delete(name);
2557       Delete(this_type);
2558     }
2559 
2560     emit_mark_varargs(l);
2561 
2562     int gencomma = !static_flag;
2563 
2564     /* Output each parameter */
2565     for (i = 0, p = l; p; i++) {
2566 
2567       /* Ignored varargs */
2568       if (checkAttribute(p, "varargs:ignore", "1")) {
2569 	p = nextSibling(p);
2570 	continue;
2571       }
2572 
2573       /* Ignored parameters */
2574       if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2575 	p = Getattr(p, "tmap:in:next");
2576 	continue;
2577       }
2578 
2579       /* Ignore the 'this' argument for variable wrappers */
2580       if (!(variable_wrapper_flag && i == 0) || static_flag) {
2581 	SwigType *pt = Getattr(p, "type");
2582 	String *param_type = NewString("");
2583 
2584 	/* Get the Java parameter type */
2585 	if ((tm = Getattr(p, "tmap:jstype"))) {
2586 	  substituteClassname(pt, tm);
2587 	  Printf(param_type, "%s", tm);
2588 	} else {
2589 	  Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
2590 	}
2591 
2592 	if (gencomma)
2593 	  Printf(imcall, ", ");
2594 
2595 	String *arg = makeParameterName(n, p, i, setter_flag);
2596 
2597 	// Use typemaps to transform type used in Java proxy wrapper (in proxy class) to type used in JNI function (in intermediary class)
2598 	if ((tm = Getattr(p, "tmap:javain"))) {
2599 	  addThrows(n, "tmap:javain", p);
2600 	  substituteClassname(pt, tm);
2601 	  Replaceall(tm, "$javainput", arg);
2602           String *pre = Getattr(p, "tmap:javain:pre");
2603           if (pre) {
2604             substituteClassname(pt, pre);
2605             Replaceall(pre, "$javainput", arg);
2606             if (Len(pre_code) > 0)
2607               Printf(pre_code, "\n");
2608             Printv(pre_code, pre, NIL);
2609           }
2610           String *post = Getattr(p, "tmap:javain:post");
2611           if (post) {
2612             substituteClassname(pt, post);
2613             Replaceall(post, "$javainput", arg);
2614             if (Len(post_code) > 0)
2615               Printf(post_code, "\n");
2616             Printv(post_code, post, NIL);
2617           }
2618 	  Printv(imcall, tm, NIL);
2619 	} else {
2620 	  Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
2621 	}
2622 
2623 	/* Add parameter to proxy function */
2624 	if (gencomma >= 2) {
2625 	  Printf(function_code, ", ");
2626 	  if (is_interface)
2627 	    Printf(interface_class_code, ", ");
2628 	}
2629 	gencomma = 2;
2630 	Printf(function_code, "%s %s", param_type, arg);
2631 	if (is_interface)
2632 	  Printf(interface_class_code, "%s %s", param_type, arg);
2633 
2634 	if (prematureGarbageCollectionPreventionParameter(pt, p)) {
2635           String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
2636           if (pgcppname) {
2637             String *argname = Copy(pgcppname);
2638             Replaceall(argname, "$javainput", arg);
2639             Printf(imcall, ", %s", argname);
2640             Delete(argname);
2641           } else {
2642             Printf(imcall, ", %s", arg);
2643           }
2644         }
2645 
2646 	Delete(arg);
2647 	Delete(param_type);
2648       }
2649       p = Getattr(p, "tmap:in:next");
2650     }
2651 
2652     Printf(imcall, ")");
2653     Printf(function_code, ")");
2654 
2655     // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in proxy class)
2656     if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
2657       addThrows(n, "tmap:javaout", n);
2658       bool is_pre_code = Len(pre_code) > 0;
2659       bool is_post_code = Len(post_code) > 0;
2660       if (is_pre_code || is_post_code) {
2661         Replaceall(tm, "\n ", "\n   "); // add extra indentation to code in typemap
2662         if (is_post_code) {
2663           Insert(tm, 0, "\n    try ");
2664           Printv(tm, " finally {\n", post_code, "\n    }", NIL);
2665         } else {
2666           Insert(tm, 0, "\n    ");
2667         }
2668         if (is_pre_code) {
2669           Insert(tm, 0, pre_code);
2670           Insert(tm, 0, "\n");
2671         }
2672 	Insert(tm, 0, "{");
2673 	Printf(tm, "\n  }");
2674       }
2675       if (GetFlag(n, "feature:new"))
2676 	Replaceall(tm, "$owner", "true");
2677       else
2678 	Replaceall(tm, "$owner", "false");
2679       substituteClassname(t, tm);
2680 
2681       // For director methods: generate code to selectively make a normal polymorphic call or
2682       // an explicit method call - needed to prevent infinite recursion calls in director methods.
2683       Node *explicit_n = Getattr(n, "explicitcallnode");
2684       if (explicit_n) {
2685 	String *ex_overloaded_name = getOverloadedName(explicit_n);
2686 	String *ex_intermediary_function_name = Swig_name_member(getNSpace(), getClassPrefix(), ex_overloaded_name);
2687 
2688 	String *ex_imcall = Copy(imcall);
2689 	Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
2690 	Replaceall(imcall, "$imfuncname", intermediary_function_name);
2691 
2692 	String *excode = NewString("");
2693 	if (!Cmp(return_type, "void"))
2694 	  Printf(excode, "if (getClass() == %s.class) %s; else %s", proxy_class_name, imcall, ex_imcall);
2695 	else
2696 	  Printf(excode, "(getClass() == %s.class) ? %s : %s", proxy_class_name, imcall, ex_imcall);
2697 
2698 	Clear(imcall);
2699 	Printv(imcall, excode, NIL);
2700 	Delete(ex_overloaded_name);
2701 	Delete(excode);
2702       } else {
2703 	Replaceall(imcall, "$imfuncname", intermediary_function_name);
2704       }
2705 
2706       Replaceall(tm, "$jnicall", imcall);
2707     } else {
2708       Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
2709     }
2710 
2711     if (is_interface) {
2712       Printf(interface_class_code, ")");
2713       generateThrowsClause(n, interface_class_code);
2714       Printf(interface_class_code, ";\n");
2715     }
2716     generateThrowsClause(n, function_code);
2717     Printf(function_code, " %s\n\n", tm ? tm : empty_string);
2718     Printv(proxy_class_code, function_code, NIL);
2719 
2720     Delete(pre_code);
2721     Delete(post_code);
2722     Delete(function_code);
2723     Delete(return_type);
2724     Delete(imcall);
2725   }
2726 
2727   /* ----------------------------------------------------------------------
2728    * constructorHandler()
2729    * ---------------------------------------------------------------------- */
2730 
constructorHandler(Node * n)2731   virtual int constructorHandler(Node *n) {
2732 
2733     ParmList *l = Getattr(n, "parms");
2734     String *tm;
2735     Parm *p;
2736     int i;
2737     String *function_code = NewString("");
2738     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
2739     String *helper_args = NewString("");
2740     String *pre_code = NewString("");
2741     String *post_code = NewString("");
2742     String *im_return_type = NewString("");
2743     bool feature_director = (parentNode(n) && Swig_directorclass(n));
2744 
2745     Language::constructorHandler(n);
2746 
2747     // Wrappers not wanted for some methods where the parameters cannot be overloaded in Java
2748     if (Getattr(n, "overload:ignore"))
2749       return SWIG_OK;
2750 
2751     if (proxy_flag) {
2752       String *overloaded_name = getOverloadedName(n);
2753       String *mangled_overname = Swig_name_construct(getNSpace(), overloaded_name);
2754       String *imcall = NewString("");
2755 
2756       const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
2757       methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
2758 
2759       tm = Getattr(n, "tmap:jtype"); // typemaps were attached earlier to the node
2760       Printf(im_return_type, "%s", tm);
2761 
2762       // Translate and write javadoc comment if flagged
2763       if (doxygen && doxygenTranslator->hasDocumentation(n)) {
2764 	String *doxygen_comments = doxygenTranslator->getDocumentation(n, "  ");
2765 	if (comment_creation_chatter)
2766 	  Printf(function_code, "/* This was generated from constructionhandler() */\n");
2767 	Printv(function_code, Char(doxygen_comments), NIL);
2768 	Delete(doxygen_comments);
2769       }
2770 
2771       Printf(function_code, "  %s %s(", methodmods, proxy_class_name);
2772       Printf(helper_code, "  static private %s SwigConstruct%s(", im_return_type, proxy_class_name);
2773 
2774       Printv(imcall, full_imclass_name, ".", mangled_overname, "(", NIL);
2775 
2776       /* Attach the non-standard typemaps to the parameter list */
2777       Swig_typemap_attach_parms("in", l, NULL);
2778       Swig_typemap_attach_parms("jtype", l, NULL);
2779       Swig_typemap_attach_parms("jstype", l, NULL);
2780       Swig_typemap_attach_parms("javain", l, NULL);
2781 
2782       emit_mark_varargs(l);
2783 
2784       int gencomma = 0;
2785 
2786       /* Output each parameter */
2787       for (i = 0, p = l; p; i++) {
2788 
2789 	/* Ignored varargs */
2790 	if (checkAttribute(p, "varargs:ignore", "1")) {
2791 	  p = nextSibling(p);
2792 	  continue;
2793 	}
2794 
2795 	/* Ignored parameters */
2796 	if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2797 	  p = Getattr(p, "tmap:in:next");
2798 	  continue;
2799 	}
2800 
2801 	SwigType *pt = Getattr(p, "type");
2802 	String *param_type = NewString("");
2803 
2804 	/* Get the Java parameter type */
2805 	if ((tm = Getattr(p, "tmap:jstype"))) {
2806 	  substituteClassname(pt, tm);
2807 	  Printf(param_type, "%s", tm);
2808 	} else {
2809 	  Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
2810 	}
2811 
2812 	if (gencomma)
2813 	  Printf(imcall, ", ");
2814 
2815 	String *arg = makeParameterName(n, p, i, false);
2816 
2817 	// Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class)
2818 	if ((tm = Getattr(p, "tmap:javain"))) {
2819 	  addThrows(n, "tmap:javain", p);
2820 	  substituteClassname(pt, tm);
2821 	  Replaceall(tm, "$javainput", arg);
2822           String *pre = Getattr(p, "tmap:javain:pre");
2823           if (pre) {
2824             substituteClassname(pt, pre);
2825             Replaceall(pre, "$javainput", arg);
2826             if (Len(pre_code) > 0)
2827               Printf(pre_code, "\n");
2828             Printv(pre_code, pre, NIL);
2829           }
2830           String *post = Getattr(p, "tmap:javain:post");
2831           if (post) {
2832             substituteClassname(pt, post);
2833             Replaceall(post, "$javainput", arg);
2834             if (Len(post_code) > 0)
2835               Printf(post_code, "\n");
2836             Printv(post_code, post, NIL);
2837           }
2838 	  Printv(imcall, tm, NIL);
2839 	} else {
2840 	  Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
2841 	}
2842 
2843 	/* Add parameter to proxy function */
2844 	if (gencomma) {
2845 	  Printf(function_code, ", ");
2846 	  Printf(helper_code, ", ");
2847 	  Printf(helper_args, ", ");
2848         }
2849 	Printf(function_code, "%s %s", param_type, arg);
2850 	Printf(helper_code, "%s %s", param_type, arg);
2851 	Printf(helper_args, "%s", arg);
2852 	++gencomma;
2853 
2854 	if (prematureGarbageCollectionPreventionParameter(pt, p)) {
2855           String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
2856           if (pgcppname) {
2857             String *argname = Copy(pgcppname);
2858             Replaceall(argname, "$javainput", arg);
2859             Printf(imcall, ", %s", argname);
2860             Delete(argname);
2861           } else {
2862             Printf(imcall, ", %s", arg);
2863           }
2864         }
2865 
2866 	Delete(arg);
2867 	Delete(param_type);
2868 	p = Getattr(p, "tmap:in:next");
2869       }
2870 
2871       Printf(imcall, ")");
2872 
2873       Printf(function_code, ")");
2874       Printf(helper_code, ")");
2875       generateThrowsClause(n, function_code);
2876 
2877       /* Insert the javaconstruct typemap, doing the replacement for $directorconnect, as needed */
2878       Hash *attributes = NewHash();
2879       String *typemap_lookup_type = Getattr(getCurrentClass(), "classtypeobj");
2880       String *construct_tm = Copy(typemapLookup(n, "javaconstruct", typemap_lookup_type,
2881 						WARN_JAVA_TYPEMAP_JAVACONSTRUCT_UNDEF, attributes));
2882       if (construct_tm) {
2883 	if (!feature_director) {
2884 	  Replaceall(construct_tm, "$directorconnect", "");
2885 	} else {
2886 	  String *connect_attr = Getattr(attributes, "tmap:javaconstruct:directorconnect");
2887 
2888 	  if (connect_attr) {
2889 	    Replaceall(construct_tm, "$directorconnect", connect_attr);
2890 	  } else {
2891 	    Swig_warning(WARN_JAVA_NO_DIRECTORCONNECT_ATTR, input_file, line_number, "\"directorconnect\" attribute missing in %s \"javaconstruct\" typemap.\n",
2892 			 Getattr(n, "name"));
2893 	    Replaceall(construct_tm, "$directorconnect", "");
2894 	  }
2895 	}
2896 
2897 	Printv(function_code, " ", construct_tm, "\n", NIL);
2898       }
2899 
2900       bool is_pre_code = Len(pre_code) > 0;
2901       bool is_post_code = Len(post_code) > 0;
2902       if (is_pre_code || is_post_code) {
2903         generateThrowsClause(n, helper_code);
2904         Printf(helper_code, " {\n");
2905         if (is_pre_code) {
2906           Printv(helper_code, pre_code, "\n", NIL);
2907         }
2908         if (is_post_code) {
2909           Printf(helper_code, "    try {\n");
2910           Printv(helper_code, "      return ", imcall, ";\n", NIL);
2911           Printv(helper_code, "    } finally {\n", post_code, "\n    }", NIL);
2912         } else {
2913           Printv(helper_code, "    return ", imcall, ";", NIL);
2914         }
2915         Printf(helper_code, "\n  }\n");
2916         String *helper_name = NewStringf("%s.SwigConstruct%s(%s)", proxy_class_name, proxy_class_name, helper_args);
2917         Printv(proxy_class_code, helper_code, "\n", NIL);
2918         Replaceall(function_code, "$imcall", helper_name);
2919         Delete(helper_name);
2920       } else {
2921         Replaceall(function_code, "$imcall", imcall);
2922       }
2923 
2924       Printv(proxy_class_code, function_code, "\n", NIL);
2925 
2926       Delete(helper_args);
2927       Delete(im_return_type);
2928       Delete(pre_code);
2929       Delete(post_code);
2930       Delete(construct_tm);
2931       Delete(attributes);
2932       Delete(overloaded_name);
2933       Delete(imcall);
2934     }
2935 
2936     return SWIG_OK;
2937   }
2938 
2939   /* ----------------------------------------------------------------------
2940    * destructorHandler()
2941    * ---------------------------------------------------------------------- */
2942 
destructorHandler(Node * n)2943   virtual int destructorHandler(Node *n) {
2944     Language::destructorHandler(n);
2945     String *symname = Getattr(n, "sym:name");
2946 
2947     if (proxy_flag) {
2948       Printv(destructor_call, full_imclass_name, ".", Swig_name_destroy(getNSpace(), symname), "(swigCPtr)", NIL);
2949       generateThrowsClause(n, destructor_throws_clause);
2950       const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
2951       if (methodmods)
2952 	Setattr(getCurrentClass(), "destructmethodmodifiers", methodmods);
2953     }
2954     return SWIG_OK;
2955   }
2956 
2957   /* ----------------------------------------------------------------------
2958    * membervariableHandler()
2959    * ---------------------------------------------------------------------- */
2960 
membervariableHandler(Node * n)2961   virtual int membervariableHandler(Node *n) {
2962     variable_name = Getattr(n, "sym:name");
2963     wrapping_member_flag = true;
2964     variable_wrapper_flag = true;
2965     Language::membervariableHandler(n);
2966     wrapping_member_flag = false;
2967     variable_wrapper_flag = false;
2968     return SWIG_OK;
2969   }
2970 
2971   /* ----------------------------------------------------------------------
2972    * staticmembervariableHandler()
2973    * ---------------------------------------------------------------------- */
2974 
staticmembervariableHandler(Node * n)2975   virtual int staticmembervariableHandler(Node *n) {
2976     variable_name = Getattr(n, "sym:name");
2977     wrapping_member_flag = true;
2978     static_flag = true;
2979     Language::staticmembervariableHandler(n);
2980     wrapping_member_flag = false;
2981     static_flag = false;
2982     return SWIG_OK;
2983   }
2984 
2985   /* ----------------------------------------------------------------------
2986    * memberconstantHandler()
2987    * ---------------------------------------------------------------------- */
2988 
memberconstantHandler(Node * n)2989   virtual int memberconstantHandler(Node *n) {
2990     variable_name = Getattr(n, "sym:name");
2991     wrapping_member_flag = true;
2992     Language::memberconstantHandler(n);
2993     wrapping_member_flag = false;
2994     return SWIG_OK;
2995   }
2996 
2997   /* -----------------------------------------------------------------------------
2998    * getOverloadedName()
2999    * ----------------------------------------------------------------------------- */
3000 
getOverloadedName(Node * n)3001   String *getOverloadedName(Node *n) {
3002 
3003     /* Although JNI functions are designed to handle overloaded Java functions,
3004      * a Java long is used for all classes in the SWIG intermediary class.
3005      * The intermediary class methods are thus mangled when overloaded to give
3006      * a unique name. */
3007     String *overloaded_name = NewStringf("%s", Getattr(n, "sym:name"));
3008 
3009     if (Getattr(n, "sym:overloaded")) {
3010       Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
3011     }
3012 
3013     return overloaded_name;
3014   }
3015 
3016   /* -----------------------------------------------------------------------------
3017    * moduleClassFunctionHandler()
3018    * ----------------------------------------------------------------------------- */
3019 
moduleClassFunctionHandler(Node * n)3020   void moduleClassFunctionHandler(Node *n) {
3021     SwigType *t = Getattr(n, "type");
3022     ParmList *l = Getattr(n, "parms");
3023     String *tm;
3024     Parm *p;
3025     int i;
3026     String *imcall = NewString("");
3027     String *return_type = NewString("");
3028     String *function_code = NewString("");
3029     int num_arguments = 0;
3030     String *overloaded_name = getOverloadedName(n);
3031     String *func_name = NULL;
3032     bool setter_flag = false;
3033     String *pre_code = NewString("");
3034     String *post_code = NewString("");
3035 
3036     // Translate and write javadoc comment if flagged
3037     if (doxygen && doxygenTranslator->hasDocumentation(n)) {
3038       String *doxygen_comments = doxygenTranslator->getDocumentation(n, "  ");
3039       if (comment_creation_chatter)
3040 	Printf(function_code, "/* This was generated from moduleClassFunctionHandler() */\n");
3041       Printv(function_code, doxygen_comments, NIL);
3042       Delete(doxygen_comments);
3043     }
3044 
3045     if (l) {
3046       if (SwigType_type(Getattr(l, "type")) == T_VOID) {
3047 	l = nextSibling(l);
3048       }
3049     }
3050 
3051     /* Attach the non-standard typemaps to the parameter list */
3052     Swig_typemap_attach_parms("jstype", l, NULL);
3053     Swig_typemap_attach_parms("javain", l, NULL);
3054 
3055     /* Get return types */
3056     if ((tm = Swig_typemap_lookup("jstype", n, "", 0))) {
3057       substituteClassname(t, tm);
3058       Printf(return_type, "%s", tm);
3059     } else {
3060       Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(t, 0));
3061     }
3062 
3063     /* Change function name for global variables */
3064     if (proxy_flag && global_variable_flag) {
3065       // Capitalize the first letter in the variable to create a JavaBean type getter/setter function name
3066       func_name = NewString("");
3067       setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(getNSpace(), variable_name)) == 0);
3068       if (setter_flag)
3069 	Printf(func_name, "set");
3070       else
3071 	Printf(func_name, "get");
3072       Putc(toupper((int) *Char(variable_name)), func_name);
3073       Printf(func_name, "%s", Char(variable_name) + 1);
3074     } else {
3075       func_name = Copy(Getattr(n, "sym:name"));
3076     }
3077 
3078     /* Start generating the function */
3079     const String *methodmods = Getattr(n, "feature:java:methodmodifiers");
3080     methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
3081     Printf(function_code, "  %s static %s %s(", methodmods, return_type, func_name);
3082     Printv(imcall, imclass_name, ".", overloaded_name, "(", NIL);
3083 
3084     /* Get number of required and total arguments */
3085     num_arguments = emit_num_arguments(l);
3086 
3087     bool global_or_member_variable = global_variable_flag || (wrapping_member_flag && !enum_constant_flag);
3088     int gencomma = 0;
3089 
3090     /* Output each parameter */
3091     for (i = 0, p = l; i < num_arguments; i++) {
3092 
3093       /* Ignored parameters */
3094       while (checkAttribute(p, "tmap:in:numinputs", "0")) {
3095 	p = Getattr(p, "tmap:in:next");
3096       }
3097 
3098       SwigType *pt = Getattr(p, "type");
3099       String *param_type = NewString("");
3100 
3101       /* Get the Java parameter type */
3102       if ((tm = Getattr(p, "tmap:jstype"))) {
3103 	substituteClassname(pt, tm);
3104 	Printf(param_type, "%s", tm);
3105       } else {
3106 	Swig_warning(WARN_JAVA_TYPEMAP_JSTYPE_UNDEF, input_file, line_number, "No jstype typemap defined for %s\n", SwigType_str(pt, 0));
3107       }
3108 
3109       if (gencomma)
3110 	Printf(imcall, ", ");
3111 
3112       String *arg = makeParameterName(n, p, i, global_or_member_variable);
3113 
3114       // Use typemaps to transform type used in Java wrapper function (in proxy class) to type used in JNI function (in intermediary class)
3115       if ((tm = Getattr(p, "tmap:javain"))) {
3116 	addThrows(n, "tmap:javain", p);
3117 	substituteClassname(pt, tm);
3118 	Replaceall(tm, "$javainput", arg);
3119 	String *pre = Getattr(p, "tmap:javain:pre");
3120 	if (pre) {
3121 	  substituteClassname(pt, pre);
3122 	  Replaceall(pre, "$javainput", arg);
3123           if (Len(pre_code) > 0)
3124             Printf(pre_code, "\n");
3125 	  Printv(pre_code, pre, NIL);
3126 	}
3127 	String *post = Getattr(p, "tmap:javain:post");
3128 	if (post) {
3129 	  substituteClassname(pt, post);
3130 	  Replaceall(post, "$javainput", arg);
3131           if (Len(post_code) > 0)
3132             Printf(post_code, "\n");
3133 	  Printv(post_code, post, NIL);
3134 	}
3135 	Printv(imcall, tm, NIL);
3136       } else {
3137 	Swig_warning(WARN_JAVA_TYPEMAP_JAVAIN_UNDEF, input_file, line_number, "No javain typemap defined for %s\n", SwigType_str(pt, 0));
3138       }
3139 
3140       /* Add parameter to module class function */
3141       if (gencomma >= 2)
3142 	Printf(function_code, ", ");
3143       gencomma = 2;
3144       Printf(function_code, "%s %s", param_type, arg);
3145 
3146       if (prematureGarbageCollectionPreventionParameter(pt, p)) {
3147         String *pgcppname = Getattr(p, "tmap:javain:pgcppname");
3148         if (pgcppname) {
3149           String *argname = Copy(pgcppname);
3150           Replaceall(argname, "$javainput", arg);
3151           Printf(imcall, ", %s", argname);
3152           Delete(argname);
3153         } else {
3154           Printf(imcall, ", %s", arg);
3155         }
3156       }
3157 
3158       p = Getattr(p, "tmap:in:next");
3159       Delete(arg);
3160       Delete(param_type);
3161     }
3162 
3163     Printf(imcall, ")");
3164     Printf(function_code, ")");
3165 
3166     // Transform return type used in JNI function (in intermediary class) to type used in Java wrapper function (in module class)
3167     if ((tm = Swig_typemap_lookup("javaout", n, "", 0))) {
3168       addThrows(n, "tmap:javaout", n);
3169       bool is_pre_code = Len(pre_code) > 0;
3170       bool is_post_code = Len(post_code) > 0;
3171       if (is_pre_code || is_post_code) {
3172         Replaceall(tm, "\n ", "\n   "); // add extra indentation to code in typemap
3173         if (is_post_code) {
3174           Insert(tm, 0, "\n    try ");
3175           Printv(tm, " finally {\n", post_code, "\n    }", NIL);
3176         } else {
3177           Insert(tm, 0, "\n    ");
3178         }
3179         if (is_pre_code) {
3180           Insert(tm, 0, pre_code);
3181           Insert(tm, 0, "\n");
3182         }
3183 	Insert(tm, 0, "{");
3184 	Printf(tm, "\n  }");
3185       }
3186       if (GetFlag(n, "feature:new"))
3187 	Replaceall(tm, "$owner", "true");
3188       else
3189 	Replaceall(tm, "$owner", "false");
3190       substituteClassname(t, tm);
3191       Replaceall(tm, "$jnicall", imcall);
3192     } else {
3193       Swig_warning(WARN_JAVA_TYPEMAP_JAVAOUT_UNDEF, input_file, line_number, "No javaout typemap defined for %s\n", SwigType_str(t, 0));
3194     }
3195 
3196     generateThrowsClause(n, function_code);
3197     Printf(function_code, " %s\n\n", tm ? tm : empty_string);
3198     Printv(module_class_code, function_code, NIL);
3199 
3200     Delete(pre_code);
3201     Delete(post_code);
3202     Delete(function_code);
3203     Delete(return_type);
3204     Delete(imcall);
3205     Delete(func_name);
3206   }
3207 
3208   /*----------------------------------------------------------------------
3209    * replaceSpecialVariables()
3210    *--------------------------------------------------------------------*/
3211 
replaceSpecialVariables(String * method,String * tm,Parm * parm)3212   virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
3213     (void)method;
3214     SwigType *type = Getattr(parm, "type");
3215     substituteClassname(type, tm);
3216   }
3217 
3218   /*----------------------------------------------------------------------
3219    * decodeEnumFeature()
3220    * Decode the possible enum features, which are one of:
3221    *   %javaenum(simple)
3222    *   %javaenum(typeunsafe) - default
3223    *   %javaenum(typesafe)
3224    *   %javaenum(proper)
3225    *--------------------------------------------------------------------*/
3226 
decodeEnumFeature(Node * n)3227   EnumFeature decodeEnumFeature(Node *n) {
3228     EnumFeature enum_feature = TypeunsafeEnum;
3229     String *feature = Getattr(n, "feature:java:enum");
3230     if (feature) {
3231       if (Cmp(feature, "simple") == 0)
3232 	enum_feature = SimpleEnum;
3233       else if (Cmp(feature, "typesafe") == 0)
3234 	enum_feature = TypesafeEnum;
3235       else if (Cmp(feature, "proper") == 0)
3236 	enum_feature = ProperEnum;
3237     }
3238     return enum_feature;
3239   }
3240 
3241   /* -----------------------------------------------------------------------
3242    * enumValue()
3243    * This method will return a string with an enum value to use in Java generated
3244    * code. If the %javaconst feature is not used, the string will contain the intermediary
3245    * class call to obtain the enum value. The intermediary class and JNI methods to obtain
3246    * the enum value will be generated. Otherwise the C/C++ enum value will be used if there
3247    * is one and hopefully it will compile as Java code - e.g. 20 as in: enum E{e=20};
3248    * The %javaconstvalue feature overrides all other ways to generate the constant value.
3249    * The caller must delete memory allocated for the returned string.
3250    * ------------------------------------------------------------------------ */
3251 
enumValue(Node * n)3252   String *enumValue(Node *n) {
3253     String *symname = Getattr(n, "sym:name");
3254 
3255     // Check for the %javaconstvalue feature
3256     String *value = Getattr(n, "feature:java:constvalue");
3257 
3258     if (!value) {
3259       // The %javaconst feature determines how the constant value is obtained
3260       int const_feature_flag = GetFlag(n, "feature:java:const");
3261 
3262       if (const_feature_flag) {
3263 	// Use the C syntax to make a true Java constant and hope that it compiles as Java code
3264 	value = Getattr(n, "enumvalue") ? Copy(Getattr(n, "enumvalue")) : Copy(Getattr(n, "enumvalueex"));
3265       } else {
3266 	String *newsymname = 0;
3267 	if (!getCurrentClass() || !proxy_flag) {
3268 	  String *enumClassPrefix = getEnumClassPrefix();
3269 	  if (enumClassPrefix) {
3270 	    // A global scoped enum
3271 	    newsymname = Swig_name_member(0, enumClassPrefix, symname);
3272 	    symname = newsymname;
3273 	  }
3274 	}
3275 
3276 	// Get the enumvalue from a JNI call
3277 	if (!getCurrentClass() || !cparse_cplusplus || !proxy_flag) {
3278 	  // Strange hack to change the name
3279 	  Setattr(n, "name", Getattr(n, "value"));	/* for wrapping of enums in a namespace when emit_action is used */
3280 	  constantWrapper(n);
3281 	  value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), symname));
3282 	} else {
3283 	  memberconstantHandler(n);
3284 	  value = NewStringf("%s.%s()", full_imclass_name ? full_imclass_name : imclass_name, Swig_name_get(getNSpace(), Swig_name_member(0, getEnumClassPrefix(), symname)));
3285 	}
3286 	Delete(newsymname);
3287       }
3288     }
3289     return value;
3290   }
3291 
3292   /* -----------------------------------------------------------------------------
3293    * getEnumName()
3294    *
3295    * If jnidescriptor is set, inner class names are separated with '$' otherwise a '.'
3296    * and the package is also not added to the name.
3297    * ----------------------------------------------------------------------------- */
3298 
getEnumName(SwigType * t,bool jnidescriptor)3299   String *getEnumName(SwigType *t, bool jnidescriptor) {
3300     Node *enumname = NULL;
3301     Node *n = enumLookup(t);
3302     if (n) {
3303       enumname = Getattr(n, "enumname");
3304       if (!enumname || jnidescriptor) {
3305 	String *symname = Getattr(n, "sym:name");
3306 	if (symname) {
3307 	  // Add in class scope when referencing enum if not a global enum
3308 	  String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
3309 	  String *proxyname = 0;
3310 	  if (scopename_prefix) {
3311 	    proxyname = getProxyName(scopename_prefix, jnidescriptor);
3312 	  }
3313 	  if (proxyname) {
3314 	    const char *class_separator = jnidescriptor ? "$" : ".";
3315 	    enumname = NewStringf("%s%s%s", proxyname, class_separator, symname);
3316 	  } else {
3317 	    // global enum or enum in a namespace
3318 	    String *nspace = Getattr(n, "sym:nspace");
3319 	    if (nspace) {
3320 	      if (package && !jnidescriptor)
3321 		enumname = NewStringf("%s.%s.%s", package, nspace, symname);
3322 	      else
3323 		enumname = NewStringf("%s.%s", nspace, symname);
3324 	    } else {
3325 	      enumname = Copy(symname);
3326 	    }
3327 	  }
3328 	  if (!jnidescriptor) {
3329 	    Setattr(n, "enumname", enumname); // Cache it
3330 	    Delete(enumname);
3331 	  }
3332 	  Delete(scopename_prefix);
3333 	}
3334       }
3335     }
3336 
3337     return enumname;
3338   }
3339 
3340   /* -----------------------------------------------------------------------------
3341    * substituteClassname()
3342    *
3343    * Substitute the special variable $javaclassname with the proxy class name for classes/structs/unions
3344    * that SWIG knows about. Also substitutes enums with enum name.
3345    * Otherwise use the $descriptor name for the Java class name. Note that the $&javaclassname substitution
3346    * is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
3347    * Note that the path separator is a '.' unless jnidescriptor is set.
3348    * Inputs:
3349    *   pt - parameter type
3350    *   tm - typemap contents that might contain the special variable to be replaced
3351    *   jnidescriptor - if set, inner class names are separated with '$' otherwise a '/' is used for the path separator
3352    * Outputs:
3353    *   tm - typemap contents complete with the special variable substitution
3354    * Return:
3355    *   substitution_performed - flag indicating if a substitution was performed
3356    * ----------------------------------------------------------------------------- */
3357 
substituteClassname(SwigType * pt,String * tm,bool jnidescriptor=false)3358   bool substituteClassname(SwigType *pt, String *tm, bool jnidescriptor = false) {
3359     bool substitution_performed = false;
3360     SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
3361     SwigType *strippedtype = SwigType_strip_qualifiers(type);
3362 
3363     if (Strstr(tm, "$javaclassname")) {
3364       SwigType *classnametype = Copy(strippedtype);
3365       substituteClassnameSpecialVariable(classnametype, tm, "$javaclassname", jnidescriptor);
3366       substitution_performed = true;
3367       Delete(classnametype);
3368     }
3369     if (Strstr(tm, "$*javaclassname")) {
3370       SwigType *classnametype = Copy(strippedtype);
3371       Delete(SwigType_pop(classnametype));
3372       if (Len(classnametype) > 0) {
3373 	substituteClassnameSpecialVariable(classnametype, tm, "$*javaclassname", jnidescriptor);
3374 	substitution_performed = true;
3375       }
3376       Delete(classnametype);
3377     }
3378     if (Strstr(tm, "$&javaclassname")) {
3379       SwigType *classnametype = Copy(strippedtype);
3380       SwigType_add_pointer(classnametype);
3381       substituteClassnameSpecialVariable(classnametype, tm, "$&javaclassname", jnidescriptor);
3382       substitution_performed = true;
3383       Delete(classnametype);
3384     }
3385     if (Strstr(tm, "$javainterfacename")) {
3386       SwigType *interfacenametype = Copy(strippedtype);
3387       substituteInterfacenameSpecialVariable(interfacenametype, tm, "$javainterfacename", jnidescriptor, true);
3388       substitution_performed = true;
3389       Delete(interfacenametype);
3390     }
3391     if (Strstr(tm, "$*javainterfacename")) {
3392       SwigType *interfacenametype = Copy(strippedtype);
3393       Delete(SwigType_pop(interfacenametype));
3394       if (Len(interfacenametype) > 0) {
3395 	substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*javainterfacename", jnidescriptor, true);
3396 	substitution_performed = true;
3397       }
3398       Delete(interfacenametype);
3399     }
3400     if (Strstr(tm, "$&javainterfacename")) {
3401       SwigType *interfacenametype = Copy(strippedtype);
3402       SwigType_add_pointer(interfacenametype);
3403       substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&javainterfacename", jnidescriptor, true);
3404       substitution_performed = true;
3405       Delete(interfacenametype);
3406     }
3407     if (Strstr(tm, "$interfacename")) {
3408       SwigType *interfacenametype = Copy(strippedtype);
3409       substituteInterfacenameSpecialVariable(interfacenametype, tm, "$interfacename", jnidescriptor, false);
3410       substitution_performed = true;
3411       Delete(interfacenametype);
3412     }
3413     if (Strstr(tm, "$*interfacename")) {
3414       SwigType *interfacenametype = Copy(strippedtype);
3415       Delete(SwigType_pop(interfacenametype));
3416       if (Len(interfacenametype) > 0) {
3417 	substituteInterfacenameSpecialVariable(interfacenametype, tm, "$*interfacename", jnidescriptor, false);
3418 	substitution_performed = true;
3419       }
3420       Delete(interfacenametype);
3421     }
3422     if (Strstr(tm, "$&interfacename")) {
3423       SwigType *interfacenametype = Copy(strippedtype);
3424       SwigType_add_pointer(interfacenametype);
3425       substituteInterfacenameSpecialVariable(interfacenametype, tm, "$&interfacename", jnidescriptor, false);
3426       substitution_performed = true;
3427       Delete(interfacenametype);
3428     }
3429 
3430     Delete(strippedtype);
3431     Delete(type);
3432 
3433     return substitution_performed;
3434   }
3435 
3436   /* -----------------------------------------------------------------------------
3437    * substituteClassnameSpecialVariable()
3438    * ----------------------------------------------------------------------------- */
3439 
substituteClassnameSpecialVariable(SwigType * classnametype,String * tm,const char * classnamespecialvariable,bool jnidescriptor)3440   void substituteClassnameSpecialVariable(SwigType *classnametype, String *tm, const char *classnamespecialvariable, bool jnidescriptor) {
3441     String *replacementname;
3442 
3443     if (SwigType_isenum(classnametype)) {
3444       String *enumname = getEnumName(classnametype, jnidescriptor);
3445       if (enumname) {
3446 	replacementname = Copy(enumname);
3447       } else {
3448         bool anonymous_enum = (Cmp(classnametype, "enum ") == 0);
3449 	if (anonymous_enum) {
3450 	  replacementname = NewString("int");
3451 	} else {
3452 	  // An unknown enum - one that has not been parsed (neither a C enum forward reference nor a definition) or an ignored enum
3453 	  replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
3454 	  Replace(replacementname, "enum ", "", DOH_REPLACE_ANY);
3455 	  Setattr(swig_types_hash, replacementname, classnametype);
3456 	}
3457       }
3458     } else {
3459       String *classname = getProxyName(classnametype, jnidescriptor); // getProxyName() works for pointers to classes too
3460       if (classname) {
3461 	replacementname = Copy(classname);
3462       } else {
3463 	// use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
3464 	replacementname = NewStringf("SWIGTYPE%s", SwigType_manglestr(classnametype));
3465 
3466 	// Add to hash table so that the type wrapper classes can be created later
3467 	Setattr(swig_types_hash, replacementname, classnametype);
3468       }
3469     }
3470     if (jnidescriptor)
3471       Replaceall(replacementname,".","/");
3472     Replaceall(tm, classnamespecialvariable, replacementname);
3473 
3474     Delete(replacementname);
3475   }
3476 
3477   /* -----------------------------------------------------------------------------
3478    * substituteInterfacenameSpecialVariable()
3479    * ----------------------------------------------------------------------------- */
3480 
substituteInterfacenameSpecialVariable(SwigType * interfacenametype,String * tm,const char * interfacenamespecialvariable,bool jnidescriptor,bool qualified)3481   void substituteInterfacenameSpecialVariable(SwigType *interfacenametype, String *tm, const char *interfacenamespecialvariable, bool jnidescriptor, bool qualified) {
3482 
3483     String *interfacename = getInterfaceName(interfacenametype/*, jnidescriptor*/, qualified);
3484     if (interfacename) {
3485       String *replacementname = Copy(interfacename);
3486 
3487       if (jnidescriptor)
3488 	Replaceall(replacementname,".","/");
3489       Replaceall(tm, interfacenamespecialvariable, replacementname);
3490 
3491       Delete(replacementname);
3492     }
3493   }
3494 
3495   /* -----------------------------------------------------------------------------
3496    * emitTypeWrapperClass()
3497    * ----------------------------------------------------------------------------- */
3498 
emitTypeWrapperClass(String * classname,SwigType * type)3499   void emitTypeWrapperClass(String *classname, SwigType *type) {
3500     Node *n = NewHash();
3501     Setfile(n, input_file);
3502     Setline(n, line_number);
3503 
3504     String *swigtype = NewString("");
3505     String *filen = NewStringf("%s%s.java", SWIG_output_directory(), classname);
3506     File *f_swigtype = NewFile(filen, "w", SWIG_output_files());
3507     if (!f_swigtype) {
3508       FileErrorDisplay(filen);
3509       SWIG_exit(EXIT_FAILURE);
3510     }
3511     Append(filenames_list, Copy(filen));
3512     Delete(filen);
3513     filen = NULL;
3514 
3515     // Start writing out the type wrapper class file
3516     emitBanner(f_swigtype);
3517 
3518     if (package)
3519       Printf(f_swigtype, "package %s;\n", package);
3520 
3521     // Pure Java baseclass and interfaces
3522     const String *pure_baseclass = typemapLookup(n, "javabase", type, WARN_NONE);
3523     const String *pure_interfaces = typemapLookup(n, "javainterfaces", type, WARN_NONE);
3524 
3525     // Emit the class
3526     Printv(swigtype, typemapLookup(n, "javaimports", type, WARN_NONE),	// Import statements
3527 	   "\n", typemapLookup(n, "javaclassmodifiers", type, WARN_JAVA_TYPEMAP_CLASSMOD_UNDEF),	// Class modifiers
3528 	   " $javaclassname",	// Class name and bases
3529 	   *Char(pure_baseclass) ? " extends " : "", pure_baseclass, *Char(pure_interfaces) ?	// Interfaces
3530 	   " implements " : "", pure_interfaces, " {", typemapLookup(n, "javabody", type, WARN_JAVA_TYPEMAP_JAVABODY_UNDEF),	// main body of class
3531 	   typemapLookup(n, "javacode", type, WARN_NONE),	// extra Java code
3532 	   "}\n", "\n", NIL);
3533 
3534     Replaceall(swigtype, "$javaclassname", classname);
3535     Replaceall(swigtype, "$module", module_class_name);
3536     Replaceall(swigtype, "$imclassname", imclass_name);
3537 
3538     // For unknown enums
3539     Replaceall(swigtype, "$static ", "");
3540     Replaceall(swigtype, "$enumvalues", "");
3541 
3542     Printv(f_swigtype, swigtype, NIL);
3543 
3544     Delete(f_swigtype);
3545     Delete(swigtype);
3546     Delete(n);
3547   }
3548 
3549   /* -----------------------------------------------------------------------------
3550    * typemapLookup()
3551    * n - for input only and must contain info for Getfile(n) and Getline(n) to work
3552    * tmap_method - typemap method name
3553    * type - typemap type to lookup
3554    * warning - warning number to issue if no typemaps found
3555    * typemap_attributes - the typemap attributes are attached to this node and will
3556    *   also be used for temporary storage if non null
3557    * return is never NULL, unlike Swig_typemap_lookup()
3558    * ----------------------------------------------------------------------------- */
3559 
typemapLookup(Node * n,const_String_or_char_ptr tmap_method,SwigType * type,int warning,Node * typemap_attributes=0)3560   const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
3561     Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
3562     Setattr(node, "type", type);
3563     Setfile(node, Getfile(n));
3564     Setline(node, Getline(n));
3565     const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
3566     if (!tm) {
3567       tm = empty_string;
3568       if (warning != WARN_NONE)
3569 	Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
3570     }
3571     if (!typemap_attributes)
3572       Delete(node);
3573     return tm;
3574   }
3575 
3576   /* -----------------------------------------------------------------------------
3577    * addThrows()
3578    *
3579    * Adds exception classes to a throws list. The throws list is the list of classes
3580    * that will form the Java throws clause. Mainly for checked exceptions.
3581    * ----------------------------------------------------------------------------- */
3582 
addThrows(Node * n,const String * attribute,Node * parameter)3583   void addThrows(Node *n, const String *attribute, Node *parameter) {
3584     // Get the comma separated exception classes for the throws clause - held in typemap/feature's "throws" attribute
3585     String *throws_attribute = NewStringf("%s:throws", attribute);
3586     String *throws = Getattr(parameter, throws_attribute);
3587 
3588     if (throws && Len(throws) > 0) {
3589       String *throws_list = Getattr(n, "java:throwslist");
3590       if (!throws_list) {
3591 	throws_list = NewList();
3592 	Setattr(n, "java:throwslist", throws_list);
3593       }
3594       // Put the exception classes in the throws clause into a temporary List
3595       List *temp_classes_list = Split(throws, ',', INT_MAX);
3596 
3597       // Add the exception classes to the node throws list, but don't duplicate if already in list
3598       if (temp_classes_list && Len(temp_classes_list) > 0) {
3599 	for (Iterator cls = First(temp_classes_list); cls.item; cls = Next(cls)) {
3600 	  String *exception_class = NewString(cls.item);
3601 	  Replaceall(exception_class, " ", "");	// remove spaces
3602 	  Replaceall(exception_class, "\t", "");	// remove tabs
3603 	  if (Len(exception_class) > 0) {
3604 	    // $javaclassname substitution
3605 	    SwigType *pt = Getattr(parameter, "type");
3606 	    substituteClassname(pt, exception_class);
3607 
3608 	    // Don't duplicate the Java exception class in the throws clause
3609 	    bool found_flag = false;
3610 	    for (Iterator item = First(throws_list); item.item; item = Next(item)) {
3611 	      if (Strcmp(item.item, exception_class) == 0)
3612 		found_flag = true;
3613 	    }
3614 	    if (!found_flag)
3615 	      Append(throws_list, exception_class);
3616 	  }
3617 	  Delete(exception_class);
3618 	}
3619       }
3620       Delete(temp_classes_list);
3621     }
3622     Delete(throws_attribute);
3623   }
3624 
3625   /* -----------------------------------------------------------------------------
3626    * generateThrowsClause()
3627    *
3628    * Generates throws clause for checked exception
3629    * ----------------------------------------------------------------------------- */
3630 
generateThrowsClause(Node * n,String * code)3631   void generateThrowsClause(Node *n, String *code) {
3632     // Add the throws clause into code
3633     List *throws_list = Getattr(n, "java:throwslist");
3634     if (throws_list) {
3635       Iterator cls = First(throws_list);
3636       Printf(code, " throws %s", cls.item);
3637       while ((cls = Next(cls)).item)
3638 	Printf(code, ", %s", cls.item);
3639     }
3640   }
3641 
3642   /* -----------------------------------------------------------------------------
3643    * prematureGarbageCollectionPreventionParameter()
3644    *
3645    * Get the proxy class name for use in an additional generated parameter. The
3646    * additional parameter is added to a native method call purely to prevent
3647    * premature garbage collection of proxy classes which pass their C++ class pointer
3648    * in a Java long to the JNI layer.
3649    * ----------------------------------------------------------------------------- */
3650 
prematureGarbageCollectionPreventionParameter(SwigType * t,Parm * p)3651   String *prematureGarbageCollectionPreventionParameter(SwigType *t, Parm *p) {
3652     String *pgcpp_java_type = 0;
3653     String *jtype = NewString(Getattr(p, "tmap:jtype"));
3654 
3655     // Strip C comments
3656     String *stripped_jtype = Swig_strip_c_comments(jtype);
3657     if (stripped_jtype) {
3658       Delete(jtype);
3659       jtype = stripped_jtype;
3660     }
3661 
3662     // Remove whitespace
3663     Replaceall(jtype, " ", "");
3664     Replaceall(jtype, "\t", "");
3665 
3666     if (Cmp(jtype, "long") == 0) {
3667       if (proxy_flag) {
3668 	if (!GetFlag(p, "tmap:jtype:nopgcpp") && !nopgcpp_flag) {
3669 	  String *interface_name = getInterfaceName(t, true);
3670           pgcpp_java_type = interface_name ? interface_name : getProxyName(t);
3671           if (!pgcpp_java_type) {
3672             // Look for proxy class parameters passed to C++ layer using non-default typemaps, ie not one of above types
3673             String *jstype = NewString(Getattr(p, "tmap:jstype"));
3674             if (jstype) {
3675               Hash *classes = getClassHash();
3676               if (classes) {
3677                 // Strip C comments
3678                 String *stripped_jstype = Swig_strip_c_comments(jstype);
3679                 if (stripped_jstype) {
3680                   Delete(jstype);
3681                   jstype = stripped_jstype;
3682                 }
3683                 // Remove whitespace
3684                 Replaceall(jstype, " ", "");
3685                 Replaceall(jstype, "\t", "");
3686 
3687                 Iterator ki;
3688                 for (ki = First(classes); ki.key; ki = Next(ki)) {
3689                   Node *cls = ki.item;
3690                   if (cls && !Getattr(cls, "feature:ignore")) {
3691                     String *symname = Getattr(cls, "sym:name");
3692                     if (symname && Strcmp(symname, jstype) == 0) {
3693                       pgcpp_java_type = symname;
3694                     }
3695                   }
3696                 }
3697               }
3698             }
3699             Delete(jstype);
3700           }
3701 	}
3702       }
3703     }
3704     Delete(jtype);
3705     return pgcpp_java_type;
3706   }
3707 
3708   /* -----------------------------------------------------------------------------
3709    * outputDirectory()
3710    *
3711    * Return the directory to use for generating Java classes/enums and create the
3712    * subdirectory (does not create if language specific outdir does not exist).
3713    * ----------------------------------------------------------------------------- */
3714 
outputDirectory(String * nspace)3715   String *outputDirectory(String *nspace) {
3716     String *output_directory = Copy(SWIG_output_directory());
3717     if (nspace) {
3718       String *nspace_subdirectory = Copy(nspace);
3719       Replaceall(nspace_subdirectory, ".", SWIG_FILE_DELIMITER);
3720       String *newdir_error = Swig_new_subdirectory(output_directory, nspace_subdirectory);
3721       if (newdir_error) {
3722 	Printf(stderr, "%s\n", newdir_error);
3723 	Delete(newdir_error);
3724 	SWIG_exit(EXIT_FAILURE);
3725       }
3726       Printv(output_directory, nspace_subdirectory, SWIG_FILE_DELIMITER, 0);
3727       Delete(nspace_subdirectory);
3728     }
3729     return output_directory;
3730   }
3731 
3732   /*----------------------------------------------------------------------
3733    * Start of director methods
3734    *--------------------------------------------------------------------*/
3735 
3736   /*----------------------------------------------------------------------
3737    * getUpcallJNIMethod()
3738    *--------------------------------------------------------------------*/
3739 
getUpcallJNIMethod(String * descrip)3740   String *getUpcallJNIMethod(String *descrip) {
3741     static struct {
3742       char code;
3743       const char *method;
3744     } upcall_methods[] = {
3745       {
3746       'B', "CallStaticByteMethod"}, {
3747       'C', "CallStaticCharMethod"}, {
3748       'D', "CallStaticDoubleMethod"}, {
3749       'F', "CallStaticFloatMethod"}, {
3750       'I', "CallStaticIntMethod"}, {
3751       'J', "CallStaticLongMethod"}, {
3752       'L', "CallStaticObjectMethod"}, {
3753       'S', "CallStaticShortMethod"}, {
3754       'V', "CallStaticVoidMethod"}, {
3755       'Z', "CallStaticBooleanMethod"}, {
3756       '[', "CallStaticObjectMethod"}
3757     };
3758 
3759     char code;
3760     int i;
3761 
3762     code = *Char(descrip);
3763     for (i = 0; i < (int) (sizeof(upcall_methods) / sizeof(upcall_methods[0])); ++i)
3764       if (code == upcall_methods[i].code)
3765 	return NewString(upcall_methods[i].method);
3766     return NULL;
3767   }
3768 
3769   /*----------------------------------------------------------------------
3770    * emitDirectorUpcalls()
3771    *--------------------------------------------------------------------*/
3772 
emitDirectorUpcalls()3773   void emitDirectorUpcalls() {
3774     if (n_dmethods) {
3775       Wrapper *w = NewWrapper();
3776       String *jni_imclass_name = makeValidJniName(imclass_name);
3777       String *swig_module_init = NewString("swig_module_init");
3778       String *swig_module_init_jni = makeValidJniName(swig_module_init);
3779       String *dmethod_data = NewString("");
3780       int n_methods = 0;
3781       Iterator udata_iter;
3782 
3783       udata_iter = First(dmethods_seq);
3784       while (udata_iter.item) {
3785 	UpcallData *udata = udata_iter.item;
3786 	Printf(dmethod_data, "  { \"%s\", \"%s\" }", Getattr(udata, "imclass_method"), Getattr(udata, "imclass_fdesc"));
3787 	++n_methods;
3788 
3789 	udata_iter = Next(udata_iter);
3790 
3791 	if (udata_iter.item)
3792 	  Putc(',', dmethod_data);
3793 	Putc('\n', dmethod_data);
3794       }
3795 
3796       Printf(f_runtime, "namespace Swig {\n");
3797       Printf(f_runtime, "  namespace {\n");
3798       Printf(f_runtime, "    jclass jclass_%s = NULL;\n", imclass_name);
3799       Printf(f_runtime, "    jmethodID director_method_ids[%d];\n", n_methods);
3800       Printf(f_runtime, "  }\n");
3801       Printf(f_runtime, "}\n");
3802 
3803       Printf(w->def, "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls) {", jnipackage, jni_imclass_name, swig_module_init_jni);
3804       Printf(w->code, "static struct {\n");
3805       Printf(w->code, "  const char *method;\n");
3806       Printf(w->code, "  const char *signature;\n");
3807       Printf(w->code, "} methods[%d] = {\n", n_methods);
3808       Printv(w->code, dmethod_data, NIL);
3809       Printf(w->code, "};\n");
3810 
3811       Wrapper_add_local(w, "i", "int i");
3812 
3813       Printf(w->code, "Swig::jclass_%s = (jclass) jenv->NewGlobalRef(jcls);\n", imclass_name);
3814       Printf(w->code, "if (!Swig::jclass_%s) return;\n", imclass_name);
3815       Printf(w->code, "for (i = 0; i < (int) (sizeof(methods)/sizeof(methods[0])); ++i) {\n");
3816       Printf(w->code, "  Swig::director_method_ids[i] = jenv->GetStaticMethodID(jcls, methods[i].method, methods[i].signature);\n");
3817       Printf(w->code, "  if (!Swig::director_method_ids[i]) return;\n");
3818       Printf(w->code, "}\n");
3819 
3820       Printf(w->code, "}\n");
3821 
3822       Wrapper_print(w, f_wrappers);
3823       Delete(dmethod_data);
3824       Delete(swig_module_init_jni);
3825       Delete(swig_module_init);
3826       Delete(jni_imclass_name);
3827       DelWrapper(w);
3828     }
3829   }
3830 
3831   /*----------------------------------------------------------------------
3832    * emitDirectorExtraMethods()
3833    *
3834    * This is where the director connect method is generated.
3835    *--------------------------------------------------------------------*/
emitDirectorExtraMethods(Node * n)3836   void emitDirectorExtraMethods(Node *n) {
3837     if (!Swig_directorclass(n))
3838       return;
3839 
3840     // Output the director connect method:
3841     String *jni_imclass_name = makeValidJniName(imclass_name);
3842     String *norm_name = SwigType_namestr(Getattr(n, "name"));
3843     String *swig_director_connect = Swig_name_member(getNSpace(), getClassPrefix(), "director_connect");
3844     String *swig_director_connect_jni = makeValidJniName(swig_director_connect);
3845     String *smartptr = Getattr(n, "feature:smartptr");
3846     String *dirClassName = directorClassName(n);
3847     Wrapper *code_wrap;
3848 
3849     Printf(imclass_class_code, "  public final static native void %s(%s obj, long cptr, boolean mem_own, boolean weak_global);\n",
3850 	   swig_director_connect, full_proxy_class_name);
3851 
3852     code_wrap = NewWrapper();
3853     Printf(code_wrap->def,
3854 	   "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jswig_mem_own, "
3855 	   "jboolean jweak_global) {\n", jnipackage, jni_imclass_name, swig_director_connect_jni);
3856 
3857     if (smartptr) {
3858       Printf(code_wrap->code, "  %s *obj = *((%s **)&objarg);\n", smartptr, smartptr);
3859       Printf(code_wrap->code, "  (void)jcls;\n");
3860       Printf(code_wrap->code, "  // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
3861       Printf(code_wrap->code, "  // Avoids using smart pointer specific API.\n");
3862       Printf(code_wrap->code, "  %s *director = static_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
3863     }
3864     else {
3865       Printf(code_wrap->code, "  %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
3866       Printf(code_wrap->code, "  (void)jcls;\n");
3867       Printf(code_wrap->code, "  %s *director = static_cast<%s *>(obj);\n", dirClassName, dirClassName);
3868     }
3869 
3870     Printf(code_wrap->code, "  director->swig_connect_director(jenv, jself, jenv->GetObjectClass(jself), "
3871 	   "(jswig_mem_own == JNI_TRUE), (jweak_global == JNI_TRUE));\n");
3872     Printf(code_wrap->code, "}\n");
3873 
3874     Wrapper_print(code_wrap, f_wrappers);
3875     DelWrapper(code_wrap);
3876 
3877     Delete(swig_director_connect_jni);
3878     Delete(swig_director_connect);
3879 
3880     // Output the swigReleaseOwnership, swigTakeOwnership methods:
3881     String *changeown_method_name = Swig_name_member(getNSpace(), getClassPrefix(), "change_ownership");
3882     String *changeown_jnimethod_name = makeValidJniName(changeown_method_name);
3883 
3884     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);
3885 
3886     code_wrap = NewWrapper();
3887     Printf(code_wrap->def,
3888 	   "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls, jobject jself, jlong objarg, jboolean jtake_or_release) {\n",
3889 	   jnipackage, jni_imclass_name, changeown_jnimethod_name);
3890 
3891     if (Len(smartptr)) {
3892         Printf(code_wrap->code, "  %s *obj = *((%s **)&objarg);\n", smartptr, smartptr);
3893         Printf(code_wrap->code, "  // Keep a local instance of the smart pointer around while we are using the raw pointer\n");
3894         Printf(code_wrap->code, "  // Avoids using smart pointer specific API.\n");
3895         Printf(code_wrap->code, "  %s *director = dynamic_cast<%s *>(obj->operator->());\n", dirClassName, dirClassName);
3896     } else {
3897         Printf(code_wrap->code, "  %s *obj = *((%s **)&objarg);\n", norm_name, norm_name);
3898         Printf(code_wrap->code, "  %s *director = dynamic_cast<%s *>(obj);\n", dirClassName, dirClassName);
3899     }
3900 
3901     Printf(code_wrap->code, "  (void)jcls;\n");
3902     Printf(code_wrap->code, "  if (director) {\n");
3903     Printf(code_wrap->code, "    director->swig_java_change_ownership(jenv, jself, jtake_or_release ? true : false);\n");
3904     Printf(code_wrap->code, "  }\n");
3905     Printf(code_wrap->code, "}\n");
3906 
3907     Wrapper_print(code_wrap, f_wrappers);
3908     DelWrapper(code_wrap);
3909 
3910     Delete(changeown_method_name);
3911     Delete(changeown_jnimethod_name);
3912     Delete(norm_name);
3913     Delete(dirClassName);
3914     Delete(jni_imclass_name);
3915   }
3916 
3917   /*----------------------------------------------------------------------
3918    * emitCodeTypemap()
3919    *
3920    * Output a code typemap that uses $methodname and $jnicall, as used
3921    * in the directordisconnect, director_release and director_take
3922    * typemaps.
3923    *--------------------------------------------------------------------*/
3924 
emitCodeTypemap(Node * n,bool derived,SwigType * lookup_type,const String * typemap,const String * methodname,const String * jnicall)3925   void emitCodeTypemap(Node *n, bool derived, SwigType *lookup_type, const String *typemap, const String *methodname, const String *jnicall) {
3926     const String *tm = NULL;
3927     Node *tmattrs = NewHash();
3928     String *lookup_tmname = NewString(typemap);
3929     String *method_attr_name;
3930     String *method_attr;
3931 
3932     if (derived) {
3933       Append(lookup_tmname, "_derived");
3934     }
3935 
3936     tm = typemapLookup(n, lookup_tmname, lookup_type, WARN_NONE, tmattrs);
3937     method_attr_name = NewStringf("tmap:%s:%s", lookup_tmname, methodname);
3938     method_attr = Getattr(tmattrs, method_attr_name);
3939 
3940     if (*Char(tm)) {
3941       if (method_attr) {
3942 	String *codebody = Copy(tm);
3943 	Replaceall(codebody, "$methodname", method_attr);
3944 	Replaceall(codebody, "$jnicall", jnicall);
3945 	Append(proxy_class_def, codebody);
3946 	Delete(codebody);
3947       } else {
3948 	Swig_error(input_file, line_number, "No %s method name attribute for %s\n", lookup_tmname, proxy_class_name);
3949       }
3950     } else {
3951       Swig_error(input_file, line_number, "No %s typemap for %s\n", lookup_tmname, proxy_class_name);
3952     }
3953 
3954     Delete(tmattrs);
3955     Delete(lookup_tmname);
3956     // Delete(method_attr);
3957   }
3958 
3959   /* -----------------------------------------------------------------------------
3960    * substitutePackagePath()
3961    *
3962    * Replace $packagepath using the javapackage typemap associated with passed
3963    * parm or global package if p is 0. "$packagepath/" is replaced with "" if
3964    * no package is set. Note that the path separator is a '/'.
3965    * ----------------------------------------------------------------------------- */
3966 
substitutePackagePath(String * text,Parm * p)3967   void substitutePackagePath(String *text, Parm *p) {
3968     String *pkg_path= 0;
3969 
3970     if (p)
3971       pkg_path = Swig_typemap_lookup("javapackage", p, "", 0);
3972     if (!pkg_path || Len(pkg_path) == 0)
3973       pkg_path = Copy(package_path);
3974 
3975     if (Len(pkg_path) > 0) {
3976       Replaceall(pkg_path, ".", "/");
3977       Replaceall(text, "$packagepath", pkg_path);
3978     } else {
3979       Replaceall(text, "$packagepath/", empty_string);
3980       Replaceall(text, "$packagepath", empty_string);
3981     }
3982     Delete(pkg_path);
3983   }
3984 
3985   /* ---------------------------------------------------------------
3986    * Canonicalize the JNI field descriptor
3987    *
3988    * Replace the $packagepath and $javaclassname family of special
3989    * variables with the desired package and Java proxy name as
3990    * required in the JNI field descriptors.
3991    *
3992    * !!SFM!! If $packagepath occurs in the field descriptor, but
3993    * package_path isn't set (length == 0), then strip it and the
3994    * optional trailing '/' from the resulting name.
3995    *
3996    * --------------------------------------------------------------- */
3997 
canonicalizeJNIDescriptor(String * descriptor_in,Parm * p)3998   String *canonicalizeJNIDescriptor(String *descriptor_in, Parm *p) {
3999     SwigType *type = Getattr(p, "type");
4000     String *descriptor_out = Copy(descriptor_in);
4001 
4002     substituteClassname(type, descriptor_out, true);
4003     substitutePackagePath(descriptor_out, p);
4004 
4005     return descriptor_out;
4006   }
4007 
4008   /* ---------------------------------------------------------------
4009    * classDirectorMethod()
4010    *
4011    * Emit a virtual director method to pass a method call on to the
4012    * underlying Java object.
4013    *
4014    * --------------------------------------------------------------- */
4015 
classDirectorMethod(Node * n,Node * parent,String * super)4016   int classDirectorMethod(Node *n, Node *parent, String *super) {
4017     String *c_classname = Getattr(parent, "name");
4018     String *name = Getattr(n, "name");
4019     String *symname = Getattr(n, "sym:name");
4020     SwigType *returntype = Getattr(n, "type");
4021     String *overloaded_name = getOverloadedName(n);
4022     String *storage = Getattr(n, "storage");
4023     String *value = Getattr(n, "value");
4024     String *decl = Getattr(n, "decl");
4025     String *declaration = NewString("");
4026     String *tm;
4027     Parm *p;
4028     int i;
4029     Wrapper *w = NewWrapper();
4030     ParmList *l = Getattr(n, "parms");
4031     bool is_void = !(Cmp(returntype, "void"));
4032     String *qualified_return = 0;
4033     bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
4034     int status = SWIG_OK;
4035     bool output_director = true;
4036     String *dirclassname = directorClassName(parent);
4037     String *qualified_name = NewStringf("%s::%s", dirclassname, name);
4038     String *jnidesc = NewString("");
4039     String *classdesc = NewString("");
4040     String *jniret_desc = NewString("");
4041     String *classret_desc = NewString("");
4042     SwigType *c_ret_type = NULL;
4043     String *jupcall_args = NewString("swigjobj");
4044     String *imclass_dmethod;
4045     String *callback_def = NewString("");
4046     String *callback_code = NewString("");
4047     String *imcall_args = NewString("");
4048     int classmeth_off = curr_class_dmethod - first_class_dmethod;
4049     bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
4050     String *qualified_classname = getProxyName(getClassName());
4051 
4052     // Kludge Alert: functionWrapper sets sym:overload properly, but it
4053     // isn't at this point, so we have to manufacture it ourselves. At least
4054     // we're consistent with the sym:overload name in functionWrapper. (?? when
4055     // does the overloaded method name get set?)
4056 
4057     imclass_dmethod = NewStringf("%s", Swig_name_member(getNSpace(), dirclassname, overloaded_name));
4058 
4059     qualified_return = SwigType_rcaststr(returntype, "c_result");
4060 
4061     if (!is_void && (!ignored_method || pure_virtual)) {
4062       if (!SwigType_isclass(returntype)) {
4063 	if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
4064 	  String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
4065 	  Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
4066 	  Delete(construct_result);
4067 	} else {
4068 	  String *base_typename = SwigType_base(returntype);
4069 	  String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
4070 	  Symtab *symtab = Getattr(n, "sym:symtab");
4071 	  Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
4072 
4073 	  if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstracts"))) {
4074 	    /* initialize pointers to something sane. Same for abstract
4075 	       classes when a reference is returned. */
4076 	    Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
4077 	  } else {
4078 	    /* If returning a reference, initialize the pointer to a sane
4079 	       default - if a Java exception occurs, then the pointer returns
4080 	       something other than a NULL-initialized reference. */
4081 	    SwigType *noref_type = SwigType_del_reference(Copy(returntype));
4082 	    String *noref_ltype = SwigType_lstr(noref_type, 0);
4083 	    String *return_ltype = SwigType_lstr(returntype, 0);
4084 
4085 	    Wrapper_add_localv(w, "result_default", "static", noref_ltype, "result_default", NIL);
4086 	    Wrapper_add_localv(w, "c_result", return_ltype, "c_result", NIL);
4087 	    Printf(w->code, "result_default = SwigValueInit< %s >();\n", noref_ltype);
4088 	    Printf(w->code, "c_result = &result_default;\n");
4089 	    Delete(return_ltype);
4090 	    Delete(noref_ltype);
4091 	    Delete(noref_type);
4092 	  }
4093 
4094 	  Delete(base_typename);
4095 	  Delete(resolved_typename);
4096 	}
4097       } else {
4098 	SwigType *vt;
4099 
4100 	vt = cplus_value_type(returntype);
4101 	if (!vt) {
4102 	  Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
4103 	} else {
4104 	  Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
4105 	  Delete(vt);
4106 	}
4107       }
4108     }
4109 
4110     /* Create the intermediate class wrapper */
4111     tm = Swig_typemap_lookup("jtype", n, "", 0);
4112     if (tm) {
4113       Printf(callback_def, "  public static %s %s(%s jself", tm, imclass_dmethod, qualified_classname);
4114     } else {
4115       Swig_warning(WARN_JAVA_TYPEMAP_JTYPE_UNDEF, input_file, line_number, "No jtype typemap defined for %s\n", SwigType_str(returntype, 0));
4116     }
4117 
4118     String *cdesc = NULL;
4119     SwigType *covariant = Getattr(n, "covariant");
4120     SwigType *adjustedreturntype = covariant ? covariant : returntype;
4121     Parm *adjustedreturntypeparm = NewParmNode(adjustedreturntype, n);
4122 
4123     if (Swig_typemap_lookup("directorin", adjustedreturntypeparm, "", 0)
4124 	&& (cdesc = Getattr(adjustedreturntypeparm, "tmap:directorin:descriptor"))) {
4125 
4126       // Note that in the case of polymorphic (covariant) return types, the
4127       // method's return type is changed to be the base of the C++ return
4128       // type
4129       String *jnidesc_canon = canonicalizeJNIDescriptor(cdesc, adjustedreturntypeparm);
4130       Append(classret_desc, jnidesc_canon);
4131       Delete(jnidesc_canon);
4132     } else {
4133       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",
4134 	  SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
4135       output_director = false;
4136     }
4137 
4138     /* Get the JNI field descriptor for this return type, add the JNI field descriptor
4139        to jniret_desc */
4140     if ((c_ret_type = Swig_typemap_lookup("jni", n, "", 0))) {
4141       Parm *tp = NewParmNode(c_ret_type, n);
4142 
4143       if (!is_void && !ignored_method) {
4144 	String *jretval_decl = NewStringf("%s jresult", c_ret_type);
4145 	Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
4146 	Delete(jretval_decl);
4147       }
4148 
4149       String *jdesc = NULL;
4150       if (Swig_typemap_lookup("directorin", tp, "", 0)
4151 	  && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) {
4152 
4153 	// Objects marshalled passing a Java class across JNI boundary use jobject - the nouse flag indicates this
4154 	// We need the specific Java class name instead of the generic 'Ljava/lang/Object;'
4155 	if (GetFlag(tp, "tmap:directorin:nouse"))
4156 	  jdesc = cdesc;
4157 	String *jnidesc_canon = canonicalizeJNIDescriptor(jdesc, tp);
4158 	Append(jniret_desc, jnidesc_canon);
4159 	Delete(jnidesc_canon);
4160       } else {
4161 	Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
4162 		     "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
4163 		     SwigType_str(c_ret_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
4164 	output_director = false;
4165       }
4166 
4167       Delete(tp);
4168     } else {
4169       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",
4170 	  SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
4171       output_director = false;
4172     }
4173 
4174     Delete(adjustedreturntypeparm);
4175 
4176     Swig_director_parms_fixup(l);
4177 
4178     /* Attach the standard typemaps */
4179     Swig_typemap_attach_parms("out", l, 0);
4180     Swig_typemap_attach_parms("jni", l, 0);
4181     Swig_typemap_attach_parms("jtype", l, 0);
4182     Swig_typemap_attach_parms("directorin", l, w);
4183     Swig_typemap_attach_parms("javadirectorin", l, 0);
4184     Swig_typemap_attach_parms("directorargout", l, w);
4185 
4186     if (!ignored_method) {
4187       /* Add Java environment pointer to wrapper */
4188       String *jenvstr = NewString("jenv");
4189       String *jobjstr = NewString("swigjobj");
4190 
4191       Wrapper_add_localv(w, "swigjnienv", "JNIEnvWrapper", "swigjnienv(this)", NIL, NIL);
4192       Wrapper_add_localv(w, jenvstr, "JNIEnv *", jenvstr, "= swigjnienv.getJNIEnv()", NIL);
4193       Wrapper_add_localv(w, jobjstr, "jobject", jobjstr, "= (jobject) NULL", NIL);
4194       Delete(jenvstr);
4195       Delete(jobjstr);
4196 
4197       /* Preamble code */
4198       Printf(w->code, "if (!swig_override[%d]) {\n", classmeth_off);
4199     }
4200 
4201     if (!pure_virtual) {
4202       String *super_call = Swig_method_call(super, l);
4203       if (is_void) {
4204 	Printf(w->code, "%s;\n", super_call);
4205 	if (!ignored_method)
4206 	  Printf(w->code, "return;\n");
4207       } else {
4208 	Printf(w->code, "return %s;\n", super_call);
4209       }
4210       Delete(super_call);
4211     } else {
4212       Printf(w->code, "SWIG_JavaThrowException(JNIEnvWrapper(this).getJNIEnv(), SWIG_JavaDirectorPureVirtual, ");
4213       Printf(w->code, "\"Attempted to invoke pure virtual method %s::%s.\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
4214 
4215       /* Make sure that we return something in the case of a pure
4216        * virtual method call for syntactical reasons. */
4217       if (!is_void)
4218 	Printf(w->code, "return %s;", qualified_return);
4219       else if (!ignored_method)
4220 	Printf(w->code, "return;\n");
4221     }
4222 
4223     if (!ignored_method) {
4224       Printf(w->code, "}\n");
4225       Printf(w->code, "swigjobj = swig_get_self(jenv);\n");
4226       Printf(w->code, "if (swigjobj && jenv->IsSameObject(swigjobj, NULL) == JNI_FALSE) {\n");
4227     }
4228 
4229     /* Start the Java field descriptor for the intermediate class's upcall (insert jself object) */
4230     Parm *tp = NewParmNode(c_classname, n);
4231     String *jdesc;
4232 
4233     if ((tm = Swig_typemap_lookup("directorin", tp, "", 0))
4234 	&& (jdesc = Getattr(tp, "tmap:directorin:descriptor"))) {
4235       String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp);
4236       Append(jnidesc, jni_canon);
4237       Delete(jni_canon);
4238       Delete(tm);
4239     } else {
4240       Swig_warning(WARN_TYPEMAP_DIRECTORIN_UNDEF, input_file, line_number,
4241 		   "No or improper directorin typemap for type %s  for use in %s::%s (skipping director method)\n",
4242 		   SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
4243       output_director = false;
4244     }
4245 
4246     Delete(tp);
4247 
4248     /* Go through argument list, convert from native to Java */
4249     for (i = 0, p = l; p; ++i) {
4250       /* Is this superfluous? */
4251       while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
4252 	p = Getattr(p, "tmap:directorin:next");
4253       }
4254 
4255       SwigType *pt = Getattr(p, "type");
4256       String *ln = makeParameterName(n, p, i, false);
4257       String *c_param_type = NULL;
4258       String *c_decl = NewString("");
4259       String *arg = NewString("");
4260 
4261       Printf(arg, "j%s", ln);
4262 
4263       /* Add various typemap's 'throws' clauses */
4264       addThrows(n, "tmap:directorin", p);
4265       addThrows(n, "tmap:out", p);
4266 
4267       /* And add to the upcall args */
4268       Printf(jupcall_args, ", %s", arg);
4269 
4270       /* Get parameter's intermediary C type */
4271       if ((c_param_type = Getattr(p, "tmap:jni"))) {
4272 	Parm *tp = NewParm(c_param_type, Getattr(p, "name"), n);
4273 	String *desc_tm = NULL, *jdesc = NULL, *cdesc = NULL;
4274 
4275 	/* Add to local variables */
4276 	Printf(c_decl, "%s %s", c_param_type, arg);
4277 	if (!ignored_method)
4278 	  Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
4279 
4280 	/* Add input marshalling code and update JNI field descriptor */
4281 	if ((desc_tm = Swig_typemap_lookup("directorin", tp, "", 0))
4282 	    && (jdesc = Getattr(tp, "tmap:directorin:descriptor"))
4283 	    && (tm = Getattr(p, "tmap:directorin"))
4284 	    && (cdesc = Getattr(p, "tmap:directorin:descriptor"))) {
4285 
4286 	  // Objects marshalled by passing a Java class across the JNI boundary use jobject as the JNI type -
4287 	  // the nouse flag indicates this. We need the specific Java class name instead of the generic 'Ljava/lang/Object;'
4288 	  if (GetFlag(tp, "tmap:directorin:nouse"))
4289 	    jdesc = cdesc;
4290 	  String *jni_canon = canonicalizeJNIDescriptor(jdesc, tp);
4291 	  Append(jnidesc, jni_canon);
4292 	  Delete(jni_canon);
4293 
4294 	  Setattr(p, "emit:directorinput", arg);
4295 	  Replaceall(tm, "$input", arg);
4296 	  Replaceall(tm, "$owner", "0");
4297 
4298 	  if (Len(tm))
4299 	    if (!ignored_method)
4300 	      Printf(w->code, "%s\n", tm);
4301 
4302 	  /* Add parameter to the intermediate class code if generating the
4303 	   * intermediate's upcall code */
4304 	  if ((tm = Getattr(p, "tmap:jtype"))) {
4305 	    String *din = Copy(Getattr(p, "tmap:javadirectorin"));
4306             addThrows(n, "tmap:javadirectorin", p);
4307 
4308 	    if (din) {
4309 	      Replaceall(din, "$module", module_class_name);
4310 	      Replaceall(din, "$imclassname", imclass_name);
4311 	      substituteClassname(pt, din);
4312 	      Replaceall(din, "$jniinput", ln);
4313 
4314 	      if (i > 0)
4315 		Printf(imcall_args, ", ");
4316 	      Printf(callback_def, ", %s %s", tm, ln);
4317 
4318 	      if (Cmp(din, ln)) {
4319 		Printv(imcall_args, din, NIL);
4320 	      } else
4321 		Printv(imcall_args, ln, NIL);
4322 
4323 	      jni_canon = canonicalizeJNIDescriptor(cdesc, p);
4324 	      Append(classdesc, jni_canon);
4325 	      Delete(jni_canon);
4326 	    } else {
4327 	      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",
4328 		  SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
4329 	      output_director = false;
4330 	    }
4331 	  } else {
4332 	    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",
4333 		SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
4334 	    output_director = false;
4335 	  }
4336 
4337 	  p = Getattr(p, "tmap:directorin:next");
4338 
4339 	  Delete(desc_tm);
4340 	} else {
4341 	  if (!desc_tm) {
4342 	    Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number,
4343 			 "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
4344 			 SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
4345 	    p = nextSibling(p);
4346 	  } else if (!jdesc) {
4347 	    Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number,
4348 			 "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
4349 			 SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
4350 	    p = Getattr(p, "tmap:directorin:next");
4351 	  } else if (!tm) {
4352 	    Swig_warning(WARN_JAVA_TYPEMAP_JAVADIRECTORIN_UNDEF, input_file, line_number,
4353 			 "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
4354 			 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
4355 	    p = nextSibling(p);
4356 	  } else if (!cdesc) {
4357 	    Swig_warning(WARN_JAVA_TYPEMAP_DIRECTORIN_NODESC, input_file, line_number,
4358 			 "Missing JNI descriptor in directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
4359 			 SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
4360 	    p = Getattr(p, "tmap:directorin:next");
4361 	  }
4362 
4363 	  output_director = false;
4364 	}
4365 
4366       } else {
4367 	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",
4368 	    SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
4369 	output_director = false;
4370 	p = nextSibling(p);
4371       }
4372 
4373       Delete(arg);
4374       Delete(c_decl);
4375       Delete(ln);
4376     }
4377 
4378     /* header declaration, start wrapper definition */
4379     String *target;
4380     SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : Getattr(n, "classDirectorMethods:type");
4381     target = Swig_method_decl(rtype, decl, qualified_name, l, 0);
4382     Printf(w->def, "%s", target);
4383     Delete(qualified_name);
4384     Delete(target);
4385     target = Swig_method_decl(rtype, decl, name, l, 1);
4386     Printf(declaration, "    virtual %s", target);
4387     Delete(target);
4388 
4389     // Add any exception specifications to the methods in the director class
4390     // Get any Java exception classes in the throws typemap
4391     ParmList *throw_parm_list = NULL;
4392 
4393     // May need to add Java throws clause to director methods if %catches defined
4394     // Get any Java exception classes in the throws typemap
4395     ParmList *catches_list = Getattr(n, "catchlist");
4396     if (catches_list) {
4397       Swig_typemap_attach_parms("throws", catches_list, 0);
4398       Swig_typemap_attach_parms("directorthrows", catches_list, 0);
4399       for (p = catches_list; p; p = nextSibling(p)) {
4400 	addThrows(n, "tmap:throws", p);
4401       }
4402     }
4403 
4404     if (Getattr(n, "noexcept")) {
4405       Append(w->def, " noexcept");
4406       Append(declaration, " noexcept");
4407     }
4408     if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
4409       int gencomma = 0;
4410 
4411       Append(w->def, " throw(");
4412       Append(declaration, " throw(");
4413 
4414       if (throw_parm_list) {
4415 	Swig_typemap_attach_parms("throws", throw_parm_list, 0);
4416 	Swig_typemap_attach_parms("directorthrows", throw_parm_list, 0);
4417       }
4418       for (p = throw_parm_list; p; p = nextSibling(p)) {
4419 	if (Getattr(p, "tmap:throws")) {
4420 	  // %catches replaces the specified exception specification
4421 	  if (!catches_list) {
4422 	    addThrows(n, "tmap:throws", p);
4423 	  }
4424 
4425 	  if (gencomma++) {
4426 	    Append(w->def, ", ");
4427 	    Append(declaration, ", ");
4428 	  }
4429 
4430 	  Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
4431 	  Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
4432 	}
4433       }
4434 
4435       Append(w->def, ")");
4436       Append(declaration, ")");
4437     }
4438 
4439     Append(w->def, " {");
4440     Append(declaration, ";\n");
4441 
4442     /* Emit the intermediate class's upcall to the actual class */
4443 
4444     String *upcall = NewStringf("jself.%s(%s)", symname, imcall_args);
4445 
4446     // Handle exception classes specified in the "except" feature's "throws" attribute
4447     addThrows(n, "feature:except", n);
4448 
4449     if (!is_void) {
4450       if ((tm = Swig_typemap_lookup("javadirectorout", n, "", 0))) {
4451         addThrows(n, "tmap:javadirectorout", n);
4452 	substituteClassname(returntype, tm);
4453 	Replaceall(tm, "$javacall", upcall);
4454 
4455 	Printf(callback_code, "    return %s;\n", tm);
4456       }
4457 
4458       if ((tm = Swig_typemap_lookup("out", n, "", 0)))
4459         addThrows(n, "tmap:out", n);
4460 
4461       Delete(tm);
4462     } else
4463       Printf(callback_code, "    %s;\n", upcall);
4464 
4465     Printf(callback_code, "  }\n");
4466     Delete(upcall);
4467 
4468     /* Finish off the inherited upcall's definition */
4469     Putc(')', callback_def);
4470     generateThrowsClause(n, callback_def);
4471     Printf(callback_def, " {\n");
4472 
4473     if (!ignored_method) {
4474       /* Emit the actual upcall through */
4475       String *imclass_desc = NewStringf("(%s)%s", jnidesc, jniret_desc);
4476       String *class_desc = NewStringf("(%s)%s", classdesc, classret_desc);
4477       UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, imclass_desc, class_desc, decl);
4478       String *methid = Getattr(udata, "imclass_methodidx");
4479       String *methop = getUpcallJNIMethod(jniret_desc);
4480 
4481       if (!is_void)
4482 	Printf(w->code, "jresult = (%s) ", c_ret_type);
4483 
4484       Printf(w->code, "jenv->%s(Swig::jclass_%s, Swig::director_method_ids[%s], %s);\n", methop, imclass_name, methid, jupcall_args);
4485 
4486       // Generate code to handle any Java exception thrown by director delegation
4487       directorExceptHandler(n, catches_list ? catches_list : throw_parm_list, w);
4488 
4489       if (!is_void) {
4490 	String *jresult_str = NewString("jresult");
4491 	String *result_str = NewString("c_result");
4492 
4493 	/* Copy jresult into c_result... */
4494 	if ((tm = Swig_typemap_lookup("directorout", n, result_str, w))) {
4495 	  addThrows(n, "tmap:directorout", n);
4496 	  Replaceall(tm, "$input", jresult_str);
4497 	  Replaceall(tm, "$result", result_str);
4498 	  Printf(w->code, "%s\n", tm);
4499 	} else {
4500 	  Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
4501 		       "Unable to use return type %s used in %s::%s (skipping director method)\n",
4502 		       SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
4503 	  output_director = false;
4504 	}
4505 
4506 	Delete(jresult_str);
4507 	Delete(result_str);
4508       }
4509 
4510       /* Marshal outputs */
4511       for (p = l; p;) {
4512 	if ((tm = Getattr(p, "tmap:directorargout"))) {
4513 	  addThrows(n, "tmap:directorargout", p);
4514 	  Replaceall(tm, "$result", makeParameterName(n, p, i, false));
4515 	  Replaceall(tm, "$input", Getattr(p, "emit:directorinput"));
4516 	  Printv(w->code, tm, "\n", NIL);
4517 	  p = Getattr(p, "tmap:directorargout:next");
4518 	} else {
4519 	  p = nextSibling(p);
4520 	}
4521       }
4522 
4523       Delete(imclass_desc);
4524       Delete(class_desc);
4525 
4526       /* Terminate wrapper code */
4527       Printf(w->code, "} else {\n");
4528       Printf(w->code, "SWIG_JavaThrowException(jenv, SWIG_JavaNullPointerException, \"null upcall object in %s::%s \");\n",
4529 	     SwigType_namestr(c_classname), SwigType_namestr(name));
4530       Printf(w->code, "}\n");
4531 
4532       Printf(w->code, "if (swigjobj) jenv->DeleteLocalRef(swigjobj);\n");
4533 
4534       if (!is_void)
4535 	Printf(w->code, "return %s;", qualified_return);
4536     }
4537 
4538     Printf(w->code, "}");
4539 
4540     // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
4541     String *inline_extra_method = NewString("");
4542     if (dirprot_mode() && !is_public(n) && !pure_virtual) {
4543       Printv(inline_extra_method, declaration, NIL);
4544       String *extra_method_name = NewStringf("%sSwigPublic", name);
4545       Replaceall(inline_extra_method, name, extra_method_name);
4546       Replaceall(inline_extra_method, ";\n", " {\n      ");
4547       if (!is_void)
4548 	Printf(inline_extra_method, "return ");
4549       String *methodcall = Swig_method_call(super, l);
4550       Printv(inline_extra_method, methodcall, ";\n    }\n", NIL);
4551       Delete(methodcall);
4552       Delete(extra_method_name);
4553     }
4554 
4555     /* emit the director method */
4556     if (status == SWIG_OK && output_director) {
4557       if (!is_void) {
4558 	Replaceall(w->code, "$null", qualified_return);
4559       } else {
4560 	Replaceall(w->code, "$null", "");
4561       }
4562       if (!GetFlag(n, "feature:ignore"))
4563 	Printv(imclass_directors, callback_def, callback_code, NIL);
4564       if (!Getattr(n, "defaultargs")) {
4565 	Replaceall(w->code, "$symname", symname);
4566 	Wrapper_print(w, f_directors);
4567 	Printv(f_directors_h, declaration, NIL);
4568 	Printv(f_directors_h, inline_extra_method, NIL);
4569       }
4570     }
4571 
4572     Delete(inline_extra_method);
4573     Delete(qualified_return);
4574     Delete(jnidesc);
4575     Delete(c_ret_type);
4576     Delete(jniret_desc);
4577     Delete(declaration);
4578     Delete(callback_def);
4579     Delete(callback_code);
4580     DelWrapper(w);
4581 
4582     return status;
4583   }
4584 
4585   /* ------------------------------------------------------------
4586    * directorExceptHandler()
4587    *
4588    * Emit code to map Java exceptions back to C++ exceptions when
4589    * feature("director:except") is applied to a method node.
4590    * This is generated after the Java method upcall.
4591    * ------------------------------------------------------------ */
4592 
directorExceptHandler(Node * n,ParmList * throw_parm_list,Wrapper * w)4593   void directorExceptHandler(Node *n, ParmList *throw_parm_list, Wrapper *w) {
4594 
4595     String *directorexcept = Getattr(n, "feature:director:except");
4596     if (!directorexcept) {
4597       directorexcept = NewString("");
4598       Printf(directorexcept, "jthrowable $error = jenv->ExceptionOccurred();\n");
4599       Printf(directorexcept, "if ($error) {");
4600       Printf(directorexcept, "$directorthrowshandlers\n");
4601       Printf(directorexcept, "  Swig::DirectorException::raise(jenv, $error);\n");
4602       Printf(directorexcept, "}\n");
4603     } else {
4604       directorexcept = Copy(directorexcept);
4605     }
4606 
4607     // Can explicitly disable director:except by setting to "" or "0"
4608     if (Len(directorexcept) > 0 && Cmp(directorexcept, "0") != 0) {
4609 
4610       // Replace $packagepath
4611       substitutePackagePath(directorexcept, 0);
4612 
4613       // Replace $directorthrowshandlers with any defined typemap handlers (or nothing)
4614       if (Strstr(directorexcept, "$directorthrowshandlers")) {
4615 	String *directorthrowshandlers_code = NewString("");
4616 
4617 	for (Parm *p = throw_parm_list; p; p = nextSibling(p)) {
4618 	  String *tm = Getattr(p, "tmap:directorthrows");
4619 
4620 	  if (tm) {
4621 	    // replace $packagepath/$javaclassname
4622 	    String *directorthrows = canonicalizeJNIDescriptor(tm, p);
4623 	    Printv(directorthrowshandlers_code, directorthrows, NIL);
4624 	    Delete(directorthrows);
4625 	  } else {
4626 	    String *t = Getattr(p,"type");
4627 	    Swig_warning(WARN_TYPEMAP_DIRECTORTHROWS_UNDEF, Getfile(n), Getline(n), "No directorthrows typemap defined for %s\n", SwigType_str(t, 0));
4628 	  }
4629 	}
4630 	Replaceall(directorexcept, "$directorthrowshandlers", directorthrowshandlers_code);
4631 	Delete(directorthrowshandlers_code);
4632       }
4633 
4634       Replaceall(directorexcept, "$error", "swigerror");
4635       Printf(w->code, "    %s\n", directorexcept);
4636     }
4637     Delete(directorexcept);
4638   }
4639 
4640   /* ------------------------------------------------------------
4641    * directorPrefixArgs()
4642    * ------------------------------------------------------------ */
4643 
directorPrefixArgs(Node * n)4644   void directorPrefixArgs(Node *n) {
4645     Parm *p;
4646 
4647     /* Need to prepend 'jenv' to the director constructor's argument list */
4648 
4649     String *jenv_type = NewString("JNIEnv");
4650 
4651     SwigType_add_pointer(jenv_type);
4652 
4653     p = NewParm(jenv_type, NewString("jenv"), n);
4654     Setattr(p, "arg:byname", "1");
4655     set_nextSibling(p, NULL);
4656 
4657     Setattr(n, "director:prefix_args", p);
4658   }
4659 
4660   /* ------------------------------------------------------------
4661    * classDirectorConstructor()
4662    * ------------------------------------------------------------ */
4663 
classDirectorConstructor(Node * n)4664   int classDirectorConstructor(Node *n) {
4665     Node *parent = parentNode(n);
4666     String *decl = Getattr(n, "decl");
4667     String *supername = Swig_class_name(parent);
4668     String *dirclassname = directorClassName(parent);
4669     String *sub = NewString("");
4670     Parm *p;
4671     ParmList *superparms = Getattr(n, "parms");
4672     ParmList *parms;
4673     int argidx = 0;
4674 
4675     /* Assign arguments to superclass's parameters, if not already done */
4676     for (p = superparms; p; p = nextSibling(p)) {
4677       String *pname = Getattr(p, "name");
4678 
4679       if (!pname) {
4680 	pname = NewStringf("arg%d", argidx++);
4681 	Setattr(p, "name", pname);
4682       }
4683     }
4684 
4685     /* insert jenv prefix argument */
4686     parms = CopyParmList(superparms);
4687 
4688     String *jenv_type = NewString("JNIEnv");
4689     SwigType_add_pointer(jenv_type);
4690     p = NewParm(jenv_type, NewString("jenv"), n);
4691     set_nextSibling(p, parms);
4692     parms = p;
4693 
4694     directorPrefixArgs(n);
4695 
4696     if (!Getattr(n, "defaultargs")) {
4697       /* constructor */
4698       {
4699 	String *basetype = Getattr(parent, "classtype");
4700 	String *target = Swig_method_decl(0, decl, dirclassname, parms, 0);
4701 	String *call = Swig_csuperclass_call(0, basetype, superparms);
4702 	String *classtype = SwigType_namestr(Getattr(n, "name"));
4703 
4704 	Printf(f_directors, "%s::%s : %s, %s {\n", dirclassname, target, call, Getattr(parent, "director:ctor"));
4705 	Printf(f_directors, "}\n\n");
4706 
4707 	Delete(classtype);
4708 	Delete(target);
4709 	Delete(call);
4710       }
4711 
4712       /* constructor header */
4713       {
4714 	String *target = Swig_method_decl(0, decl, dirclassname, parms, 1);
4715 	Printf(f_directors_h, "    %s;\n", target);
4716 	Delete(target);
4717       }
4718     }
4719 
4720     Delete(sub);
4721     Delete(supername);
4722     Delete(jenv_type);
4723     Delete(parms);
4724     Delete(dirclassname);
4725     return Language::classDirectorConstructor(n);
4726   }
4727 
4728   /* ------------------------------------------------------------
4729    * classDirectorDefaultConstructor()
4730    * ------------------------------------------------------------ */
4731 
classDirectorDefaultConstructor(Node * n)4732   int classDirectorDefaultConstructor(Node *n) {
4733     String *classname = Swig_class_name(n);
4734     String *classtype = SwigType_namestr(Getattr(n, "name"));
4735     String *dirClassName = directorClassName(n);
4736     Wrapper *w = NewWrapper();
4737 
4738     Printf(w->def, "%s::%s(JNIEnv *jenv) : %s {", dirClassName, dirClassName, Getattr(n, "director:ctor"));
4739     Printf(w->code, "}\n");
4740     Wrapper_print(w, f_directors);
4741 
4742     Printf(f_directors_h, "    %s(JNIEnv *jenv);\n", dirClassName);
4743     DelWrapper(w);
4744     Delete(classtype);
4745     Delete(classname);
4746     Delete(dirClassName);
4747     directorPrefixArgs(n);
4748     return Language::classDirectorDefaultConstructor(n);
4749   }
4750 
4751 
4752   /* ------------------------------------------------------------
4753    * classDirectorInit()
4754    * ------------------------------------------------------------ */
4755 
classDirectorInit(Node * n)4756   int classDirectorInit(Node *n) {
4757     Delete(none_comparison);
4758     none_comparison = NewString("");	// not used
4759 
4760     Delete(director_ctor_code);
4761     director_ctor_code = NewString("$director_new");
4762 
4763     directorDeclaration(n);
4764 
4765     Printf(f_directors_h, "%s {\n", Getattr(n, "director:decl"));
4766     Printf(f_directors_h, "\npublic:\n");
4767     Printf(f_directors_h, "    void swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global);\n");
4768 
4769     /* Keep track of the director methods for this class */
4770     first_class_dmethod = curr_class_dmethod = n_dmethods;
4771 
4772     return Language::classDirectorInit(n);
4773   }
4774 
4775   /* ----------------------------------------------------------------------
4776    * classDirectorDestructor()
4777    * ---------------------------------------------------------------------- */
4778 
classDirectorDestructor(Node * n)4779   int classDirectorDestructor(Node *n) {
4780     Node *current_class = getCurrentClass();
4781     String *full_classname = Getattr(current_class, "name");
4782     String *classname = Swig_class_name(current_class);
4783     String *dirClassName = directorClassName(current_class);
4784     Wrapper *w = NewWrapper();
4785 
4786     if (Getattr(n, "noexcept")) {
4787       Printf(f_directors_h, "    virtual ~%s() noexcept;\n", dirClassName);
4788       Printf(w->def, "%s::~%s() noexcept {\n", dirClassName, dirClassName);
4789     } else if (Getattr(n, "throw")) {
4790       Printf(f_directors_h, "    virtual ~%s() throw();\n", dirClassName);
4791       Printf(w->def, "%s::~%s() throw() {\n", dirClassName, dirClassName);
4792     } else {
4793       Printf(f_directors_h, "    virtual ~%s();\n", dirClassName);
4794       Printf(w->def, "%s::~%s() {\n", dirClassName, dirClassName);
4795     }
4796 
4797     /* Ensure that correct directordisconnect typemap's method name is called
4798      * here: */
4799 
4800     Node *disconn_attr = NewHash();
4801     String *disconn_methodname = NULL;
4802 
4803     typemapLookup(n, "directordisconnect", full_classname, WARN_NONE, disconn_attr);
4804     disconn_methodname = Getattr(disconn_attr, "tmap:directordisconnect:methodname");
4805 
4806     Printv(w->code, "  swig_disconnect_director_self(\"", disconn_methodname, "\");\n", "}\n", NIL);
4807 
4808     Wrapper_print(w, f_directors);
4809 
4810     DelWrapper(w);
4811     Delete(disconn_attr);
4812     Delete(classname);
4813     Delete(dirClassName);
4814     return SWIG_OK;
4815   }
4816 
4817   /* ------------------------------------------------------------
4818    * classDirectorEnd()
4819    * ------------------------------------------------------------ */
4820 
classDirectorEnd(Node * n)4821   int classDirectorEnd(Node *n) {
4822     String *full_classname = Getattr(n, "name");
4823     String *classname = getProxyName(full_classname, true);
4824     String *director_classname = directorClassName(n);
4825     String *internal_classname;
4826 
4827     Wrapper *w = NewWrapper();
4828 
4829     if (Len(package_path) > 0)
4830       internal_classname = NewStringf("%s/%s", package_path, classname);
4831     else
4832       internal_classname = NewStringf("%s", classname);
4833 
4834     // If the namespace is multiple levels, the result of getNSpace() will have inserted
4835     // .'s to delimit namespaces, so we need to replace those with /'s
4836     Replace(internal_classname, NSPACE_SEPARATOR, "/", DOH_REPLACE_ANY);
4837 
4838     Wrapper_add_localv(w, "baseclass", "static jclass baseclass", "= 0", NIL);
4839     Printf(w->def, "void %s::swig_connect_director(JNIEnv *jenv, jobject jself, jclass jcls, bool swig_mem_own, bool weak_global) {", director_classname);
4840 
4841     if (first_class_dmethod != curr_class_dmethod) {
4842       Printf(w->def, "static struct {\n");
4843       Printf(w->def, "const char *mname;\n");
4844       Printf(w->def, "const char *mdesc;\n");
4845       Printf(w->def, "jmethodID base_methid;\n");
4846       Printf(w->def, "} methods[] = {\n");
4847 
4848       for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
4849 	UpcallData *udata = Getitem(dmethods_seq, i);
4850 
4851 	Printf(w->def, "{ \"%s\", \"%s\", NULL }", Getattr(udata, "method"), Getattr(udata, "fdesc"));
4852 	if (i != curr_class_dmethod - 1)
4853 	  Putc(',', w->def);
4854 	Putc('\n', w->def);
4855       }
4856 
4857       Printf(w->def, "};\n");
4858     }
4859 
4860     Printf(w->code, "if (swig_set_self(jenv, jself, swig_mem_own, weak_global)) {\n");
4861     Printf(w->code, "if (!baseclass) {\n");
4862     Printf(w->code, "baseclass = jenv->FindClass(\"%s\");\n", internal_classname);
4863     Printf(w->code, "if (!baseclass) return;\n");
4864     Printf(w->code, "baseclass = (jclass) jenv->NewGlobalRef(baseclass);\n");
4865     Printf(w->code, "}\n");
4866 
4867     int n_methods = curr_class_dmethod - first_class_dmethod;
4868 
4869     if (n_methods) {
4870       /* Emit the swig_overrides() method and the swig_override array */
4871       Printf(f_directors_h, "public:\n");
4872       Printf(f_directors_h, "    bool swig_overrides(int n) {\n");
4873       Printf(f_directors_h, "      return (n < %d ? swig_override[n] : false);\n", n_methods);
4874       Printf(f_directors_h, "    }\n");
4875       Printf(f_directors_h, "protected:\n");
4876       Printf(f_directors_h, "    Swig::BoolArray<%d> swig_override;\n", n_methods);
4877 
4878       /* Emit the code to look up the class's methods, initialize the override array */
4879 
4880       Printf(w->code, "bool derived = (jenv->IsSameObject(baseclass, jcls) ? false : true);\n");
4881       Printf(w->code, "for (int i = 0; i < %d; ++i) {\n", n_methods);
4882       Printf(w->code, "  if (!methods[i].base_methid) {\n");
4883       Printf(w->code, "    methods[i].base_methid = jenv->GetMethodID(baseclass, methods[i].mname, methods[i].mdesc);\n");
4884       Printf(w->code, "    if (!methods[i].base_methid) return;\n");
4885       Printf(w->code, "  }\n");
4886       // Generally, derived classes have a mix of overridden and
4887       // non-overridden methods and it is worth making a GetMethodID
4888       // check during initialization to determine if each method is
4889       // overridden, thus avoiding unnecessary calls into Java.
4890       //
4891       // On the other hand, when derived classes are
4892       // expected to override all director methods then the
4893       // GetMethodID calls are inefficient, and it is better to let
4894       // the director unconditionally call up into Java.  The resulting code
4895       // will still behave correctly (though less efficiently) when Java
4896       // code doesn't override a given method.
4897       //
4898       // The assumeoverride feature on a director controls whether or not
4899       // overrides are assumed.
4900       if (GetFlag(n, "feature:director:assumeoverride")) {
4901         Printf(w->code, "  swig_override[i] = derived;\n");
4902       } else {
4903         Printf(w->code, "  swig_override[i] = false;\n");
4904         Printf(w->code, "  if (derived) {\n");
4905         Printf(w->code, "    jmethodID methid = jenv->GetMethodID(jcls, methods[i].mname, methods[i].mdesc);\n");
4906         Printf(w->code, "    swig_override[i] = (methid != methods[i].base_methid);\n");
4907         Printf(w->code, "    jenv->ExceptionClear();\n");
4908         Printf(w->code, "  }\n");
4909       }
4910       Printf(w->code, "}\n");
4911     } else {
4912       Printf(f_directors_h, "public:\n");
4913       Printf(f_directors_h, "    bool swig_overrides(int n) {\n");
4914       Printf(f_directors_h, "      return false;\n");
4915       Printf(f_directors_h, "    }\n");
4916     }
4917 
4918     Printf(f_directors_h, "};\n\n");
4919     Printf(w->code, "}\n");
4920     Printf(w->code, "}\n");
4921 
4922     Wrapper_print(w, f_directors);
4923 
4924     DelWrapper(w);
4925     Delete(internal_classname);
4926 
4927     return Language::classDirectorEnd(n);
4928   }
4929 
4930   /* --------------------------------------------------------------------
4931    * classDirectorDisown()
4932    * ------------------------------------------------------------------*/
4933 
classDirectorDisown(Node * n)4934   virtual int classDirectorDisown(Node *n) {
4935     (void) n;
4936     return SWIG_OK;
4937   }
4938 
4939   /*----------------------------------------------------------------------
4940    * extraDirectorProtectedCPPMethodsRequired()
4941    *--------------------------------------------------------------------*/
4942 
extraDirectorProtectedCPPMethodsRequired() const4943   bool extraDirectorProtectedCPPMethodsRequired() const {
4944     return false;
4945   }
4946 
4947   /*----------------------------------------------------------------------
4948    * directorDeclaration()
4949    *
4950    * Generate the director class's declaration
4951    * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
4952    *--------------------------------------------------------------------*/
4953 
directorDeclaration(Node * n)4954   void directorDeclaration(Node *n) {
4955     String *base = Getattr(n, "classtype");
4956     String *class_ctor = NewString("Swig::Director(jenv)");
4957 
4958     String *directorname = directorClassName(n);
4959     String *declaration = Swig_class_declaration(n, directorname);
4960 
4961     Printf(declaration, " : public %s, public Swig::Director", base);
4962 
4963     // Stash stuff for later.
4964     Setattr(n, "director:decl", declaration);
4965     Setattr(n, "director:ctor", class_ctor);
4966   }
4967 
4968   /*----------------------------------------------------------------------
4969    * nestedClassesSupport()
4970    *--------------------------------------------------------------------*/
4971 
nestedClassesSupport() const4972   NestedClassSupport nestedClassesSupport() const {
4973     return NCS_Full;
4974   }
4975 };				/* class JAVA */
4976 
4977 /* -----------------------------------------------------------------------------
4978  * swig_java()    - Instantiate module
4979  * ----------------------------------------------------------------------------- */
4980 
new_swig_java()4981 static Language *new_swig_java() {
4982   return new JAVA();
4983 }
swig_java(void)4984 extern "C" Language *swig_java(void) {
4985   return new_swig_java();
4986 }
4987 
4988 /* -----------------------------------------------------------------------------
4989  * Static member variables
4990  * ----------------------------------------------------------------------------- */
4991 
4992 const char *JAVA::usage = "\
4993 Java Options (available with -java)\n\
4994      -doxygen        - Convert C++ doxygen comments to JavaDoc comments in proxy classes\n\
4995      -debug-doxygen-parser     - Display doxygen parser module debugging information\n\
4996      -debug-doxygen-translator - Display doxygen translator module debugging information\n\
4997      -nopgcpp        - Suppress premature garbage collection prevention parameter\n\
4998      -noproxy        - Generate the low-level functional interface instead\n\
4999                        of proxy classes\n\
5000      -oldvarnames    - Old intermediary method names for variable wrappers\n\
5001      -package <name> - Set name of the Java package to <name>\n\
5002 \n";
5003