PageRenderTime 56ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/trunk/Source/Modules/modula3.cxx

#
C++ | 1989 lines | 1329 code | 217 blank | 443 comment | 410 complexity | 77bcef6f2edb8e97a88f2d4725146fc0 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0

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

  1. /* -----------------------------------------------------------------------------
  2. * 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. * modula3.cxx
  10. *
  11. * Modula3 language module for SWIG.
  12. * ----------------------------------------------------------------------------- */
  13. char cvsroot_modula3_cxx[] = "$Id: modula3.cxx 12830 2011-10-30 21:51:50Z wsfulton $";
  14. /*
  15. Text formatted with
  16. indent -sob -br -ce -nut -npsl
  17. */
  18. /*
  19. Report:
  20. - It's not a good concept to use member variables or global variables
  21. for passing parameters to functions.
  22. It's not a good concept to use functions of superclasses for specific services.
  23. E.g. For SWIG this means: Generating accessor functions for member variables
  24. is the most common but no general task to be processed in membervariableHandler.
  25. Better provide a service function which generates accessor function code
  26. and equip this service function with all parameters needed for input (parse node)
  27. and output (generated code).
  28. - How can I make globalvariableHandler not to generate
  29. interface functions to two accessor functions
  30. (that don't exist) ?
  31. - How can I generate a typemap that turns every C reference argument into
  32. its Modula 3 counterpart, that is
  33. void test(Complex &z);
  34. PROCEDURE test(VAR z:Complex);
  35. - neither $*n_mangle nor $*n_type nor $*n_ltype return the type without
  36. pointer converted to Modula3 equivalent,
  37. $*n_mangle is the variant closest to what I expect
  38. - using a typemap like
  39. typemap(m3wrapintype) int * %{VAR $1_name: INTEGER%}
  40. has the advantages:
  41. - one C parameter can be turned into multiple M3 parameters
  42. - the argument can be renamed
  43. - using typemaps like
  44. typemap(m3wrapinmode) int * "VAR"
  45. typemap(m3wrapintype) int * "INTEGER"
  46. has the advantages:
  47. - multiple parameters with same type and default value can be bundled
  48. - more conform to the other language modules
  49. - Where takes the reduction of multi-typemaps place?
  50. How can I preserve all parameters for functions of the intermediary class?
  51. The answer is Getattrs(n,"tmap:m3rawintype:next")
  52. - Char() can be used to transform a String to (char *)
  53. which can be used for output with printf
  54. - What is the while (checkAttribute()) loop in functionWrapper good for?
  55. Appearently for skipping (numinputs=0) typemaps.
  56. - SWIGTYPE const * - typemap is ignored, whereas
  57. SWIGTYPE * - typemap is invoked, why?
  58. Had it been (const SWIGTYPE *) instead?
  59. - enumeration items should definitely be equipped
  60. with its plain numerical value
  61. One could add tag 'numvalue' in CParse/parser.y,
  62. but it is still possible that someone declares an
  63. enumeration using a symbolic constant.
  64. I have quickly hacked
  65. that the successive number is assigned
  66. if "enumvalue" has suffix "+1".
  67. The ultimate solution would be to generate a C program
  68. which includes the header and outputs all constants.
  69. This program might be compiled and run
  70. by 'make' or by SWIG and the resulting output is fed back to SWIG.
  71. - It's a bad idea to interpret feature value ""
  72. 'disable feature' because the value ""
  73. might be sensible in case of feature:modula3:oldprefix.
  74. - What's the difference between "sym:name" and "name" ?
  75. "name" is the original name and
  76. "sym:name" is probably modified by the user using %rename
  77. - Is it possible for 'configure' to find out if m3pp is installed
  78. and to invoke it for generated Modula3 files?
  79. - It would be better to separate an arguments purpose and its name,
  80. because an output variable with name "OUTPUT" is not very descriptive.
  81. In case of PLPlot this could be solved by typedefs
  82. that assign special purposes to the array types.
  83. - Can one interpret $n_basetype as the identifier matched with SWIGTYPE ?
  84. SWIG's odds:
  85. - arguments of type (Node *) for SWIG functions
  86. should be most often better (const Node *):
  87. Swig_symbol_qualified, Getattr, nodeType, parentNode
  88. - unique identifier style instead of
  89. NewString, Getattr, firstChild
  90. - 'class'.name is qualified,
  91. 'enum'.name and 'enumitem'.name is not
  92. - Swig_symbol_qualified() returns NIL for enumeration nodes
  93. - Is there a function that creates a C representation of a SWIG type string?
  94. ToDo:
  95. - create WeakRefs only for resources returned by function marked with %newobject
  96. -> part of output conversion
  97. - clean typemap conception
  98. - should a multi-typemap for m3wrapouttype skip the corresponding input parameters?
  99. when yes - How to handle inout-arguments? In this case like in-argument.
  100. - C++ classes
  101. - C++ exceptions
  102. - allow for moving RECORD and OBJECT definitions
  103. to separate files, with the main type called T
  104. - call-back functions
  105. - special option: fast access to class members by pointer arithmetic,
  106. member offsets can be determined by a C++ program that print them.
  107. - emit enumeration definitions when its first item is declared,
  108. currently enumerations are emitted at the beginning of the file
  109. Done:
  110. - addThrow should convert the typemap by itself
  111. - not possible because routine for attaching mapped types to parameter nodes
  112. won't work for the function node
  113. - turning error codes into exceptions
  114. -> part of output value checking
  115. - create WeakRefs for resources allocated by the library
  116. -> part of output conversion
  117. - TRY..FINALLY..END; can be omitted
  118. - if there is no m3wrapfreearg
  119. - no exception can be raised in the body (empty RAISES) list
  120. */
  121. #include "swigmod.h"
  122. #include <limits.h> // for INT_MAX
  123. #include <ctype.h>
  124. #define USAGE_ARG_DIR "m3wrapargdir typemap expect values: in, out, inout\n"
  125. class MODULA3:public Language {
  126. public:
  127. enum block_type { no_block, constant, variable, blocktype, revelation };
  128. private:
  129. struct M3File {
  130. String *f;
  131. Hash *import;
  132. block_type bt;
  133. /* VC++ 6 doesn't allow the access to 'no_block'
  134. if it is a private member of MODULA3 class */
  135. M3File():f(NewString("")), import(NewHash()), bt(no_block) {
  136. }
  137. ~M3File() {
  138. Delete(f);
  139. Delete(import);
  140. }
  141. /* -----------------------------------------------------------------------------
  142. * enterBlock()
  143. *
  144. * Make sure that a given declaration is written to the right declaration block,
  145. * that is constants are written after "CONST" and so on ...
  146. * ----------------------------------------------------------------------------- */
  147. void enterBlock(block_type newbt) {
  148. static const char *ident[] = { "", "\nCONST\n", "\nVAR\n", "\nTYPE\n", "\nREVEAL\n" };
  149. #ifdef DEBUG
  150. if ((bt < 0) || (4 < bt)) {
  151. printf("bt %d out of range\n", bt);
  152. }
  153. #endif
  154. if (newbt != bt) {
  155. Append(f, ident[newbt]);
  156. bt = newbt;
  157. }
  158. }
  159. };
  160. static const char *usage;
  161. const String *empty_string;
  162. Hash *swig_types_hash;
  163. File *f_begin;
  164. File *f_runtime;
  165. File *f_header;
  166. File *f_wrappers;
  167. File *f_init;
  168. bool proxy_flag; // Flag for generating proxy classes
  169. bool have_default_constructor_flag;
  170. bool native_function_flag; // Flag for when wrapping a native function
  171. bool enum_constant_flag; // Flag for when wrapping an enum or constant
  172. bool static_flag; // Flag for when wrapping a static functions or member variables
  173. bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
  174. bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
  175. bool global_variable_flag; // Flag for when wrapping a global variable
  176. bool old_variable_names; // Flag for old style variable names in the intermediary class
  177. bool unsafe_module;
  178. String *m3raw_name; // raw interface name
  179. M3File m3raw_intf; // raw interface
  180. M3File m3raw_impl; // raw implementation (usually empty)
  181. String *m3wrap_name; // wrapper module
  182. M3File m3wrap_intf;
  183. M3File m3wrap_impl;
  184. String *m3makefile;
  185. String *targetlibrary;
  186. String *proxy_class_def;
  187. String *proxy_class_code;
  188. String *proxy_class_name;
  189. String *variable_name; //Name of a variable being wrapped
  190. String *variable_type; //Type of this variable
  191. String *enumeration_name; //Name of the current enumeration type
  192. Hash *enumeration_items; //and its members
  193. int enumeration_max;
  194. Hash *enumeration_coll; //Collection of all enumerations.
  195. /* The items are nodes with members:
  196. "items" - hash of with key 'itemname' and content 'itemvalue'
  197. "max" - maximum value in item list
  198. */
  199. String *constant_values;
  200. String *constantfilename;
  201. String *renamefilename;
  202. String *typemapfilename;
  203. String *m3raw_imports; //intermediary class imports from %pragma
  204. String *module_imports; //module imports from %pragma
  205. String *m3raw_baseclass; //inheritance for intermediary class class from %pragma
  206. String *module_baseclass; //inheritance for module class from %pragma
  207. String *m3raw_interfaces; //interfaces for intermediary class class from %pragma
  208. String *module_interfaces; //interfaces for module class from %pragma
  209. String *m3raw_class_modifiers; //class modifiers for intermediary class overriden by %pragma
  210. String *m3wrap_modifiers; //class modifiers for module class overriden by %pragma
  211. String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
  212. String *m3raw_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
  213. String *destructor_call; //C++ destructor call if any
  214. String *outfile;
  215. enum type_additions { none, pointer, reference };
  216. public:
  217. /* -----------------------------------------------------------------------------
  218. * MODULA3()
  219. * ----------------------------------------------------------------------------- */
  220. MODULA3():
  221. empty_string(NewString("")),
  222. swig_types_hash(NULL),
  223. f_begin(NULL),
  224. f_runtime(NULL),
  225. f_header(NULL),
  226. f_wrappers(NULL),
  227. f_init(NULL),
  228. proxy_flag(true),
  229. have_default_constructor_flag(false),
  230. native_function_flag(false),
  231. enum_constant_flag(false),
  232. static_flag(false),
  233. variable_wrapper_flag(false),
  234. wrapping_member_flag(false),
  235. global_variable_flag(false),
  236. old_variable_names(false),
  237. unsafe_module(false),
  238. m3raw_name(NULL),
  239. m3raw_intf(),
  240. m3raw_impl(),
  241. m3wrap_name(NULL),
  242. m3wrap_intf(),
  243. m3wrap_impl(),
  244. m3makefile(NULL),
  245. targetlibrary(NULL),
  246. proxy_class_def(NULL),
  247. proxy_class_code(NULL),
  248. proxy_class_name(NULL),
  249. variable_name(NULL),
  250. variable_type(NULL),
  251. enumeration_name(NULL),
  252. enumeration_items(NULL),
  253. enumeration_max(0),
  254. enumeration_coll(NULL),
  255. constant_values(NULL),
  256. constantfilename(NULL),
  257. renamefilename(NULL),
  258. typemapfilename(NULL),
  259. m3raw_imports(NULL),
  260. module_imports(NULL),
  261. m3raw_baseclass(NULL),
  262. module_baseclass(NULL),
  263. m3raw_interfaces(NULL),
  264. module_interfaces(NULL),
  265. m3raw_class_modifiers(NULL),
  266. m3wrap_modifiers(NULL),
  267. upcasts_code(NULL),
  268. m3raw_cppcasts_code(NULL),
  269. destructor_call(NULL),
  270. outfile(NULL) {
  271. }
  272. /************** some utility functions ***************/
  273. /* -----------------------------------------------------------------------------
  274. * getMappedType()
  275. *
  276. * Return the type of 'p' mapped by 'map'.
  277. * Print a standard warning if 'p' can't be mapped.
  278. * ----------------------------------------------------------------------------- */
  279. String *getMappedType(Node *p, const char *map) {
  280. String *mapattr = NewString("tmap:");
  281. Append(mapattr, map);
  282. String *tm = Getattr(p, mapattr);
  283. if (tm == NIL) {
  284. Swig_warning(WARN_MODULA3_TYPEMAP_TYPE_UNDEF, input_file, line_number,
  285. "No '%s' typemap defined for type '%s'\n", map, SwigType_str(Getattr(p, "type"), 0));
  286. }
  287. Delete(mapattr);
  288. return tm;
  289. }
  290. /* -----------------------------------------------------------------------------
  291. * getMappedTypeNew()
  292. *
  293. * Similar to getMappedType but uses Swig_type_lookup_new.
  294. * ----------------------------------------------------------------------------- */
  295. String *getMappedTypeNew(Node *n, const char *map, const char *lname = "", bool warn = true) {
  296. String *tm = Swig_typemap_lookup(map, n, lname, 0);
  297. if ((tm == NIL) && warn) {
  298. Swig_warning(WARN_MODULA3_TYPEMAP_TYPE_UNDEF, input_file, line_number,
  299. "No '%s' typemap defined for type '%s'\n", map, SwigType_str(Getattr(n, "type"), 0));
  300. }
  301. return tm;
  302. }
  303. /* -----------------------------------------------------------------------------
  304. * attachMappedType()
  305. *
  306. * Obtain the type mapped by 'map' and attach it to the node
  307. * ----------------------------------------------------------------------------- */
  308. void attachMappedType(Node *n, const char *map, const char *lname = "") {
  309. String *tm = Swig_typemap_lookup(map, n, lname, 0);
  310. if (tm != NIL) {
  311. String *attr = NewStringf("tmap:%s", map);
  312. Setattr(n, attr, tm);
  313. Delete(attr);
  314. }
  315. }
  316. /* -----------------------------------------------------------------------------
  317. * skipIgnored()
  318. *
  319. * Skip all parameters that have 'numinputs=0'
  320. * with respect to a given typemap.
  321. * ----------------------------------------------------------------------------- */
  322. Node *skipIgnored(Node *p, const char *map) {
  323. String *niattr = NewStringf("tmap:%s:numinputs", map);
  324. String *nextattr = NewStringf("tmap:%s:next", map);
  325. while ((p != NIL) && checkAttribute(p, niattr, "0")) {
  326. p = Getattr(p, nextattr);
  327. }
  328. Delete(nextattr);
  329. Delete(niattr);
  330. return p;
  331. }
  332. /* -----------------------------------------------------------------------------
  333. * isInParam()
  334. * isOutParam()
  335. *
  336. * Check if the parameter is intended for input or for output.
  337. * ----------------------------------------------------------------------------- */
  338. bool isInParam(Node *p) {
  339. String *dir = Getattr(p, "tmap:m3wrapargdir");
  340. //printf("dir for %s: %s\n", Char(Getattr(p,"name")), Char(dir));
  341. if ((dir == NIL) || (Strcmp(dir, "in") == 0)
  342. || (Strcmp(dir, "inout") == 0)) {
  343. return true;
  344. } else if (Strcmp(dir, "out") == 0) {
  345. return false;
  346. } else {
  347. printf("%s", USAGE_ARG_DIR);
  348. return false;
  349. }
  350. }
  351. bool isOutParam(Node *p) {
  352. String *dir = Getattr(p, "tmap:m3wrapargdir");
  353. if ((dir == NIL) || (Strcmp(dir, "in") == 0)) {
  354. return false;
  355. } else if ((Strcmp(dir, "out") == 0) || (Strcmp(dir, "inout") == 0)) {
  356. return true;
  357. } else {
  358. printf("%s", USAGE_ARG_DIR);
  359. return false;
  360. }
  361. }
  362. /* -----------------------------------------------------------------------------
  363. * printAttrs()
  364. *
  365. * For debugging: Show all attributes of a node and their values.
  366. * ----------------------------------------------------------------------------- */
  367. void printAttrs(Node *n) {
  368. Iterator it;
  369. for (it = First(n); it.key != NIL; it = Next(it)) {
  370. printf("%s = %s\n", Char(it.key), Char(Getattr(n, it.key)));
  371. }
  372. }
  373. /* -----------------------------------------------------------------------------
  374. * hasPrefix()
  375. *
  376. * Check if a string have a given prefix.
  377. * ----------------------------------------------------------------------------- */
  378. bool hasPrefix(const String *str, const String *prefix) {
  379. int len_prefix = Len(prefix);
  380. return (Len(str) > len_prefix)
  381. && (Strncmp(str, prefix, len_prefix) == 0);
  382. }
  383. /* -----------------------------------------------------------------------------
  384. * getQualifiedName()
  385. *
  386. * Return fully qualified identifier of n.
  387. * ----------------------------------------------------------------------------- */
  388. #if 0
  389. // Swig_symbol_qualified returns NIL for enumeration nodes
  390. String *getQualifiedName(Node *n) {
  391. String *qual = Swig_symbol_qualified(n);
  392. String *name = Getattr(n, "name");
  393. if (hasContent(qual)) {
  394. return NewStringf("%s::%s", qual, name);
  395. } else {
  396. return name;
  397. }
  398. }
  399. #else
  400. String *getQualifiedName(Node *n) {
  401. String *name = Copy(Getattr(n, "name"));
  402. n = parentNode(n);
  403. while (n != NIL) {
  404. const String *type = nodeType(n);
  405. if ((Strcmp(type, "class") == 0) || (Strcmp(type, "struct") == 0) || (Strcmp(type, "namespace") == 0)) {
  406. String *newname = NewStringf("%s::%s", Getattr(n, "name"), name);
  407. Delete(name);
  408. //name = newname;
  409. // Hmpf, the class name is already qualified.
  410. return newname;
  411. }
  412. n = parentNode(n);
  413. }
  414. //printf("qualified name: %s\n", Char(name));
  415. return name;
  416. }
  417. #endif
  418. /* -----------------------------------------------------------------------------
  419. * nameToModula3()
  420. *
  421. * Turn usual C identifiers like "this_is_an_identifier"
  422. * into usual Modula 3 identifier like "thisIsAnIdentifier"
  423. * ----------------------------------------------------------------------------- */
  424. String *nameToModula3(const String *sym, bool leadingCap) {
  425. int len_sym = Len(sym);
  426. char *csym = Char(sym);
  427. char *m3sym = new char[len_sym + 1];
  428. int i, j;
  429. bool cap = leadingCap;
  430. for (i = 0, j = 0; j < len_sym; j++) {
  431. char c = csym[j];
  432. if ((c == '_') || (c == ':')) {
  433. cap = true;
  434. } else {
  435. if (isdigit(c)) {
  436. m3sym[i] = c;
  437. cap = true;
  438. } else {
  439. if (cap) {
  440. m3sym[i] = (char)toupper(c);
  441. } else {
  442. m3sym[i] = (char)tolower(c);
  443. }
  444. cap = false;
  445. }
  446. i++;
  447. }
  448. }
  449. m3sym[i] = 0;
  450. String *result = NewString(m3sym);
  451. delete[]m3sym;
  452. return result;
  453. }
  454. /* -----------------------------------------------------------------------------
  455. * capitalizeFirst()
  456. *
  457. * Make the first character upper case.
  458. * ----------------------------------------------------------------------------- */
  459. String *capitalizeFirst(const String *str) {
  460. return NewStringf("%c%s", toupper(*Char(str)), Char(str) + 1);
  461. }
  462. /* -----------------------------------------------------------------------------
  463. * prefixedNameToModula3()
  464. *
  465. * If feature modula3:oldprefix and modula3:newprefix is present
  466. * and the C identifier has leading 'oldprefix'
  467. * then it is replaced by the 'newprefix'.
  468. * The rest is converted to Modula style.
  469. * ----------------------------------------------------------------------------- */
  470. String *prefixedNameToModula3(Node *n, const String *sym, bool leadingCap) {
  471. String *oldPrefix = Getattr(n, "feature:modula3:oldprefix");
  472. String *newPrefix = Getattr(n, "feature:modula3:newprefix");
  473. String *result = NewString("");
  474. char *short_sym = Char(sym);
  475. // if at least one prefix feature is present
  476. // the replacement takes place
  477. if ((oldPrefix != NIL) || (newPrefix != NIL)) {
  478. if ((oldPrefix == NIL) || hasPrefix(sym, oldPrefix)) {
  479. short_sym += Len(oldPrefix);
  480. if (newPrefix != NIL) {
  481. Append(result, newPrefix);
  482. }
  483. }
  484. }
  485. String *suffix = nameToModula3(short_sym, leadingCap || hasContent(newPrefix));
  486. Append(result, suffix);
  487. Delete(suffix);
  488. return result;
  489. }
  490. /* -----------------------------------------------------------------------------
  491. * hasContent()
  492. *
  493. * Check if the string exists and contains something.
  494. * ----------------------------------------------------------------------------- */
  495. bool hasContent(const String *str) {
  496. return (str != NIL) && (Strcmp(str, "") != 0);
  497. }
  498. /* -----------------------------------------------------------------------------
  499. * openWriteFile()
  500. *
  501. * Caution: The file must be freshly allocated and will be destroyed
  502. * by this routine.
  503. * ----------------------------------------------------------------------------- */
  504. File *openWriteFile(String *name) {
  505. File *file = NewFile(name, "w", SWIG_output_files());
  506. if (!file) {
  507. FileErrorDisplay(name);
  508. SWIG_exit(EXIT_FAILURE);
  509. }
  510. Delete(name);
  511. return file;
  512. }
  513. /* -----------------------------------------------------------------------------
  514. * aToL()
  515. *
  516. * like atol but with additional user warning
  517. * ----------------------------------------------------------------------------- */
  518. long aToL(const String *value) {
  519. char *endptr;
  520. long numvalue = strtol(Char(value), &endptr, 0);
  521. if (*endptr != 0) {
  522. Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "The string <%s> does not denote a numeric value.\n", value);
  523. }
  524. return numvalue;
  525. }
  526. /* -----------------------------------------------------------------------------
  527. * strToL()
  528. *
  529. * like strtol but returns if the conversion was successful
  530. * ----------------------------------------------------------------------------- */
  531. bool strToL(const String *value, long &numvalue) {
  532. char *endptr;
  533. numvalue = strtol(Char(value), &endptr, 0);
  534. return (*endptr == 0);
  535. }
  536. /* -----------------------------------------------------------------------------
  537. * evalExpr()
  538. *
  539. * Evaluate simple expression as they may occur in "enumvalue" attributes.
  540. * ----------------------------------------------------------------------------- */
  541. bool evalExpr(String *value, long &numvalue) {
  542. // Split changes file status of String and thus cannot receive 'const' strings
  543. //printf("evaluate <%s>\n", Char(value));
  544. List *summands = Split(value, '+', INT_MAX);
  545. Iterator sm = First(summands);
  546. numvalue = 0;
  547. for (; sm.item != NIL; sm = Next(sm)) {
  548. String *smvalue = Getattr(constant_values, sm.item);
  549. long smnumvalue;
  550. if (smvalue != NIL) {
  551. if (!strToL(smvalue, smnumvalue)) {
  552. //printf("evaluation: abort 0 <%s>\n", Char(smvalue));
  553. return false;
  554. }
  555. } else {
  556. if (!strToL(sm.item, smnumvalue)) {
  557. //printf("evaluation: abort 1 <%s>\n", Char(sm));
  558. return false;
  559. }
  560. }
  561. numvalue += smnumvalue;
  562. }
  563. //printf("evaluation: return %ld\n", numvalue);
  564. return true;
  565. }
  566. /* -----------------------------------------------------------------------------
  567. * log2()
  568. *
  569. * Determine the position of the single bit of a power of two.
  570. * Returns true if the given number is a power of two.
  571. * ----------------------------------------------------------------------------- */
  572. bool log2(long n, long &exp) {
  573. exp = 0;
  574. while (n > 0) {
  575. if ((n & 1) != 0) {
  576. return n == 1;
  577. }
  578. exp++;
  579. n >>= 1;
  580. }
  581. return false;
  582. }
  583. /* -----------------------------------------------------------------------------
  584. * writeArg
  585. *
  586. * Write a function argument or RECORD entry definition.
  587. * Bundles arguments of same type and default value.
  588. * 'name.next==NIL' denotes the end of the entry or argument list.
  589. * ----------------------------------------------------------------------------- */
  590. bool equalNilStr(const String *str0, const String *str1) {
  591. if (str0 == NIL) {
  592. return (str1 == NIL);
  593. //return (str0==NIL) == (str1==NIL);
  594. } else {
  595. return (str1 != NIL) && (Cmp(str0, str1) == 0);
  596. //return Cmp(str0,str1)==0;
  597. }
  598. }
  599. struct writeArgState {
  600. String *mode, *name, *type, *value;
  601. bool hold;
  602. writeArgState():mode(NIL), name(NIL), type(NIL), value(NIL), hold(false) {
  603. }
  604. };
  605. void writeArg(File *f, writeArgState & state, String *mode, String *name, String *type, String *value) {
  606. /* skip the first argument,
  607. only store the information for the next call in this case */
  608. if (state.name != NIL) {
  609. if ((!state.hold) && (state.mode != NIL)) {
  610. Printf(f, "%s ", state.mode);
  611. }
  612. if ((name != NIL) && equalNilStr(state.mode, mode) && equalNilStr(state.type, type) && (state.value == NIL) && (value == NIL)
  613. /* the same expression may have different values
  614. due to side effects of the called function */
  615. /*equalNilStr(state.value,value) */
  616. ) {
  617. Printf(f, "%s, ", state.name);
  618. state.hold = true;
  619. } else {
  620. Append(f, state.name);
  621. if (state.type != NIL) {
  622. Printf(f, ": %s", state.type);
  623. }
  624. if (state.value != NIL) {
  625. Printf(f, ":= %s", state.value);
  626. }
  627. Append(f, ";\n");
  628. state.hold = false;
  629. }
  630. }
  631. /* at the next call the current argument will be the previous one */
  632. state.mode = mode;
  633. state.name = name;
  634. state.type = type;
  635. state.value = value;
  636. }
  637. /* -----------------------------------------------------------------------------
  638. * getProxyName()
  639. *
  640. * Test to see if a type corresponds to something wrapped with a proxy class
  641. * Return NULL if not otherwise the proxy class name
  642. * ----------------------------------------------------------------------------- */
  643. String *getProxyName(SwigType *t) {
  644. if (proxy_flag) {
  645. Node *n = classLookup(t);
  646. if (n) {
  647. return Getattr(n, "sym:name");
  648. }
  649. }
  650. return NULL;
  651. }
  652. /*************** language processing ********************/
  653. /* ------------------------------------------------------------
  654. * main()
  655. * ------------------------------------------------------------ */
  656. virtual void main(int argc, char *argv[]) {
  657. SWIG_library_directory("modula3");
  658. // Look for certain command line options
  659. for (int i = 1; i < argc; i++) {
  660. if (argv[i]) {
  661. if (strcmp(argv[i], "-generateconst") == 0) {
  662. if (argv[i + 1]) {
  663. constantfilename = NewString(argv[i + 1]);
  664. Swig_mark_arg(i);
  665. Swig_mark_arg(i + 1);
  666. i++;
  667. } else {
  668. Swig_arg_error();
  669. }
  670. } else if (strcmp(argv[i], "-generaterename") == 0) {
  671. if (argv[i + 1]) {
  672. renamefilename = NewString(argv[i + 1]);
  673. Swig_mark_arg(i);
  674. Swig_mark_arg(i + 1);
  675. i++;
  676. } else {
  677. Swig_arg_error();
  678. }
  679. } else if (strcmp(argv[i], "-generatetypemap") == 0) {
  680. if (argv[i + 1]) {
  681. typemapfilename = NewString(argv[i + 1]);
  682. Swig_mark_arg(i);
  683. Swig_mark_arg(i + 1);
  684. i++;
  685. } else {
  686. Swig_arg_error();
  687. }
  688. } else if (strcmp(argv[i], "-noproxy") == 0) {
  689. Swig_mark_arg(i);
  690. proxy_flag = false;
  691. } else if (strcmp(argv[i], "-oldvarnames") == 0) {
  692. Swig_mark_arg(i);
  693. old_variable_names = true;
  694. } else if (strcmp(argv[i], "-help") == 0) {
  695. Printf(stdout, "%s\n", usage);
  696. }
  697. }
  698. }
  699. // Add a symbol to the parser for conditional compilation
  700. Preprocessor_define("SWIGMODULA3 1", 0);
  701. // Add typemap definitions
  702. SWIG_typemap_lang("modula3");
  703. SWIG_config_file("modula3.swg");
  704. allow_overloading();
  705. }
  706. /* ---------------------------------------------------------------------
  707. * top()
  708. * --------------------------------------------------------------------- */
  709. virtual int top(Node *n) {
  710. if (hasContent(constantfilename) || hasContent(renamefilename) || hasContent(typemapfilename)) {
  711. int result = SWIG_OK;
  712. if (hasContent(constantfilename)) {
  713. result = generateConstantTop(n) && result;
  714. }
  715. if (hasContent(renamefilename)) {
  716. result = generateRenameTop(n) && result;
  717. }
  718. if (hasContent(typemapfilename)) {
  719. result = generateTypemapTop(n) && result;
  720. }
  721. return result;
  722. } else {
  723. return generateM3Top(n);
  724. }
  725. }
  726. void scanConstant(File *file, Node *n) {
  727. Node *child = firstChild(n);
  728. while (child != NIL) {
  729. String *constname = NIL;
  730. String *type = nodeType(child);
  731. if ((Strcmp(type, "enumitem") == 0)
  732. || (Strcmp(type, "constant") == 0)) {
  733. #if 1
  734. constname = getQualifiedName(child);
  735. #else
  736. constname = Getattr(child, "value");
  737. if ((!hasContent(constname))
  738. || (('0' <= *Char(constname)) && (*Char(constname) <= '9'))) {
  739. constname = Getattr(child, "name");
  740. }
  741. #endif
  742. }
  743. if (constname != NIL) {
  744. Printf(file, " printf(\"%%%%constnumeric(%%Lg) %s;\\n\", (long double)%s);\n", constname, constname);
  745. }
  746. scanConstant(file, child);
  747. child = nextSibling(child);
  748. }
  749. }
  750. int generateConstantTop(Node *n) {
  751. File *file = openWriteFile(NewStringf("%s.c", constantfilename));
  752. if (CPlusPlus) {
  753. Printf(file, "#include <cstdio>\n");
  754. } else {
  755. Printf(file, "#include <stdio.h>\n");
  756. }
  757. Printf(file, "#include \"%s\"\n", input_file);
  758. Printf(file, "\n");
  759. Printf(file, "int main (int argc, char *argv[]) {\n");
  760. Printf(file, "\
  761. /*This progam must work for floating point numbers and integers.\n\
  762. Thus all numbers are converted to double precision floating point format.*/\n");
  763. scanConstant(file, n);
  764. Printf(file, " return 0;\n");
  765. Printf(file, "}\n");
  766. Close(file);
  767. return SWIG_OK;
  768. }
  769. void scanRename(File *file, Node *n) {
  770. Node *child = firstChild(n);
  771. while (child != NIL) {
  772. String *type = nodeType(child);
  773. if (Strcmp(type, "cdecl") == 0) {
  774. ParmList *p = Getattr(child, "parms");
  775. if (p != NIL) {
  776. String *name = getQualifiedName(child);
  777. String *m3name = nameToModula3(name, true);
  778. /*don't know how to get the original C type identifiers */
  779. //String *arguments = createCSignature (child);
  780. Printf(file, "%%rename(\"%s\") %s;\n", m3name, name);
  781. /*Printf(file, "%%rename(\"%s\") %s %s(%s);\n",
  782. m3name, Getattr(n,"type"), name, arguments); */
  783. Delete(name);
  784. Delete(m3name);
  785. //Delete (arguments);
  786. }
  787. }
  788. scanRename(file, child);
  789. child = nextSibling(child);
  790. }
  791. }
  792. int generateRenameTop(Node *n) {
  793. File *file = openWriteFile(NewStringf("%s.i", renamefilename));
  794. Printf(file, "\
  795. /* This file was generated from %s\n\
  796. by SWIG with option -generaterename. */\n\
  797. \n", input_file);
  798. scanRename(file, n);
  799. Close(file);
  800. return SWIG_OK;
  801. }
  802. void scanTypemap(File *file, Node *n) {
  803. Node *child = firstChild(n);
  804. while (child != NIL) {
  805. String *type = nodeType(child);
  806. //printf("nodetype %s\n", Char(type));
  807. String *storage = Getattr(child, "storage");
  808. if ((Strcmp(type, "class") == 0) || ((Strcmp(type, "cdecl") == 0) && (storage != NIL)
  809. && (Strcmp(storage, "typedef") == 0))) {
  810. String *name = getQualifiedName(child);
  811. String *m3name = nameToModula3(name, true);
  812. Printf(file, "%%typemap(\"m3wrapintype\") %s %%{%s%%}\n", name, m3name);
  813. Printf(file, "%%typemap(\"m3rawintype\") %s %%{%s%%}\n", name, m3name);
  814. Printf(file, "\n");
  815. }
  816. scanTypemap(file, child);
  817. child = nextSibling(child);
  818. }
  819. }
  820. int generateTypemapTop(Node *n) {
  821. File *file = openWriteFile(NewStringf("%s.i", typemapfilename));
  822. Printf(file, "\
  823. /* This file was generated from %s\n\
  824. by SWIG with option -generatetypemap. */\n\
  825. \n", input_file);
  826. scanTypemap(file, n);
  827. Close(file);
  828. return SWIG_OK;
  829. }
  830. int generateM3Top(Node *n) {
  831. /* Initialize all of the output files */
  832. outfile = Getattr(n, "outfile");
  833. f_begin = NewFile(outfile, "w", SWIG_output_files());
  834. if (!f_begin) {
  835. FileErrorDisplay(outfile);
  836. SWIG_exit(EXIT_FAILURE);
  837. }
  838. f_runtime = NewString("");
  839. f_init = NewString("");
  840. f_header = NewString("");
  841. f_wrappers = NewString("");
  842. m3makefile = NewString("");
  843. /* Register file targets with the SWIG file handler */
  844. Swig_register_filebyname("header", f_header);
  845. Swig_register_filebyname("wrapper", f_wrappers);
  846. Swig_register_filebyname("begin", f_begin);
  847. Swig_register_filebyname("runtime", f_runtime);
  848. Swig_register_filebyname("init", f_init);
  849. Swig_register_filebyname("m3rawintf", m3raw_intf.f);
  850. Swig_register_filebyname("m3rawimpl", m3raw_impl.f);
  851. Swig_register_filebyname("m3wrapintf", m3wrap_intf.f);
  852. Swig_register_filebyname("m3wrapimpl", m3wrap_impl.f);
  853. Swig_register_filebyname("m3makefile", m3makefile);
  854. swig_types_hash = NewHash();
  855. String *name = Getattr(n, "name");
  856. // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
  857. Node *optionsnode = Getattr(Getattr(n, "module"), "options");
  858. if (optionsnode != NIL) {
  859. String *m3raw_name_tmp = Getattr(optionsnode, "m3rawname");
  860. if (m3raw_name_tmp != NIL) {
  861. m3raw_name = Copy(m3raw_name_tmp);
  862. }
  863. }
  864. if (m3raw_name == NIL) {
  865. m3raw_name = NewStringf("%sRaw", name);
  866. }
  867. Setattr(m3wrap_impl.import, m3raw_name, "");
  868. m3wrap_name = Copy(name);
  869. proxy_class_def = NewString("");
  870. proxy_class_code = NewString("");
  871. m3raw_baseclass = NewString("");
  872. m3raw_interfaces = NewString("");
  873. m3raw_class_modifiers = NewString(""); // package access only to the intermediary class by default
  874. m3raw_imports = NewString("");
  875. m3raw_cppcasts_code = NewString("");
  876. m3wrap_modifiers = NewString("public");
  877. module_baseclass = NewString("");
  878. module_interfaces = NewString("");
  879. module_imports = NewString("");
  880. upcasts_code = NewString("");
  881. Swig_banner(f_begin);
  882. Printf(f_runtime, "\n");
  883. Printf(f_runtime, "#define SWIGMODULA3\n");
  884. Printf(f_runtime, "\n");
  885. Swig_name_register("wrapper", "Modula3_%f");
  886. if (old_variable_names) {
  887. Swig_name_register("set", "set_%n%v");
  888. Swig_name_register("get", "get_%n%v");
  889. }
  890. Printf(f_wrappers, "\n#ifdef __cplusplus\n");
  891. Printf(f_wrappers, "extern \"C\" {\n");
  892. Printf(f_wrappers, "#endif\n\n");
  893. constant_values = NewHash();
  894. scanForConstPragmas(n);
  895. enumeration_coll = NewHash();
  896. collectEnumerations(enumeration_coll, n);
  897. /* Emit code */
  898. Language::top(n);
  899. // Generate m3makefile
  900. // This will be unnecessary if SWIG is invoked from Quake.
  901. {
  902. File *file = openWriteFile(NewStringf("%sm3makefile", Swig_file_dirname(outfile)));
  903. Printf(file, "%% automatically generated quake file for %s\n\n", name);
  904. /* Write the fragments written by '%insert'
  905. collected while 'top' processed the parse tree */
  906. Printv(file, m3makefile, NIL);
  907. Printf(file, "import(\"libm3\")\n");
  908. //Printf(file, "import_lib(\"%s\",\"/usr/lib\")\n", name);
  909. Printf(file, "module(\"%s\")\n", m3raw_name);
  910. Printf(file, "module(\"%s\")\n\n", m3wrap_name);
  911. if (targetlibrary != NIL) {
  912. Printf(file, "library(\"%s\")\n", targetlibrary);
  913. } else {
  914. Printf(file, "library(\"m3%s\")\n", name);
  915. }
  916. Close(file);
  917. }
  918. // Generate the raw interface
  919. {
  920. File *file = openWriteFile(NewStringf("%s%s.i3", Swig_file_dirname(outfile), m3raw_name));
  921. emitBanner(file);
  922. Printf(file, "INTERFACE %s;\n\n", m3raw_name);
  923. emitImportStatements(m3raw_intf.import, file);
  924. Printf(file, "\n");
  925. // Write the interface generated within 'top'
  926. Printv(file, m3raw_intf.f, NIL);
  927. Printf(file, "\nEND %s.\n", m3raw_name);
  928. Close(file);
  929. }
  930. // Generate the raw module
  931. {
  932. File *file = openWriteFile(NewStringf("%s%s.m3", Swig_file_dirname(outfile), m3raw_name));
  933. emitBanner(file);
  934. Printf(file, "MODULE %s;\n\n", m3raw_name);
  935. emitImportStatements(m3raw_impl.import, file);
  936. Printf(file, "\n");
  937. // will be empty usually
  938. Printv(file, m3raw_impl.f, NIL);
  939. Printf(file, "BEGIN\nEND %s.\n", m3raw_name);
  940. Close(file);
  941. }
  942. // Generate the interface for the comfort wrappers
  943. {
  944. File *file = openWriteFile(NewStringf("%s%s.i3", Swig_file_dirname(outfile), m3wrap_name));
  945. emitBanner(file);
  946. Printf(file, "INTERFACE %s;\n", m3wrap_name);
  947. emitImportStatements(m3wrap_intf.import, file);
  948. Printf(file, "\n");
  949. {
  950. Iterator it = First(enumeration_coll);
  951. if (it.key != NIL) {
  952. Printf(file, "TYPE\n");
  953. }
  954. for (; it.key != NIL; it = Next(it)) {
  955. Printf(file, "\n");
  956. emitEnumeration(file, it.key, it.item);
  957. }
  958. }
  959. // Add the wrapper methods
  960. Printv(file, m3wrap_intf.f, NIL);
  961. // Finish off the class
  962. Printf(file, "\nEND %s.\n", m3wrap_name);
  963. Close(file);
  964. }
  965. // Generate the wrapper routines implemented in Modula 3
  966. {
  967. File *file = openWriteFile(NewStringf("%s%s.m3", Swig_file_dirname(outfile), m3wrap_name));
  968. emitBanner(file);
  969. if (unsafe_module) {
  970. Printf(file, "UNSAFE ");
  971. }
  972. Printf(file, "MODULE %s;\n\n", m3wrap_name);
  973. emitImportStatements(m3wrap_impl.import, file);
  974. Printf(file, "\n");
  975. // Add the wrapper methods
  976. Printv(file, m3wrap_impl.f, NIL);
  977. Printf(file, "\nBEGIN\nEND %s.\n", m3wrap_name);
  978. Close(file);
  979. }
  980. if (upcasts_code)
  981. Printv(f_wrappers, upcasts_code, NIL);
  982. Printf(f_wrappers, "#ifdef __cplusplus\n");
  983. Printf(f_wrappers, "}\n");
  984. Printf(f_wrappers, "#endif\n");
  985. // Output a Modula 3 type wrapper class for each SWIG type
  986. for (Iterator swig_type = First(swig_types_hash); swig_type.item != NIL; swig_type = Next(swig_type)) {
  987. emitTypeWrapperClass(swig_type.key, swig_type.item);
  988. }
  989. Delete(swig_types_hash);
  990. swig_types_hash = NULL;
  991. Delete(constant_values);
  992. constant_values = NULL;
  993. Delete(enumeration_coll);
  994. enumeration_coll = NULL;
  995. Delete(m3raw_name);
  996. m3raw_name = NULL;
  997. Delete(m3raw_baseclass);
  998. m3raw_baseclass = NULL;
  999. Delete(m3raw_interfaces);
  1000. m3raw_interfaces = NULL;
  1001. Delete(m3raw_class_modifiers);
  1002. m3raw_class_modifiers = NULL;
  1003. Delete(m3raw_imports);
  1004. m3raw_imports = NULL;
  1005. Delete(m3raw_cppcasts_code);
  1006. m3raw_cppcasts_code = NULL;
  1007. Delete(proxy_class_def);
  1008. proxy_class_def = NULL;
  1009. Delete(proxy_class_code);
  1010. proxy_class_code = NULL;
  1011. Delete(m3wrap_name);
  1012. m3wrap_name = NULL;
  1013. Delete(m3wrap_modifiers);
  1014. m3wrap_modifiers = NULL;
  1015. Delete(targetlibrary);
  1016. targetlibrary = NULL;
  1017. Delete(module_baseclass);
  1018. module_baseclass = NULL;
  1019. Delete(module_interfaces);
  1020. module_interfaces = NULL;
  1021. Delete(module_imports);
  1022. module_imports = NULL;
  1023. Delete(upcasts_code);
  1024. upcasts_code = NULL;
  1025. Delete(constantfilename);
  1026. constantfilename = NULL;
  1027. Delete(renamefilename);
  1028. renamefilename = NULL;
  1029. Delete(typemapfilename);
  1030. typemapfilename = NULL;
  1031. /* Close all of the files */
  1032. Dump(f_runtime, f_begin);
  1033. Dump(f_header, f_begin);
  1034. Dump(f_wrappers, f_begin);
  1035. Wrapper_pretty_print(f_init, f_begin);
  1036. Delete(f_header);
  1037. Delete(f_wrappers);
  1038. Delete(f_init);
  1039. Close(f_begin);
  1040. Delete(f_runtime);
  1041. Delete(f_begin);
  1042. return SWIG_OK;
  1043. }
  1044. /* -----------------------------------------------------------------------------
  1045. * emitBanner()
  1046. * ----------------------------------------------------------------------------- */
  1047. void emitBanner(File *f) {
  1048. Printf(f, "(*******************************************************************************\n");
  1049. Swig_banner_target_lang(f, " *");
  1050. Printf(f, "*******************************************************************************)\n\n");
  1051. }
  1052. /* ----------------------------------------------------------------------
  1053. * nativeWrapper()
  1054. * ---------------------------------------------------------------------- */
  1055. virtual int nativeWrapper(Node *n) {
  1056. String *wrapname = Getattr(n, "wrap:name");
  1057. if (!addSymbol(wrapname, n))
  1058. return SWIG_ERROR;
  1059. if (Getattr(n, "type")) {
  1060. Swig_save("nativeWrapper", n, "name", NIL);
  1061. Setattr(n, "name", wrapname);
  1062. native_function_flag = true;
  1063. functionWrapper(n);
  1064. Swig_restore(n);
  1065. native_function_flag = false;
  1066. } else {
  1067. Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
  1068. }
  1069. return SWIG_OK;
  1070. }
  1071. /* ----------------------------------------------------------------------
  1072. * functionWrapper()
  1073. * ---------------------------------------------------------------------- */
  1074. virtual int functionWrapper(Node *n) {
  1075. String *type = nodeType(n);
  1076. String *funcType = Getattr(n, "modula3:functype");
  1077. String *rawname = Getattr(n, "name");
  1078. String *symname = Getattr(n, "sym:name");
  1079. String *capname = capitalizeFirst(symname);
  1080. //String *wname = Swig_name_wrapper(symname);
  1081. //printf("function: %s\n", Char(symname));
  1082. //printf(" purpose: %s\n", Char(funcType));
  1083. if (Strcmp(type, "cdecl") == 0) {
  1084. if (funcType == NIL) {
  1085. // no wrapper needed for plain functions
  1086. emitM3RawPrototype(n, rawname, symname);
  1087. emitM3Wrapper(n, symname);
  1088. } else if (Strcmp(funcType, "method") == 0) {
  1089. Setattr(n, "modula3:funcname", capname);
  1090. emitCWrapper(n, capname);
  1091. emitM3RawPrototype(n, capname, capname);
  1092. emitM3Wrapper(n, capname);
  1093. } else if (Strcmp(funcType, "accessor") == 0) {
  1094. /*
  1095. * Generate the proxy class properties for public member variables.
  1096. * Not for enums and constants.
  1097. */
  1098. if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
  1099. // Capitalize the first letter in the function name
  1100. Setattr(n, "proxyfuncname", capname);
  1101. Setattr(n, "imfuncname", symname);
  1102. if (hasPrefix(capname, "Set")) {
  1103. Setattr(n, "modula3:setname", capname);
  1104. } else {
  1105. Setattr(n, "modula3:getname", capname);
  1106. }
  1107. emitCWrapper(n, capname);
  1108. emitM3RawPrototype(n, capname, capname);
  1109. emitM3Wrapper(n, capname);
  1110. //proxyClassFunctionHandler(n);
  1111. }
  1112. #ifdef DEBUG
  1113. } else {
  1114. Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Function type <%s> unknown.\n", Char(funcType));
  1115. #endif
  1116. }
  1117. } else if ((Strcmp(type, "constructor") == 0) || (Strcmp(type, "destructor") == 0)) {
  1118. emitCWrapper(n, capname);
  1119. emitM3RawPrototype(n, capname, capname);
  1120. emitM3Wrapper(n, capname);
  1121. }
  1122. // a Java relict
  1123. #if 0
  1124. if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
  1125. emitM3Wrapper(n, capname);
  1126. }
  1127. #endif
  1128. Delete(capname);
  1129. return SWIG_OK;
  1130. }
  1131. /* ----------------------------------------------------------------------
  1132. * emitCWrapper()
  1133. *
  1134. * Generate the wrapper in C which calls C++ methods.
  1135. * ---------------------------------------------------------------------- */
  1136. virtual int emitCWrapper(Node *n, const String *wname) {
  1137. String *rawname = Getattr(n, "name");
  1138. String *c_return_type = NewString("");
  1139. String *cleanup = NewString("");
  1140. String *outarg = NewString("");
  1141. String *body = NewString("");
  1142. Hash *throws_hash = NewHash();
  1143. ParmList *l = Getattr(n, "parms");
  1144. SwigType *t = Getattr(n, "type");
  1145. String *symname = Getattr(n, "sym:name");
  1146. if (!Getattr(n, "sym:overloaded")) {
  1147. if (!addSymbol(wname, n)) {
  1148. return SWIG_ERROR;
  1149. }
  1150. }
  1151. // A new wrapper function object
  1152. Wrapper *f = NewWrapper();
  1153. /* Attach the non-standard typemaps to the parameter list. */
  1154. Swig_typemap_attach_parms("ctype", l, f);
  1155. /* Get return types */
  1156. {
  1157. String *tm = getMappedTypeNew(n, "ctype", "");
  1158. if (tm != NIL) {
  1159. Printf(c_return_type, "%s", tm);
  1160. }
  1161. }
  1162. bool is_void_return = (Cmp(c_return_type, "void") == 0);
  1163. if (!is_void_return) {
  1164. Wrapper_add_localv(f, "cresult", c_return_type, "cresult = 0", NIL);
  1165. }
  1166. Printv(f->def, " SWIGEXPORT ", c_return_type, " ", wname, "(", NIL);
  1167. // Emit all of the local variables for holding arguments.
  1168. emit_parameter_variables(l, f);
  1169. /* Attach the standard typemaps */
  1170. emit_attach_parmmaps(l, f);
  1171. Setattr(n, "wrap:parms", l);
  1172. // Generate signature and argument conversion for C wrapper
  1173. {
  1174. Parm *p;
  1175. attachParameterNames(n, "tmap:name", "c:wrapname", "m3arg%d");
  1176. bool gencomma = false;
  1177. for (p = skipIgnored(l, "in"); p; p = skipIgnored(p, "in")) {
  1178. String *arg = Getattr(p, "c:wrapname");
  1179. {
  1180. /* Get the ctype types of the parameter */
  1181. String *c_param_type = getMappedType(p, "ctype");
  1182. // Add parameter to C function
  1183. Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
  1184. Delete(c_param_type);
  1185. gencomma = true;
  1186. }
  1187. // Get typemap for this argument
  1188. String *tm = getMappedType(p, "in");
  1189. if (tm != NIL) {
  1190. addThrows(throws_hash, "in", p);
  1191. Replaceall(tm, "$input", arg);
  1192. Setattr(p, "emit:input", arg); /*??? */
  1193. Printf(f->code, "%s\n", tm);
  1194. p = Getattr(p, "tmap:in:next");
  1195. } else {
  1196. p = nextSibling(p);
  1197. }
  1198. }
  1199. }
  1200. /* Insert constraint checking code */
  1201. {
  1202. Parm *p;
  1203. for (p = l; p;) {
  1204. String *tm = Getattr(p, "tmap:check");
  1205. if (tm != NIL) {
  1206. addThrows(throws_hash, "check", p);
  1207. Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
  1208. Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
  1209. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  1210. Printv(f->code, tm, "\n", NIL);
  1211. p = Getattr(p, "tmap:check:next");
  1212. } else {
  1213. p = nextSibling(p);
  1214. }
  1215. }
  1216. }
  1217. /* Insert cleanup code */
  1218. {
  1219. Parm *p;
  1220. for (p = l; p;) {
  1221. String *tm = Getattr(p, "tmap:freearg");
  1222. if (tm != NIL) {
  1223. addThrows(throws_hash, "freearg", p);
  1224. Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
  1225. Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
  1226. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  1227. Printv(cleanup, tm, "\n", NIL);
  1228. p = Getattr(p, "tmap:freearg:next");
  1229. } else {
  1230. p = nextSibling(p);
  1231. }
  1232. }
  1233. }
  1234. /* Insert argument output code */
  1235. {
  1236. Parm *p;
  1237. for (p = l; p;) {
  1238. String *tm = Getattr(p, "tmap:argout");
  1239. if (tm != NIL) {
  1240. addThrows(throws_hash, "argout", p);
  1241. Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
  1242. Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
  1243. Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
  1244. Replaceall(tm, "$result", "cresult");
  1245. Replaceall(tm, "$input", Getattr(p, "emit:input"));
  1246. Printv(outarg, tm, "\n", NIL);
  1247. p = Getattr(p, "tmap:argout:next");
  1248. } else {
  1249. p = nextSibling(p);
  1250. }
  1251. }
  1252. }
  1253. // Get any Modula 3 exception classes in the throws typemap
  1254. ParmList *throw_parm_list = NULL;
  1255. if ((throw_parm_list = Getattr(n, "catchlist"))) {
  1256. Swig_typemap_attach_parms("throws", throw_parm_list, f);
  1257. Parm *p;
  1258. for (p = throw_parm_list; p; p = nextSibling(p)) {
  1259. addThrows(throws_hash, "throws", p);
  1260. }
  1261. }
  1262. if (Cmp(nodeType(n), "constant") == 0) {
  1263. // Wrapping a constant hack
  1264. Swig_save("functionWrapper", n, "wrap:action", NIL);
  1265. // below based on Swig_VargetToFunction()
  1266. SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
  1267. Setattr(n, "wrap:action", NewStringf("%s = (%s)(%s);", Swig_cresult_name(), SwigType_lstr(ty, 0), Getattr(n, "value")));
  1268. }
  1269. Setattr(n, "wrap:name", wname);
  1270. // Now write code to make the function call
  1271. if (!native_function_flag) {
  1272. String *actioncode = emit_action(n);
  1273. if (Cmp(nodeType(n), "constant") == 0) {
  1274. Swig_restore(n);
  1275. }
  1276. /* Return value if necessary */
  1277. String *tm;
  1278. if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) {
  1279. addThrows(throws_hash, "out", n);
  1280. Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
  1281. Replaceall(tm, "$target", "cresult"); /* deprecated */
  1282. Replaceall(tm, "$result", "cresult");
  1283. Printf(f->code, "%s", tm);
  1284. if (hasContent(tm))
  1285. Printf(f->code, "\n");
  1286. } else {
  1287. Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t, 0), rawname);
  1288. }
  1289. emit_return_variable(n, t, f);
  1290. }
  1291. /* Output argument output code */
  1292. Printv(f->code, outarg, NIL);
  1293. /* Output cleanup code */
  1294. Printv(f->code, cleanup, NIL);
  1295. /* Look to see if there is any newfree cleanup code */
  1296. if (GetFlag(n, "feature:new")) {
  1297. String *tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0);
  1298. if (tm != NIL) {
  1299. addThrows(throws_hash, "newfree", n);
  1300. Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
  1301. Printf(f->code, "%s\n", tm);
  1302. }
  1303. }
  1304. /* See if there is any return cleanup code */
  1305. if (!native_function_flag) {
  1306. String *tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0);
  1307. if (tm != NIL) {
  1308. Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */
  1309. Printf(f->code, "%s\n", tm);
  1310. }
  1311. }
  1312. /* Finish C wrapper */
  1313. Printf(f->def, ") {");
  1314. if (!is_void_return)
  1315. Printv(f->code, " return cresult;\n", NIL);
  1316. Printf(f->code, "}\n");
  1317. /* Substitute the cleanup code */
  1318. Replaceall(f->code, "$cleanup", cleanup);
  1319. /* Substitute the function name */
  1320. Replaceall(f->code, "$symname", symname);
  1321. if (!is_void_return) {
  1322. Replaceall(f->code, "$null", "0");
  1323. } else {
  1324. Replaceall(f->code, "$null", "");
  1325. }
  1326. /* Dump the function out */
  1327. if (!native_function_flag) {
  1328. Wrapper_print(f, f_wrappers);
  1329. }
  1330. Delete(c_return_type);
  1331. Delete(cleanup);
  1332. Delete(outarg);
  1333. Delete(body);
  1334. Delete(throws_hash);
  1335. DelWrapper(f);
  1336. return SWIG_OK;
  1337. }
  1338. /* ----------------------------------------------------------------------
  1339. * emitM3RawPrototype()
  1340. *
  1341. * Generate an EXTERNAL procedure declaration in Modula 3
  1342. * which is the interface to an existing C routine or a C wrapper.
  1343. * ---------------------------------------------------------------------- */
  1344. virtual int emitM3RawPrototype(Node *n, const String *cname, const String *m3name) {
  1345. String *im_return_type = NewString("");
  1346. //String *symname = Getattr(n,"sym:name");
  1347. ParmList *l = Getattr(n, "parms");
  1348. /* Attach the non-standard typemaps to the parameter list. */
  1349. Swig_typemap_attach_parms("m3rawinmode", l, NULL);
  1350. Swig_typemap_attach_parms("m3rawintype", l, NULL);
  1351. /* Get return types */
  1352. bool has_return;
  1353. {
  1354. String *tm = getMappedTypeNew(n, "m3rawrettype", "");
  1355. if (tm != NIL) {
  1356. Printf(im_return_type, "%s", tm);

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