PageRenderTime 66ms CodeModel.GetById 30ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Source/Modules/go.cxx

#
C++ | 2221 lines | 1701 code | 259 blank | 261 comment | 364 complexity | 78793f1dd6d1ffe0524db92217de5307 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0

Large files files are truncated, but you can click here to view the full file

  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. * go.cxx
  6. *
  7. * Go language module for SWIG.
  8. * ----------------------------------------------------------------------------- */
  9. char cvsroot_go_cxx[] = "$Id";
  10. #include "swigmod.h"
  11. #include "cparse.h"
  12. #include <ctype.h>
  13. #ifdef HAVE_GCCGO_46
  14. #define GCCGO_46_DEFAULT true
  15. #else
  16. #define GCCGO_46_DEFAULT false
  17. #endif
  18. class GO:public Language {
  19. static const char *const usage;
  20. // Go package name.
  21. String *package;
  22. // Flag for generating gccgo output.
  23. bool gccgo_flag;
  24. // Flag for generating gccgo 4.6 output.
  25. bool gccgo_46_flag;
  26. // Prefix to use with gccgo.
  27. String *go_prefix;
  28. // Name of shared library to import.
  29. String *soname;
  30. // Size in bits of the C type "long".
  31. int long_type_size;
  32. /* Output files */
  33. File *f_c_begin;
  34. File *f_go_begin;
  35. File *f_gc_begin;
  36. /* Output fragments */
  37. File *f_c_runtime;
  38. File *f_c_header;
  39. File *f_c_wrappers;
  40. File *f_c_init;
  41. File *f_c_directors;
  42. File *f_c_directors_h;
  43. File *f_go_runtime;
  44. File *f_go_header;
  45. File *f_go_wrappers;
  46. File *f_gc_runtime;
  47. File *f_gc_header;
  48. File *f_gc_wrappers;
  49. // True if we imported a module.
  50. bool saw_import;
  51. // If not NULL, name of import package being processed.
  52. String *imported_package;
  53. // Build interface methods while handling a class. This is only
  54. // non-NULL when we are handling methods.
  55. String *interfaces;
  56. // The class node while handling a class. This is only non-NULL
  57. // when we are handling methods.
  58. Node *class_node;
  59. // The class name while handling a class. This is only non-NULL
  60. // when we are handling methods. This is the name of the class as
  61. // SWIG sees it.
  62. String *class_name;
  63. // The receiver name while handling a class. This is only non-NULL
  64. // when we are handling methods. This is the name of the class
  65. // as run through goCPointerType.
  66. String *class_receiver;
  67. // A hash table of method names that we have seen when processing a
  68. // class. This lets us detect base class methods that we don't want
  69. // to use.
  70. Hash *class_methods;
  71. // True when we are generating the wrapper functions for a variable.
  72. bool making_variable_wrappers;
  73. // True when working with a static member function.
  74. bool is_static_member_function;
  75. // A hash table of types that we have seen but which may not have
  76. // been defined. The index is a SwigType.
  77. Hash *undefined_types;
  78. // A hash table of classes which were defined. The index is a Go
  79. // type name.
  80. Hash *defined_types;
  81. public:
  82. GO():package(NULL),
  83. gccgo_flag(false),
  84. gccgo_46_flag(GCCGO_46_DEFAULT),
  85. go_prefix(NULL),
  86. soname(NULL),
  87. long_type_size(32),
  88. f_c_begin(NULL),
  89. f_go_begin(NULL),
  90. f_gc_begin(NULL),
  91. f_c_runtime(NULL),
  92. f_c_header(NULL),
  93. f_c_wrappers(NULL),
  94. f_c_init(NULL),
  95. f_c_directors(NULL),
  96. f_c_directors_h(NULL),
  97. f_go_runtime(NULL),
  98. f_go_header(NULL),
  99. f_go_wrappers(NULL),
  100. f_gc_runtime(NULL),
  101. f_gc_header(NULL),
  102. f_gc_wrappers(NULL),
  103. saw_import(false),
  104. imported_package(NULL),
  105. interfaces(NULL),
  106. class_node(NULL),
  107. class_name(NULL),
  108. class_receiver(NULL),
  109. class_methods(NULL),
  110. making_variable_wrappers(false),
  111. is_static_member_function(false),
  112. undefined_types(NULL),
  113. defined_types(NULL) {
  114. director_multiple_inheritance = 1;
  115. director_language = 1;
  116. director_prot_ctor_code = NewString("_swig_gopanic(\"accessing abstract class or protected constructor\");");
  117. }
  118. private:
  119. /* ------------------------------------------------------------
  120. * main()
  121. * ------------------------------------------------------------ */
  122. virtual void main(int argc, char *argv[]) {
  123. SWIG_library_directory("go");
  124. // Process command line options.
  125. for (int i = 1; i < argc; i++) {
  126. if (argv[i]) {
  127. if (strcmp(argv[i], "-package") == 0) {
  128. if (argv[i + 1]) {
  129. package = NewString(argv[i + 1]);
  130. Swig_mark_arg(i);
  131. Swig_mark_arg(i + 1);
  132. i++;
  133. } else {
  134. Swig_arg_error();
  135. }
  136. } else if (strcmp(argv[i], "-gccgo") == 0) {
  137. Swig_mark_arg(i);
  138. gccgo_flag = true;
  139. } else if (strcmp(argv[i], "-gccgo-46") == 0) {
  140. Swig_mark_arg(i);
  141. gccgo_46_flag = true;
  142. } else if (strcmp(argv[i], "-no-gccgo-46") == 0) {
  143. Swig_mark_arg(i);
  144. gccgo_46_flag = false;
  145. } else if (strcmp(argv[i], "-go-prefix") == 0) {
  146. if (argv[i + 1]) {
  147. go_prefix = NewString(argv[i + 1]);
  148. Swig_mark_arg(i);
  149. Swig_mark_arg(i + 1);
  150. i++;
  151. } else {
  152. Swig_arg_error();
  153. }
  154. } else if (strcmp(argv[i], "-soname") == 0) {
  155. if (argv[i + 1]) {
  156. soname = NewString(argv[i + 1]);
  157. Swig_mark_arg(i);
  158. Swig_mark_arg(i + 1);
  159. i++;
  160. } else {
  161. Swig_arg_error();
  162. }
  163. } else if (strcmp(argv[i], "-longsize") == 0) {
  164. if (argv[i + 1]) {
  165. long_type_size = atoi(argv[i + 1]);
  166. if (long_type_size != 32 && long_type_size != 64) {
  167. Printf(stderr, "-longsize not 32 or 64\n");
  168. Swig_arg_error();
  169. }
  170. Swig_mark_arg(i);
  171. Swig_mark_arg(i + 1);
  172. ++i;
  173. } else {
  174. Swig_arg_error();
  175. }
  176. } else if (strcmp(argv[i], "-help") == 0) {
  177. Printf(stdout, "%s\n", usage);
  178. }
  179. }
  180. }
  181. if (gccgo_flag && !go_prefix) {
  182. go_prefix = NewString("go");
  183. }
  184. // Add preprocessor symbol to parser.
  185. Preprocessor_define("SWIGGO 1", 0);
  186. if (gccgo_flag) {
  187. Preprocessor_define("SWIGGO_GCCGO 1", 0);
  188. }
  189. if (long_type_size == 32) {
  190. Preprocessor_define("SWIGGO_LONG_TYPE_SIZE 32", 0);
  191. } else {
  192. Preprocessor_define("SWIGGO_LONG_TYPE_SIZE 64", 0);
  193. }
  194. // Add typemap definitions.
  195. SWIG_typemap_lang("go");
  196. SWIG_config_file("go.swg");
  197. allow_overloading();
  198. }
  199. /* ---------------------------------------------------------------------
  200. * top()
  201. *
  202. * For 6g/8g, we are going to create the following files:
  203. *
  204. * 1) A .c or .cxx file compiled with gcc. This file will contain
  205. * function wrappers. Each wrapper will take a pointer to a
  206. * struct holding the arguments, unpack them, and call the real
  207. * function.
  208. *
  209. * 2) A .go file which defines the Go form of all types, and which
  210. * defines Go function wrappers. Each wrapper will call the C
  211. * function wrapper in the second file.
  212. *
  213. * 3) A .c file compiled with 6c/8c. This file will define
  214. * Go-callable C function wrappers. Each wrapper will use
  215. * cgocall to call the function wrappers in the first file.
  216. *
  217. * When generating code for gccgo, we don't need the third file, and
  218. * the function wrappers in the first file have a different form.
  219. *
  220. * --------------------------------------------------------------------- */
  221. virtual int top(Node *n) {
  222. Node *optionsnode = Getattr(Getattr(n, "module"), "options");
  223. if (optionsnode) {
  224. if (Getattr(optionsnode, "directors")) {
  225. allow_directors();
  226. }
  227. if (Getattr(optionsnode, "dirprot")) {
  228. allow_dirprot();
  229. }
  230. allow_allprotected(GetFlag(optionsnode, "allprotected"));
  231. }
  232. String *module = Getattr(n, "name");
  233. if (!package) {
  234. package = Copy(module);
  235. }
  236. if (!soname) {
  237. soname = Copy(package);
  238. Append(soname, ".so");
  239. }
  240. // Get filenames.
  241. String *c_filename = Getattr(n, "outfile");
  242. String *c_filename_h = Getattr(n, "outfile_h");
  243. String *go_filename = NewString("");
  244. Printf(go_filename, "%s%s.go", SWIG_output_directory(), module);
  245. String *gc_filename = NULL;
  246. if (!gccgo_flag) {
  247. gc_filename = NewString("");
  248. Printf(gc_filename, "%s%s_gc.c", SWIG_output_directory(), module);
  249. }
  250. // Open files.
  251. f_c_begin = NewFile(c_filename, "w", SWIG_output_files());
  252. if (!f_c_begin) {
  253. FileErrorDisplay(c_filename);
  254. SWIG_exit(EXIT_FAILURE);
  255. }
  256. if (directorsEnabled()) {
  257. if (!c_filename_h) {
  258. Printf(stderr, "Unable to determine outfile_h\n");
  259. SWIG_exit(EXIT_FAILURE);
  260. }
  261. f_c_directors_h = NewFile(c_filename_h, "w", SWIG_output_files());
  262. if (!f_c_directors_h) {
  263. FileErrorDisplay(c_filename_h);
  264. SWIG_exit(EXIT_FAILURE);
  265. }
  266. }
  267. f_go_begin = NewFile(go_filename, "w", SWIG_output_files());
  268. if (!f_go_begin) {
  269. FileErrorDisplay(go_filename);
  270. SWIG_exit(EXIT_FAILURE);
  271. }
  272. if (!gccgo_flag) {
  273. f_gc_begin = NewFile(gc_filename, "w", SWIG_output_files());
  274. if (!f_gc_begin) {
  275. FileErrorDisplay(gc_filename);
  276. SWIG_exit(EXIT_FAILURE);
  277. }
  278. }
  279. f_c_runtime = NewString("");
  280. f_c_header = NewString("");
  281. f_c_wrappers = NewString("");
  282. f_c_init = NewString("");
  283. f_c_directors = NewString("");
  284. f_go_runtime = NewString("");
  285. f_go_header = NewString("");
  286. f_go_wrappers = NewString("");
  287. if (!gccgo_flag) {
  288. f_gc_runtime = NewString("");
  289. f_gc_header = NewString("");
  290. f_gc_wrappers = NewString("");
  291. }
  292. Swig_register_filebyname("begin", f_c_begin);
  293. Swig_register_filebyname("runtime", f_c_runtime);
  294. Swig_register_filebyname("header", f_c_header);
  295. Swig_register_filebyname("wrapper", f_c_wrappers);
  296. Swig_register_filebyname("init", f_c_init);
  297. Swig_register_filebyname("director", f_c_directors);
  298. Swig_register_filebyname("director_h", f_c_directors_h);
  299. Swig_register_filebyname("go_begin", f_go_begin);
  300. Swig_register_filebyname("go_runtime", f_go_runtime);
  301. Swig_register_filebyname("go_header", f_go_header);
  302. Swig_register_filebyname("go_wrapper", f_go_wrappers);
  303. if (!gccgo_flag) {
  304. Swig_register_filebyname("gc_begin", f_gc_begin);
  305. Swig_register_filebyname("gc_runtime", f_gc_runtime);
  306. Swig_register_filebyname("gc_header", f_gc_header);
  307. Swig_register_filebyname("gc_wrapper", f_gc_wrappers);
  308. }
  309. Swig_banner(f_c_begin);
  310. if (directorsEnabled()) {
  311. Printf(f_c_runtime, "#define SWIG_DIRECTORS\n");
  312. Swig_banner(f_c_directors_h);
  313. Printf(f_c_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module);
  314. Printf(f_c_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module);
  315. Printf(f_c_directors, "\n// C++ director class methods.\n");
  316. Printf(f_c_directors, "#include \"%s\"\n\n", Swig_file_filename(c_filename_h));
  317. }
  318. Swig_banner(f_go_begin);
  319. if (!gccgo_flag) {
  320. Swig_banner(f_gc_begin);
  321. Printf(f_gc_begin, "\n/* This file should be compiled with 6c/8c. */\n");
  322. Printf(f_gc_begin, "#pragma dynimport _ _ \"%s\"\n", soname);
  323. }
  324. // Output module initialization code.
  325. Printf(f_go_begin, "\npackage %s\n\n", package);
  326. // All the C++ wrappers should be extern "C".
  327. Printv(f_c_wrappers, "#ifdef __cplusplus\n", "extern \"C\" {\n", "#endif\n\n", NULL);
  328. // Set up the hash table for types not defined by SWIG.
  329. undefined_types = NewHash();
  330. defined_types = NewHash();
  331. // Emit code.
  332. Language::top(n);
  333. // Write out definitions for the types not defined by SWIG.
  334. Printv(f_go_wrappers, "\n", NULL);
  335. for (Iterator p = First(undefined_types); p.key; p = Next(p)) {
  336. String *ty = goType(NULL, p.key);
  337. if (!Getattr(defined_types, ty)) {
  338. String *cp = goCPointerType(p.key, false);
  339. if (!Getattr(defined_types, cp)) {
  340. Printv(f_go_wrappers, "type ", cp, " uintptr\n", NULL);
  341. Printv(f_go_wrappers, "type ", ty, " interface {\n", NULL);
  342. Printv(f_go_wrappers, "\tSwigcptr() uintptr;\n", NULL);
  343. Printv(f_go_wrappers, "}\n", NULL);
  344. Printv(f_go_wrappers, "func (p ", cp, ") Swigcptr() uintptr {\n", NULL);
  345. Printv(f_go_wrappers, "\treturn uintptr(p)\n", NULL);
  346. Printv(f_go_wrappers, "}\n\n", NULL);
  347. }
  348. Delete(cp);
  349. }
  350. Delete(ty);
  351. }
  352. Delete(undefined_types);
  353. Delete(defined_types);
  354. /* Write and cleanup */
  355. Dump(f_c_header, f_c_runtime);
  356. if (directorsEnabled()) {
  357. Printf(f_c_directors_h, "#endif\n");
  358. Close(f_c_directors_h);
  359. Delete(f_c_directors_h);
  360. f_c_directors_h = NULL;
  361. Dump(f_c_directors, f_c_runtime);
  362. Close(f_c_directors);
  363. Delete(f_c_directors);
  364. f_c_directors = NULL;
  365. }
  366. // End the extern "C".
  367. Printv(f_c_wrappers, "#ifdef __cplusplus\n", "}\n", "#endif\n\n", NULL);
  368. Dump(f_c_runtime, f_c_begin);
  369. Dump(f_c_wrappers, f_c_begin);
  370. Dump(f_c_init, f_c_begin);
  371. Dump(f_go_header, f_go_begin);
  372. Dump(f_go_runtime, f_go_begin);
  373. Dump(f_go_wrappers, f_go_begin);
  374. if (!gccgo_flag) {
  375. Dump(f_gc_header, f_gc_begin);
  376. Dump(f_gc_runtime, f_gc_begin);
  377. Dump(f_gc_wrappers, f_gc_begin);
  378. }
  379. Delete(f_c_runtime);
  380. Delete(f_c_header);
  381. Delete(f_c_wrappers);
  382. Delete(f_c_init);
  383. Delete(f_go_runtime);
  384. Delete(f_go_header);
  385. Delete(f_go_wrappers);
  386. if (!gccgo_flag) {
  387. Delete(f_gc_runtime);
  388. Delete(f_gc_header);
  389. Delete(f_gc_wrappers);
  390. }
  391. Close(f_c_begin);
  392. Delete(f_c_begin);
  393. Close(f_go_begin);
  394. Delete(f_go_begin);
  395. if (!gccgo_flag) {
  396. Close(f_gc_begin);
  397. Delete(f_gc_begin);
  398. }
  399. return SWIG_OK;
  400. }
  401. /* ------------------------------------------------------------
  402. * importDirective()
  403. *
  404. * Handle a SWIG import statement by generating a Go import
  405. * statement.
  406. * ------------------------------------------------------------ */
  407. virtual int importDirective(Node *n) {
  408. String *hold_import = imported_package;
  409. String *modname = Getattr(n, "module");
  410. if (modname) {
  411. Printv(f_go_begin, "import \"", modname, "\"\n", NULL);
  412. imported_package = modname;
  413. saw_import = true;
  414. }
  415. int r = Language::importDirective(n);
  416. imported_package = hold_import;
  417. return r;
  418. }
  419. /* ----------------------------------------------------------------------
  420. * functionWrapper()
  421. *
  422. * Implement a function.
  423. * ---------------------------------------------------------------------- */
  424. virtual int functionWrapper(Node *n) {
  425. if (GetFlag(n, "feature:ignore")) {
  426. return SWIG_OK;
  427. }
  428. // We don't need explicit calls.
  429. if (GetFlag(n, "explicitcall")) {
  430. return SWIG_OK;
  431. }
  432. String *name = Getattr(n, "sym:name");
  433. String *nodetype = Getattr(n, "nodeType");
  434. bool is_static = is_static_member_function || isStatic(n);
  435. bool is_friend = isFriend(n);
  436. bool is_ctor_dtor = false;
  437. SwigType *result = Getattr(n, "type");
  438. // For some reason SWIG changs the "type" value during the call to
  439. // functionWrapper. We need to remember the type for possible
  440. // overload processing.
  441. Setattr(n, "go:type", Copy(result));
  442. String *go_name;
  443. String *r1 = NULL;
  444. if (making_variable_wrappers) {
  445. // Change the name of the variable setter and getter functions
  446. // to be more Go like.
  447. bool is_set = Strcmp(Char(name) + Len(name) - 4, "_set") == 0;
  448. assert(is_set || Strcmp(Char(name) + Len(name) - 4, "_get") == 0);
  449. // Start with Set or Get.
  450. go_name = NewString(is_set ? "Set" : "Get");
  451. // If this is a static variable, put in the class name,
  452. // capitalized.
  453. if (is_static && class_name) {
  454. String *ccn = exportedName(class_name);
  455. Append(go_name, ccn);
  456. Delete(ccn);
  457. }
  458. // Add the rest of the name, capitalized, dropping the _set or
  459. // _get.
  460. String *c1 = removeClassname(name);
  461. String *c2 = exportedName(c1);
  462. char *p = Char(c2);
  463. int len = Len(p);
  464. for (int i = 0; i < len - 4; ++i) {
  465. Putc(p[i], go_name);
  466. }
  467. Delete(c2);
  468. Delete(c1);
  469. if (!checkIgnoredParameters(n, go_name)) {
  470. Delete(go_name);
  471. return SWIG_NOWRAP;
  472. }
  473. } else if (Cmp(nodetype, "constructor") == 0) {
  474. is_ctor_dtor = true;
  475. // Change the name of a constructor to be more Go like. Change
  476. // new_ to New, and capitalize the class name.
  477. assert(Strncmp(name, "new_", 4) == 0);
  478. String *c1 = NewString(Char(name) + 4);
  479. String *c2 = exportedName(c1);
  480. go_name = NewString("New");
  481. Append(go_name, c2);
  482. Delete(c2);
  483. Delete(c1);
  484. if (Swig_methodclass(n) && Swig_directorclass(n)
  485. && Strcmp(Char(Getattr(n, "wrap:action")), director_prot_ctor_code) != 0) {
  486. // The core SWIG code skips the first parameter when
  487. // generating the $nondirector_new string. Recreate the
  488. // action in this case. But don't it if we are using the
  489. // special code for an abstract class.
  490. String *call = Swig_cppconstructor_call(getClassType(),
  491. Getattr(n, "parms"));
  492. SwigType *type = Copy(getClassType());
  493. SwigType_add_pointer(type);
  494. String *cres = Swig_cresult(type, Swig_cresult_name(), call);
  495. Setattr(n, "wrap:action", cres);
  496. }
  497. } else if (Cmp(nodetype, "destructor") == 0) {
  498. // No need to emit protected destructors.
  499. if (!is_public(n)) {
  500. return SWIG_OK;
  501. }
  502. is_ctor_dtor = true;
  503. // Change the name of a destructor to be more Go like. Change
  504. // delete_ to Delete and capitalize the class name.
  505. assert(Strncmp(name, "delete_", 7) == 0);
  506. String *c1 = NewString(Char(name) + 7);
  507. String *c2 = exportedName(c1);
  508. go_name = NewString("Delete");
  509. Append(go_name, c2);
  510. Delete(c2);
  511. Delete(c1);
  512. result = NewString("void");
  513. r1 = result;
  514. } else {
  515. if (!checkFunctionVisibility(n, NULL)) {
  516. return SWIG_OK;
  517. }
  518. go_name = buildGoName(name, is_static, is_friend);
  519. if (!checkIgnoredParameters(n, go_name)) {
  520. Delete(go_name);
  521. return SWIG_NOWRAP;
  522. }
  523. }
  524. String *overname = NULL;
  525. if (Getattr(n, "sym:overloaded")) {
  526. overname = Getattr(n, "sym:overname");
  527. } else {
  528. String *scope;
  529. if (!class_name || is_static || is_ctor_dtor) {
  530. scope = NULL;
  531. } else {
  532. scope = NewString("swiggoscope.");
  533. Append(scope, class_name);
  534. }
  535. if (!checkNameConflict(go_name, n, scope)) {
  536. Delete(go_name);
  537. return SWIG_NOWRAP;
  538. }
  539. }
  540. String *wname = Swig_name_wrapper(name);
  541. if (overname) {
  542. Append(wname, overname);
  543. }
  544. Setattr(n, "wrap:name", wname);
  545. ParmList *parms = Getattr(n, "parms");
  546. Setattr(n, "wrap:parms", parms);
  547. int r = makeWrappers(n, name, go_name, overname, wname, NULL, parms, result, is_static);
  548. if (r != SWIG_OK) {
  549. return r;
  550. }
  551. if (Getattr(n, "sym:overloaded") && !Getattr(n, "sym:nextSibling")) {
  552. String *scope ;
  553. if (!class_name || is_static || is_ctor_dtor) {
  554. scope = NULL;
  555. } else {
  556. scope = NewString("swiggoscope.");
  557. Append(scope, class_name);
  558. }
  559. if (!checkNameConflict(go_name, n, scope)) {
  560. Delete(go_name);
  561. return SWIG_NOWRAP;
  562. }
  563. String *receiver = class_receiver;
  564. if (is_static || is_ctor_dtor) {
  565. receiver = NULL;
  566. }
  567. r = makeDispatchFunction(n, go_name, receiver, is_static, NULL, false);
  568. if (r != SWIG_OK) {
  569. return r;
  570. }
  571. }
  572. Delete(wname);
  573. Delete(go_name);
  574. Delete(r1);
  575. return SWIG_OK;
  576. }
  577. /* ----------------------------------------------------------------------
  578. * staticmemberfunctionHandler()
  579. *
  580. * For some reason the language code removes the "storage" attribute
  581. * for a static function before calling functionWrapper, which means
  582. * that we have no way of knowing whether a function is static or
  583. * not. That makes no sense in the Go context. Here we note that a
  584. * function is static.
  585. * ---------------------------------------------------------------------- */
  586. int staticmemberfunctionHandler(Node *n) {
  587. assert(!is_static_member_function);
  588. is_static_member_function = true;
  589. int r = Language::staticmemberfunctionHandler(n);
  590. is_static_member_function = false;
  591. return r;
  592. }
  593. /* ----------------------------------------------------------------------
  594. * makeWrappers()
  595. *
  596. * Write out the various function wrappers.
  597. * n: The function we are emitting.
  598. * name: The function name.
  599. * go_name: The name of the function in Go.
  600. * overname: The overload string for overloaded function.
  601. * wname: The SWIG wrapped name--the name of the C function.
  602. * base: A list of the names of base classes, in the case where this
  603. * is is a vritual method not defined in the current class.
  604. * parms: The parameters.
  605. * result: The result type.
  606. * is_static: Whether this is a static method or member.
  607. * ---------------------------------------------------------------------- */
  608. int makeWrappers(Node *n, String *name, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static) {
  609. assert(result);
  610. bool needs_wrapper;
  611. int r = goFunctionWrapper(n, name, go_name, overname, wname, base, parms, result, is_static, &needs_wrapper);
  612. if (r != SWIG_OK) {
  613. return r;
  614. }
  615. if (!gccgo_flag) {
  616. r = gcFunctionWrapper(n, name, go_name, overname, wname, parms, result, is_static, needs_wrapper);
  617. if (r != SWIG_OK) {
  618. return r;
  619. }
  620. r = gccFunctionWrapper(n, base, wname, parms, result);
  621. if (r != SWIG_OK) {
  622. return r;
  623. }
  624. } else {
  625. r = gccgoFunctionWrapper(n, base, wname, parms, result);
  626. if (r != SWIG_OK) {
  627. return r;
  628. }
  629. }
  630. if (class_methods) {
  631. Setattr(class_methods, Getattr(n, "name"), NewString(""));
  632. }
  633. return SWIG_OK;
  634. }
  635. /* ----------------------------------------------------------------------
  636. * goFunctionWrapper()
  637. *
  638. * Write out a function wrapper in Go. When not implementing a
  639. * method, the actual code is all in C; here we just declare the C
  640. * function. When implementing a method, we have to call the C
  641. * function, because it will have a different name. If base is not
  642. * NULL, then we are being called to forward a virtual method to a
  643. * base class.
  644. * ---------------------------------------------------------------------- */
  645. int goFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, List *base, ParmList *parms, SwigType *result, bool is_static, bool *p_needs_wrapper) {
  646. Wrapper *dummy = NewWrapper();
  647. emit_attach_parmmaps(parms, dummy);
  648. Swig_typemap_attach_parms("default", parms, dummy);
  649. Swig_typemap_attach_parms("gotype", parms, dummy);
  650. int parm_count = emit_num_arguments(parms);
  651. int required_count = emit_num_required(parms);
  652. String *receiver = class_receiver;
  653. if (receiver && is_static) {
  654. receiver = NULL;
  655. }
  656. String *nodetype = Getattr(n, "nodeType");
  657. bool is_constructor = Cmp(nodetype, "constructor") == 0;
  658. bool is_destructor = Cmp(nodetype, "destructor") == 0;
  659. if (is_constructor || is_destructor) {
  660. assert(class_receiver);
  661. assert(!base);
  662. receiver = NULL;
  663. }
  664. bool add_to_interface = (interfaces && !is_constructor && !is_destructor && !is_static && !overname && checkFunctionVisibility(n, NULL));
  665. bool needs_wrapper = (gccgo_flag || receiver || is_constructor || is_destructor || parm_count > required_count);
  666. // See whether any of the function parameters are represented by
  667. // interface values When calling the C++ code, we need to convert
  668. // back to a uintptr.
  669. if (!needs_wrapper) {
  670. Parm *p = parms;
  671. for (int i = 0; i < parm_count; ++i) {
  672. p = getParm(p);
  673. String *ty = Getattr(p, "type");
  674. if (goTypeIsInterface(p, ty)) {
  675. needs_wrapper = true;
  676. break;
  677. }
  678. p = nextParm(p);
  679. }
  680. }
  681. if (goTypeIsInterface(n, result)) {
  682. needs_wrapper = true;
  683. }
  684. *p_needs_wrapper = needs_wrapper;
  685. // If this is a method, first declare the C function we will call.
  686. // If we do not need a wrapper, then we will only be writing a
  687. // declaration.
  688. String *wrapper_name = NULL;
  689. if (needs_wrapper) {
  690. wrapper_name = buildGoWrapperName(name, overname);
  691. if (gccgo_flag && !gccgo_46_flag) {
  692. Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
  693. }
  694. Printv(f_go_wrappers, "func ", wrapper_name, "(", NULL);
  695. if (parm_count > required_count) {
  696. Printv(f_go_wrappers, "int", NULL);
  697. }
  698. Parm *p = getParm(parms);
  699. Swig_cparm_name(p, 0);
  700. int i = 0;
  701. if (is_destructor) {
  702. if (parm_count > required_count) {
  703. Printv(f_go_wrappers, ", ", NULL);
  704. }
  705. Printv(f_go_wrappers, "uintptr", NULL);
  706. ++i;
  707. p = nextParm(p);
  708. } else if (receiver && (base || !is_constructor)) {
  709. if (parm_count > required_count) {
  710. Printv(f_go_wrappers, ", ", NULL);
  711. }
  712. Printv(f_go_wrappers, receiver, NULL);
  713. if (!base) {
  714. ++i;
  715. p = nextParm(p);
  716. }
  717. }
  718. for (; i < parm_count; ++i) {
  719. p = getParm(p);
  720. // Give the parameter a name we will use below.
  721. Swig_cparm_name(p, i);
  722. if (i > 0 || (base && receiver) || parm_count > required_count) {
  723. Printv(f_go_wrappers, ", ", NULL);
  724. }
  725. String *tm = goWrapperType(p, Getattr(p, "type"), false);
  726. Printv(f_go_wrappers, tm, NULL);
  727. Delete(tm);
  728. p = nextParm(p);
  729. }
  730. Printv(f_go_wrappers, ")", NULL);
  731. if (is_constructor) {
  732. Printv(f_go_wrappers, " ", class_receiver, NULL);
  733. } else {
  734. if (SwigType_type(result) != T_VOID) {
  735. String *tm = goWrapperType(n, result, true);
  736. Printv(f_go_wrappers, " ", tm, NULL);
  737. Delete(tm);
  738. }
  739. }
  740. if (gccgo_flag && gccgo_46_flag) {
  741. Printv(f_go_wrappers, " __asm__ (\"", go_prefix, "_", wname, "\")", NULL);
  742. }
  743. Printv(f_go_wrappers, "\n\n", NULL);
  744. }
  745. // Start defining the Go function.
  746. if (!needs_wrapper && gccgo_flag && !gccgo_46_flag) {
  747. Printv(f_go_wrappers, "//extern ", go_prefix, "_", wname, "\n", NULL);
  748. }
  749. Printv(f_go_wrappers, "func ", NULL);
  750. Parm *p = parms;
  751. int pi = 0;
  752. // Add the receiver if this is a method.
  753. if (receiver) {
  754. Printv(f_go_wrappers, "(", NULL);
  755. if (base && receiver) {
  756. Printv(f_go_wrappers, "_swig_base", NULL);
  757. } else {
  758. Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
  759. p = nextParm(p);
  760. ++pi;
  761. }
  762. Printv(f_go_wrappers, " ", receiver, ") ", NULL);
  763. }
  764. Printv(f_go_wrappers, go_name, NULL);
  765. if (overname) {
  766. Printv(f_go_wrappers, overname, NULL);
  767. }
  768. Printv(f_go_wrappers, "(", NULL);
  769. // If we are doing methods, add this function to the interface.
  770. if (add_to_interface) {
  771. Printv(interfaces, "\t", go_name, "(", NULL);
  772. }
  773. // Write out the parameters to both the function definition and
  774. // the interface.
  775. String *parm_print = NewString("");
  776. for (; pi < parm_count; ++pi) {
  777. p = getParm(p);
  778. if (pi == 0 && is_destructor) {
  779. String *cl = exportedName(class_name);
  780. Printv(parm_print, Getattr(p, "lname"), " ", cl, NULL);
  781. Delete(cl);
  782. } else {
  783. if (pi > (receiver && !base ? 1 : 0)) {
  784. Printv(parm_print, ", ", NULL);
  785. }
  786. if (pi >= required_count) {
  787. Printv(parm_print, "_swig_args ...interface{}", NULL);
  788. break;
  789. }
  790. if (needs_wrapper) {
  791. Printv(parm_print, Getattr(p, "lname"), " ", NULL);
  792. }
  793. String *tm = goType(p, Getattr(p, "type"));
  794. Printv(parm_print, tm, NULL);
  795. Delete(tm);
  796. }
  797. p = nextParm(p);
  798. }
  799. Printv(parm_print, ")", NULL);
  800. // Write out the result type.
  801. if (is_constructor) {
  802. String *cl = exportedName(class_name);
  803. Printv(parm_print, " ", cl, NULL);
  804. Delete(cl);
  805. } else {
  806. if (SwigType_type(result) != T_VOID) {
  807. String *tm = goType(n, result);
  808. Printv(parm_print, " ", tm, NULL);
  809. Delete(tm);
  810. }
  811. }
  812. Printv(f_go_wrappers, parm_print, NULL);
  813. if (add_to_interface) {
  814. Printv(interfaces, parm_print, "\n", NULL);
  815. }
  816. // If this is a wrapper, we need to actually call the C function.
  817. if (needs_wrapper) {
  818. Printv(f_go_wrappers, " {\n", NULL);
  819. if (parm_count > required_count) {
  820. Parm *p = parms;
  821. int i;
  822. for (i = 0; i < required_count; ++i) {
  823. p = getParm(p);
  824. p = nextParm(p);
  825. }
  826. for (; i < parm_count; ++i) {
  827. p = getParm(p);
  828. String *tm = goType(p, Getattr(p, "type"));
  829. Printv(f_go_wrappers, "\tvar ", Getattr(p, "lname"), " ", tm, "\n", NULL);
  830. Printf(f_go_wrappers, "\tif len(_swig_args) > %d {\n", i - required_count);
  831. Printf(f_go_wrappers, "\t\t%s = _swig_args[%d].(%s)\n", Getattr(p, "lname"), i - required_count, tm);
  832. Printv(f_go_wrappers, "\t}\n", NULL);
  833. Delete(tm);
  834. p = nextParm(p);
  835. }
  836. }
  837. if (gccgo_flag && !gccgo_46_flag) {
  838. Printv(f_go_wrappers, "\tsyscall.Entersyscall()\n", NULL);
  839. Printv(f_go_wrappers, "\tdefer syscall.Exitsyscall()\n", NULL);
  840. }
  841. Printv(f_go_wrappers, "\t", NULL);
  842. if (SwigType_type(result) != T_VOID) {
  843. Printv(f_go_wrappers, "return ", NULL);
  844. }
  845. Printv(f_go_wrappers, wrapper_name, "(", NULL);
  846. if (parm_count > required_count) {
  847. Printv(f_go_wrappers, "len(_swig_args)", NULL);
  848. }
  849. if (base && receiver) {
  850. if (parm_count > required_count) {
  851. Printv(f_go_wrappers, ", ", NULL);
  852. }
  853. Printv(f_go_wrappers, "_swig_base", NULL);
  854. }
  855. Parm *p = parms;
  856. for (int i = 0; i < parm_count; ++i) {
  857. p = getParm(p);
  858. if (i > 0 || (base && receiver)
  859. || parm_count > required_count) {
  860. Printv(f_go_wrappers, ", ", NULL);
  861. }
  862. Printv(f_go_wrappers, Getattr(p, "lname"), NULL);
  863. // If this is a destructor, then the C function expects the
  864. // C++ value, and we have the interface. We need to get the
  865. // C++ value. The same is true for a type represented as an
  866. // interface.
  867. if ((i == 0 && is_destructor) || ((i > 0 || !receiver || base || is_constructor) && goTypeIsInterface(p, Getattr(p, "type")))) {
  868. Printv(f_go_wrappers, ".Swigcptr()", NULL);
  869. }
  870. p = nextParm(p);
  871. }
  872. Printv(f_go_wrappers, ")\n", NULL);
  873. Printv(f_go_wrappers, "}\n", NULL);
  874. } else {
  875. if (gccgo_flag && gccgo_46_flag) {
  876. Printv(f_go_wrappers, " __asm__ (\"", go_prefix, "_", wname, "\")\n", NULL);
  877. }
  878. }
  879. Printv(f_go_wrappers, "\n", NULL);
  880. Delete(wrapper_name);
  881. DelWrapper(dummy);
  882. return SWIG_OK;
  883. }
  884. /* ----------------------------------------------------------------------
  885. * gcFunctionWrapper()
  886. *
  887. * This is used for 6g/8g, not for gccgo. Write out the function
  888. * wrapper which will be compiled with 6c/8c.
  889. * ---------------------------------------------------------------------- */
  890. int gcFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, ParmList *parms, SwigType *result, bool is_static, bool needs_wrapper) {
  891. Wrapper *f = NewWrapper();
  892. Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"\"\n", NULL);
  893. Printv(f->def, "extern void (*", wname, ")(void*);\n", NULL);
  894. Printv(f->def, "static void (*x", wname, ")(void*) = ", wname, ";\n", NULL);
  895. Printv(f->def, "\n", NULL);
  896. Printv(f->def, "void\n", NULL);
  897. Wrapper *dummy = NewWrapper();
  898. emit_attach_parmmaps(parms, dummy);
  899. Swig_typemap_attach_parms("default", parms, dummy);
  900. Swig_typemap_attach_parms("gosize", parms, dummy);
  901. int parm_count = emit_num_arguments(parms);
  902. int required_count = emit_num_required(parms);
  903. String *parm_size = NewString("");
  904. if (parm_count > required_count) {
  905. Append(parm_size, "SWIG_PARM_SIZE");
  906. }
  907. if (class_receiver && !is_static) {
  908. if (Len(parm_size) > 0) {
  909. Append(parm_size, " + ");
  910. }
  911. Append(parm_size, "SWIG_PARM_SIZE");
  912. }
  913. Parm *p = parms;
  914. for (int i = 0; i < parm_count; ++i) {
  915. p = getParm(p);
  916. addGcTypeSize(p, Getattr(p, "type"), parm_size);
  917. p = nextParm(p);
  918. }
  919. if (SwigType_type(result) != T_VOID) {
  920. addGcTypeSize(n, result, parm_size);
  921. }
  922. if (Len(parm_size) == 0) {
  923. Append(parm_size, "1");
  924. }
  925. String *fn_name;
  926. if (!needs_wrapper) {
  927. fn_name = Copy(go_name);
  928. if (overname) {
  929. Append(fn_name, overname);
  930. }
  931. } else {
  932. fn_name = buildGoWrapperName(name, overname);
  933. }
  934. // \xc2\xb7 is UTF-8 for U+00B7 which is Unicode 'Middle Dot'
  935. Printv(f->def, "\xc2\xb7", fn_name, "(struct { uint8 x[", parm_size, "];} p)", NULL);
  936. Delete(fn_name);
  937. Delete(parm_size);
  938. Printv(f->code, "{\n", NULL);
  939. Printv(f->code, "\truntime\xc2\xb7" "cgocall(x", wname, ", &p);\n", NULL);
  940. Printv(f->code, "}\n", NULL);
  941. Printv(f->code, "\n", NULL);
  942. Wrapper_print(f, f_gc_wrappers);
  943. DelWrapper(f);
  944. DelWrapper(dummy);
  945. return SWIG_OK;
  946. }
  947. /* ----------------------------------------------------------------------
  948. * getGcTypeSize()
  949. *
  950. * Return the size to use when passing a type from 6g/8g to 6c/8c.
  951. * ---------------------------------------------------------------------- */
  952. String *addGcTypeSize(Node *n, SwigType *type, String *orig) {
  953. if (Len(orig) > 0) {
  954. Append(orig, " + ");
  955. }
  956. String *go = goType(n, type);
  957. if (Cmp(go, "string") == 0) {
  958. // A string has a pointer and a length.
  959. Append(orig, "(2 * SWIG_PARM_SIZE)");
  960. } else if (Strncmp(go, "[]", 2) == 0) {
  961. // A slice has a pointer, a length, and a capacity. The
  962. // length and capacity are always 4 bytes.
  963. Append(orig, "(SWIG_PARM_SIZE + 8)");
  964. } else if (Strcmp(go, "float64") == 0) {
  965. Append(orig, "8");
  966. } else if (Strcmp(go, "complex64") == 0) {
  967. Append(orig, "8");
  968. } else if (Strcmp(go, "complex128") == 0) {
  969. Append(orig, "16");
  970. } else {
  971. Append(orig, "SWIG_PARM_SIZE");
  972. }
  973. return orig;
  974. }
  975. /* ----------------------------------------------------------------------
  976. * gccFunctionWrapper()
  977. *
  978. * This is used for 6g/8g, not for gccgo. Write out the function
  979. * wrapper which will be compiled with gcc. If the base parameter
  980. * is not NULL, this is calls the base class method rather than
  981. * executing the SWIG wrapper code.
  982. * ---------------------------------------------------------------------- */
  983. int gccFunctionWrapper(Node *n, List *base, String *wname, ParmList *parms, SwigType *result) {
  984. Wrapper *f = NewWrapper();
  985. Swig_save("gccFunctionWrapper", n, "parms", NULL);
  986. Parm *base_parm = NULL;
  987. if (base && !isStatic(n)) {
  988. SwigType *base_type = Copy(getClassType());
  989. SwigType_add_pointer(base_type);
  990. base_parm = NewParm(base_type, NewString("arg1"), n);
  991. set_nextSibling(base_parm, parms);
  992. parms = base_parm;
  993. }
  994. emit_parameter_variables(parms, f);
  995. emit_attach_parmmaps(parms, f);
  996. int parm_count = emit_num_arguments(parms);
  997. int required_count = emit_num_required(parms);
  998. emit_return_variable(n, result, f);
  999. // Start the function definition.
  1000. Printv(f->def, "void\n", wname, "(void *swig_v)\n", "{\n", NULL);
  1001. // The single function parameter is a pointer to the real argument
  1002. // values. Define the structure that it points to.
  1003. Printv(f->code, "\tstruct swigargs {\n", NULL);
  1004. if (parm_count > required_count) {
  1005. Printv(f->code, "\t\tint _swig_optargc;\n", NULL);
  1006. }
  1007. Parm *p = parms;
  1008. for (int i = 0; i < parm_count; ++i) {
  1009. p = getParm(p);
  1010. String *ln = Getattr(p, "lname");
  1011. SwigType *pt = Getattr(p, "type");
  1012. String *ct = gcCTypeForGoValue(p, pt, ln);
  1013. Printv(f->code, "\t\t\t", ct, ";\n", NULL);
  1014. Delete(ct);
  1015. p = nextParm(p);
  1016. }
  1017. if (SwigType_type(result) != T_VOID) {
  1018. Printv(f->code, "\t\tlong : 0;\n", NULL);
  1019. String *ln = NewString(Swig_cresult_name());
  1020. String *ct = gcCTypeForGoValue(n, result, ln);
  1021. Delete(ln);
  1022. Printv(f->code, "\t\t", ct, ";\n", NULL);
  1023. Delete(ct);
  1024. }
  1025. Printv(f->code, "\t} *swig_a = (struct swigargs *) swig_v;\n", NULL);
  1026. Printv(f->code, "\n", NULL);
  1027. // Copy the input arguments out of the structure into the
  1028. // parameter variables.
  1029. p = parms;
  1030. for (int i = 0; i < parm_count; ++i) {
  1031. p = getParm(p);
  1032. String *tm = Getattr(p, "tmap:in");
  1033. if (!tm) {
  1034. Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument\n", SwigType_str(Getattr(p, "type"), 0));
  1035. } else {
  1036. String *ln = Getattr(p, "lname");
  1037. String *input = NewString("");
  1038. Printv(input, "swig_a->", ln, NULL);
  1039. Replaceall(tm, "$input", input);
  1040. Setattr(p, "emit:input", input);
  1041. if (i < required_count) {
  1042. Printv(f->code, "\t", tm, "\n", NULL);
  1043. } else {
  1044. Printf(f->code, "\tif (swig_a->_swig_optargc > %d) {\n", i - required_count);
  1045. Printv(f->code, "\t\t", tm, "\n", NULL);
  1046. Printv(f->code, "\t}\n", NULL);
  1047. }
  1048. }
  1049. p = nextParm(p);
  1050. }
  1051. Printv(f->code, "\n", NULL);
  1052. // Do the real work of the function.
  1053. checkConstraints(parms, f);
  1054. emitGoAction(n, base, parms, result, f);
  1055. argout(parms, f);
  1056. cleanupFunction(n, f, parms);
  1057. Printv(f->code, "}\n", NULL);
  1058. Wrapper_print(f, f_c_wrappers);
  1059. Swig_restore(n);
  1060. DelWrapper(f);
  1061. Delete(base_parm);
  1062. return SWIG_OK;
  1063. }
  1064. /* ----------------------------------------------------------------------
  1065. * gccgoFunctionWrapper()
  1066. *
  1067. * This is used for gccgo, not 6g/8g. Write out the function
  1068. * wrapper which will be compiled with gcc. If the base parameter
  1069. * is not NULL, this is calls the base class method rather than
  1070. * executing the SWIG wrapper code.
  1071. * ---------------------------------------------------------------------- */
  1072. int gccgoFunctionWrapper(Node *n, List *base, String *wname, ParmList *parms, SwigType *result) {
  1073. Wrapper *f = NewWrapper();
  1074. Swig_save("gccgoFunctionWrapper", n, "parms", NULL);
  1075. Parm *base_parm = NULL;
  1076. if (base && !isStatic(n)) {
  1077. SwigType *base_type = Copy(getClassType());
  1078. SwigType_add_pointer(base_type);
  1079. base_parm = NewParm(base_type, NewString("arg1"), n);
  1080. set_nextSibling(base_parm, parms);
  1081. parms = base_parm;
  1082. }
  1083. emit_parameter_variables(parms, f);
  1084. emit_attach_parmmaps(parms, f);
  1085. int parm_count = emit_num_arguments(parms);
  1086. int required_count = emit_num_required(parms);
  1087. emit_return_variable(n, result, f);
  1088. // Start the function definition.
  1089. String *fnname = NewString("");
  1090. Printv(fnname, go_prefix, "_", wname, "(", NULL);
  1091. if (parm_count > required_count) {
  1092. Printv(fnname, "int _swig_optargc", NULL);
  1093. }
  1094. Parm *p = parms;
  1095. for (int i = 0; i < parm_count; ++i) {
  1096. p = getParm(p);
  1097. SwigType *pt = Copy(Getattr(p, "type"));
  1098. if (SwigType_isarray(pt)) {
  1099. SwigType_del_array(pt);
  1100. SwigType_add_pointer(pt);
  1101. }
  1102. String *pn = NewString("g");
  1103. Append(pn, Getattr(p, "lname"));
  1104. String *ct = gccgoCTypeForGoValue(p, pt, pn);
  1105. if (i > 0 || parm_count > required_count) {
  1106. Printv(fnname, ", ", NULL);
  1107. }
  1108. Printv(fnname, ct, NULL);
  1109. Delete(ct);
  1110. Delete(pn);
  1111. Delete(pt);
  1112. p = nextParm(p);
  1113. }
  1114. Printv(fnname, ")", NULL);
  1115. if (SwigType_type(result) == T_VOID) {
  1116. Printv(f->def, "void ", fnname, NULL);
  1117. } else {
  1118. String *ct = gccgoCTypeForGoValue(n, result, fnname);
  1119. Printv(f->def, ct, NULL);
  1120. Delete(ct);
  1121. }
  1122. Printv(f->def, " {\n", NULL);
  1123. Delete(fnname);
  1124. if (SwigType_type(result) != T_VOID) {
  1125. String *ln = NewString("go_result");
  1126. String *ct = gccgoCTypeForGoValue(n, result, ln);
  1127. Wrapper_add_local(f, "go_result", ct);
  1128. Delete(ct);
  1129. Delete(ln);
  1130. }
  1131. // Copy the parameters into the variables which hold their values,
  1132. // applying appropriate transformations.
  1133. p = parms;
  1134. for (int i = 0; i < parm_count; ++i) {
  1135. p = getParm(p);
  1136. String *tm = Getattr(p, "tmap:in");
  1137. if (!tm) {
  1138. Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number,
  1139. "Unable to use type %s as a function argument\n", SwigType_str(Getattr(p, "type"), 0));
  1140. } else {
  1141. String *ln = Getattr(p, "lname");
  1142. String *pn = NewString("g");
  1143. Append(pn, ln);
  1144. Replaceall(tm, "$input", pn);
  1145. Setattr(p, "emit:input", pn);
  1146. if (i < required_count) {
  1147. Printv(f->code, " ", tm, "\n", NULL);
  1148. } else {
  1149. Printf(f->code, " if (_swig_optargc > %d) {\n", i - required_count);
  1150. Printv(f->code, " ", tm, "\n", NULL);
  1151. Printv(f->code, " }\n", NULL);
  1152. }
  1153. }
  1154. p = nextParm(p);
  1155. }
  1156. Printv(f->code, "\n", NULL);
  1157. // Do the real work of the function.
  1158. checkConstraints(parms, f);
  1159. emitGoAction(n, base, parms, result, f);
  1160. argout(parms, f);
  1161. cleanupFunction(n, f, parms);
  1162. if (SwigType_type(result) != T_VOID) {
  1163. Printv(f->code, " return go_result;\n", NULL);
  1164. }
  1165. Printv(f->code, "}\n", NULL);
  1166. Wrapper_print(f, f_c_wrappers);
  1167. Swig_restore(n);
  1168. DelWrapper(f);
  1169. Delete(base_parm);
  1170. return SWIG_OK;
  1171. }
  1172. /* -----------------------------------------------------------------------
  1173. * checkConstraints()
  1174. *
  1175. * Check parameter constraints if any. This is used for the C/C++
  1176. * function. This assumes that each parameter has an "emit:input"
  1177. * property with the name to use to refer to that parameter.
  1178. * ----------------------------------------------------------------------- */
  1179. void checkConstraints(ParmList *parms, Wrapper *f) {
  1180. Parm *p = parms;
  1181. while (p) {
  1182. String *tm = Getattr(p, "tmap:check");
  1183. if (!tm) {
  1184. p = nextSibling(p);
  1185. } else {
  1186. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  1187. Printv(f->code, tm, "\n\n", NULL);
  1188. p = Getattr(p, "tmap:check:next");
  1189. }
  1190. }
  1191. }
  1192. /* -----------------------------------------------------------------------
  1193. * getGoAction()
  1194. *
  1195. * Get the action of the function. This is used for C/C++ function.
  1196. * ----------------------------------------------------------------------- */
  1197. void emitGoAction(Node *n, List *base, ParmList *parms, SwigType *result, Wrapper *f) {
  1198. String *actioncode;
  1199. if (!base || isStatic(n)) {
  1200. Swig_director_emit_dynamic_cast(n, f);
  1201. actioncode = emit_action(n);
  1202. } else {
  1203. // Call the base class method.
  1204. actioncode = NewString("");
  1205. String *current = NewString("");
  1206. if (!gccgo_flag) {
  1207. Printv(current, "swig_a->", NULL);
  1208. }
  1209. Printv(current, Getattr(parms, "lname"), NULL);
  1210. int vc = 0;
  1211. for (Iterator bi = First(base); bi.item; bi = Next(bi)) {
  1212. Printf(actioncode, " %s *swig_b%d = (%s *)%s;\n", bi.item, vc, bi.item, current);
  1213. Delete(current);
  1214. current = NewString("");
  1215. Printf(current, "swig_b%d", vc);
  1216. ++vc;
  1217. }
  1218. String *code = Copy(Getattr(n, "wrap:action"));
  1219. Replaceall(code, Getattr(parms, "lname"), current);
  1220. Printv(actioncode, code, "\n", NULL);
  1221. }
  1222. Swig_save("emitGoAction", n, "type", "tmap:out", NULL);
  1223. Setattr(n, "type", result);
  1224. String *tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode);
  1225. if (!tm) {
  1226. Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s\n", SwigType_str(result, 0));
  1227. } else {
  1228. if (!gccgo_flag) {
  1229. static const String *swig_a_result = NewStringf("swig_a->%s", Swig_cresult_name());
  1230. Replaceall(tm, "$result", swig_a_result);
  1231. } else {
  1232. Replaceall(tm, "$result", "go_result");
  1233. }
  1234. if (GetFlag(n, "feature:new")) {
  1235. Replaceall(tm, "$owner", "1");
  1236. } else {
  1237. Replaceall(tm, "$owner", "0");
  1238. }
  1239. Printv(f->code, tm, "\n", NULL);
  1240. Delete(tm);
  1241. }
  1242. Swig_restore(n);
  1243. }
  1244. /* -----------------------------------------------------------------------
  1245. * argout()
  1246. *
  1247. * Handle argument output code if any. This is used for the C/C++
  1248. * function. This assumes that each parameter has an "emit:input"
  1249. * property with the name to use to refer to that parameter.
  1250. * ----------------------------------------------------------------------- */
  1251. void argout(ParmList *parms, Wrapper *f) {
  1252. Parm *p = parms;
  1253. while (p) {
  1254. String *tm = Getattr(p, "tmap:argout");
  1255. if (!tm) {
  1256. p = nextSibling(p);
  1257. } else {
  1258. Replaceall(tm, "$result", Swig_cresult_name());
  1259. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  1260. Printv(f->code, tm, "\n", NULL);
  1261. p = Getattr(p, "tmap:argout:next");
  1262. }
  1263. }
  1264. }
  1265. /* -----------------------------------------------------------------------
  1266. * freearg()
  1267. *
  1268. * Handle argument cleanup code if any. This is used for the C/C++
  1269. * function. This assumes that each parameter has an "emit:input"
  1270. * property with the name to use to refer to that parameter.
  1271. * ----------------------------------------------------------------------- */
  1272. String *freearg(ParmList *parms) {
  1273. String *ret = NewString("");
  1274. Parm *p = parms;
  1275. while (p) {
  1276. String *tm = Getattr(p, "tmap:freearg");
  1277. if (!tm) {
  1278. p = nextSibling(p);
  1279. } else {
  1280. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  1281. Printv(ret, tm, "\n", NULL);
  1282. p = Getattr(p, "tmap:freearg:next");
  1283. }
  1284. }
  1285. return ret;
  1286. }
  1287. /* -----------------------------------------------------------------------
  1288. * cleanupFunction()
  1289. *
  1290. * Final function cleanup code.
  1291. * ----------------------------------------------------------------------- */
  1292. void cleanupFunction(Node *n, Wrapper *f, ParmList *parms) {
  1293. String *cleanup = freearg(parms);
  1294. Printv(f->code, cleanup, NULL);
  1295. if (GetFlag(n, "feature:new")) {
  1296. String *tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0);
  1297. if (tm) {
  1298. Replaceall(tm, "$source", Swig_cresult_name());
  1299. Printv(f->code, tm, "\n", NULL);
  1300. Delete(tm);
  1301. }
  1302. }
  1303. Replaceall(f->code, "$cleanup", cleanup);
  1304. Delete(cleanup);
  1305. Replaceall(f->code, "$symname", Getattr(n, "sym:name"));
  1306. }
  1307. /* -----------------------------------------------------------------------
  1308. * variableHandler()
  1309. *
  1310. * This exists just to set the making_variable_wrappers flag.
  1311. * ----------------------------------------------------------------------- */
  1312. virtual int variableHandler(Node *n) {
  1313. assert(!making_variable_wrappers);
  1314. making_variable_wrappers = true;
  1315. int r = Language::variableHandler(n);
  1316. making_variable_wrappers = false;
  1317. return r;
  1318. }
  1319. /* -----------------------------------------------------------------------
  1320. * constantWrapper()
  1321. *
  1322. * Product a const declaration.
  1323. * ------------------------------------------------------------------------ */
  1324. virtual int constantWrapper(Node *n) {
  1325. SwigType *type = Getattr(n, "type");
  1326. if (!SwigType_issimple(type) && SwigType_type(type) != T_STRING) {
  1327. return goComplexConstant(n, type);
  1328. }
  1329. if (Getattr(n, "storage") && Strcmp(Getattr(n, "storage"), "static") == 0) {
  1330. return goComplexConstant(n, type);
  1331. }
  1332. String *go_name = buildGoName(Getattr(n, "sym:name"), false, false);
  1333. String *tm = goType(n, type);
  1334. String *value = Getattr(n, "value");
  1335. String *copy = NULL;
  1336. if (SwigType_type(type) == T_BOOL) {
  1337. if (Cmp(value, "true") != 0 && Cmp(value, "false") != 0) {
  1338. return goComplexConstant(n, type);
  1339. }
  1340. } else if (SwigType_type(type) == T_STRING || SwigType_type(type) == T_CHAR) {
  1341. // Backslash sequences are somewhat different in Go and C/C++.
  1342. if (Strchr(value, '\\') != 0) {
  1343. return goComplexConstant(n, type);
  1344. }
  1345. } else {
  1346. // Accept a 0x prefix, and strip combinations of u and l
  1347. // suffixes. Otherwise accept digits, decimal point, and
  1348. // exponentiation. Treat anything else as too complicated to
  1349. // handle as a Go constant.
  1350. char *p = Char(value);
  1351. int len = strlen(p);
  1352. bool need_copy = false;
  1353. while (len > 0) {
  1354. char c = p[len - 1];
  1355. if (c != 'l' && c != 'L' && c != 'u' && c != 'U') {
  1356. break;
  1357. }
  1358. --len;
  1359. need_copy = true;
  1360. }
  1361. bool is_hex = false;
  1362. int i = 0;
  1363. if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
  1364. i = 2;
  1365. is_hex = true;
  1366. }
  1367. for (; i < len; ++i) {
  1368. switch (p[i]) {
  1369. case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
  1370. break;
  1371. case 'a': case 'b': case 'c': case 'd': case 'f': case 'A': case 'B': case 'C': case 'D': case 'F':
  1372. if (!is_hex) {
  1373. return goComplexConstant(n, type);
  1374. }
  1375. break;
  1376. case '.': case 'e': case 'E': case '+': case '-':
  1377. break;
  1378. default:
  1379. return goComplexConstant(n, type);
  1380. }
  1381. }
  1382. if (need_copy) {
  1383. copy = Copy(value);
  1384. Replaceall(copy, p + len, "");
  1385. value = copy;
  1386. }
  1387. }
  1388. if (!checkNameConflict(go_name, n, NULL)) {
  1389. Delete(tm);
  1390. Delete(go_name);
  1391. Delete(copy);
  1392. return SWIG_NOWRAP;
  1393. }
  1394. Printv(f_go_wrappers, "const ", go_name, " ", tm, " = ", NULL);
  1395. if (SwigType_type(type) == T_STRING) {
  1396. Printv(f_go_wrappers, "\"", value, "\"", NULL);
  1397. } else if (SwigType_type(type) == T_CHAR) {
  1398. Printv(f_go_wrappers, "'", value, "'", NULL);
  1399. } else {
  1400. Printv(f_go_wrappers, value, NULL);
  1401. }
  1402. Printv(f_go_wrappers, "\n", NULL);
  1403. Delete(tm);
  1404. Delete(go_name);
  1405. Delete(copy);
  1406. return SWIG_OK;
  1407. }
  1408. /* ----------------------------------------------------------------------
  1409. * enumDeclaration()
  1410. *
  1411. * A C++ enum type turns into a Named go int type.
  1412. * ---------------------------------------------------------------------- */
  1413. virtual int enumDeclaration(Node *n) {
  1414. String *name = goEnumName(n);
  1415. if (Strcmp(name, "int") != 0) {
  1416. if (!ImportMode || !imported_package) {
  1417. if (!checkNameConflict(name, n, NULL)) {
  1418. Delete(name);
  1419. return SWIG_NOWRAP;
  1420. }
  1421. Printv(f_go_wrappers, "type ", name, " int\n", NULL);
  1422. } else {
  1423. String *nw = NewString("");
  1424. Printv(nw, imported_package, ".", name, NULL);
  1425. Setattr(n, "go:enumname", nw);
  1426. }
  1427. }
  1428. Delete(name);
  1429. return Language::enumDeclaration(n);
  1430. }
  1431. /* -----------------------------------------------------------------------
  1432. * enumvalueDeclaration()
  1433. *
  1434. * Declare a single value of an enum type. We fetch the value by
  1435. * calling a C/C++ function.
  1436. * ------------------------------------------------------------------------ */
  1437. virtual int enumvalueDeclaration(Node *n) {
  1438. if (!is_public(n)) {
  1439. return SWIG_OK;
  1440. }
  1441. if (Getattr(parentNode(n), "unnamed")) {
  1442. Setattr(n, "type", NewString("…

Large files files are truncated, but you can click here to view the full file