PageRenderTime 52ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Source/Modules/chicken.cxx

#
C++ | 1541 lines | 1157 code | 269 blank | 115 comment | 312 complexity | 1e964c86556ddb2647a0afa787b85533 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
  1. /* -----------------------------------------------------------------------------
  2. * This file is part of SWIG, which is licensed as a whole under version 3
  3. * (or any later version) of the GNU General Public License. Some additional
  4. * terms also apply to certain portions of SWIG. The full details of the SWIG
  5. * license and copyrights can be found in the LICENSE and COPYRIGHT files
  6. * included with the SWIG source code as distributed by the SWIG developers
  7. * and at http://www.swig.org/legal.html.
  8. *
  9. * chicken.cxx
  10. *
  11. * CHICKEN language module for SWIG.
  12. * ----------------------------------------------------------------------------- */
  13. char cvsroot_chicken_cxx[] = "$Id: chicken.cxx 12830 2011-10-30 21:51:50Z wsfulton $";
  14. #include "swigmod.h"
  15. #include <ctype.h>
  16. static const char *usage = (char *) "\
  17. \
  18. CHICKEN Options (available with -chicken)\n\
  19. -closprefix <prefix> - Prepend <prefix> to all clos identifiers\n\
  20. -noclosuses - Do not (declare (uses ...)) in scheme file\n\
  21. -nocollection - Do not register pointers with chicken garbage\n\
  22. collector and export destructors\n\
  23. -nounit - Do not (declare (unit ...)) in scheme file\n\
  24. -proxy - Export TinyCLOS class definitions\n\
  25. -unhideprimitive - Unhide the primitive: symbols\n\
  26. -useclassprefix - Prepend the class name to all clos identifiers\n\
  27. \n";
  28. static char *module = 0;
  29. static char *chicken_path = (char *) "chicken";
  30. static int num_methods = 0;
  31. static File *f_begin = 0;
  32. static File *f_runtime = 0;
  33. static File *f_header = 0;
  34. static File *f_wrappers = 0;
  35. static File *f_init = 0;
  36. static String *chickentext = 0;
  37. static String *closprefix = 0;
  38. static String *swigtype_ptr = 0;
  39. static String *f_sym_size = 0;
  40. /* some options */
  41. static int declare_unit = 1;
  42. static int no_collection = 0;
  43. static int clos_uses = 1;
  44. /* C++ Support + Clos Classes */
  45. static int clos = 0;
  46. static String *c_class_name = 0;
  47. static String *class_name = 0;
  48. static String *short_class_name = 0;
  49. static int in_class = 0;
  50. static int have_constructor = 0;
  51. static bool exporting_destructor = false;
  52. static bool exporting_constructor = false;
  53. static String *constructor_name = 0;
  54. static String *member_name = 0;
  55. /* sections of the .scm code */
  56. static String *scm_const_defs = 0;
  57. static String *clos_class_defines = 0;
  58. static String *clos_methods = 0;
  59. /* Some clos options */
  60. static int useclassprefix = 0;
  61. static String *clossymnameprefix = 0;
  62. static int hide_primitive = 1;
  63. static Hash *primitive_names = 0;
  64. /* Used for overloading constructors */
  65. static int has_constructor_args = 0;
  66. static List *constructor_arg_types = 0;
  67. static String *constructor_dispatch = 0;
  68. static Hash *overload_parameter_lists = 0;
  69. class CHICKEN:public Language {
  70. public:
  71. virtual void main(int argc, char *argv[]);
  72. virtual int top(Node *n);
  73. virtual int functionWrapper(Node *n);
  74. virtual int variableWrapper(Node *n);
  75. virtual int constantWrapper(Node *n);
  76. virtual int classHandler(Node *n);
  77. virtual int memberfunctionHandler(Node *n);
  78. virtual int membervariableHandler(Node *n);
  79. virtual int constructorHandler(Node *n);
  80. virtual int destructorHandler(Node *n);
  81. virtual int validIdentifier(String *s);
  82. virtual int staticmembervariableHandler(Node *n);
  83. virtual int staticmemberfunctionHandler(Node *n);
  84. virtual int importDirective(Node *n);
  85. protected:
  86. void addMethod(String *scheme_name, String *function);
  87. /* Return true iff T is a pointer type */
  88. int isPointer(SwigType *t);
  89. void dispatchFunction(Node *n);
  90. String *chickenNameMapping(String *, const_String_or_char_ptr );
  91. String *chickenPrimitiveName(String *);
  92. String *runtimeCode();
  93. String *defaultExternalRuntimeFilename();
  94. String *buildClosFunctionCall(List *types, const_String_or_char_ptr closname, const_String_or_char_ptr funcname);
  95. };
  96. /* -----------------------------------------------------------------------
  97. * swig_chicken() - Instantiate module
  98. * ----------------------------------------------------------------------- */
  99. static Language *new_swig_chicken() {
  100. return new CHICKEN();
  101. }
  102. extern "C" {
  103. Language *swig_chicken(void) {
  104. return new_swig_chicken();
  105. }
  106. }
  107. void CHICKEN::main(int argc, char *argv[]) {
  108. int i;
  109. SWIG_library_directory(chicken_path);
  110. // Look for certain command line options
  111. for (i = 1; i < argc; i++) {
  112. if (argv[i]) {
  113. if (strcmp(argv[i], "-help") == 0) {
  114. fputs(usage, stdout);
  115. SWIG_exit(0);
  116. } else if (strcmp(argv[i], "-proxy") == 0) {
  117. clos = 1;
  118. Swig_mark_arg(i);
  119. } else if (strcmp(argv[i], "-closprefix") == 0) {
  120. if (argv[i + 1]) {
  121. clossymnameprefix = NewString(argv[i + 1]);
  122. Swig_mark_arg(i);
  123. Swig_mark_arg(i + 1);
  124. i++;
  125. } else {
  126. Swig_arg_error();
  127. }
  128. } else if (strcmp(argv[i], "-useclassprefix") == 0) {
  129. useclassprefix = 1;
  130. Swig_mark_arg(i);
  131. } else if (strcmp(argv[i], "-unhideprimitive") == 0) {
  132. hide_primitive = 0;
  133. Swig_mark_arg(i);
  134. } else if (strcmp(argv[i], "-nounit") == 0) {
  135. declare_unit = 0;
  136. Swig_mark_arg(i);
  137. } else if (strcmp(argv[i], "-noclosuses") == 0) {
  138. clos_uses = 0;
  139. Swig_mark_arg(i);
  140. } else if (strcmp(argv[i], "-nocollection") == 0) {
  141. no_collection = 1;
  142. Swig_mark_arg(i);
  143. }
  144. }
  145. }
  146. if (!clos)
  147. hide_primitive = 0;
  148. // Add a symbol for this module
  149. Preprocessor_define("SWIGCHICKEN 1", 0);
  150. // Set name of typemaps
  151. SWIG_typemap_lang("chicken");
  152. // Read in default typemaps */
  153. SWIG_config_file("chicken.swg");
  154. allow_overloading();
  155. }
  156. int CHICKEN::top(Node *n) {
  157. String *chicken_filename = NewString("");
  158. File *f_scm;
  159. String *scmmodule;
  160. /* Initialize all of the output files */
  161. String *outfile = Getattr(n, "outfile");
  162. f_begin = NewFile(outfile, "w", SWIG_output_files());
  163. if (!f_begin) {
  164. FileErrorDisplay(outfile);
  165. SWIG_exit(EXIT_FAILURE);
  166. }
  167. f_runtime = NewString("");
  168. f_init = NewString("");
  169. f_header = NewString("");
  170. f_wrappers = NewString("");
  171. chickentext = NewString("");
  172. closprefix = NewString("");
  173. f_sym_size = NewString("");
  174. primitive_names = NewHash();
  175. overload_parameter_lists = NewHash();
  176. /* Register file targets with the SWIG file handler */
  177. Swig_register_filebyname("header", f_header);
  178. Swig_register_filebyname("wrapper", f_wrappers);
  179. Swig_register_filebyname("begin", f_begin);
  180. Swig_register_filebyname("runtime", f_runtime);
  181. Swig_register_filebyname("init", f_init);
  182. Swig_register_filebyname("chicken", chickentext);
  183. Swig_register_filebyname("closprefix", closprefix);
  184. clos_class_defines = NewString("");
  185. clos_methods = NewString("");
  186. scm_const_defs = NewString("");
  187. Swig_banner(f_begin);
  188. Printf(f_runtime, "\n");
  189. Printf(f_runtime, "#define SWIGCHICKEN\n");
  190. if (no_collection)
  191. Printf(f_runtime, "#define SWIG_CHICKEN_NO_COLLECTION 1\n");
  192. Printf(f_runtime, "\n");
  193. /* Set module name */
  194. module = Swig_copy_string(Char(Getattr(n, "name")));
  195. scmmodule = NewString(module);
  196. Replaceall(scmmodule, "_", "-");
  197. Printf(f_header, "#define SWIG_init swig_%s_init\n", module);
  198. Printf(f_header, "#define SWIG_name \"%s\"\n", scmmodule);
  199. Printf(f_wrappers, "#ifdef __cplusplus\n");
  200. Printf(f_wrappers, "extern \"C\" {\n");
  201. Printf(f_wrappers, "#endif\n\n");
  202. Language::top(n);
  203. SwigType_emit_type_table(f_runtime, f_wrappers);
  204. Printf(f_wrappers, "#ifdef __cplusplus\n");
  205. Printf(f_wrappers, "}\n");
  206. Printf(f_wrappers, "#endif\n");
  207. Printf(f_init, "C_kontinue (continuation, ret);\n");
  208. Printf(f_init, "}\n\n");
  209. Printf(f_init, "#ifdef __cplusplus\n");
  210. Printf(f_init, "}\n");
  211. Printf(f_init, "#endif\n");
  212. Printf(chicken_filename, "%s%s.scm", SWIG_output_directory(), module);
  213. if ((f_scm = NewFile(chicken_filename, "w", SWIG_output_files())) == 0) {
  214. FileErrorDisplay(chicken_filename);
  215. SWIG_exit(EXIT_FAILURE);
  216. }
  217. Swig_banner_target_lang(f_scm, ";;");
  218. Printf(f_scm, "\n");
  219. if (declare_unit)
  220. Printv(f_scm, "(declare (unit ", scmmodule, "))\n\n", NIL);
  221. Printv(f_scm, "(declare \n",
  222. tab4, "(hide swig-init swig-init-return)\n",
  223. tab4, "(foreign-declare \"C_extern void swig_", module, "_init(C_word,C_word,C_word) C_noret;\"))\n", NIL);
  224. Printv(f_scm, "(define swig-init (##core#primitive \"swig_", module, "_init\"))\n", NIL);
  225. Printv(f_scm, "(define swig-init-return (swig-init))\n\n", NIL);
  226. if (clos) {
  227. //Printf (f_scm, "(declare (uses tinyclos))\n");
  228. //New chicken versions have tinyclos as an egg
  229. Printf(f_scm, "(require-extension tinyclos)\n");
  230. Replaceall(closprefix, "$module", scmmodule);
  231. Printf(f_scm, "%s\n", closprefix);
  232. Printf(f_scm, "%s\n", clos_class_defines);
  233. Printf(f_scm, "%s\n", clos_methods);
  234. } else {
  235. Printf(f_scm, "%s\n", scm_const_defs);
  236. }
  237. Printf(f_scm, "%s\n", chickentext);
  238. Close(f_scm);
  239. Delete(f_scm);
  240. char buftmp[20];
  241. sprintf(buftmp, "%d", num_methods);
  242. Replaceall(f_init, "$nummethods", buftmp);
  243. Replaceall(f_init, "$symsize", f_sym_size);
  244. if (hide_primitive)
  245. Replaceall(f_init, "$veclength", buftmp);
  246. else
  247. Replaceall(f_init, "$veclength", "0");
  248. Delete(chicken_filename);
  249. Delete(chickentext);
  250. Delete(closprefix);
  251. Delete(overload_parameter_lists);
  252. Delete(clos_class_defines);
  253. Delete(clos_methods);
  254. Delete(scm_const_defs);
  255. /* Close all of the files */
  256. Delete(primitive_names);
  257. Delete(scmmodule);
  258. Dump(f_runtime, f_begin);
  259. Dump(f_header, f_begin);
  260. Dump(f_wrappers, f_begin);
  261. Wrapper_pretty_print(f_init, f_begin);
  262. Delete(f_header);
  263. Delete(f_wrappers);
  264. Delete(f_sym_size);
  265. Delete(f_init);
  266. Close(f_begin);
  267. Delete(f_runtime);
  268. Delete(f_begin);
  269. return SWIG_OK;
  270. }
  271. int CHICKEN::functionWrapper(Node *n) {
  272. String *name = Getattr(n, "name");
  273. String *iname = Getattr(n, "sym:name");
  274. SwigType *d = Getattr(n, "type");
  275. ParmList *l = Getattr(n, "parms");
  276. Parm *p;
  277. int i;
  278. String *wname;
  279. Wrapper *f;
  280. String *mangle = NewString("");
  281. String *get_pointers;
  282. String *cleanup;
  283. String *argout;
  284. String *tm;
  285. String *overname = 0;
  286. String *declfunc = 0;
  287. String *scmname;
  288. bool any_specialized_arg = false;
  289. List *function_arg_types = NewList();
  290. int num_required;
  291. int num_arguments;
  292. int have_argout;
  293. Printf(mangle, "\"%s\"", SwigType_manglestr(d));
  294. if (Getattr(n, "sym:overloaded")) {
  295. overname = Getattr(n, "sym:overname");
  296. } else {
  297. if (!addSymbol(iname, n))
  298. return SWIG_ERROR;
  299. }
  300. f = NewWrapper();
  301. wname = NewString("");
  302. get_pointers = NewString("");
  303. cleanup = NewString("");
  304. argout = NewString("");
  305. declfunc = NewString("");
  306. scmname = NewString(iname);
  307. Replaceall(scmname, "_", "-");
  308. /* Local vars */
  309. Wrapper_add_local(f, "resultobj", "C_word resultobj");
  310. /* Write code to extract function parameters. */
  311. emit_parameter_variables(l, f);
  312. /* Attach the standard typemaps */
  313. emit_attach_parmmaps(l, f);
  314. Setattr(n, "wrap:parms", l);
  315. /* Get number of required and total arguments */
  316. num_arguments = emit_num_arguments(l);
  317. num_required = emit_num_required(l);
  318. Append(wname, Swig_name_wrapper(iname));
  319. if (overname) {
  320. Append(wname, overname);
  321. }
  322. // Check for interrupts
  323. Printv(f->code, "C_trace(\"", scmname, "\");\n", NIL);
  324. Printv(f->def, "static ", "void ", wname, " (C_word argc, C_word closure, C_word continuation", NIL);
  325. Printv(declfunc, "void ", wname, "(C_word,C_word,C_word", NIL);
  326. /* Generate code for argument marshalling */
  327. for (i = 0, p = l; i < num_arguments; i++) {
  328. while (checkAttribute(p, "tmap:in:numinputs", "0")) {
  329. p = Getattr(p, "tmap:in:next");
  330. }
  331. SwigType *pt = Getattr(p, "type");
  332. String *ln = Getattr(p, "lname");
  333. Printf(f->def, ", C_word scm%d", i + 1);
  334. Printf(declfunc, ",C_word");
  335. /* Look for an input typemap */
  336. if ((tm = Getattr(p, "tmap:in"))) {
  337. String *parse = Getattr(p, "tmap:in:parse");
  338. if (!parse) {
  339. String *source = NewStringf("scm%d", i + 1);
  340. Replaceall(tm, "$source", source);
  341. Replaceall(tm, "$target", ln);
  342. Replaceall(tm, "$input", source);
  343. Setattr(p, "emit:input", source); /* Save the location of
  344. the object */
  345. if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
  346. Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
  347. } else {
  348. Replaceall(tm, "$disown", "0");
  349. }
  350. if (i >= num_required)
  351. Printf(get_pointers, "if (argc-2>%i && (%s)) {\n", i, source);
  352. Printv(get_pointers, tm, "\n", NIL);
  353. if (i >= num_required)
  354. Printv(get_pointers, "}\n", NIL);
  355. if (clos) {
  356. if (i < num_required) {
  357. if (strcmp("void", Char(pt)) != 0) {
  358. Node *class_node = 0;
  359. String *clos_code = Getattr(p, "tmap:in:closcode");
  360. class_node = classLookup(pt);
  361. if (clos_code && class_node) {
  362. String *class_name = NewStringf("<%s>", Getattr(class_node, "sym:name"));
  363. Replaceall(class_name, "_", "-");
  364. Append(function_arg_types, class_name);
  365. Append(function_arg_types, Copy(clos_code));
  366. any_specialized_arg = true;
  367. Delete(class_name);
  368. } else {
  369. Append(function_arg_types, "<top>");
  370. Append(function_arg_types, "$input");
  371. }
  372. }
  373. }
  374. }
  375. Delete(source);
  376. }
  377. p = Getattr(p, "tmap:in:next");
  378. continue;
  379. } else {
  380. Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
  381. break;
  382. }
  383. }
  384. /* finish argument marshalling */
  385. Printf(f->def, ") {");
  386. Printf(declfunc, ")");
  387. if (num_required != num_arguments) {
  388. Append(function_arg_types, "^^##optional$$");
  389. }
  390. /* First check the number of arguments is correct */
  391. if (num_arguments != num_required)
  392. Printf(f->code, "if (argc-2<%i || argc-2>%i) C_bad_argc(argc,%i);\n", num_required, num_arguments, num_required + 2);
  393. else
  394. Printf(f->code, "if (argc!=%i) C_bad_argc(argc,%i);\n", num_arguments + 2, num_arguments + 2);
  395. /* Now piece together the first part of the wrapper function */
  396. Printv(f->code, get_pointers, NIL);
  397. /* Insert constraint checking code */
  398. for (p = l; p;) {
  399. if ((tm = Getattr(p, "tmap:check"))) {
  400. Replaceall(tm, "$target", Getattr(p, "lname"));
  401. Printv(f->code, tm, "\n", NIL);
  402. p = Getattr(p, "tmap:check:next");
  403. } else {
  404. p = nextSibling(p);
  405. }
  406. }
  407. /* Insert cleanup code */
  408. for (p = l; p;) {
  409. if ((tm = Getattr(p, "tmap:freearg"))) {
  410. Replaceall(tm, "$source", Getattr(p, "lname"));
  411. Printv(cleanup, tm, "\n", NIL);
  412. p = Getattr(p, "tmap:freearg:next");
  413. } else {
  414. p = nextSibling(p);
  415. }
  416. }
  417. /* Insert argument output code */
  418. have_argout = 0;
  419. for (p = l; p;) {
  420. if ((tm = Getattr(p, "tmap:argout"))) {
  421. if (!have_argout) {
  422. have_argout = 1;
  423. // Print initial argument output code
  424. Printf(argout, "SWIG_Chicken_SetupArgout\n");
  425. }
  426. Replaceall(tm, "$source", Getattr(p, "lname"));
  427. Replaceall(tm, "$target", "resultobj");
  428. Replaceall(tm, "$arg", Getattr(p, "emit:input"));
  429. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  430. Printf(argout, "%s", tm);
  431. p = Getattr(p, "tmap:argout:next");
  432. } else {
  433. p = nextSibling(p);
  434. }
  435. }
  436. Setattr(n, "wrap:name", wname);
  437. /* Emit the function call */
  438. String *actioncode = emit_action(n);
  439. /* Return the function value */
  440. if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
  441. Replaceall(tm, "$source", Swig_cresult_name());
  442. Replaceall(tm, "$target", "resultobj");
  443. Replaceall(tm, "$result", "resultobj");
  444. if (GetFlag(n, "feature:new")) {
  445. Replaceall(tm, "$owner", "1");
  446. } else {
  447. Replaceall(tm, "$owner", "0");
  448. }
  449. Printf(f->code, "%s", tm);
  450. if (have_argout)
  451. Printf(f->code, "\nSWIG_APPEND_VALUE(resultobj);\n");
  452. } else {
  453. Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(d, 0), name);
  454. }
  455. emit_return_variable(n, d, f);
  456. /* Insert the argumetn output code */
  457. Printv(f->code, argout, NIL);
  458. /* Output cleanup code */
  459. Printv(f->code, cleanup, NIL);
  460. /* Look to see if there is any newfree cleanup code */
  461. if (GetFlag(n, "feature:new")) {
  462. if ((tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0))) {
  463. Replaceall(tm, "$source", Swig_cresult_name());
  464. Printf(f->code, "%s\n", tm);
  465. }
  466. }
  467. /* See if there is any return cleanup code */
  468. if ((tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0))) {
  469. Replaceall(tm, "$source", Swig_cresult_name());
  470. Printf(f->code, "%s\n", tm);
  471. }
  472. if (have_argout) {
  473. Printf(f->code, "C_kontinue(continuation,C_SCHEME_END_OF_LIST);\n");
  474. } else {
  475. if (exporting_constructor && clos && hide_primitive) {
  476. /* Don't return a proxy, the wrapped CLOS class is the proxy */
  477. Printf(f->code, "C_kontinue(continuation,resultobj);\n");
  478. } else {
  479. // make the continuation the proxy creation function, if one exists
  480. Printv(f->code, "{\n",
  481. "C_word func;\n",
  482. "SWIG_Chicken_FindCreateProxy(func, resultobj)\n",
  483. "if (C_swig_is_closurep(func))\n",
  484. " ((C_proc4)(void *)C_block_item(func, 0))(4,func,continuation,resultobj,C_SCHEME_FALSE);\n",
  485. "else\n", " C_kontinue(continuation, resultobj);\n", "}\n", NIL);
  486. }
  487. }
  488. /* Error handling code */
  489. #ifdef USE_FAIL
  490. Printf(f->code, "fail:\n");
  491. Printv(f->code, cleanup, NIL);
  492. Printf(f->code, "swig_panic (\"failure in " "'$symname' SWIG function wrapper\");\n");
  493. #endif
  494. Printf(f->code, "}\n");
  495. /* Substitute the cleanup code */
  496. Replaceall(f->code, "$cleanup", cleanup);
  497. /* Substitute the function name */
  498. Replaceall(f->code, "$symname", iname);
  499. Replaceall(f->code, "$result", "resultobj");
  500. /* Dump the function out */
  501. Printv(f_wrappers, "static ", declfunc, " C_noret;\n", NIL);
  502. Wrapper_print(f, f_wrappers);
  503. /* Now register the function with the interpreter. */
  504. if (!Getattr(n, "sym:overloaded")) {
  505. if (exporting_destructor && !no_collection) {
  506. Printf(f_init, "((swig_chicken_clientdata *)(SWIGTYPE%s->clientdata))->destroy = (swig_chicken_destructor) %s;\n", swigtype_ptr, wname);
  507. } else {
  508. addMethod(scmname, wname);
  509. }
  510. /* Only export if we are not in a class, or if in a class memberfunction */
  511. if (!in_class || member_name) {
  512. String *method_def;
  513. String *clos_name;
  514. if (in_class)
  515. clos_name = NewString(member_name);
  516. else
  517. clos_name = chickenNameMapping(scmname, (char *) "");
  518. if (!any_specialized_arg) {
  519. method_def = NewString("");
  520. Printv(method_def, "(define ", clos_name, " ", chickenPrimitiveName(scmname), ")", NIL);
  521. } else {
  522. method_def = buildClosFunctionCall(function_arg_types, clos_name, chickenPrimitiveName(scmname));
  523. }
  524. Printv(clos_methods, method_def, "\n", NIL);
  525. Delete(clos_name);
  526. Delete(method_def);
  527. }
  528. if (have_constructor && !has_constructor_args && any_specialized_arg) {
  529. has_constructor_args = 1;
  530. constructor_arg_types = Copy(function_arg_types);
  531. }
  532. } else {
  533. /* add function_arg_types to overload hash */
  534. List *flist = Getattr(overload_parameter_lists, scmname);
  535. if (!flist) {
  536. flist = NewList();
  537. Setattr(overload_parameter_lists, scmname, flist);
  538. }
  539. Append(flist, Copy(function_arg_types));
  540. if (!Getattr(n, "sym:nextSibling")) {
  541. dispatchFunction(n);
  542. }
  543. }
  544. Delete(wname);
  545. Delete(get_pointers);
  546. Delete(cleanup);
  547. Delete(declfunc);
  548. Delete(mangle);
  549. Delete(function_arg_types);
  550. DelWrapper(f);
  551. return SWIG_OK;
  552. }
  553. int CHICKEN::variableWrapper(Node *n) {
  554. char *name = GetChar(n, "name");
  555. char *iname = GetChar(n, "sym:name");
  556. SwigType *t = Getattr(n, "type");
  557. ParmList *l = Getattr(n, "parms");
  558. String *wname = NewString("");
  559. String *mangle = NewString("");
  560. String *tm;
  561. String *tm2 = NewString("");
  562. String *argnum = NewString("0");
  563. String *arg = NewString("argv[0]");
  564. Wrapper *f;
  565. String *overname = 0;
  566. String *scmname;
  567. scmname = NewString(iname);
  568. Replaceall(scmname, "_", "-");
  569. Printf(mangle, "\"%s\"", SwigType_manglestr(t));
  570. if (Getattr(n, "sym:overloaded")) {
  571. overname = Getattr(n, "sym:overname");
  572. } else {
  573. if (!addSymbol(iname, n))
  574. return SWIG_ERROR;
  575. }
  576. f = NewWrapper();
  577. /* Attach the standard typemaps */
  578. emit_attach_parmmaps(l, f);
  579. Setattr(n, "wrap:parms", l);
  580. // evaluation function names
  581. Append(wname, Swig_name_wrapper(iname));
  582. if (overname) {
  583. Append(wname, overname);
  584. }
  585. Setattr(n, "wrap:name", wname);
  586. // Check for interrupts
  587. Printv(f->code, "C_trace(\"", scmname, "\");\n", NIL);
  588. if (1 || (SwigType_type(t) != T_USER) || (isPointer(t))) {
  589. Printv(f->def, "static ", "void ", wname, "(C_word, C_word, C_word, C_word) C_noret;\n", NIL);
  590. Printv(f->def, "static " "void ", wname, "(C_word argc, C_word closure, " "C_word continuation, C_word value) {\n", NIL);
  591. Wrapper_add_local(f, "resultobj", "C_word resultobj");
  592. Printf(f->code, "if (argc!=2 && argc!=3) C_bad_argc(argc,2);\n");
  593. /* Check for a setting of the variable value */
  594. if (!GetFlag(n, "feature:immutable")) {
  595. Printf(f->code, "if (argc > 2) {\n");
  596. if ((tm = Swig_typemap_lookup("varin", n, name, 0))) {
  597. Replaceall(tm, "$source", "value");
  598. Replaceall(tm, "$target", name);
  599. Replaceall(tm, "$input", "value");
  600. /* Printv(f->code, tm, "\n",NIL); */
  601. emit_action_code(n, f->code, tm);
  602. } else {
  603. Swig_warning(WARN_TYPEMAP_VARIN_UNDEF, input_file, line_number, "Unable to set variable of type %s.\n", SwigType_str(t, 0));
  604. }
  605. Printf(f->code, "}\n");
  606. }
  607. String *varname;
  608. if (SwigType_istemplate((char *) name)) {
  609. varname = SwigType_namestr((char *) name);
  610. } else {
  611. varname = name;
  612. }
  613. // Now return the value of the variable - regardless
  614. // of evaluating or setting.
  615. if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
  616. Replaceall(tm, "$source", varname);
  617. Replaceall(tm, "$varname", varname);
  618. Replaceall(tm, "$target", "resultobj");
  619. Replaceall(tm, "$result", "resultobj");
  620. /* Printf(f->code, "%s\n", tm); */
  621. emit_action_code(n, f->code, tm);
  622. } else {
  623. Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
  624. }
  625. Printv(f->code, "{\n",
  626. "C_word func;\n",
  627. "SWIG_Chicken_FindCreateProxy(func, resultobj)\n",
  628. "if (C_swig_is_closurep(func))\n",
  629. " ((C_proc4)(void *)C_block_item(func, 0))(4,func,continuation,resultobj,C_SCHEME_FALSE);\n",
  630. "else\n", " C_kontinue(continuation, resultobj);\n", "}\n", NIL);
  631. /* Error handling code */
  632. #ifdef USE_FAIL
  633. Printf(f->code, "fail:\n");
  634. Printf(f->code, "swig_panic (\"failure in " "'%s' SWIG wrapper\");\n", proc_name);
  635. #endif
  636. Printf(f->code, "}\n");
  637. Wrapper_print(f, f_wrappers);
  638. /* Now register the variable with the interpreter. */
  639. addMethod(scmname, wname);
  640. if (!in_class || member_name) {
  641. String *clos_name;
  642. if (in_class)
  643. clos_name = NewString(member_name);
  644. else
  645. clos_name = chickenNameMapping(scmname, (char *) "");
  646. Node *class_node = classLookup(t);
  647. String *clos_code = Getattr(n, "tmap:varin:closcode");
  648. if (class_node && clos_code && !GetFlag(n, "feature:immutable")) {
  649. Replaceall(clos_code, "$input", "(car lst)");
  650. Printv(clos_methods, "(define (", clos_name, " . lst) (if (null? lst) (", chickenPrimitiveName(scmname), ") (",
  651. chickenPrimitiveName(scmname), " ", clos_code, ")))\n", NIL);
  652. } else {
  653. /* Simply re-export the procedure */
  654. if (GetFlag(n, "feature:immutable") && GetFlag(n, "feature:constasvar")) {
  655. Printv(clos_methods, "(define ", clos_name, " (", chickenPrimitiveName(scmname), "))\n", NIL);
  656. Printv(scm_const_defs, "(set! ", scmname, " (", scmname, "))\n", NIL);
  657. } else {
  658. Printv(clos_methods, "(define ", clos_name, " ", chickenPrimitiveName(scmname), ")\n", NIL);
  659. }
  660. }
  661. Delete(clos_name);
  662. }
  663. } else {
  664. Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, "Unsupported variable type %s (ignored).\n", SwigType_str(t, 0));
  665. }
  666. Delete(wname);
  667. Delete(argnum);
  668. Delete(arg);
  669. Delete(tm2);
  670. Delete(mangle);
  671. DelWrapper(f);
  672. return SWIG_OK;
  673. }
  674. /* ------------------------------------------------------------
  675. * constantWrapper()
  676. * ------------------------------------------------------------ */
  677. int CHICKEN::constantWrapper(Node *n) {
  678. char *name = GetChar(n, "name");
  679. char *iname = GetChar(n, "sym:name");
  680. SwigType *t = Getattr(n, "type");
  681. ParmList *l = Getattr(n, "parms");
  682. String *value = Getattr(n, "value");
  683. String *proc_name = NewString("");
  684. String *wname = NewString("");
  685. String *mangle = NewString("");
  686. String *tm;
  687. String *tm2 = NewString("");
  688. String *source = NewString("");
  689. String *argnum = NewString("0");
  690. String *arg = NewString("argv[0]");
  691. Wrapper *f;
  692. String *overname = 0;
  693. String *scmname;
  694. String *rvalue;
  695. SwigType *nctype;
  696. scmname = NewString(iname);
  697. Replaceall(scmname, "_", "-");
  698. Printf(source, "swig_const_%s", iname);
  699. Replaceall(source, "::", "__");
  700. Printf(mangle, "\"%s\"", SwigType_manglestr(t));
  701. if (Getattr(n, "sym:overloaded")) {
  702. overname = Getattr(n, "sym:overname");
  703. } else {
  704. if (!addSymbol(iname, n))
  705. return SWIG_ERROR;
  706. }
  707. Append(wname, Swig_name_wrapper(iname));
  708. if (overname) {
  709. Append(wname, overname);
  710. }
  711. nctype = NewString(t);
  712. if (SwigType_isconst(nctype)) {
  713. Delete(SwigType_pop(nctype));
  714. }
  715. bool is_enum_item = (Cmp(nodeType(n), "enumitem") == 0);
  716. if (SwigType_type(nctype) == T_STRING) {
  717. rvalue = NewStringf("\"%s\"", value);
  718. } else if (SwigType_type(nctype) == T_CHAR && !is_enum_item) {
  719. rvalue = NewStringf("\'%s\'", value);
  720. } else {
  721. rvalue = NewString(value);
  722. }
  723. /* Special hook for member pointer */
  724. if (SwigType_type(t) == T_MPOINTER) {
  725. Printf(f_header, "static %s = %s;\n", SwigType_str(t, source), rvalue);
  726. } else {
  727. if ((tm = Swig_typemap_lookup("constcode", n, name, 0))) {
  728. Replaceall(tm, "$source", rvalue);
  729. Replaceall(tm, "$target", source);
  730. Replaceall(tm, "$result", source);
  731. Replaceall(tm, "$value", rvalue);
  732. Printf(f_header, "%s\n", tm);
  733. } else {
  734. Swig_warning(WARN_TYPEMAP_CONST_UNDEF, input_file, line_number, "Unsupported constant value.\n");
  735. return SWIG_NOWRAP;
  736. }
  737. }
  738. f = NewWrapper();
  739. /* Attach the standard typemaps */
  740. emit_attach_parmmaps(l, f);
  741. Setattr(n, "wrap:parms", l);
  742. // evaluation function names
  743. // Check for interrupts
  744. Printv(f->code, "C_trace(\"", scmname, "\");\n", NIL);
  745. if (1 || (SwigType_type(t) != T_USER) || (isPointer(t))) {
  746. Setattr(n, "wrap:name", wname);
  747. Printv(f->def, "static ", "void ", wname, "(C_word, C_word, C_word) C_noret;\n", NIL);
  748. Printv(f->def, "static ", "void ", wname, "(C_word argc, C_word closure, " "C_word continuation) {\n", NIL);
  749. Wrapper_add_local(f, "resultobj", "C_word resultobj");
  750. Printf(f->code, "if (argc!=2) C_bad_argc(argc,2);\n");
  751. // Return the value of the variable
  752. if ((tm = Swig_typemap_lookup("varout", n, name, 0))) {
  753. Replaceall(tm, "$source", source);
  754. Replaceall(tm, "$varname", source);
  755. Replaceall(tm, "$target", "resultobj");
  756. Replaceall(tm, "$result", "resultobj");
  757. /* Printf(f->code, "%s\n", tm); */
  758. emit_action_code(n, f->code, tm);
  759. } else {
  760. Swig_warning(WARN_TYPEMAP_VAROUT_UNDEF, input_file, line_number, "Unable to read variable of type %s\n", SwigType_str(t, 0));
  761. }
  762. Printv(f->code, "{\n",
  763. "C_word func;\n",
  764. "SWIG_Chicken_FindCreateProxy(func, resultobj)\n",
  765. "if (C_swig_is_closurep(func))\n",
  766. " ((C_proc4)(void *)C_block_item(func, 0))(4,func,continuation,resultobj,C_SCHEME_FALSE);\n",
  767. "else\n", " C_kontinue(continuation, resultobj);\n", "}\n", NIL);
  768. /* Error handling code */
  769. #ifdef USE_FAIL
  770. Printf(f->code, "fail:\n");
  771. Printf(f->code, "swig_panic (\"failure in " "'%s' SWIG wrapper\");\n", proc_name);
  772. #endif
  773. Printf(f->code, "}\n");
  774. Wrapper_print(f, f_wrappers);
  775. /* Now register the variable with the interpreter. */
  776. addMethod(scmname, wname);
  777. if (!in_class || member_name) {
  778. String *clos_name;
  779. if (in_class)
  780. clos_name = NewString(member_name);
  781. else
  782. clos_name = chickenNameMapping(scmname, (char *) "");
  783. if (GetFlag(n, "feature:constasvar")) {
  784. Printv(clos_methods, "(define ", clos_name, " (", chickenPrimitiveName(scmname), "))\n", NIL);
  785. Printv(scm_const_defs, "(set! ", scmname, " (", scmname, "))\n", NIL);
  786. } else {
  787. Printv(clos_methods, "(define ", clos_name, " ", chickenPrimitiveName(scmname), ")\n", NIL);
  788. }
  789. Delete(clos_name);
  790. }
  791. } else {
  792. Swig_warning(WARN_TYPEMAP_VAR_UNDEF, input_file, line_number, "Unsupported variable type %s (ignored).\n", SwigType_str(t, 0));
  793. }
  794. Delete(wname);
  795. Delete(nctype);
  796. Delete(proc_name);
  797. Delete(argnum);
  798. Delete(arg);
  799. Delete(tm2);
  800. Delete(mangle);
  801. Delete(source);
  802. Delete(rvalue);
  803. DelWrapper(f);
  804. return SWIG_OK;
  805. }
  806. int CHICKEN::classHandler(Node *n) {
  807. /* Create new strings for building up a wrapper function */
  808. have_constructor = 0;
  809. constructor_dispatch = 0;
  810. constructor_name = 0;
  811. c_class_name = NewString(Getattr(n, "sym:name"));
  812. class_name = NewString("");
  813. short_class_name = NewString("");
  814. Printv(class_name, "<", c_class_name, ">", NIL);
  815. Printv(short_class_name, c_class_name, NIL);
  816. Replaceall(class_name, "_", "-");
  817. Replaceall(short_class_name, "_", "-");
  818. if (!addSymbol(class_name, n))
  819. return SWIG_ERROR;
  820. /* Handle inheritance */
  821. String *base_class = NewString("");
  822. List *baselist = Getattr(n, "bases");
  823. if (baselist && Len(baselist)) {
  824. Iterator base = First(baselist);
  825. while (base.item) {
  826. if (!Getattr(base.item, "feature:ignore"))
  827. Printv(base_class, "<", Getattr(base.item, "sym:name"), "> ", NIL);
  828. base = Next(base);
  829. }
  830. }
  831. Replaceall(base_class, "_", "-");
  832. String *scmmod = NewString(module);
  833. Replaceall(scmmod, "_", "-");
  834. Printv(clos_class_defines, "(define ", class_name, "\n", " (make <swig-metaclass-", scmmod, "> 'name \"", short_class_name, "\"\n", NIL);
  835. Delete(scmmod);
  836. if (Len(base_class)) {
  837. Printv(clos_class_defines, " 'direct-supers (list ", base_class, ")\n", NIL);
  838. } else {
  839. Printv(clos_class_defines, " 'direct-supers (list <object>)\n", NIL);
  840. }
  841. Printf(clos_class_defines, " 'direct-slots (list 'swig-this\n");
  842. String *mangled_classname = Swig_name_mangle(Getattr(n, "sym:name"));
  843. SwigType *ct = NewStringf("p.%s", Getattr(n, "name"));
  844. swigtype_ptr = SwigType_manglestr(ct);
  845. Printf(f_runtime, "static swig_chicken_clientdata _swig_chicken_clientdata%s = { 0 };\n", mangled_classname);
  846. Printv(f_init, "SWIG_TypeClientData(SWIGTYPE", swigtype_ptr, ", (void *) &_swig_chicken_clientdata", mangled_classname, ");\n", NIL);
  847. SwigType_remember(ct);
  848. /* Emit all of the members */
  849. in_class = 1;
  850. Language::classHandler(n);
  851. in_class = 0;
  852. Printf(clos_class_defines, ")))\n\n");
  853. if (have_constructor) {
  854. Printv(clos_methods, "(define-method (initialize (obj ", class_name, ") initargs)\n", " (swig-initialize obj initargs ", NIL);
  855. if (constructor_arg_types) {
  856. String *initfunc_name = NewStringf("%s@@SWIG@initmethod", class_name);
  857. String *func_call = buildClosFunctionCall(constructor_arg_types, initfunc_name, chickenPrimitiveName(constructor_name));
  858. Printf(clos_methods, "%s)\n)\n", initfunc_name);
  859. Printf(clos_methods, "(declare (hide %s))\n", initfunc_name);
  860. Printf(clos_methods, "%s\n", func_call);
  861. Delete(func_call);
  862. Delete(initfunc_name);
  863. Delete(constructor_arg_types);
  864. constructor_arg_types = 0;
  865. } else if (constructor_dispatch) {
  866. Printf(clos_methods, "%s)\n)\n", constructor_dispatch);
  867. Delete(constructor_dispatch);
  868. constructor_dispatch = 0;
  869. } else {
  870. Printf(clos_methods, "%s)\n)\n", chickenPrimitiveName(constructor_name));
  871. }
  872. Delete(constructor_name);
  873. constructor_name = 0;
  874. } else {
  875. Printv(clos_methods, "(define-method (initialize (obj ", class_name, ") initargs)\n", " (swig-initialize obj initargs (lambda x #f)))\n", NIL);
  876. }
  877. /* export class initialization function */
  878. if (clos) {
  879. String *funcname = NewString(mangled_classname);
  880. Printf(funcname, "_swig_chicken_setclosclass");
  881. String *closfuncname = NewString(funcname);
  882. Replaceall(closfuncname, "_", "-");
  883. Printv(f_wrappers, "static void ", funcname, "(C_word,C_word,C_word,C_word) C_noret;\n",
  884. "static void ", funcname, "(C_word argc, C_word closure, C_word continuation, C_word cl) {\n",
  885. " C_trace(\"", funcname, "\");\n",
  886. " if (argc!=3) C_bad_argc(argc,3);\n",
  887. " swig_chicken_clientdata *cdata = (swig_chicken_clientdata *) SWIGTYPE", swigtype_ptr, "->clientdata;\n",
  888. " cdata->gc_proxy_create = CHICKEN_new_gc_root();\n",
  889. " CHICKEN_gc_root_set(cdata->gc_proxy_create, cl);\n", " C_kontinue(continuation, C_SCHEME_UNDEFINED);\n", "}\n", NIL);
  890. addMethod(closfuncname, funcname);
  891. Printv(clos_methods, "(", chickenPrimitiveName(closfuncname), " (lambda (x lst) (if lst ",
  892. "(cons (make ", class_name, " 'swig-this x) lst) ", "(make ", class_name, " 'swig-this x))))\n\n", NIL);
  893. Delete(closfuncname);
  894. Delete(funcname);
  895. }
  896. Delete(mangled_classname);
  897. Delete(swigtype_ptr);
  898. swigtype_ptr = 0;
  899. Delete(class_name);
  900. Delete(short_class_name);
  901. Delete(c_class_name);
  902. class_name = 0;
  903. short_class_name = 0;
  904. c_class_name = 0;
  905. return SWIG_OK;
  906. }
  907. int CHICKEN::memberfunctionHandler(Node *n) {
  908. String *iname = Getattr(n, "sym:name");
  909. String *proc = NewString(iname);
  910. Replaceall(proc, "_", "-");
  911. member_name = chickenNameMapping(proc, short_class_name);
  912. Language::memberfunctionHandler(n);
  913. Delete(member_name);
  914. member_name = NULL;
  915. Delete(proc);
  916. return SWIG_OK;
  917. }
  918. int CHICKEN::staticmemberfunctionHandler(Node *n) {
  919. String *iname = Getattr(n, "sym:name");
  920. String *proc = NewString(iname);
  921. Replaceall(proc, "_", "-");
  922. member_name = NewStringf("%s-%s", short_class_name, proc);
  923. Language::staticmemberfunctionHandler(n);
  924. Delete(member_name);
  925. member_name = NULL;
  926. Delete(proc);
  927. return SWIG_OK;
  928. }
  929. int CHICKEN::membervariableHandler(Node *n) {
  930. String *iname = Getattr(n, "sym:name");
  931. //String *pb = SwigType_typedef_resolve_all(SwigType_base(Getattr(n, "type")));
  932. Language::membervariableHandler(n);
  933. String *proc = NewString(iname);
  934. Replaceall(proc, "_", "-");
  935. //Node *class_node = Swig_symbol_clookup(pb, Getattr(n, "sym:symtab"));
  936. Node *class_node = classLookup(Getattr(n, "type"));
  937. //String *getfunc = NewStringf("%s-%s-get", short_class_name, proc);
  938. //String *setfunc = NewStringf("%s-%s-set", short_class_name, proc);
  939. String *getfunc = Swig_name_get(NSPACE_TODO, Swig_name_member(NSPACE_TODO, c_class_name, iname));
  940. Replaceall(getfunc, "_", "-");
  941. String *setfunc = Swig_name_set(NSPACE_TODO, Swig_name_member(NSPACE_TODO, c_class_name, iname));
  942. Replaceall(setfunc, "_", "-");
  943. Printv(clos_class_defines, " (list '", proc, " ':swig-virtual ':swig-get ", chickenPrimitiveName(getfunc), NIL);
  944. if (!GetFlag(n, "feature:immutable")) {
  945. if (class_node) {
  946. Printv(clos_class_defines, " ':swig-set (lambda (x y) (", chickenPrimitiveName(setfunc), " x (slot-ref y 'swig-this))))\n", NIL);
  947. } else {
  948. Printv(clos_class_defines, " ':swig-set ", chickenPrimitiveName(setfunc), ")\n", NIL);
  949. }
  950. } else {
  951. Printf(clos_class_defines, ")\n");
  952. }
  953. Delete(proc);
  954. Delete(setfunc);
  955. Delete(getfunc);
  956. return SWIG_OK;
  957. }
  958. int CHICKEN::staticmembervariableHandler(Node *n) {
  959. String *iname = Getattr(n, "sym:name");
  960. String *proc = NewString(iname);
  961. Replaceall(proc, "_", "-");
  962. member_name = NewStringf("%s-%s", short_class_name, proc);
  963. Language::staticmembervariableHandler(n);
  964. Delete(member_name);
  965. member_name = NULL;
  966. Delete(proc);
  967. return SWIG_OK;
  968. }
  969. int CHICKEN::constructorHandler(Node *n) {
  970. have_constructor = 1;
  971. has_constructor_args = 0;
  972. exporting_constructor = true;
  973. Language::constructorHandler(n);
  974. exporting_constructor = false;
  975. has_constructor_args = 1;
  976. String *iname = Getattr(n, "sym:name");
  977. constructor_name = Swig_name_construct(NSPACE_TODO, iname);
  978. Replaceall(constructor_name, "_", "-");
  979. return SWIG_OK;
  980. }
  981. int CHICKEN::destructorHandler(Node *n) {
  982. if (no_collection)
  983. member_name = NewStringf("delete-%s", short_class_name);
  984. exporting_destructor = true;
  985. Language::destructorHandler(n);
  986. exporting_destructor = false;
  987. if (no_collection) {
  988. Delete(member_name);
  989. member_name = NULL;
  990. }
  991. return SWIG_OK;
  992. }
  993. int CHICKEN::importDirective(Node *n) {
  994. String *modname = Getattr(n, "module");
  995. if (modname && clos_uses) {
  996. // Find the module node for this imported module. It should be the
  997. // first child but search just in case.
  998. Node *mod = firstChild(n);
  999. while (mod && Strcmp(nodeType(mod), "module") != 0)
  1000. mod = nextSibling(mod);
  1001. if (mod) {
  1002. String *name = Getattr(mod, "name");
  1003. if (name) {
  1004. Printf(closprefix, "(declare (uses %s))\n", name);
  1005. }
  1006. }
  1007. }
  1008. return Language::importDirective(n);
  1009. }
  1010. String *CHICKEN::buildClosFunctionCall(List *types, const_String_or_char_ptr closname, const_String_or_char_ptr funcname) {
  1011. String *method_signature = NewString("");
  1012. String *func_args = NewString("");
  1013. String *func_call = NewString("");
  1014. Iterator arg_type;
  1015. int arg_count = 0;
  1016. int optional_arguments = 0;
  1017. for (arg_type = First(types); arg_type.item; arg_type = Next(arg_type)) {
  1018. if (Strcmp(arg_type.item, "^^##optional$$") == 0) {
  1019. optional_arguments = 1;
  1020. } else {
  1021. Printf(method_signature, " (arg%i %s)", arg_count, arg_type.item);
  1022. arg_type = Next(arg_type);
  1023. if (!arg_type.item)
  1024. break;
  1025. String *arg = NewStringf("arg%i", arg_count);
  1026. String *access_arg = Copy(arg_type.item);
  1027. Replaceall(access_arg, "$input", arg);
  1028. Printf(func_args, " %s", access_arg);
  1029. Delete(arg);
  1030. Delete(access_arg);
  1031. }
  1032. arg_count++;
  1033. }
  1034. if (optional_arguments) {
  1035. Printf(func_call, "(define-method (%s %s . args) (apply %s %s args))", closname, method_signature, funcname, func_args);
  1036. } else {
  1037. Printf(func_call, "(define-method (%s %s) (%s %s))", closname, method_signature, funcname, func_args);
  1038. }
  1039. Delete(method_signature);
  1040. Delete(func_args);
  1041. return func_call;
  1042. }
  1043. extern "C" {
  1044. /* compares based on non-primitive names */
  1045. static int compareTypeListsHelper(const DOH *a, const DOH *b, int opt_equal) {
  1046. List *la = (List *) a;
  1047. List *lb = (List *) b;
  1048. Iterator ia = First(la);
  1049. Iterator ib = First(lb);
  1050. while (ia.item && ib.item) {
  1051. int ret = Strcmp(ia.item, ib.item);
  1052. if (ret)
  1053. return ret;
  1054. ia = Next(Next(ia));
  1055. ib = Next(Next(ib));
  1056. } if (opt_equal && ia.item && Strcmp(ia.item, "^^##optional$$") == 0)
  1057. return 0;
  1058. if (ia.item)
  1059. return -1;
  1060. if (opt_equal && ib.item && Strcmp(ib.item, "^^##optional$$") == 0)
  1061. return 0;
  1062. if (ib.item)
  1063. return 1;
  1064. return 0;
  1065. }
  1066. static int compareTypeLists(const DOH *a, const DOH *b) {
  1067. return compareTypeListsHelper(a, b, 0);
  1068. }
  1069. }
  1070. void CHICKEN::dispatchFunction(Node *n) {
  1071. /* Last node in overloaded chain */
  1072. int maxargs;
  1073. String *tmp = NewString("");
  1074. String *dispatch = Swig_overload_dispatch(n, "%s (2+$numargs,closure," "continuation$commaargs);", &maxargs);
  1075. /* Generate a dispatch wrapper for all overloaded functions */
  1076. Wrapper *f = NewWrapper();
  1077. String *iname = Getattr(n, "sym:name");
  1078. String *wname = NewString("");
  1079. String *scmname = NewString(iname);
  1080. Replaceall(scmname, "_", "-");
  1081. Append(wname, Swig_name_wrapper(iname));
  1082. Printv(f->def, "static void real_", wname, "(C_word, C_word, C_word, C_word) C_noret;\n", NIL);
  1083. Printv(f->def, "static void real_", wname, "(C_word oldargc, C_word closure, C_word continuation, C_word args) {", NIL);
  1084. Wrapper_add_local(f, "argc", "int argc");
  1085. Printf(tmp, "C_word argv[%d]", maxargs + 1);
  1086. Wrapper_add_local(f, "argv", tmp);
  1087. Wrapper_add_local(f, "ii", "int ii");
  1088. Wrapper_add_local(f, "t", "C_word t = args");
  1089. Printf(f->code, "if (!C_swig_is_list (args)) {\n");
  1090. Printf(f->code, " swig_barf (SWIG_BARF1_BAD_ARGUMENT_TYPE, " "\"Argument #1 must be a list of overloaded arguments\");\n");
  1091. Printf(f->code, "}\n");
  1092. Printf(f->code, "argc = C_unfix (C_i_length (args));\n");
  1093. Printf(f->code, "for (ii = 0; (ii < argc) && (ii < %d); ii++, t = C_block_item (t, 1)) {\n", maxargs);
  1094. Printf(f->code, "argv[ii] = C_block_item (t, 0);\n");
  1095. Printf(f->code, "}\n");
  1096. Printv(f->code, dispatch, "\n", NIL);
  1097. Printf(f->code, "swig_barf (SWIG_BARF1_BAD_ARGUMENT_TYPE," "\"No matching function for overloaded '%s'\");\n", iname);
  1098. Printv(f->code, "}\n", NIL);
  1099. Wrapper_print(f, f_wrappers);
  1100. addMethod(scmname, wname);
  1101. DelWrapper(f);
  1102. f = NewWrapper();
  1103. /* varargs */
  1104. Printv(f->def, "void ", wname, "(C_word, C_word, C_word, ...) C_noret;\n", NIL);
  1105. Printv(f->def, "void ", wname, "(C_word c, C_word t0, C_word t1, ...) {", NIL);
  1106. Printv(f->code,
  1107. "C_word t2;\n",
  1108. "va_list v;\n",
  1109. "C_word *a, c2 = c;\n",
  1110. "C_save_rest (t1, c2, 2);\n", "a = C_alloc((c-2)*3);\n", "t2 = C_restore_rest (a, C_rest_count (0));\n", "real_", wname, " (3, t0, t1, t2);\n", NIL);
  1111. Printv(f->code, "}\n", NIL);
  1112. Wrapper_print(f, f_wrappers);
  1113. /* Now deal with overloaded function when exporting clos */
  1114. if (clos) {
  1115. List *flist = Getattr(overload_parameter_lists, scmname);
  1116. if (flist) {
  1117. Delattr(overload_parameter_lists, scmname);
  1118. SortList(flist, compareTypeLists);
  1119. String *clos_name;
  1120. if (have_constructor && !has_constructor_args) {
  1121. has_constructor_args = 1;
  1122. constructor_dispatch = NewStringf("%s@SWIG@new@dispatch", short_class_name);
  1123. clos_name = Copy(constructor_dispatch);
  1124. Printf(clos_methods, "(declare (hide %s))\n", clos_name);
  1125. } else if (in_class)
  1126. clos_name = NewString(member_name);
  1127. else
  1128. clos_name = chickenNameMapping(scmname, (char *) "");
  1129. Iterator f;
  1130. List *prev = 0;
  1131. int all_primitive = 1;
  1132. /* first check for duplicates and an empty call */
  1133. String *newlist = NewList();
  1134. for (f = First(flist); f.item; f = Next(f)) {
  1135. /* check if cur is a duplicate of prev */
  1136. if (prev && compareTypeListsHelper(f.item, prev, 1) == 0) {
  1137. Delete(f.item);
  1138. } else {
  1139. Append(newlist, f.item);
  1140. prev = f.item;
  1141. Iterator j;
  1142. for (j = First(f.item); j.item; j = Next(j)) {
  1143. if (Strcmp(j.item, "^^##optional$$") != 0 && Strcmp(j.item, "<top>") != 0)
  1144. all_primitive = 0;
  1145. }
  1146. }
  1147. }
  1148. Delete(flist);
  1149. flist = newlist;
  1150. if (all_primitive) {
  1151. Printf(clos_methods, "(define %s %s)\n", clos_name, chickenPrimitiveName(scmname));
  1152. } else {
  1153. for (f = First(flist); f.item; f = Next(f)) {
  1154. /* now export clos code for argument */
  1155. String *func_call = buildClosFunctionCall(f.item, clos_name, chickenPrimitiveName(scmname));
  1156. Printf(clos_methods, "%s\n", func_call);
  1157. Delete(f.item);
  1158. Delete(func_call);
  1159. }
  1160. }
  1161. Delete(clos_name);
  1162. Delete(flist);
  1163. }
  1164. }
  1165. DelWrapper(f);
  1166. Delete(dispatch);
  1167. Delete(tmp);
  1168. Delete(wname);
  1169. }
  1170. int CHICKEN::isPointer(SwigType *t) {
  1171. return SwigType_ispointer(SwigType_typedef_resolve_all(t));
  1172. }
  1173. void CHICKEN::addMethod(String *scheme_name, String *function) {
  1174. String *sym = NewString("");
  1175. if (clos) {
  1176. Append(sym, "primitive:");
  1177. }
  1178. Append(sym, scheme_name);
  1179. /* add symbol to Chicken internal symbol table */
  1180. if (hide_primitive) {
  1181. Printv(f_init, "{\n",
  1182. " C_word *p0 = a;\n", " *(a++)=C_CLOSURE_TYPE|1;\n", " *(a++)=(C_word)", function, ";\n", " C_mutate(return_vec++, (C_word)p0);\n", "}\n", NIL);
  1183. } else {
  1184. Printf(f_sym_size, "+C_SIZEOF_INTERNED_SYMBOL(%d)", Len(sym));
  1185. Printf(f_init, "sym = C_intern (&a, %d, \"%s\");\n", Len(sym), sym);
  1186. Printv(f_init, "C_mutate ((C_word*)sym+1, (*a=C_CLOSURE_TYPE|1, a[1]=(C_word)", function, ", tmp=(C_word)a, a+=2, tmp));\n", NIL);
  1187. }
  1188. if (hide_primitive) {
  1189. Setattr(primitive_names, scheme_name, NewStringf("(vector-ref swig-init-return %i)", num_methods));
  1190. } else {
  1191. Setattr(primitive_names, scheme_name, Copy(sym));
  1192. }
  1193. num_methods++;
  1194. Delete(sym);
  1195. }
  1196. String *CHICKEN::chickenPrimitiveName(String *name) {
  1197. String *value = Getattr(primitive_names, name);
  1198. if (value)
  1199. return value;
  1200. else {
  1201. Swig_error(input_file, line_number, "Internal Error: attempting to reference non-existant primitive name %s\n", name);
  1202. return NewString("#f");
  1203. }
  1204. }
  1205. int CHICKEN::validIdentifier(String *s) {
  1206. char *c = Char(s);
  1207. /* Check whether we have an R5RS identifier. */
  1208. /* <identifier> --> <initial> <subsequent>* | <peculiar identifier> */
  1209. /* <initial> --> <letter> | <special initial> */
  1210. if (!(isalpha(*c) || (*c == '!') || (*c == '$') || (*c == '%')
  1211. || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':')
  1212. || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?')
  1213. || (*c == '^') || (*c == '_') || (*c == '~'))) {
  1214. /* <peculiar identifier> --> + | - | ... */
  1215. if ((strcmp(c, "+") == 0)
  1216. || strcmp(c, "-") == 0 || strcmp(c, "...") == 0)
  1217. return 1;
  1218. else
  1219. return 0;
  1220. }
  1221. /* <subsequent> --> <initial> | <digit> | <special subsequent> */
  1222. while (*c) {
  1223. if (!(isalnum(*c) || (*c == '!') || (*c == '$') || (*c == '%')
  1224. || (*c == '&') || (*c == '*') || (*c == '/') || (*c == ':')
  1225. || (*c == '<') || (*c == '=') || (*c == '>') || (*c == '?')
  1226. || (*c == '^') || (*c == '_') || (*c == '~') || (*c == '+')
  1227. || (*c == '-') || (*c == '.') || (*c == '@')))
  1228. return 0;
  1229. c++;
  1230. }
  1231. return 1;
  1232. }
  1233. /* ------------------------------------------------------------
  1234. * closNameMapping()
  1235. * Maps the identifier from C++ to the CLOS based on command
  1236. * line parameters and such.
  1237. * If class_name = "" that means the mapping is for a function or
  1238. * variable not attached to any class.
  1239. * ------------------------------------------------------------ */
  1240. String *CHICKEN::chickenNameMapping(String *name, const_String_or_char_ptr class_name) {
  1241. String *n = NewString("");
  1242. if (Strcmp(class_name, "") == 0) {
  1243. // not part of a class, so no class name to prefix
  1244. if (clossymnameprefix) {
  1245. Printf(n, "%s%s", clossymnameprefix, name);
  1246. } else {
  1247. Printf(n, "%s", name);
  1248. }
  1249. } else {
  1250. if (useclassprefix) {
  1251. Printf(n, "%s-%s", class_name, name);
  1252. } else {
  1253. if (clossymnameprefix) {
  1254. Printf(n, "%s%s", clossymnameprefix, name);
  1255. } else {
  1256. Printf(n, "%s", name);
  1257. }
  1258. }
  1259. }
  1260. return n;
  1261. }
  1262. String *CHICKEN::runtimeCode() {
  1263. String *s = Swig_include_sys("chickenrun.swg");
  1264. if (!s) {
  1265. Printf(stderr, "*** Unable to open 'chickenrun.swg'\n");
  1266. s = NewString("");
  1267. }
  1268. return s;
  1269. }
  1270. String *CHICKEN::defaultExternalRuntimeFilename() {
  1271. return NewString("swigchickenrun.h");
  1272. }