/tags/rel-1-3-24/SWIG/Source/Modules/ocaml.cxx

# · C++ · 1946 lines · 1291 code · 261 blank · 394 comment · 210 complexity · 3ae55c323c8d351a5911e17ba25ee0ed MD5 · raw file

Large files are truncated click here to view the full file

  1. /******************************************************************************
  2. * Simplified Wrapper and Interface Generator (SWIG)
  3. *
  4. * Author : Art Yerkes
  5. * Modified from mzscheme.cxx : David Beazley
  6. *
  7. * Please read the file LICENSE for the copyright and terms by which SWIG
  8. * can be used and distributed.
  9. *****************************************************************************/
  10. char cvsroot_ocaml_cxx[] = "$Header$";
  11. /***********************************************************************
  12. * $Header$
  13. *
  14. * ocaml.cxx
  15. *
  16. * Definitions for adding functions to Ocaml 101
  17. ***********************************************************************/
  18. #include "swigmod.h"
  19. #include <ctype.h>
  20. static const char *usage = (char*)
  21. ("Ocaml Options (available with -ocaml)\n"
  22. "-prefix <name> - Set a prefix <name> to be prepended to all names\n"
  23. "-where - Emit library location\n"
  24. "-suffix <name> - Change .cxx to something else\n"
  25. "\n");
  26. static int classmode = 0;
  27. static int in_constructor = 0, in_destructor = 0, in_copyconst = 0;
  28. static int const_enum = 0;
  29. static int static_member_function = 0;
  30. static int generate_sizeof = 0;
  31. static char *prefix=0;
  32. static char *ocaml_path=(char*)"ocaml";
  33. static String *classname=0;
  34. static String *module=0;
  35. static String *init_func_def = 0;
  36. static String *f_classtemplate = 0;
  37. static String *name_qualifier = 0;
  38. static Hash *seen_enums = 0;
  39. static Hash *seen_enumvalues = 0;
  40. static Hash *seen_constructors = 0;
  41. static File *f_header = 0;
  42. static File *f_runtime = 0;
  43. static File *f_wrappers = 0;
  44. static File *f_directors = 0;
  45. static File *f_directors_h = 0;
  46. static File *f_init = 0;
  47. static File *f_mlout = 0;
  48. static File *f_mliout = 0;
  49. static File *f_mlbody = 0;
  50. static File *f_mlibody = 0;
  51. static File *f_mltail = 0;
  52. static File *f_mlitail = 0;
  53. static File *f_enumtypes_type = 0;
  54. static File *f_enumtypes_value = 0;
  55. static File *f_class_ctors = 0;
  56. static File *f_class_ctors_end = 0;
  57. static File *f_enum_to_int = 0;
  58. static File *f_int_to_enum = 0;
  59. class OCAML : public Language {
  60. public:
  61. OCAML()
  62. {
  63. director_prot_ctor_code = NewString("");
  64. Printv(director_prot_ctor_code,
  65. "if ( $comparison ) { /* subclassed */\n",
  66. " $director_new \n",
  67. "} else {\n",
  68. " failwith(\"accessing abstract class or protected constructor\"); \n",
  69. "}\n", NIL);
  70. director_multiple_inheritance = 1;
  71. director_language = 1;
  72. }
  73. String *Swig_class_name(Node *n) {
  74. String *name;
  75. name = Copy(Getattr(n, "sym:name"));
  76. return name;
  77. }
  78. void PrintIncludeArg() {
  79. Printv(stdout,SWIG_LIB,SWIG_FILE_DELIMETER,ocaml_path,
  80. "\n",NIL);
  81. }
  82. /* ------------------------------------------------------------
  83. * main()
  84. * ------------------------------------------------------------ */
  85. virtual void main (int argc, char *argv[]) {
  86. int i;
  87. prefix = 0;
  88. SWIG_library_directory(ocaml_path);
  89. // Look for certain command line options
  90. for (i = 1; i < argc; i++) {
  91. if (argv[i]) {
  92. if (strcmp (argv[i], "-help") == 0) {
  93. fputs (usage, stderr);
  94. SWIG_exit (0);
  95. } else if (strcmp (argv[i], "-where") == 0) {
  96. PrintIncludeArg();
  97. SWIG_exit (0);
  98. } else if (strcmp (argv[i], "-prefix") == 0) {
  99. if (argv[i + 1]) {
  100. prefix = new char[strlen(argv[i + 1]) + 2];
  101. strcpy(prefix, argv[i + 1]);
  102. Swig_mark_arg (i);
  103. Swig_mark_arg (i + 1);
  104. i++;
  105. } else {
  106. Swig_arg_error();
  107. }
  108. } else if (strcmp (argv[i], "-suffix") == 0) {
  109. if (argv[i + 1]) {
  110. SWIG_config_cppext( argv[i+1] );
  111. Swig_mark_arg (i);
  112. Swig_mark_arg (i+1);
  113. i++;
  114. } else
  115. Swig_arg_error();
  116. }
  117. }
  118. }
  119. // If a prefix has been specified make sure it ends in a '_'
  120. if (prefix) {
  121. if (prefix[strlen (prefix)] != '_') {
  122. prefix[strlen (prefix) + 1] = 0;
  123. prefix[strlen (prefix)] = '_';
  124. }
  125. } else
  126. prefix = (char*)"swig_";
  127. // Add a symbol for this module
  128. Preprocessor_define ("SWIGOCAML 1",0);
  129. // Set name of typemaps
  130. SWIG_typemap_lang("ocaml");
  131. // Read in default typemaps */
  132. SWIG_config_file("ocaml.i");
  133. allow_overloading();
  134. }
  135. /* Swig_director_declaration()
  136. *
  137. * Generate the full director class declaration, complete with base classes.
  138. * e.g. "class SwigDirector_myclass : public myclass, public Swig::Director {"
  139. *
  140. */
  141. String *Swig_director_declaration(Node *n) {
  142. String* classname = Swig_class_name(n);
  143. String *directorname = NewStringf("SwigDirector_%s", classname);
  144. String *base = Getattr(n, "classtype");
  145. String *declaration = Swig_class_declaration(n, directorname);
  146. Printf(declaration, " : public %s, public Swig::Director {\n", base);
  147. Delete(classname);
  148. Delete(directorname);
  149. return declaration;
  150. }
  151. /* ------------------------------------------------------------
  152. * top()
  153. *
  154. * Recognize the %module, and capture the module name.
  155. * Create the default enum cases.
  156. * Set up the named outputs:
  157. *
  158. * init
  159. * ml
  160. * mli
  161. * wrapper
  162. * header
  163. * runtime
  164. * directors
  165. * directors_h
  166. * ------------------------------------------------------------ */
  167. virtual int top(Node *n) {
  168. /* Set comparison with none for ConstructorToFunction */
  169. setSubclassInstanceCheck(NewString("caml_list_nth(args,0) != Val_unit"));
  170. /* check if directors are enabled for this module. note: this
  171. * is a "master" switch, without which no director code will be
  172. * emitted. %feature("director") statements are also required
  173. * to enable directors for individual classes or methods.
  174. *
  175. * use %module(directors="1") modulename at the start of the
  176. * interface file to enable director generation.
  177. */
  178. {
  179. Node *module = Getattr(n, "module");
  180. if (module) {
  181. Node *options = Getattr(module, "options");
  182. if (options) {
  183. if (Getattr(options, "directors")) {
  184. allow_directors();
  185. }
  186. if (Getattr(options, "dirprot")) {
  187. allow_dirprot();
  188. }
  189. if (Getattr(options, "sizeof")) {
  190. generate_sizeof = 1;
  191. }
  192. }
  193. }
  194. }
  195. /* Initialize all of the output files */
  196. String *outfile = Getattr(n,"outfile");
  197. f_runtime = NewFile(outfile,"w");
  198. if (!f_runtime) {
  199. Printf(stderr,"*** Can't open '%s'\n", outfile);
  200. SWIG_exit(EXIT_FAILURE);
  201. }
  202. f_init = NewString("");
  203. f_header = NewString("");
  204. f_wrappers = NewString("");
  205. f_directors = NewString("");
  206. f_directors_h = NewString("");
  207. f_enumtypes_type = NewString("");
  208. f_enumtypes_value = NewString("");
  209. init_func_def = NewString("");
  210. f_mlbody = NewString("");
  211. f_mlibody = NewString("");
  212. f_mltail = NewString("");
  213. f_mlitail = NewString("");
  214. f_class_ctors = NewString("");
  215. f_class_ctors_end = NewString("");
  216. f_enum_to_int = NewString("");
  217. f_int_to_enum = NewString("");
  218. f_classtemplate = NewString("");
  219. module = Getattr(n,"name");
  220. seen_constructors = NewHash();
  221. seen_enums = NewHash();
  222. seen_enumvalues = NewHash();
  223. /* Register file targets with the SWIG file handler */
  224. Swig_register_filebyname("init",init_func_def);
  225. Swig_register_filebyname("header",f_header);
  226. Swig_register_filebyname("wrapper",f_wrappers);
  227. Swig_register_filebyname("runtime",f_runtime);
  228. Swig_register_filebyname("mli",f_mlibody);
  229. Swig_register_filebyname("ml",f_mlbody);
  230. Swig_register_filebyname("mlitail",f_mlitail);
  231. Swig_register_filebyname("mltail",f_mltail);
  232. Swig_register_filebyname("director",f_directors);
  233. Swig_register_filebyname("director_h",f_directors_h);
  234. Swig_register_filebyname("classtemplate",f_classtemplate);
  235. Swig_register_filebyname("class_ctors",f_class_ctors);
  236. Swig_name_register("set","%v__set__");
  237. Swig_name_register("get","%v__get__");
  238. Printf( f_runtime,
  239. "/* -*- buffer-read-only: t -*- vi: set ro: */\n" );
  240. Printf( f_runtime, "#define SWIG_MODULE \"%s\"\n", module );
  241. /* Module name */
  242. Printf( f_mlbody, "let module_name = \"%s\"\n", module );
  243. Printf( f_mlibody, "val module_name : string\n" );
  244. Printf( f_enum_to_int,
  245. "let enum_to_int x (v : c_obj) =\n"
  246. " match v with\n"
  247. " C_enum _y ->\n"
  248. " (let y = _y in match (x : c_enum_type) with\n"
  249. " `unknown -> "
  250. " (match y with\n"
  251. " `Int x -> (Swig.C_int x)\n"
  252. " | _ -> raise (LabelNotFromThisEnum v))\n" );
  253. Printf( f_int_to_enum,
  254. "let int_to_enum x y =\n"
  255. " match (x : c_enum_type) with\n"
  256. " `unknown -> C_enum (`Int y)\n" );
  257. Swig_banner (f_runtime);
  258. if( directorsEnabled() ) {
  259. Printf( f_runtime, "#define SWIG_DIRECTORS\n");
  260. Swig_insert_file("director.swg", f_directors_h);
  261. }
  262. /* Produce the enum_to_int and int_to_enum functions */
  263. Printf(f_enumtypes_type,"open Swig\n"
  264. "type c_enum_type = [ \n `unknown\n" );
  265. Printf(f_enumtypes_value,"type c_enum_value = [ \n `Int of int\n" );
  266. String *mlfile = NewString("");
  267. String *mlifile = NewString("");
  268. Printv(mlfile,module,".ml",NIL);
  269. Printv(mlifile,module,".mli",NIL);
  270. String *mlfilen = NewStringf("%s%s", SWIG_output_directory(),mlfile);
  271. if ((f_mlout = NewFile(mlfilen,"w")) == 0) {
  272. Printf(stderr,"Unable to open %s\n", mlfilen);
  273. SWIG_exit (EXIT_FAILURE);
  274. }
  275. String *mlifilen = NewStringf("%s%s", SWIG_output_directory(),mlifile);
  276. if ((f_mliout = NewFile(mlifilen,"w")) == 0) {
  277. Printf(stderr,"Unable to open %s\n", mlifilen);
  278. SWIG_exit (EXIT_FAILURE);
  279. }
  280. Language::top(n);
  281. Printf( f_enum_to_int,
  282. ") | _ -> (C_int (get_int v))\n"
  283. "let _ = Callback.register \"%s_enum_to_int\" enum_to_int\n",
  284. module );
  285. Printf( f_mlibody,
  286. "val enum_to_int : c_enum_type -> c_obj -> Swig.c_obj\n" );
  287. Printf( f_int_to_enum,
  288. "let _ = Callback.register \"%s_int_to_enum\" int_to_enum\n",
  289. module );
  290. Printf( f_mlibody,
  291. "val int_to_enum : c_enum_type -> int -> c_obj\n" );
  292. Printf( f_init,
  293. "SWIGEXT void f_%s_init() {\n"
  294. "%s"
  295. "}\n",
  296. module, init_func_def );
  297. Printf( f_mlbody,
  298. "external f_init : unit -> unit = \"f_%s_init\" ;;\n"
  299. "let _ = f_init ()\n",
  300. module, module );
  301. Printf( f_enumtypes_type, "]\n" );
  302. Printf( f_enumtypes_value, "]\n\n"
  303. "type c_obj = c_enum_value c_obj_t\n" );
  304. SwigType_emit_type_table (f_runtime, f_wrappers);
  305. /* Close all of the files */
  306. Dump(f_directors_h,f_header);
  307. Dump(f_header,f_runtime);
  308. Dump(f_directors,f_wrappers);
  309. Dump(f_wrappers,f_runtime);
  310. Wrapper_pretty_print(f_init,f_runtime);
  311. Delete(f_header);
  312. Delete(f_wrappers);
  313. Delete(f_init);
  314. Close(f_runtime);
  315. Delete(f_runtime);
  316. Dump(f_enumtypes_type,f_mlout);
  317. Dump(f_enumtypes_value,f_mlout);
  318. Dump(f_mlbody,f_mlout);
  319. Dump(f_enum_to_int,f_mlout);
  320. Dump(f_int_to_enum,f_mlout);
  321. Delete(f_int_to_enum);
  322. Delete(f_enum_to_int);
  323. Dump(f_class_ctors,f_mlout);
  324. Dump(f_class_ctors_end,f_mlout);
  325. Dump(f_mltail,f_mlout);
  326. Close(f_mlout);
  327. Delete(f_mlout);
  328. Dump(f_enumtypes_type,f_mliout);
  329. Dump(f_enumtypes_value,f_mliout);
  330. Dump(f_mlibody,f_mliout);
  331. Dump(f_mlitail,f_mliout);
  332. Close(f_mliout);
  333. Delete(f_mliout);
  334. return SWIG_OK;
  335. }
  336. /* Produce an error for the given type */
  337. void throw_unhandled_ocaml_type_error (SwigType *d, const char *types) {
  338. Swig_warning(WARN_TYPEMAP_UNDEF, input_file, line_number,
  339. "Unable to handle type %s (%s).\n", SwigType_str(d,0),
  340. types );
  341. }
  342. /* Return true iff T is a pointer type */
  343. int
  344. is_a_pointer (SwigType *t) {
  345. return SwigType_ispointer(SwigType_typedef_resolve_all(t));
  346. }
  347. /*
  348. * Delete one reference from a given type.
  349. */
  350. void oc_SwigType_del_reference(SwigType *t) {
  351. char *c = Char(t);
  352. if (strncmp(c,"q(",2) == 0) {
  353. Delete(SwigType_pop(t));
  354. c = Char(t);
  355. }
  356. if (strncmp(c,"r.",2)) {
  357. printf("Fatal error. SwigType_del_pointer applied to non-pointer.\n");
  358. abort();
  359. }
  360. Replace(t,"r.","", DOH_REPLACE_ANY | DOH_REPLACE_FIRST);
  361. }
  362. void oc_SwigType_del_array(SwigType *t) {
  363. char *c = Char(t);
  364. if (strncmp(c,"q(",2) == 0) {
  365. Delete(SwigType_pop(t));
  366. c = Char(t);
  367. }
  368. if (strncmp(c,"a(",2) == 0) {
  369. Delete(SwigType_pop(t));
  370. }
  371. }
  372. /*
  373. * Return true iff T is a reference type
  374. */
  375. int
  376. is_a_reference (SwigType *t) {
  377. return SwigType_isreference(SwigType_typedef_resolve_all(t));
  378. }
  379. int
  380. is_an_array (SwigType *t) {
  381. return SwigType_isarray(SwigType_typedef_resolve_all(t));
  382. }
  383. /* ------------------------------------------------------------
  384. * functionWrapper()
  385. * Create a function declaration and register it with the interpreter.
  386. * ------------------------------------------------------------ */
  387. virtual int functionWrapper(Node *n) {
  388. char *iname = GetChar(n,"sym:name");
  389. SwigType *d = Getattr(n,"type");
  390. String *return_type_normalized = normalizeTemplatedClassName(d);
  391. ParmList *l = Getattr(n,"parms");
  392. Parm *p;
  393. Wrapper *f = NewWrapper();
  394. String *proc_name = NewString("");
  395. String *source = NewString("");
  396. String *target = NewString("");
  397. String *arg = NewString("");
  398. String *cleanup = NewString("");
  399. String *outarg = NewString("");
  400. String *build = NewString("");
  401. String *tm;
  402. int argout_set = 0;
  403. int i = 0;
  404. int numargs;
  405. int numreq;
  406. int newobj = Getattr(n,"feature:new") ? 1 : 0;
  407. String *nodeType = Getattr(n, "nodeType");
  408. int constructor = !Cmp(nodeType, "constructor");
  409. int destructor = (!Cmp(nodeType, "destructor"));
  410. String *storage = Getattr(n,"storage");
  411. int isVirtual = !Cmp(storage,"virtual");
  412. String *overname = 0;
  413. bool isOverloaded = Getattr(n,"sym:overloaded") ? true : false;
  414. // Make a wrapper name for this
  415. String *wname = Swig_name_wrapper(iname);
  416. if (isOverloaded) {
  417. overname = Getattr(n,"sym:overname");
  418. } else {
  419. if (!addSymbol(iname,n)) return SWIG_ERROR;
  420. }
  421. if (overname) {
  422. Append(wname, overname);
  423. }
  424. /* Do this to disambiguate functions emitted from different modules */
  425. Append(wname, module);
  426. Setattr(n,"wrap:name",wname);
  427. // Build the name for Scheme.
  428. Printv(proc_name,"_",iname,NIL);
  429. String *mangled_name = mangleNameForCaml(proc_name);
  430. if( classmode && in_constructor ) { // Emit constructor for object
  431. String *mangled_name_nounder =
  432. NewString((char *)(Char(mangled_name))+1);
  433. Printf( f_class_ctors_end,
  434. "let %s clst = _%s clst\n",
  435. mangled_name_nounder, mangled_name_nounder );
  436. Printf(f_mlibody,
  437. "val %s : c_obj -> c_obj\n",
  438. mangled_name_nounder );
  439. Delete(mangled_name_nounder);
  440. } else if( classmode && in_destructor ) {
  441. Printf(f_class_ctors,
  442. " \"~\", %s ;\n", mangled_name );
  443. } else if( classmode && !in_constructor && !in_destructor &&
  444. !static_member_function ) {
  445. String *opname = Copy(Getattr(n,"name"));
  446. Replaceall(opname,"operator ","");
  447. if( strstr( Char(mangled_name), "__get__" ) ) {
  448. String *set_name = Copy(mangled_name);
  449. if( !Getattr(n,"feature:immutable") ) {
  450. Replaceall(set_name,"__get__","__set__");
  451. Printf(f_class_ctors,
  452. " \"%s\", (fun args -> "
  453. "if args = (C_list [ raw_ptr ]) then %s args else %s args) ;\n",
  454. opname, mangled_name, set_name );
  455. Delete(set_name);
  456. } else {
  457. Printf(f_class_ctors,
  458. " \"%s\", (fun args -> "
  459. "if args = (C_list [ raw_ptr ]) then %s args else C_void) ;\n",
  460. opname, mangled_name );
  461. }
  462. } else if( strstr( Char(mangled_name), "__set__" ) ) {
  463. ; /* Nothing ... handled by the case above */
  464. } else {
  465. Printf(f_class_ctors,
  466. " \"%s\", %s ;\n",
  467. opname, mangled_name);
  468. }
  469. Delete(opname);
  470. }
  471. if( classmode && in_constructor ) {
  472. Setattr(seen_constructors,mangled_name,"true");
  473. }
  474. // writing the function wrapper function
  475. Printv(f->def,
  476. "SWIGEXT CAML_VALUE ", wname, " (", NIL);
  477. Printv(f->def, "CAML_VALUE args", NIL);
  478. Printv(f->def, ")\n{", NIL);
  479. /* Define the scheme name in C. This define is used by several
  480. macros. */
  481. //Printv(f->def, "#define FUNC_NAME \"", mangled_name, "\"", NIL);
  482. // adds local variables
  483. Wrapper_add_local(f, "args", "CAMLparam1(args)");
  484. Wrapper_add_local(f, "ret" , "SWIG_CAMLlocal2(swig_result,rv)");
  485. Wrapper_add_local(f, "_v" , "int _v = 0");
  486. if( isOverloaded ) {
  487. Wrapper_add_local(f, "i" , "int i");
  488. Wrapper_add_local(f, "argc", "int argc = caml_list_length(args)");
  489. Wrapper_add_local(f, "argv", "CAML_VALUE *argv");
  490. Printv( f->code,
  491. "argv = (CAML_VALUE *)malloc( argc * sizeof( CAML_VALUE ) );\n"
  492. "for( i = 0; i < argc; i++ ) {\n"
  493. " argv[i] = caml_list_nth(args,i);\n"
  494. "}\n", NIL );
  495. }
  496. // Declare return variable and arguments
  497. // number of parameters
  498. // they are called arg0, arg1, ...
  499. // the return value is called result
  500. d = SwigType_typedef_qualified(d);
  501. emit_args(d, l, f);
  502. /* Attach the standard typemaps */
  503. emit_attach_parmmaps(l,f);
  504. Setattr(n,"wrap:parms",l);
  505. numargs = emit_num_arguments(l);
  506. numreq = emit_num_required(l);
  507. Printf(f->code,"swig_result = Val_unit;\n" );
  508. // Now write code to extract the parameters (this is super ugly)
  509. for (i = 0, p = l; i < numargs; i++) {
  510. /* Skip ignored arguments */
  511. while (checkAttribute(p,"tmap:in:numinputs","0")) {
  512. p = Getattr(p,"tmap:in:next");
  513. }
  514. SwigType *pt = Getattr(p,"type");
  515. String *ln = Getattr(p,"lname");
  516. pt = SwigType_typedef_qualified(pt);
  517. // Produce names of source and target
  518. Clear(source);
  519. Clear(target);
  520. Clear(arg);
  521. Printf(source, "caml_list_nth(args,%d)", i);
  522. Printf(target, "%s",ln);
  523. Printv(arg, Getattr(p,"name"),NIL);
  524. if (i >= numreq) {
  525. Printf(f->code,"if (caml_list_length(args) > %d) {\n",i);
  526. }
  527. // Handle parameter types.
  528. if ((tm = Getattr(p,"tmap:in"))) {
  529. Replaceall(tm,"$source",source);
  530. Replaceall(tm,"$target",target);
  531. Replaceall(tm,"$input",source);
  532. Setattr(p,"emit:input",source);
  533. Printv(f->code, tm, "\n", NIL);
  534. p = Getattr(p,"tmap:in:next");
  535. } else {
  536. // no typemap found
  537. // check if typedef and resolve
  538. throw_unhandled_ocaml_type_error (pt,"in");
  539. p = nextSibling(p);
  540. }
  541. if (i >= numreq) {
  542. Printf(f->code,"}\n");
  543. }
  544. }
  545. /* Insert constraint checking code */
  546. for (p = l; p;) {
  547. if ((tm = Getattr(p,"tmap:check"))) {
  548. Replaceall(tm,"$target",Getattr(p,"lname"));
  549. Printv(f->code,tm,"\n",NIL);
  550. p = Getattr(p,"tmap:check:next");
  551. } else {
  552. p = nextSibling(p);
  553. }
  554. }
  555. // Pass output arguments back to the caller.
  556. for (p = l; p;) {
  557. if ((tm = Getattr(p,"tmap:argout"))) {
  558. Replaceall(tm,"$source",Getattr(p,"emit:input")); /* Deprecated */
  559. Replaceall(tm,"$target",Getattr(p,"lname")); /* Deprecated */
  560. Replaceall(tm,"$arg",Getattr(p,"emit:input"));
  561. Replaceall(tm,"$input",Getattr(p,"emit:input"));
  562. Replaceall(tm,"$ntype",
  563. normalizeTemplatedClassName(Getattr(p,"type")));
  564. Printv(outarg,tm,"\n",NIL);
  565. p = Getattr(p,"tmap:argout:next");
  566. argout_set = 1;
  567. } else {
  568. p = nextSibling(p);
  569. }
  570. }
  571. // Free up any memory allocated for the arguments.
  572. /* Insert cleanup code */
  573. for (p = l; p;) {
  574. if ((tm = Getattr(p,"tmap:freearg"))) {
  575. Replaceall(tm,"$target",Getattr(p,"lname"));
  576. Printv(cleanup,tm,"\n",NIL);
  577. p = Getattr(p,"tmap:freearg:next");
  578. } else {
  579. p = nextSibling(p);
  580. }
  581. }
  582. /* if the object is a director, and the method call originated from its
  583. * underlying python object, resolve the call by going up the c++
  584. * inheritance chain. otherwise try to resolve the method in python.
  585. * without this check an infinite loop is set up between the director and
  586. * shadow class method calls.
  587. */
  588. // NOTE: this code should only be inserted if this class is the
  589. // base class of a director class. however, in general we haven't
  590. // yet analyzed all classes derived from this one to see if they are
  591. // directors. furthermore, this class may be used as the base of
  592. // a director class defined in a completely different module at a
  593. // later time, so this test must be included whether or not directorbase
  594. // is true. we do skip this code if directors have not been enabled
  595. // at the command line to preserve source-level compatibility with
  596. // non-polymorphic swig. also, if this wrapper is for a smart-pointer
  597. // method, there is no need to perform the test since the calling object
  598. // (the smart-pointer) and the director object (the "pointee") are
  599. // distinct.
  600. if (directorsEnabled()) {
  601. if (!is_smart_pointer()) {
  602. if (/*directorbase &&*/ !constructor && !destructor
  603. && isVirtual && !Getattr(n,"feature:nodirector")) {
  604. Wrapper_add_local(f, "director", "Swig::Director *director = 0");
  605. Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
  606. Printf(f->code,
  607. "if (director && !director->swig_get_up(false))"
  608. "director->swig_set_up();\n");
  609. }
  610. }
  611. }
  612. // Now write code to make the function call
  613. emit_action(n,f);
  614. // Now have return value, figure out what to do with it.
  615. if ((tm = Swig_typemap_lookup_new("out",n,"result",0))) {
  616. Replaceall(tm,"$source","swig_result");
  617. Replaceall(tm,"$target","rv");
  618. Replaceall(tm,"$result","rv");
  619. Replaceall(tm,"$ntype",return_type_normalized);
  620. Printv(f->code, tm, "\n",NIL);
  621. } else {
  622. throw_unhandled_ocaml_type_error (d, "out");
  623. }
  624. // Dump the argument output code
  625. Printv(f->code, Char(outarg),NIL);
  626. // Dump the argument cleanup code
  627. Printv(f->code, Char(cleanup),NIL);
  628. // Look for any remaining cleanup
  629. if (Getattr(n,"feature:new")) {
  630. if ((tm = Swig_typemap_lookup_new("newfree",n,"result",0))) {
  631. Replaceall(tm,"$source","swig_result");
  632. Printv(f->code, tm, "\n",NIL);
  633. }
  634. }
  635. // Free any memory allocated by the function being wrapped..
  636. if ((tm = Swig_typemap_lookup_new("swig_result",n,"result",0))) {
  637. Replaceall(tm,"$source","result");
  638. Printv(f->code, tm, "\n",NIL);
  639. }
  640. // Wrap things up (in a manner of speaking)
  641. Printv(f->code,
  642. tab4, "swig_result = caml_list_append(swig_result,rv);\n", NIL);
  643. if( isOverloaded )
  644. Printv(f->code, "free(argv);\n", NIL);
  645. Printv(f->code,
  646. tab4, "CAMLreturn(swig_result);\n", NIL );
  647. Printv(f->code, "}\n",NIL);
  648. Wrapper_print(f, f_wrappers);
  649. if( isOverloaded ) {
  650. if( !Getattr(n,"sym:nextSibling") ) {
  651. int maxargs;
  652. Wrapper *df = NewWrapper();
  653. String *dispatch =
  654. Swig_overload_dispatch(n,
  655. "free(argv);\n"
  656. "CAMLreturn(%s(args));\n",
  657. &maxargs);
  658. Wrapper_add_local(df, "_v", "int _v = 0");
  659. Wrapper_add_local(df, "argv", "CAML_VALUE *argv");
  660. /* Undifferentiate name .. this is the dispatch function */
  661. wname = Swig_name_wrapper(iname);
  662. /* Do this to disambiguate functions emitted from different
  663. * modules */
  664. Append(wname, module);
  665. Printv(df->def,
  666. "SWIGEXT CAML_VALUE ",wname,"(CAML_VALUE args) {\n"
  667. " CAMLparam1(args);\n"
  668. " int i;\n"
  669. " int argc = caml_list_length(args);\n",NIL);
  670. Printv( df->code,
  671. "argv = (CAML_VALUE *)malloc( argc * sizeof( CAML_VALUE ) );\n"
  672. "for( i = 0; i < argc; i++ ) {\n"
  673. " argv[i] = caml_list_nth(args,i);\n"
  674. "}\n", NIL );
  675. Printv(df->code,dispatch,"\n",NIL);
  676. Printf(df->code,"failwith(\"No matching function for overloaded '%s'\");\n", iname);
  677. Printv(df->code,"}\n",NIL);
  678. Wrapper_print(df,f_wrappers);
  679. DelWrapper(df);
  680. Delete(dispatch);
  681. }
  682. }
  683. Printf(f_mlbody,
  684. "external %s_f : c_obj list -> c_obj list = \"%s\" ;;\n"
  685. "let %s arg = match %s_f (fnhelper arg) with\n"
  686. " [] -> C_void\n"
  687. "| [x] -> (if %s then Gc.finalise \n"
  688. " (fun x -> ignore ((invoke x) \"~\" C_void)) x) ; x\n"
  689. "| lst -> C_list lst ;;\n",
  690. mangled_name, wname,
  691. mangled_name, mangled_name, newobj ? "true" : "false");
  692. if( !classmode || in_constructor || in_destructor ||
  693. static_member_function )
  694. Printf(f_mlibody,
  695. "val %s : c_obj -> c_obj\n", mangled_name );
  696. Delete(proc_name);
  697. Delete(source);
  698. Delete(target);
  699. Delete(arg);
  700. Delete(outarg);
  701. Delete(cleanup);
  702. Delete(build);
  703. DelWrapper(f);
  704. return SWIG_OK;
  705. }
  706. /* ------------------------------------------------------------
  707. * variableWrapper()
  708. *
  709. * Create a link to a C variable.
  710. * This creates a single function _wrap_swig_var_varname().
  711. * This function takes a single optional argument. If supplied, it means
  712. * we are setting this variable to some value. If omitted, it means we are
  713. * simply evaluating this variable. In the set case we return C_void.
  714. *
  715. * symname is the name of the variable with respect to C. This
  716. * may need to differ from the original name in the case of enums.
  717. * enumvname is the name of the variable with respect to ocaml. This
  718. * will vary if the variable has been renamed.
  719. * ------------------------------------------------------------ */
  720. virtual int variableWrapper(Node *n) {
  721. char *name = GetChar(n,"feature:symname");
  722. String *iname = Getattr(n,"feature:enumvname");
  723. String *mname = mangleNameForCaml(iname);
  724. SwigType *t = Getattr(n,"type");
  725. String *proc_name = NewString("");
  726. char var_name[256];
  727. String *tm;
  728. String *tm2 = NewString("");;
  729. String *argnum = NewString("0");
  730. String *arg = NewString("SWIG_Field(args,0)");
  731. Wrapper *f;
  732. if( !name ) {
  733. name = GetChar(n,"name");
  734. }
  735. if( !iname ) {
  736. iname = Getattr(n,"sym:name");
  737. mname = mangleNameForCaml(NewString(iname));
  738. }
  739. if (!iname || !addSymbol(iname,n)) return SWIG_ERROR;
  740. f = NewWrapper();
  741. // evaluation function names
  742. strcpy(var_name, Char(Swig_name_wrapper(iname)));
  743. // Build the name for scheme.
  744. Printv(proc_name, iname, NIL);
  745. Printf (f->def,
  746. "SWIGEXT CAML_VALUE %s(CAML_VALUE args) {\n", var_name);
  747. // Printv(f->def, "#define FUNC_NAME \"", proc_name, "\"", NIL);
  748. Wrapper_add_local (f, "swig_result", "CAML_VALUE swig_result");
  749. if (!Getattr(n,"feature:immutable")) {
  750. /* Check for a setting of the variable value */
  751. Printf (f->code, "if (args != Val_int(0)) {\n");
  752. if ((tm = Swig_typemap_lookup_new("varin",n,name,0))) {
  753. Replaceall(tm,"$source","args");
  754. Replaceall(tm,"$target",name);
  755. Replaceall(tm,"$input","args");
  756. Printv(f->code, tm, "\n",NIL);
  757. } else if ((tm = Swig_typemap_lookup_new("in",n,name,0))) {
  758. Replaceall(tm,"$source","args");
  759. Replaceall(tm,"$target",name);
  760. Replaceall(tm,"$input","args");
  761. Printv(f->code, tm, "\n",NIL);
  762. } else {
  763. throw_unhandled_ocaml_type_error (t, "varin/in");
  764. }
  765. Printf (f->code, "}\n");
  766. }
  767. // Now return the value of the variable (regardless
  768. // of evaluating or setting)
  769. if ((tm = Swig_typemap_lookup_new("varout",n,name,0))) {
  770. Replaceall(tm,"$source",name);
  771. Replaceall(tm,"$target","swig_result");
  772. Replaceall(tm,"$result","swig_result");
  773. Printf (f->code, "%s\n", tm);
  774. } else if ((tm = Swig_typemap_lookup_new("out",n,name,0))) {
  775. Replaceall(tm,"$source",name);
  776. Replaceall(tm,"$target","swig_result");
  777. Replaceall(tm,"$result","swig_result");
  778. Printf (f->code, "%s\n", tm);
  779. } else {
  780. throw_unhandled_ocaml_type_error (t, "varout/out");
  781. }
  782. Printf (f->code, "\nreturn swig_result;\n");
  783. Printf (f->code, "}\n");
  784. Wrapper_print (f, f_wrappers);
  785. // Now add symbol to the Ocaml interpreter
  786. if( Getattr( n, "feature:immutable" ) ) {
  787. Printf( f_mlbody,
  788. "external _%s : c_obj -> Swig.c_obj = \"%s\" \n",
  789. mname, var_name );
  790. Printf( f_mlibody, "val _%s : c_obj -> Swig.c_obj\n", iname );
  791. if( const_enum ) {
  792. Printf( f_enum_to_int,
  793. " | `%s -> _%s C_void\n",
  794. mname, mname );
  795. Printf( f_int_to_enum,
  796. " if y = (get_int (_%s C_void)) then `%s else\n",
  797. mname, mname );
  798. }
  799. } else {
  800. Printf( f_mlbody, "external _%s : c_obj -> c_obj = \"%s\"\n",
  801. mname, var_name );
  802. Printf( f_mlibody, "external _%s : c_obj -> c_obj = \"%s\"\n",
  803. mname, var_name );
  804. }
  805. Delete(proc_name);
  806. Delete(argnum);
  807. Delete(arg);
  808. Delete(tm2);
  809. DelWrapper(f);
  810. return SWIG_OK;
  811. }
  812. /* ------------------------------------------------------------
  813. * staticmemberfunctionHandler --
  814. * Overridden to set static_member_function
  815. * ------------------------------------------------------------ */
  816. virtual int staticmemberfunctionHandler( Node *n ) {
  817. int rv;
  818. static_member_function = 1;
  819. rv = Language::staticmemberfunctionHandler( n );
  820. static_member_function = 0;
  821. return SWIG_OK;
  822. }
  823. /* ------------------------------------------------------------
  824. * constantWrapper()
  825. *
  826. * The one trick here is that we have to make sure we rename the
  827. * constant to something useful that doesn't collide with the
  828. * original if any exists.
  829. * ------------------------------------------------------------ */
  830. virtual int constantWrapper(Node *n) {
  831. String *name = Getattr(n,"feature:symname");
  832. SwigType *type = Getattr(n,"type");
  833. String *value = Getattr(n,"value");
  834. String *qvalue = Getattr(n,"qualified:value");
  835. String *rvalue = NewString("");
  836. String *temp = 0;
  837. if( qvalue ) value = qvalue;
  838. if( !name ) {
  839. name = mangleNameForCaml(Getattr(n,"name"));
  840. Insert(name,0,"_swig_wrap_");
  841. Setattr(n,"feature:symname",name);
  842. }
  843. // See if there's a typemap
  844. Printv(rvalue, value,NIL);
  845. if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 1)) {
  846. temp = Copy(rvalue);
  847. Clear(rvalue);
  848. Printv(rvalue, "\"", temp, "\"",NIL);
  849. Delete(temp);
  850. }
  851. if ((SwigType_type(type) == T_CHAR) && (is_a_pointer(type) == 0)) {
  852. temp = Copy(rvalue);
  853. Clear(rvalue);
  854. Printv(rvalue, "'", temp, "'",NIL);
  855. Delete(temp);
  856. }
  857. // Create variable and assign it a value
  858. Printf (f_header, "static %s = ", SwigType_lstr(type,name));
  859. if ((SwigType_type(type) == T_STRING)) {
  860. Printf (f_header, "\"%s\";\n", value);
  861. } else if (SwigType_type(type) == T_CHAR) {
  862. Printf (f_header, "\'%s\';\n", value);
  863. } else {
  864. Printf (f_header, "%s;\n", value);
  865. }
  866. Setattr(n,"feature:immutable","1");
  867. variableWrapper(n);
  868. return SWIG_OK;
  869. }
  870. int constructorHandler(Node *n) {
  871. int ret;
  872. in_constructor = 1;
  873. ret = Language::constructorHandler(n);
  874. in_constructor = 0;
  875. return ret;
  876. }
  877. /* destructorHandler:
  878. * Turn on destructor flag to inform decisions in functionWrapper
  879. */
  880. int destructorHandler(Node *n) {
  881. int ret;
  882. in_destructor = 1;
  883. ret = Language::destructorHandler(n);
  884. in_destructor = 0;
  885. return ret;
  886. }
  887. /* copyconstructorHandler:
  888. * Turn on constructor and copyconstructor flags for functionWrapper
  889. */
  890. int copyconstructorHandler(Node *n) {
  891. int ret;
  892. in_copyconst = 1;
  893. in_constructor = 1;
  894. ret = Language::copyconstructorHandler(n);
  895. in_constructor = 0;
  896. in_copyconst = 0;
  897. return ret;
  898. }
  899. /**
  900. * A simple, somewhat general purpose function for writing to multiple
  901. * streams from a source template. This allows the user to define the
  902. * class definition in ways different from the one I have here if they
  903. * want to. It will also make the class definition system easier to
  904. * fiddle with when I want to change methods, etc.
  905. */
  906. void Multiwrite( String *s ) {
  907. char *find_marker = strstr(Char(s),"(*Stream:");
  908. while( find_marker ) {
  909. char *next = strstr(find_marker,"*)");
  910. find_marker += strlen("(*Stream:");
  911. if( next ) {
  912. int num_chars = next - find_marker;
  913. String *stream_name = NewString(find_marker);
  914. Delslice(stream_name,num_chars,Len(stream_name));
  915. File *fout = Swig_filebyname(stream_name);
  916. if( fout ) {
  917. next += strlen("*)");
  918. char *following = strstr(next,"(*Stream:");
  919. find_marker = following;
  920. if( !following ) following = next + strlen(next);
  921. String *chunk = NewString(next);
  922. Delslice(chunk,following-next,Len(chunk));
  923. Printv(fout,chunk,NIL);
  924. }
  925. }
  926. }
  927. }
  928. bool isSimpleType( String *name ) {
  929. char *ch = Char(name);
  930. return
  931. !(strchr(ch,'(') || strchr(ch,'<') ||
  932. strchr(ch,')') || strchr(ch,'>'));
  933. }
  934. /* We accept all chars in identifiers because we use strings to index
  935. * them. */
  936. int validIdentifier( String *name ) {
  937. return Len(name) > 0 ? 1 : 0;
  938. }
  939. /* classHandler
  940. *
  941. * Create a "class" definition for ocaml. I thought quite a bit about
  942. * how I should do this part of it, and arrived here, using a function
  943. * invocation to select a method, and dispatch. This can obviously be
  944. * done better, but I can't see how, given that I want to support
  945. * overloaded methods, out parameters, and operators.
  946. *
  947. * I needed a system that would do this:
  948. *
  949. * a Be able to call these methods:
  950. * int foo( int x );
  951. * float foo( int x, int &out );
  952. *
  953. * b Be typeable, even in the presence of mutually dependent classes.
  954. *
  955. * c Support some form of operator invocation.
  956. *
  957. * (c) I chose strings for the method names so that "+=" would be a
  958. * valid method name, and the somewhat natural << (invoke x) "+=" y >>
  959. * would work.
  960. *
  961. * (a) (b) Since the c_obj type exists, it's easy to return C_int in one
  962. * case and C_list [ C_float ; C_int ] in the other. This makes tricky
  963. * problems with out parameters disappear; they're simply appended to the
  964. * return list.
  965. *
  966. * (b) Since every item that comes from C++ is the same type, there is no
  967. * problem with the following:
  968. *
  969. * class Foo;
  970. * class Bar { Foo *toFoo(); }
  971. * class Foo { Bar *toBar(); }
  972. *
  973. * Since the Objective caml types of Foo and Bar are the same. Now that
  974. * I correctly incorporate SWIG's typechecking, this isn't a big deal.
  975. *
  976. * The class is in the form of a function returning a c_obj. The c_obj
  977. * is a C_obj containing a function which invokes a method on the
  978. * underlying object given its type.
  979. *
  980. * The name emitted here is normalized before being sent to
  981. * Callback.register, because we need this string to look up properly
  982. * when the typemap passes the descriptor string. I've been considering
  983. * some, possibly more forgiving method that would do some transformations
  984. * on the $descriptor in order to find a potential match. This is for
  985. * later.
  986. *
  987. * Important things to note:
  988. *
  989. * We rely on exception handling (BadMethodName) in order to call an
  990. * ancestor. This can be improved.
  991. *
  992. * The method used to get :classof could be improved to look at the type
  993. * info that the base pointer contains. It's really an error to have a
  994. * SWIG-generated object that does not contain type info, since the
  995. * existence of the object means that SWIG knows the type.
  996. *
  997. * :parents could use :classof to tell what class it is and make a better
  998. * decision. This could be nice, (i.e. provide a run-time graph of C++
  999. * classes represented);.
  1000. *
  1001. * I can't think of a more elegant way of converting a C_obj fun to a
  1002. * pointer than "operator &"...
  1003. *
  1004. * Added a 'sizeof' that will allow you to do the expected thing.
  1005. * This should help users to fill buffer structs and the like (as is
  1006. * typical in windows-styled code). It's only enabled if you give
  1007. * %feature(sizeof) and then, only for simple types.
  1008. *
  1009. * Overall, carrying the list of methods and base classes has worked well.
  1010. * It allows me to give the Ocaml user introspection over their objects.
  1011. */
  1012. int classHandler( Node *n ) {
  1013. String *name = Getattr(n,"name");
  1014. String *mangled_sym_name = mangleNameForCaml(name);
  1015. String *this_class_def = NewString( f_classtemplate );
  1016. String *name_normalized = normalizeTemplatedClassName(name);
  1017. String *old_class_ctors = f_class_ctors;
  1018. String *base_classes = NewString("");
  1019. f_class_ctors = NewString("");
  1020. bool sizeof_feature = generate_sizeof && isSimpleType(name);
  1021. if( !name ) return SWIG_OK;
  1022. classname = mangled_sym_name;
  1023. classmode = true;
  1024. int rv = Language::classHandler(n);
  1025. classmode = false;
  1026. if( sizeof_feature ) {
  1027. Printf( f_wrappers,
  1028. "SWIGEXT CAML_VALUE _wrap_%s_sizeof( CAML_VALUE args ) {\n"
  1029. " CAMLparam1(args);\n"
  1030. " CAMLreturn(Val_int(sizeof(%s)));\n"
  1031. "}\n",
  1032. mangled_sym_name, name_normalized );
  1033. Printf( f_mlbody, "external __%s_sizeof : unit -> int = "
  1034. "\"_wrap_%s_sizeof\"\n",
  1035. classname, mangled_sym_name );
  1036. }
  1037. /* Insert sizeof operator for concrete classes */
  1038. if( sizeof_feature ) {
  1039. Printv(f_class_ctors, "\"sizeof\" , (fun args -> C_int (__",
  1040. classname, "_sizeof ())) ;\n", NIL);
  1041. }
  1042. /* Handle up-casts in a nice way */
  1043. List *baselist = Getattr(n,"bases");
  1044. if (baselist && Len(baselist)) {
  1045. Iterator b;
  1046. b = First(baselist);
  1047. while (b.item) {
  1048. String *bname = Getattr(b.item, "name");
  1049. if (bname) {
  1050. String *base_create = NewString("");
  1051. Printv(base_create,"(create_class \"",bname,"\")",NIL);
  1052. Printv(f_class_ctors,
  1053. " \"::",bname,"\", (fun args -> ",
  1054. base_create," args) ;\n",NIL);
  1055. Printv( base_classes, base_create, " ;\n", NIL );
  1056. }
  1057. b = Next(b);
  1058. }
  1059. }
  1060. Replaceall(this_class_def,"$classname",classname);
  1061. Replaceall(this_class_def,"$normalized",name_normalized);
  1062. Replaceall(this_class_def,"$realname",name);
  1063. Replaceall(this_class_def,"$baselist",base_classes);
  1064. Replaceall(this_class_def,"$classbody",f_class_ctors);
  1065. Delete(f_class_ctors);
  1066. f_class_ctors = old_class_ctors;
  1067. // Actually write out the class definition
  1068. Multiwrite( this_class_def );
  1069. Setattr(n,"ocaml:ctor",classname);
  1070. return rv;
  1071. }
  1072. String *normalizeTemplatedClassName( String *name ) {
  1073. String *name_normalized = SwigType_typedef_resolve_all(name);
  1074. bool took_action;
  1075. do {
  1076. took_action = false;
  1077. if( is_a_pointer(name_normalized) ) {
  1078. SwigType_del_pointer( name_normalized );
  1079. took_action = true;
  1080. }
  1081. if( is_a_reference(name_normalized) ) {
  1082. oc_SwigType_del_reference( name_normalized );
  1083. took_action = true;
  1084. }
  1085. if( is_an_array(name_normalized) ) {
  1086. oc_SwigType_del_array( name_normalized );
  1087. took_action = true;
  1088. }
  1089. } while( took_action );
  1090. return SwigType_str(name_normalized,0);
  1091. }
  1092. /*
  1093. * Produce the symbol name that ocaml will use when referring to the
  1094. * target item. I wonder if there's a better way to do this:
  1095. *
  1096. * I shudder to think about doing it with a hash lookup, but that would
  1097. * make a couple of things easier:
  1098. */
  1099. String *mangleNameForCaml( String *s ) {
  1100. String *out = Copy(s);
  1101. Replaceall(out," ","_xx");
  1102. Replaceall(out,"::","_xx");
  1103. Replaceall(out,",","_x");
  1104. Replaceall(out,"+","_xx_plus");
  1105. Replaceall(out,"-","_xx_minus");
  1106. Replaceall(out,"<","_xx_ldbrace");
  1107. Replaceall(out,">","_xx_rdbrace");
  1108. Replaceall(out,"!","_xx_not");
  1109. Replaceall(out,"%","_xx_mod");
  1110. Replaceall(out,"^","_xx_xor");
  1111. Replaceall(out,"*","_xx_star");
  1112. Replaceall(out,"&","_xx_amp");
  1113. Replaceall(out,"|","_xx_or");
  1114. Replaceall(out,"(","_xx_lparen");
  1115. Replaceall(out,")","_xx_rparen");
  1116. Replaceall(out,"[","_xx_lbrace");
  1117. Replaceall(out,"]","_xx_rbrace");
  1118. Replaceall(out,"~","_xx_bnot");
  1119. Replaceall(out,"=","_xx_equals");
  1120. Replaceall(out,"/","_xx_slash");
  1121. Replaceall(out,".","_xx_dot");
  1122. return out;
  1123. }
  1124. String *fully_qualify_enum_name( Node *n, String *name ) {
  1125. Node *parent = 0;
  1126. String *qualification = NewString("");
  1127. String *fully_qualified_name = NewString("");
  1128. String *parent_type = 0;
  1129. String *normalized_name;
  1130. parent = parentNode(n);
  1131. while( parent ) {
  1132. parent_type = nodeType(parent);
  1133. if( Getattr(parent,"name") ) {
  1134. String *parent_copy =
  1135. NewStringf("%s::",Getattr(parent,"name"));
  1136. if( !Cmp(parent_type,"class") ||
  1137. !Cmp(parent_type,"namespace") )
  1138. Insert(qualification,0,parent_copy);
  1139. Delete(parent_copy);
  1140. }
  1141. if( !Cmp( parent_type, "class" ) ) break;
  1142. parent = parentNode(parent);
  1143. }
  1144. Printf( fully_qualified_name, "%s%s", qualification, name );
  1145. normalized_name = normalizeTemplatedClassName(fully_qualified_name);
  1146. if( !strncmp(Char(normalized_name),"enum ",5) ) {
  1147. Insert(normalized_name,5,qualification);
  1148. }
  1149. return normalized_name;
  1150. }
  1151. /* Benedikt Grundmann inspired --> Enum wrap styles */
  1152. int enumvalueDeclaration(Node *n) {
  1153. String *name = Getattr(n,"name");
  1154. String *qvalue = 0;
  1155. if( name_qualifier ) {
  1156. qvalue = Copy(name_qualifier);
  1157. Printv( qvalue, name, NIL );
  1158. }
  1159. if( const_enum && name && !Getattr(seen_enumvalues,name) ) {
  1160. Setattr(seen_enumvalues,name,"true");
  1161. Setattr(n,"feature:immutable","1");
  1162. Setattr(n,"feature:enumvalue","1");
  1163. if( qvalue )
  1164. Setattr(n,"qualified:value",qvalue);
  1165. String *evname = SwigType_manglestr(qvalue);
  1166. Insert( evname, 0, "SWIG_ENUM_" );
  1167. Setattr(n,"feature:enumvname",name);
  1168. Setattr(n,"feature:symname",evname);
  1169. Delete( evname );
  1170. Printf( f_enumtypes_value, "| `%s\n", name );
  1171. return Language::enumvalueDeclaration(n);
  1172. } else return SWIG_OK;
  1173. }
  1174. /* -------------------------------------------------------------------
  1175. * This function is a bit uglier than it deserves.
  1176. *
  1177. * I used to direct lookup the name of the enum. Now that certain fixes
  1178. * have been made in other places, the names of enums are now fully
  1179. * qualified, which is a good thing, overall, but requires me to do
  1180. * some legwork.
  1181. *
  1182. * The other thing that uglifies this function is the varying way that
  1183. * typedef enum and enum are handled. I need to produce consistent names,
  1184. * which means looking up and registering by typedef and enum name. */
  1185. int enumDeclaration(Node *n) {
  1186. String *name = Getattr(n,"name");
  1187. String *oname = name ? NewString(name) : NULL;
  1188. /* name is now fully qualified */
  1189. String *fully_qualified_name = NewString(name);
  1190. bool seen_enum = false;
  1191. if( name_qualifier )
  1192. Delete(name_qualifier);
  1193. char *strip_position;
  1194. name_qualifier = fully_qualify_enum_name(n,NewString(""));
  1195. /* Recent changes have distrubed enum and template naming again.
  1196. * Will try to keep it consistent by can't guarantee much given
  1197. * that these things move around a lot.
  1198. *
  1199. * I need to figure out a way to isolate this module better.
  1200. */
  1201. if( oname ) {
  1202. strip_position = strstr(Char(oname),"::");
  1203. while( strip_position ) {
  1204. strip_position += 2;
  1205. oname = NewString( strip_position );
  1206. strip_position = strstr( Char(oname), "::" );
  1207. }
  1208. }
  1209. seen_enum = oname ?
  1210. (Getattr(seen_enums,fully_qualified_name) ? true : false) : false;
  1211. if( oname && !seen_enum ) {
  1212. const_enum = true;
  1213. Printf( f_enum_to_int, "| `%s -> (match y with\n", oname );
  1214. Printf( f_int_to_enum, "| `%s -> C_enum (\n", oname );
  1215. /* * * * A note about enum name resolution * * * *
  1216. * This code should now work, but I think we can do a bit better.
  1217. * The problem I'm having is that swig isn't very precise about
  1218. * typedef name resolution. My opinion is that SwigType_typedef
  1219. * resolve_all should *always* return the enum tag if one exists,
  1220. * rather than the admittedly friendlier enclosing typedef.
  1221. *
  1222. * This would make one of the cases below unnecessary.
  1223. * * * */
  1224. Printf( f_mlbody,
  1225. "let _ = Callback.register \"%s_marker\" (`%s)\n",
  1226. fully_qualified_name, oname );
  1227. if( !strncmp(Char(fully_qualified_name),"enum ",5) ) {
  1228. String *fq_noenum = NewString(Char(fully_qualified_name) + 5);
  1229. Printf( f_mlbody,
  1230. "let _ = Callback.register \"%s_marker\" (`%s)\n"
  1231. "let _ = Callback.register \"%s_marker\" (`%s)\n",
  1232. fq_noenum, oname,
  1233. fq_noenum, name );
  1234. }
  1235. Printf( f_enumtypes_type,"| `%s\n", oname );
  1236. Insert(fully_qualified_name,0,"enum ");
  1237. Setattr(seen_enums,fully_qualified_name,n);
  1238. }
  1239. int ret = Language::enumDeclaration(n);
  1240. if( const_enum ) {
  1241. Printf( f_int_to_enum, "`Int y)\n" );
  1242. Printf( f_enum_to_int,
  1243. "| `Int x -> Swig.C_int x\n"
  1244. "| _ -> raise (LabelNotFromThisEnum v))\n" );
  1245. }
  1246. const_enum = false;
  1247. return ret;
  1248. }
  1249. /***************************************************************************
  1250. * BEGIN C++ Director Class modifications
  1251. ***************************************************************************/
  1252. /*
  1253. * Modified polymorphism code for Ocaml language module.
  1254. * Original:
  1255. * C++/Python polymorphism demo code, copyright (C) 2002 Mark Rose
  1256. * <mrose@stm.lbl.gov>
  1257. *
  1258. * TODO
  1259. *
  1260. * Move some boilerplate code generation to Swig_...() functions.
  1261. *
  1262. */
  1263. /* ---------------------------------------------------------------
  1264. * classDirectorMethod()
  1265. *
  1266. * Emit a virtual director method to pass a method call on to the
  1267. * underlying Python object.
  1268. *
  1269. * --------------------------------------------------------------- */
  1270. int classDirectorMethod(Node *n, Node *parent, String *super) {
  1271. int is_void = 0;
  1272. int is_pointer = 0;
  1273. String *storage;
  1274. String *value;
  1275. String *decl;
  1276. String *type;
  1277. String *name;
  1278. String *classname;
  1279. String *declaration;
  1280. ParmList *l;
  1281. Wrapper *w;
  1282. String *tm;
  1283. String *wrap_args;
  1284. String *return_type;
  1285. int status = SWIG_OK;
  1286. int idx;
  1287. bool pure_virtual = false;
  1288. storage = Getattr(n, "storage");
  1289. value = Getattr(n, "value");
  1290. classname = Getattr(parent, "sym:name");
  1291. type = Getattr(n, "type");
  1292. name = Getattr(n, "name");
  1293. if (Cmp(storage,"virtual") == 0) {
  1294. if (Cmp(value,"0") == 0) {
  1295. pure_virtual = true;
  1296. }
  1297. }
  1298. w = NewWrapper();
  1299. declaration = NewString("");
  1300. Wrapper_add_local(w,"swig_result",
  1301. "CAMLparam0();\n"
  1302. "SWIG_CAMLlocal2(swig_result,args)");
  1303. /* determine if the method returns a pointer */
  1304. decl = Getattr(n, "decl");
  1305. is_pointer = SwigType_ispointer_return(decl);
  1306. is_void = (!Cmp(type, "void") && !is_pointer);
  1307. /* form complete return type */
  1308. return_type = Copy(type);
  1309. {
  1310. SwigType *t = Copy(decl);
  1311. SwigType *f = 0;
  1312. f = SwigType_pop_function(t);
  1313. SwigType_push(return_type, t);
  1314. Delete(f);
  1315. Delete(t);
  1316. }
  1317. /* virtual method definition */
  1318. l = Getattr(n, "parms");
  1319. String *target;
  1320. String *pclassname = NewStringf("SwigDirector_%s", classname);
  1321. String *qualified_name = NewStringf("%s::%s", pclassname, name);
  1322. target = Swig_method_decl(decl, qualified_name, l, 0, 0);
  1323. String *rtype = SwigType_str(type, 0);
  1324. Printf(w->def, "%s %s {", rtype, target);
  1325. Delete(qualified_name);
  1326. Delete(target);
  1327. /* header declaration */
  1328. target = Swig_method_decl(decl, name, l, 0, 1);
  1329. Printf(declaration, " virtual %s %s;\n", rtype, target);
  1330. Delete(target);
  1331. /* attach typemaps to arguments (C/C++ -> Ocaml) */
  1332. String *arglist = NewString("");
  1333. Swig_typemap_attach_parms("in", l, w);
  1334. Swig_typemap_attach_parms("directorin", l, w);
  1335. Swig_typemap_attach_parms("directorout", l, w);
  1336. Swig_typemap_attach_parms("directorargout", l, w);
  1337. Parm* p;
  1338. int num_arguments = emit_num_arguments(l);
  1339. int i;
  1340. char source[256];
  1341. wrap_args = NewString("");
  1342. int outputs = 0;
  1343. if (!is_void) outputs++;
  1344. /* build argument list and type conversion string */
  1345. for (i=0, idx=0, p = l; i < num_arguments; i++) {
  1346. while (Getattr(p, "tmap:ignore")) {
  1347. p = Getattr(p, "tmap:ignore:next");
  1348. }
  1349. if (Getattr(p, "tmap:directorargout") != 0) outputs++;
  1350. String* pname = Getattr(p, "name");
  1351. String* ptype = Getattr(p, "type");
  1352. Putc(',',arglist);
  1353. if ((tm = Getattr(p, "tmap:directorin")) != 0) {
  1354. Replaceall(tm, "$input", pname);
  1355. Replaceall(tm, "$owner", "0");
  1356. if (Len(tm) == 0) Append(tm, pname);
  1357. Printv(wrap_args, tm, "\n", NIL);
  1358. p = Getattr(p, "tmap:directorin:next");
  1359. continue;
  1360. } else
  1361. if (Cmp(ptype, "void")) {
  1362. /* special handling for pointers to other C++ director classes.
  1363. * ideally this would be left to a typemap, but there is currently no
  1364. * way to selectively apply the dynamic_cast<> to classes that have
  1365. * directors. in other words, the type "SwigDirector_$1_lname" only exists
  1366. * for classes with directors. we avoid the problem here by checking
  1367. * module.wrap::directormap, but it's not clear how to get a typemap to
  1368. * do something similar. perhaps a new default typemap (in addition
  1369. * to SWIGTYPE) called DIRECTORTYPE?
  1370. */
  1371. if (SwigType_ispointer(ptype) || SwigType_isreference(ptype)) {
  1372. Node *module = Getattr(parent, "module");
  1373. Node *target = Swig_directormap(module, ptype);
  1374. sprintf(source, "obj%d", idx++);
  1375. String *nonconst = 0;
  1376. /* strip pointer/reference --- should move to Swig/stype.c */
  1377. String *nptype = NewString(Char(ptype)+2);
  1378. /* name as pointer */
  1379. String *ppname = Copy(pname);
  1380. if (SwigType_isreference(ptype)) {
  1381. Insert(ppname,0,"&");
  1382. }
  1383. /* if necessary, cast away const since Python doesn't support it! */
  1384. if (SwigType_isconst(nptype)) {
  1385. nonconst = NewStringf("nc_tmp_%s", pname);
  1386. String *nonconst_i = NewStringf("= const_cast<%s>(%s)", SwigType_lstr(ptype, 0), ppname);
  1387. Wrapper_add_localv(w, nonconst, SwigType_lstr(ptype, 0), nonconst, nonconst_i, NIL);
  1388. Delete(nonconst_i);
  1389. Swig_warning(WARN_LANG_DISCARD_CONST, input_file, line_number,
  1390. "Target language argument '%s' discards const in director method %s::%s.\n", SwigType_str(ptype, pname), classname, name);
  1391. } else {
  1392. nonconst = Copy(ppname);
  1393. }
  1394. Delete(nptype);
  1395. Delete(ppname);
  1396. String *mangle = SwigType_manglestr(ptype);
  1397. if (target) {
  1398. String *director = NewStringf("director_%s", mangle);
  1399. Wrapper_add_localv(w, director, "Swig::Director *", director, "= 0", NIL);
  1400. Wrapper_add_localv(w, source, "CAML_VALUE", source, "= Val_unit", NIL);
  1401. Printf(wrap_args, "%s = dynamic_cast<Swig::Director *>(%s);\n", director, nonconst);