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