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