1 /* -----------------------------------------------------------------------------
2 * See the LICENSE file for information on copyright, usage and redistribution
3 * of SWIG, and the README file for authors - http://www.swig.org/release.html.
7 * Modula3 language module for SWIG.
8 * ----------------------------------------------------------------------------- */
10 char cvsroot_modula3_cxx[] = "$Id: modula3.cxx 11584 2009-08-16 00:04:29Z wsfulton $";
14 indent -sob -br -ce -nut -npsl
19 - It's not a good concept to use member variables or global variables
20 for passing parameters to functions.
21 It's not a good concept to use functions of superclasses for specific services.
22 E.g. For SWIG this means: Generating accessor functions for member variables
23 is the most common but no general task to be processed in membervariableHandler.
24 Better provide a service function which generates accessor function code
25 and equip this service function with all parameters needed for input (parse node)
26 and output (generated code).
27 - How can I make globalvariableHandler not to generate
28 interface functions to two accessor functions
30 - How can I generate a typemap that turns every C reference argument into
31 its Modula 3 counterpart, that is
32 void test(Complex &z);
33 PROCEDURE test(VAR z:Complex);
34 - neither $*n_mangle nor $*n_type nor $*n_ltype return the type without
35 pointer converted to Modula3 equivalent,
36 $*n_mangle is the variant closest to what I expect
37 - using a typemap like
38 typemap(m3wrapintype) int * %{VAR $1_name: INTEGER%}
40 - one C parameter can be turned into multiple M3 parameters
41 - the argument can be renamed
43 typemap(m3wrapinmode) int * "VAR"
44 typemap(m3wrapintype) int * "INTEGER"
46 - multiple parameters with same type and default value can be bundled
47 - more conform to the other language modules
48 - Where takes the reduction of multi-typemaps place?
49 How can I preserve all parameters for functions of the intermediary class?
50 The answer is Getattrs(n,"tmap:m3rawintype:next")
51 - Char() can be used to transform a String to (char *)
52 which can be used for output with printf
53 - What is the while (checkAttribute()) loop in functionWrapper good for?
54 Appearently for skipping (numinputs=0) typemaps.
55 - SWIGTYPE const * - typemap is ignored, whereas
56 SWIGTYPE * - typemap is invoked, why?
57 Had it been (const SWIGTYPE *) instead?
58 - enumeration items should definitely be equipped
59 with its plain numerical value
60 One could add tag 'numvalue' in CParse/parser.y,
61 but it is still possible that someone declares an
62 enumeration using a symbolic constant.
64 that the successive number is assigned
65 if "enumvalue" has suffix "+1".
66 The ultimate solution would be to generate a C program
67 which includes the header and outputs all constants.
68 This program might be compiled and run
69 by 'make' or by SWIG and the resulting output is fed back to SWIG.
70 - It's a bad idea to interpret feature value ""
71 'disable feature' because the value ""
72 might be sensible in case of feature:modula3:oldprefix.
73 - What's the difference between "sym:name" and "name" ?
74 "name" is the original name and
75 "sym:name" is probably modified by the user using %rename
76 - Is it possible for 'configure' to find out if m3pp is installed
77 and to invoke it for generated Modula3 files?
78 - It would be better to separate an arguments purpose and its name,
79 because an output variable with name "OUTPUT" is not very descriptive.
80 In case of PLPlot this could be solved by typedefs
81 that assign special purposes to the array types.
82 - Can one interpret $n_basetype as the identifier matched with SWIGTYPE ?
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
94 - Is there a function that creates a C representation of a SWIG type string?
97 - create WeakRefs only for resources returned by function marked with %newobject
98 -> part of output conversion
99 - clean typemap conception
100 - should a multi-typemap for m3wrapouttype skip the corresponding input parameters?
101 when yes - How to handle inout-arguments? In this case like in-argument.
104 - allow for moving RECORD and OBJECT definitions
105 to separate files, with the main type called T
106 - call-back functions
107 - special option: fast access to class members by pointer arithmetic,
108 member offsets can be determined by a C++ program that print them.
109 - emit enumeration definitions when its first item is declared,
110 currently enumerations are emitted at the beginning of the file
113 - addThrow should convert the typemap by itself
114 - not possible because routine for attaching mapped types to parameter nodes
115 won't work for the function node
116 - turning error codes into exceptions
117 -> part of output value checking
118 - create WeakRefs for resources allocated by the library
119 -> part of output conversion
120 - TRY..FINALLY..END; can be omitted
121 - if there is no m3wrapfreearg
122 - no exception can be raised in the body (empty RAISES) list
127 #include <limits.h> // for INT_MAX
130 #define USAGE_ARG_DIR "m3wrapargdir typemap expect values: in, out, inout\n"
132 class MODULA3:public Language {
134 enum block_type { no_block, constant, variable, blocktype, revelation };
141 /* VC++ 6 doesn't allow the access to 'no_block'
142 if it is a private member of MODULA3 class */
143 M3File():f(NewString("")), import(NewHash()), bt(no_block) {
150 /* -----------------------------------------------------------------------------
153 * Make sure that a given declaration is written to the right declaration block,
154 * that is constants are written after "CONST" and so on ...
155 * ----------------------------------------------------------------------------- */
156 void enterBlock(block_type newbt) {
157 static const char *ident[] = { "", "\nCONST\n", "\nVAR\n", "\nTYPE\n", "\nREVEAL\n" };
159 if ((bt < 0) || (4 < bt)) {
160 printf("bt %d out of range\n", bt);
164 Append(f, ident[newbt]);
171 static const char *usage;
172 const String *empty_string;
174 Hash *swig_types_hash;
181 bool proxy_flag; // Flag for generating proxy classes
182 bool have_default_constructor_flag;
183 bool native_function_flag; // Flag for when wrapping a native function
184 bool enum_constant_flag; // Flag for when wrapping an enum or constant
185 bool static_flag; // Flag for when wrapping a static functions or member variables
186 bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable
187 bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const
188 bool global_variable_flag; // Flag for when wrapping a global variable
189 bool old_variable_names; // Flag for old style variable names in the intermediary class
192 String *m3raw_name; // raw interface name
193 M3File m3raw_intf; // raw interface
194 M3File m3raw_impl; // raw implementation (usually empty)
195 String *m3wrap_name; // wrapper module
199 String *targetlibrary;
200 String *proxy_class_def;
201 String *proxy_class_code;
202 String *proxy_class_name;
203 String *variable_name; //Name of a variable being wrapped
204 String *variable_type; //Type of this variable
205 String *enumeration_name; //Name of the current enumeration type
206 Hash *enumeration_items; //and its members
208 Hash *enumeration_coll; //Collection of all enumerations.
209 /* The items are nodes with members:
210 "items" - hash of with key 'itemname' and content 'itemvalue'
211 "max" - maximum value in item list
213 String *constant_values;
214 String *constantfilename;
215 String *renamefilename;
216 String *typemapfilename;
217 String *m3raw_imports; //intermediary class imports from %pragma
218 String *module_imports; //module imports from %pragma
219 String *m3raw_baseclass; //inheritance for intermediary class class from %pragma
220 String *module_baseclass; //inheritance for module class from %pragma
221 String *m3raw_interfaces; //interfaces for intermediary class class from %pragma
222 String *module_interfaces; //interfaces for module class from %pragma
223 String *m3raw_class_modifiers; //class modifiers for intermediary class overriden by %pragma
224 String *m3wrap_modifiers; //class modifiers for module class overriden by %pragma
225 String *upcasts_code; //C++ casts for inheritance hierarchies C++ code
226 String *m3raw_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code
227 String *destructor_call; //C++ destructor call if any
230 enum type_additions { none, pointer, reference };
234 /* -----------------------------------------------------------------------------
236 * ----------------------------------------------------------------------------- */
239 empty_string(NewString("")),
240 swig_types_hash(NULL),
247 have_default_constructor_flag(false),
248 native_function_flag(false),
249 enum_constant_flag(false),
251 variable_wrapper_flag(false),
252 wrapping_member_flag(false),
253 global_variable_flag(false),
254 old_variable_names(false),
255 unsafe_module(false),
264 proxy_class_def(NULL),
265 proxy_class_code(NULL),
266 proxy_class_name(NULL),
269 enumeration_name(NULL),
270 enumeration_items(NULL),
272 enumeration_coll(NULL),
273 constant_values(NULL),
274 constantfilename(NULL),
275 renamefilename(NULL),
276 typemapfilename(NULL),
278 module_imports(NULL),
279 m3raw_baseclass(NULL),
280 module_baseclass(NULL),
281 m3raw_interfaces(NULL),
282 module_interfaces(NULL),
283 m3raw_class_modifiers(NULL),
284 m3wrap_modifiers(NULL),
286 m3raw_cppcasts_code(NULL),
287 destructor_call(NULL),
291 /************** some utility functions ***************/
293 /* -----------------------------------------------------------------------------
296 * Return the type of 'p' mapped by 'map'.
297 * Print a standard warning if 'p' can't be mapped.
298 * ----------------------------------------------------------------------------- */
300 String *getMappedType(Node *p, const char *map) {
301 String *mapattr = NewString("tmap:");
302 Append(mapattr, map);
304 String *tm = Getattr(p, mapattr);
306 Swig_warning(WARN_MODULA3_TYPEMAP_TYPE_UNDEF, input_file, line_number,
307 "No '%s' typemap defined for type '%s'\n", map, SwigType_str(Getattr(p, "type"), 0));
313 /* -----------------------------------------------------------------------------
316 * Similar to getMappedType but uses Swig_type_lookup_new.
317 * ----------------------------------------------------------------------------- */
319 String *getMappedTypeNew(Node *n, const char *map, const char *lname = "", bool warn = true) {
320 String *tm = Swig_typemap_lookup(map, n, lname, 0);
321 if ((tm == NIL) && warn) {
322 Swig_warning(WARN_MODULA3_TYPEMAP_TYPE_UNDEF, input_file, line_number,
323 "No '%s' typemap defined for type '%s'\n", map, SwigType_str(Getattr(n, "type"), 0));
328 /* -----------------------------------------------------------------------------
331 * Obtain the type mapped by 'map' and attach it to the node
332 * ----------------------------------------------------------------------------- */
334 void attachMappedType(Node *n, const char *map, const char *lname = "") {
335 String *tm = Swig_typemap_lookup(map, n, lname, 0);
337 String *attr = NewStringf("tmap:%s", map);
338 Setattr(n, attr, tm);
343 /* -----------------------------------------------------------------------------
346 * Skip all parameters that have 'numinputs=0'
347 * with respect to a given typemap.
348 * ----------------------------------------------------------------------------- */
350 Node *skipIgnored(Node *p, const char *map) {
351 String *niattr = NewStringf("tmap:%s:numinputs", map);
352 String *nextattr = NewStringf("tmap:%s:next", map);
354 while ((p != NIL) && checkAttribute(p, niattr, "0")) {
355 p = Getattr(p, nextattr);
363 /* -----------------------------------------------------------------------------
367 * Check if the parameter is intended for input or for output.
368 * ----------------------------------------------------------------------------- */
370 bool isInParam(Node *p) {
371 String *dir = Getattr(p, "tmap:m3wrapargdir");
372 //printf("dir for %s: %s\n", Char(Getattr(p,"name")), Char(dir));
373 if ((dir == NIL) || (Strcmp(dir, "in") == 0)
374 || (Strcmp(dir, "inout") == 0)) {
376 } else if (Strcmp(dir, "out") == 0) {
379 printf("%s", USAGE_ARG_DIR);
384 bool isOutParam(Node *p) {
385 String *dir = Getattr(p, "tmap:m3wrapargdir");
386 if ((dir == NIL) || (Strcmp(dir, "in") == 0)) {
388 } else if ((Strcmp(dir, "out") == 0) || (Strcmp(dir, "inout") == 0)) {
391 printf("%s", USAGE_ARG_DIR);
396 /* -----------------------------------------------------------------------------
399 * For debugging: Show all attributes of a node and their values.
400 * ----------------------------------------------------------------------------- */
401 void printAttrs(Node *n) {
403 for (it = First(n); it.key != NIL; it = Next(it)) {
404 printf("%s = %s\n", Char(it.key), Char(Getattr(n, it.key)));
408 /* -----------------------------------------------------------------------------
411 * Check if a string have a given prefix.
412 * ----------------------------------------------------------------------------- */
413 bool hasPrefix(const String *str, const String *prefix) {
414 int len_prefix = Len(prefix);
415 return (Len(str) > len_prefix)
416 && (Strncmp(str, prefix, len_prefix) == 0);
419 /* -----------------------------------------------------------------------------
422 * Return fully qualified identifier of n.
423 * ----------------------------------------------------------------------------- */
425 // Swig_symbol_qualified returns NIL for enumeration nodes
426 String *getQualifiedName(Node *n) {
427 String *qual = Swig_symbol_qualified(n);
428 String *name = Getattr(n, "name");
429 if (hasContent(qual)) {
430 return NewStringf("%s::%s", qual, name);
436 String *getQualifiedName(Node *n) {
437 String *name = Copy(Getattr(n, "name"));
440 const String *type = nodeType(n);
441 if ((Strcmp(type, "class") == 0) || (Strcmp(type, "struct") == 0) || (Strcmp(type, "namespace") == 0)) {
442 String *newname = NewStringf("%s::%s", Getattr(n, "name"), name);
445 // Hmpf, the class name is already qualified.
450 //printf("qualified name: %s\n", Char(name));
455 /* -----------------------------------------------------------------------------
458 * Turn usual C identifiers like "this_is_an_identifier"
459 * into usual Modula 3 identifier like "thisIsAnIdentifier"
460 * ----------------------------------------------------------------------------- */
461 String *nameToModula3(const String *sym, bool leadingCap) {
462 int len_sym = Len(sym);
463 char *csym = Char(sym);
464 char *m3sym = new char[len_sym + 1];
466 bool cap = leadingCap;
467 for (i = 0, j = 0; j < len_sym; j++) {
469 if ((c == '_') || (c == ':')) {
477 m3sym[i] = (char)toupper(c);
479 m3sym[i] = (char)tolower(c);
487 String *result = NewString(m3sym);
492 /* -----------------------------------------------------------------------------
495 * Make the first character upper case.
496 * ----------------------------------------------------------------------------- */
497 String *capitalizeFirst(const String *str) {
498 return NewStringf("%c%s", toupper(*Char(str)), Char(str) + 1);
501 /* -----------------------------------------------------------------------------
502 * prefixedNameToModula3()
504 * If feature modula3:oldprefix and modula3:newprefix is present
505 * and the C identifier has leading 'oldprefix'
506 * then it is replaced by the 'newprefix'.
507 * The rest is converted to Modula style.
508 * ----------------------------------------------------------------------------- */
509 String *prefixedNameToModula3(Node *n, const String *sym, bool leadingCap) {
510 String *oldPrefix = Getattr(n, "feature:modula3:oldprefix");
511 String *newPrefix = Getattr(n, "feature:modula3:newprefix");
512 String *result = NewString("");
513 char *short_sym = Char(sym);
514 // if at least one prefix feature is present
515 // the replacement takes place
516 if ((oldPrefix != NIL) || (newPrefix != NIL)) {
517 if ((oldPrefix == NIL) || hasPrefix(sym, oldPrefix)) {
518 short_sym += Len(oldPrefix);
519 if (newPrefix != NIL) {
520 Append(result, newPrefix);
524 String *suffix = nameToModula3(short_sym, leadingCap || hasContent(newPrefix));
525 Append(result, suffix);
530 /* -----------------------------------------------------------------------------
533 * Check if the string exists and contains something.
534 * ----------------------------------------------------------------------------- */
535 bool hasContent(const String *str) {
536 return (str != NIL) && (Strcmp(str, "") != 0);
539 /* -----------------------------------------------------------------------------
542 * Caution: The file must be freshly allocated and will be destroyed
544 * ----------------------------------------------------------------------------- */
546 File *openWriteFile(String *name) {
547 File *file = NewFile(name, "w", SWIG_output_files());
549 FileErrorDisplay(name);
550 SWIG_exit(EXIT_FAILURE);
556 /* -----------------------------------------------------------------------------
559 * like atol but with additional user warning
560 * ----------------------------------------------------------------------------- */
562 long aToL(const String *value) {
564 long numvalue = strtol(Char(value), &endptr, 0);
566 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "The string <%s> does not denote a numeric value.\n", value);
571 /* -----------------------------------------------------------------------------
574 * like strtol but returns if the conversion was successful
575 * ----------------------------------------------------------------------------- */
577 bool strToL(const String *value, long &numvalue) {
579 numvalue = strtol(Char(value), &endptr, 0);
580 return (*endptr == 0);
583 /* -----------------------------------------------------------------------------
586 * Evaluate simple expression as they may occur in "enumvalue" attributes.
587 * ----------------------------------------------------------------------------- */
589 bool evalExpr(String *value, long &numvalue) {
590 // Split changes file status of String and thus cannot receive 'const' strings
591 //printf("evaluate <%s>\n", Char(value));
592 List *summands = Split(value, '+', INT_MAX);
593 Iterator sm = First(summands);
595 for (; sm.item != NIL; sm = Next(sm)) {
596 String *smvalue = Getattr(constant_values, sm.item);
598 if (smvalue != NIL) {
599 if (!strToL(smvalue, smnumvalue)) {
600 //printf("evaluation: abort 0 <%s>\n", Char(smvalue));
604 if (!strToL(sm.item, smnumvalue)) {
605 //printf("evaluation: abort 1 <%s>\n", Char(sm));
609 numvalue += smnumvalue;
611 //printf("evaluation: return %ld\n", numvalue);
615 /* -----------------------------------------------------------------------------
618 * Determine the position of the single bit of a power of two.
619 * Returns true if the given number is a power of two.
620 * ----------------------------------------------------------------------------- */
622 bool log2(long n, long &exp) {
634 /* -----------------------------------------------------------------------------
637 * Write a function argument or RECORD entry definition.
638 * Bundles arguments of same type and default value.
639 * 'name.next==NIL' denotes the end of the entry or argument list.
640 * ----------------------------------------------------------------------------- */
642 bool equalNilStr(const String *str0, const String *str1) {
644 return (str1 == NIL);
645 //return (str0==NIL) == (str1==NIL);
647 return (str1 != NIL) && (Cmp(str0, str1) == 0);
648 //return Cmp(str0,str1)==0;
652 struct writeArgState {
653 String *mode, *name, *type, *value;
655 writeArgState():mode(NIL), name(NIL), type(NIL), value(NIL), hold(false) {
659 void writeArg(File *f, writeArgState & state, String *mode, String *name, String *type, String *value) {
660 /* skip the first argument,
661 only store the information for the next call in this case */
662 if (state.name != NIL) {
663 if ((!state.hold) && (state.mode != NIL)) {
664 Printf(f, "%s ", state.mode);
666 if ((name != NIL) && equalNilStr(state.mode, mode) && equalNilStr(state.type, type) && (state.value == NIL) && (value == NIL)
667 /* the same expression may have different values
668 due to side effects of the called function */
669 /*equalNilStr(state.value,value) */
671 Printf(f, "%s, ", state.name);
674 Append(f, state.name);
675 if (state.type != NIL) {
676 Printf(f, ": %s", state.type);
678 if (state.value != NIL) {
679 Printf(f, ":= %s", state.value);
685 /* at the next call the current argument will be the previous one */
692 /* -----------------------------------------------------------------------------
695 * Test to see if a type corresponds to something wrapped with a proxy class
696 * Return NULL if not otherwise the proxy class name
697 * ----------------------------------------------------------------------------- */
699 String *getProxyName(SwigType *t) {
701 Node *n = classLookup(t);
703 return Getattr(n, "sym:name");
709 /*************** language processing ********************/
711 /* ------------------------------------------------------------
713 * ------------------------------------------------------------ */
715 virtual void main(int argc, char *argv[]) {
717 SWIG_library_directory("modula3");
719 // Look for certain command line options
720 for (int i = 1; i < argc; i++) {
722 if (strcmp(argv[i], "-generateconst") == 0) {
724 constantfilename = NewString(argv[i + 1]);
726 Swig_mark_arg(i + 1);
731 } else if (strcmp(argv[i], "-generaterename") == 0) {
733 renamefilename = NewString(argv[i + 1]);
735 Swig_mark_arg(i + 1);
740 } else if (strcmp(argv[i], "-generatetypemap") == 0) {
742 typemapfilename = NewString(argv[i + 1]);
744 Swig_mark_arg(i + 1);
749 } else if (strcmp(argv[i], "-noproxy") == 0) {
752 } else if (strcmp(argv[i], "-oldvarnames") == 0) {
754 old_variable_names = true;
755 } else if (strcmp(argv[i], "-help") == 0) {
756 Printf(stdout, "%s\n", usage);
761 // Add a symbol to the parser for conditional compilation
762 Preprocessor_define("SWIGMODULA3 1", 0);
764 // Add typemap definitions
765 SWIG_typemap_lang("modula3");
766 SWIG_config_file("modula3.swg");
771 /* ---------------------------------------------------------------------
773 * --------------------------------------------------------------------- */
775 virtual int top(Node *n) {
776 if (hasContent(constantfilename) || hasContent(renamefilename) || hasContent(typemapfilename)) {
777 int result = SWIG_OK;
778 if (hasContent(constantfilename)) {
779 result = generateConstantTop(n) && result;
781 if (hasContent(renamefilename)) {
782 result = generateRenameTop(n) && result;
784 if (hasContent(typemapfilename)) {
785 result = generateTypemapTop(n) && result;
789 return generateM3Top(n);
793 void scanConstant(File *file, Node *n) {
794 Node *child = firstChild(n);
795 while (child != NIL) {
796 String *constname = NIL;
797 String *type = nodeType(child);
798 if ((Strcmp(type, "enumitem") == 0)
799 || (Strcmp(type, "constant") == 0)) {
801 constname = getQualifiedName(child);
803 constname = Getattr(child, "value");
804 if ((!hasContent(constname))
805 || (('0' <= *Char(constname)) && (*Char(constname) <= '9'))) {
806 constname = Getattr(child, "name");
810 if (constname != NIL) {
811 Printf(file, " printf(\"%%%%constnumeric(%%Lg) %s;\\n\", (long double)%s);\n", constname, constname);
813 scanConstant(file, child);
814 child = nextSibling(child);
818 int generateConstantTop(Node *n) {
819 File *file = openWriteFile(NewStringf("%s.c", constantfilename));
821 Printf(file, "#include <cstdio>\n");
823 Printf(file, "#include <stdio.h>\n");
825 Printf(file, "#include \"%s\"\n", input_file);
827 Printf(file, "int main (int argc, char *argv[]) {\n");
829 /*This progam must work for floating point numbers and integers.\n\
830 Thus all numbers are converted to double precision floating point format.*/\n");
831 scanConstant(file, n);
832 Printf(file, " return 0;\n");
838 void scanRename(File *file, Node *n) {
839 Node *child = firstChild(n);
840 while (child != NIL) {
841 String *type = nodeType(child);
842 if (Strcmp(type, "cdecl") == 0) {
843 ParmList *p = Getattr(child, "parms");
845 String *name = getQualifiedName(child);
846 String *m3name = nameToModula3(name, true);
847 /*don't know how to get the original C type identifiers */
848 //String *arguments = createCSignature (child);
849 Printf(file, "%%rename(\"%s\") %s;\n", m3name, name);
850 /*Printf(file, "%%rename(\"%s\") %s %s(%s);\n",
851 m3name, Getattr(n,"type"), name, arguments); */
854 //Delete (arguments);
857 scanRename(file, child);
858 child = nextSibling(child);
862 int generateRenameTop(Node *n) {
863 File *file = openWriteFile(NewStringf("%s.i", renamefilename));
865 /* This file was generated from %s\n\
866 by SWIG with option -generaterename. */\n\
873 void scanTypemap(File *file, Node *n) {
874 Node *child = firstChild(n);
875 while (child != NIL) {
876 String *type = nodeType(child);
877 //printf("nodetype %s\n", Char(type));
878 String *storage = Getattr(child, "storage");
879 if ((Strcmp(type, "class") == 0) || ((Strcmp(type, "cdecl") == 0) && (storage != NIL)
880 && (Strcmp(storage, "typedef") == 0))) {
881 String *name = getQualifiedName(child);
882 String *m3name = nameToModula3(name, true);
883 Printf(file, "%%typemap(\"m3wrapintype\") %s %%{%s%%}\n", name, m3name);
884 Printf(file, "%%typemap(\"m3rawintype\") %s %%{%s%%}\n", name, m3name);
887 scanTypemap(file, child);
888 child = nextSibling(child);
892 int generateTypemapTop(Node *n) {
893 File *file = openWriteFile(NewStringf("%s.i", typemapfilename));
895 /* This file was generated from %s\n\
896 by SWIG with option -generatetypemap. */\n\
898 scanTypemap(file, n);
903 int generateM3Top(Node *n) {
904 /* Initialize all of the output files */
905 outfile = Getattr(n, "outfile");
907 f_begin = NewFile(outfile, "w", SWIG_output_files());
909 FileErrorDisplay(outfile);
910 SWIG_exit(EXIT_FAILURE);
912 f_runtime = NewString("");
913 f_init = NewString("");
914 f_header = NewString("");
915 f_wrappers = NewString("");
917 m3makefile = NewString("");
919 /* Register file targets with the SWIG file handler */
920 Swig_register_filebyname("header", f_header);
921 Swig_register_filebyname("wrapper", f_wrappers);
922 Swig_register_filebyname("begin", f_begin);
923 Swig_register_filebyname("runtime", f_runtime);
924 Swig_register_filebyname("init", f_init);
926 Swig_register_filebyname("m3rawintf", m3raw_intf.f);
927 Swig_register_filebyname("m3rawimpl", m3raw_impl.f);
928 Swig_register_filebyname("m3wrapintf", m3wrap_intf.f);
929 Swig_register_filebyname("m3wrapimpl", m3wrap_impl.f);
930 Swig_register_filebyname("m3makefile", m3makefile);
932 swig_types_hash = NewHash();
934 String *name = Getattr(n, "name");
935 // Make the intermediary class and module class names. The intermediary class name can be set in the module directive.
936 Node *optionsnode = Getattr(Getattr(n, "module"), "options");
937 if (optionsnode != NIL) {
938 String *m3raw_name_tmp = Getattr(optionsnode, "m3rawname");
939 if (m3raw_name_tmp != NIL) {
940 m3raw_name = Copy(m3raw_name_tmp);
943 if (m3raw_name == NIL) {
944 m3raw_name = NewStringf("%sRaw", name);
946 Setattr(m3wrap_impl.import, m3raw_name, "");
948 m3wrap_name = Copy(name);
950 proxy_class_def = NewString("");
951 proxy_class_code = NewString("");
952 m3raw_baseclass = NewString("");
953 m3raw_interfaces = NewString("");
954 m3raw_class_modifiers = NewString(""); // package access only to the intermediary class by default
955 m3raw_imports = NewString("");
956 m3raw_cppcasts_code = NewString("");
957 m3wrap_modifiers = NewString("public");
958 module_baseclass = NewString("");
959 module_interfaces = NewString("");
960 module_imports = NewString("");
961 upcasts_code = NewString("");
963 Swig_banner(f_begin);
965 Printf(f_runtime, "\n");
966 Printf(f_runtime, "#define SWIGMODULA3\n");
967 Printf(f_runtime, "\n");
969 Swig_name_register((char *) "wrapper", (char *) "Modula3_%f");
970 if (old_variable_names) {
971 Swig_name_register((char *) "set", (char *) "set_%v");
972 Swig_name_register((char *) "get", (char *) "get_%v");
975 Printf(f_wrappers, "\n#ifdef __cplusplus\n");
976 Printf(f_wrappers, "extern \"C\" {\n");
977 Printf(f_wrappers, "#endif\n\n");
979 constant_values = NewHash();
980 scanForConstPragmas(n);
981 enumeration_coll = NewHash();
982 collectEnumerations(enumeration_coll, n);
987 // Generate m3makefile
988 // This will be unnecessary if SWIG is invoked from Quake.
990 File *file = openWriteFile(NewStringf("%sm3makefile", Swig_file_dirname(outfile)));
992 Printf(file, "%% automatically generated quake file for %s\n\n", name);
994 /* Write the fragments written by '%insert'
995 collected while 'top' processed the parse tree */
996 Printv(file, m3makefile, NIL);
998 Printf(file, "import(\"libm3\")\n");
999 //Printf(file, "import_lib(\"%s\",\"/usr/lib\")\n", name);
1000 Printf(file, "module(\"%s\")\n", m3raw_name);
1001 Printf(file, "module(\"%s\")\n\n", m3wrap_name);
1003 if (targetlibrary != NIL) {
1004 Printf(file, "library(\"%s\")\n", targetlibrary);
1006 Printf(file, "library(\"m3%s\")\n", name);
1011 // Generate the raw interface
1013 File *file = openWriteFile(NewStringf("%s%s.i3", Swig_file_dirname(outfile), m3raw_name));
1017 Printf(file, "INTERFACE %s;\n\n", m3raw_name);
1019 emitImportStatements(m3raw_intf.import, file);
1022 // Write the interface generated within 'top'
1023 Printv(file, m3raw_intf.f, NIL);
1025 Printf(file, "\nEND %s.\n", m3raw_name);
1029 // Generate the raw module
1031 File *file = openWriteFile(NewStringf("%s%s.m3", Swig_file_dirname(outfile), m3raw_name));
1035 Printf(file, "MODULE %s;\n\n", m3raw_name);
1037 emitImportStatements(m3raw_impl.import, file);
1040 // will be empty usually
1041 Printv(file, m3raw_impl.f, NIL);
1043 Printf(file, "BEGIN\nEND %s.\n", m3raw_name);
1047 // Generate the interface for the comfort wrappers
1049 File *file = openWriteFile(NewStringf("%s%s.i3", Swig_file_dirname(outfile), m3wrap_name));
1053 Printf(file, "INTERFACE %s;\n", m3wrap_name);
1055 emitImportStatements(m3wrap_intf.import, file);
1059 Iterator it = First(enumeration_coll);
1060 if (it.key != NIL) {
1061 Printf(file, "TYPE\n");
1063 for (; it.key != NIL; it = Next(it)) {
1065 emitEnumeration(file, it.key, it.item);
1069 // Add the wrapper methods
1070 Printv(file, m3wrap_intf.f, NIL);
1072 // Finish off the class
1073 Printf(file, "\nEND %s.\n", m3wrap_name);
1077 // Generate the wrapper routines implemented in Modula 3
1079 File *file = openWriteFile(NewStringf("%s%s.m3", Swig_file_dirname(outfile), m3wrap_name));
1083 if (unsafe_module) {
1084 Printf(file, "UNSAFE ");
1086 Printf(file, "MODULE %s;\n\n", m3wrap_name);
1088 emitImportStatements(m3wrap_impl.import, file);
1091 // Add the wrapper methods
1092 Printv(file, m3wrap_impl.f, NIL);
1094 Printf(file, "\nBEGIN\nEND %s.\n", m3wrap_name);
1099 Printv(f_wrappers, upcasts_code, NIL);
1101 Printf(f_wrappers, "#ifdef __cplusplus\n");
1102 Printf(f_wrappers, "}\n");
1103 Printf(f_wrappers, "#endif\n");
1105 // Output a Modula 3 type wrapper class for each SWIG type
1106 for (Iterator swig_type = First(swig_types_hash); swig_type.item != NIL; swig_type = Next(swig_type)) {
1107 emitTypeWrapperClass(swig_type.key, swig_type.item);
1110 Delete(swig_types_hash);
1111 swig_types_hash = NULL;
1112 Delete(constant_values);
1113 constant_values = NULL;
1114 Delete(enumeration_coll);
1115 enumeration_coll = NULL;
1118 Delete(m3raw_baseclass);
1119 m3raw_baseclass = NULL;
1120 Delete(m3raw_interfaces);
1121 m3raw_interfaces = NULL;
1122 Delete(m3raw_class_modifiers);
1123 m3raw_class_modifiers = NULL;
1124 Delete(m3raw_imports);
1125 m3raw_imports = NULL;
1126 Delete(m3raw_cppcasts_code);
1127 m3raw_cppcasts_code = NULL;
1128 Delete(proxy_class_def);
1129 proxy_class_def = NULL;
1130 Delete(proxy_class_code);
1131 proxy_class_code = NULL;
1132 Delete(m3wrap_name);
1134 Delete(m3wrap_modifiers);
1135 m3wrap_modifiers = NULL;
1136 Delete(targetlibrary);
1137 targetlibrary = NULL;
1138 Delete(module_baseclass);
1139 module_baseclass = NULL;
1140 Delete(module_interfaces);
1141 module_interfaces = NULL;
1142 Delete(module_imports);
1143 module_imports = NULL;
1144 Delete(upcasts_code);
1145 upcasts_code = NULL;
1146 Delete(constantfilename);
1147 constantfilename = NULL;
1148 Delete(renamefilename);
1149 renamefilename = NULL;
1150 Delete(typemapfilename);
1151 typemapfilename = NULL;
1153 /* Close all of the files */
1154 Dump(f_runtime, f_begin);
1155 Dump(f_header, f_begin);
1156 Dump(f_wrappers, f_begin);
1157 Wrapper_pretty_print(f_init, f_begin);
1167 /* -----------------------------------------------------------------------------
1169 * ----------------------------------------------------------------------------- */
1171 void emitBanner(File *f) {
1172 Printf(f, "(*******************************************************************************\n");
1173 Swig_banner_target_lang(f, " *");
1174 Printf(f, "*******************************************************************************)\n\n");
1177 /* ----------------------------------------------------------------------
1179 * ---------------------------------------------------------------------- */
1181 virtual int nativeWrapper(Node *n) {
1182 String *wrapname = Getattr(n, "wrap:name");
1184 if (!addSymbol(wrapname, n))
1187 if (Getattr(n, "type")) {
1188 Swig_save("nativeWrapper", n, "name", NIL);
1189 Setattr(n, "name", wrapname);
1190 native_function_flag = true;
1193 native_function_flag = false;
1195 Printf(stderr, "%s : Line %d. No return type for %%native method %s.\n", input_file, line_number, Getattr(n, "wrap:name"));
1201 /* ----------------------------------------------------------------------
1203 * ---------------------------------------------------------------------- */
1205 virtual int functionWrapper(Node *n) {
1206 String *type = nodeType(n);
1207 String *funcType = Getattr(n, "modula3:functype");
1208 String *rawname = Getattr(n, "name");
1209 String *symname = Getattr(n, "sym:name");
1210 String *capname = capitalizeFirst(symname);
1211 //String *wname = Swig_name_wrapper(symname);
1213 //printf("function: %s\n", Char(symname));
1214 //printf(" purpose: %s\n", Char(funcType));
1216 if (Strcmp(type, "cdecl") == 0) {
1217 if (funcType == NIL) {
1218 // no wrapper needed for plain functions
1219 emitM3RawPrototype(n, rawname, symname);
1220 emitM3Wrapper(n, symname);
1221 } else if (Strcmp(funcType, "method") == 0) {
1222 Setattr(n, "modula3:funcname", capname);
1223 emitCWrapper(n, capname);
1224 emitM3RawPrototype(n, capname, capname);
1225 emitM3Wrapper(n, capname);
1226 } else if (Strcmp(funcType, "accessor") == 0) {
1228 * Generate the proxy class properties for public member variables.
1229 * Not for enums and constants.
1231 if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
1232 // Capitalize the first letter in the function name
1233 Setattr(n, "proxyfuncname", capname);
1234 Setattr(n, "imfuncname", symname);
1235 if (hasPrefix(capname, "Set")) {
1236 Setattr(n, "modula3:setname", capname);
1238 Setattr(n, "modula3:getname", capname);
1241 emitCWrapper(n, capname);
1242 emitM3RawPrototype(n, capname, capname);
1243 emitM3Wrapper(n, capname);
1244 //proxyClassFunctionHandler(n);
1248 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Function type <%s> unknown.\n", Char(funcType));
1251 } else if ((Strcmp(type, "constructor") == 0) || (Strcmp(type, "destructor") == 0)) {
1252 emitCWrapper(n, capname);
1253 emitM3RawPrototype(n, capname, capname);
1254 emitM3Wrapper(n, capname);
1258 if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) {
1259 emitM3Wrapper(n, capname);
1268 /* ----------------------------------------------------------------------
1271 * Generate the wrapper in C which calls C++ methods.
1272 * ---------------------------------------------------------------------- */
1274 virtual int emitCWrapper(Node *n, const String *wname) {
1275 String *rawname = Getattr(n, "name");
1276 String *c_return_type = NewString("");
1277 String *cleanup = NewString("");
1278 String *outarg = NewString("");
1279 String *body = NewString("");
1280 Hash *throws_hash = NewHash();
1281 ParmList *l = Getattr(n, "parms");
1282 SwigType *t = Getattr(n, "type");
1283 String *symname = Getattr(n, "sym:name");
1285 if (!Getattr(n, "sym:overloaded")) {
1286 if (!addSymbol(wname, n)) {
1290 // A new wrapper function object
1291 Wrapper *f = NewWrapper();
1293 /* Attach the non-standard typemaps to the parameter list. */
1294 Swig_typemap_attach_parms("ctype", l, f);
1296 /* Get return types */
1298 String *tm = getMappedTypeNew(n, "ctype", "");
1300 Printf(c_return_type, "%s", tm);
1304 bool is_void_return = (Cmp(c_return_type, "void") == 0);
1305 if (!is_void_return) {
1306 Wrapper_add_localv(f, "cresult", c_return_type, "cresult = 0", NIL);
1309 Printv(f->def, " SWIGEXPORT ", c_return_type, " ", wname, "(", NIL);
1311 // Emit all of the local variables for holding arguments.
1312 emit_parameter_variables(l, f);
1314 /* Attach the standard typemaps */
1315 emit_attach_parmmaps(l, f);
1316 Setattr(n, "wrap:parms", l);
1318 // Generate signature and argument conversion for C wrapper
1321 attachParameterNames(n, "tmap:name", "c:wrapname", "m3arg%d");
1322 bool gencomma = false;
1323 for (p = skipIgnored(l, "in"); p != NULL; p = skipIgnored(p, "in")) {
1325 String *arg = Getattr(p, "c:wrapname");
1327 /* Get the ctype types of the parameter */
1328 String *c_param_type = getMappedType(p, "ctype");
1329 // Add parameter to C function
1330 Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
1331 Delete(c_param_type);
1335 // Get typemap for this argument
1336 String *tm = getMappedType(p, "in");
1338 addThrows(throws_hash, "in", p);
1339 Replaceall(tm, "$input", arg);
1340 Setattr(p, "emit:input", arg); /*??? */
1341 Printf(f->code, "%s\n", tm);
1342 p = Getattr(p, "tmap:in:next");
1349 /* Insert constraint checking code */
1353 String *tm = Getattr(p, "tmap:check");
1355 addThrows(throws_hash, "check", p);
1356 Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
1357 Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
1358 Replaceall(tm, "$input", Getattr(p, "emit:input"));
1359 Printv(f->code, tm, "\n", NIL);
1360 p = Getattr(p, "tmap:check:next");
1367 /* Insert cleanup code */
1371 String *tm = Getattr(p, "tmap:freearg");
1373 addThrows(throws_hash, "freearg", p);
1374 Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
1375 Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
1376 Replaceall(tm, "$input", Getattr(p, "emit:input"));
1377 Printv(cleanup, tm, "\n", NIL);
1378 p = Getattr(p, "tmap:freearg:next");
1385 /* Insert argument output code */
1389 String *tm = Getattr(p, "tmap:argout");
1391 addThrows(throws_hash, "argout", p);
1392 Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */
1393 Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */
1394 Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */
1395 Replaceall(tm, "$result", "cresult");
1396 Replaceall(tm, "$input", Getattr(p, "emit:input"));
1397 Printv(outarg, tm, "\n", NIL);
1398 p = Getattr(p, "tmap:argout:next");
1405 // Get any Modula 3 exception classes in the throws typemap
1406 ParmList *throw_parm_list = NULL;
1407 if ((throw_parm_list = Getattr(n, "catchlist"))) {
1408 Swig_typemap_attach_parms("throws", throw_parm_list, f);
1410 for (p = throw_parm_list; p; p = nextSibling(p)) {
1411 addThrows(throws_hash, "throws", p);
1415 if (Cmp(nodeType(n), "constant") == 0) {
1416 // Wrapping a constant hack
1417 Swig_save("functionWrapper", n, "wrap:action", NIL);
1419 // below based on Swig_VargetToFunction()
1420 SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
1421 Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value")));
1424 Setattr(n, "wrap:name", wname);
1426 // Now write code to make the function call
1427 if (!native_function_flag) {
1428 String *actioncode = emit_action(n);
1430 if (Cmp(nodeType(n), "constant") == 0) {
1434 /* Return value if necessary */
1436 if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
1437 addThrows(throws_hash, "out", n);
1438 Replaceall(tm, "$source", "result"); /* deprecated */
1439 Replaceall(tm, "$target", "cresult"); /* deprecated */
1440 Replaceall(tm, "$result", "cresult");
1441 Printf(f->code, "%s", tm);
1443 Printf(f->code, "\n");
1445 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);
1447 emit_return_variable(n, t, f);
1450 /* Output argument output code */
1451 Printv(f->code, outarg, NIL);
1453 /* Output cleanup code */
1454 Printv(f->code, cleanup, NIL);
1456 /* Look to see if there is any newfree cleanup code */
1457 if (GetFlag(n, "feature:new")) {
1458 String *tm = Swig_typemap_lookup("newfree", n, "result", 0);
1460 addThrows(throws_hash, "newfree", n);
1461 Replaceall(tm, "$source", "result"); /* deprecated */
1462 Printf(f->code, "%s\n", tm);
1466 /* See if there is any return cleanup code */
1467 if (!native_function_flag) {
1468 String *tm = Swig_typemap_lookup("ret", n, "result", 0);
1470 Replaceall(tm, "$source", "result"); /* deprecated */
1471 Printf(f->code, "%s\n", tm);
1475 /* Finish C wrapper */
1476 Printf(f->def, ") {");
1478 if (!is_void_return)
1479 Printv(f->code, " return cresult;\n", NIL);
1480 Printf(f->code, "}\n");
1482 /* Substitute the cleanup code */
1483 Replaceall(f->code, "$cleanup", cleanup);
1485 /* Substitute the function name */
1486 Replaceall(f->code, "$symname", symname);
1488 if (!is_void_return) {
1489 Replaceall(f->code, "$null", "0");
1491 Replaceall(f->code, "$null", "");
1494 /* Dump the function out */
1495 if (!native_function_flag) {
1496 Wrapper_print(f, f_wrappers);
1499 Delete(c_return_type);
1503 Delete(throws_hash);
1508 /* ----------------------------------------------------------------------
1509 * emitM3RawPrototype()
1511 * Generate an EXTERNAL procedure declaration in Modula 3
1512 * which is the interface to an existing C routine or a C wrapper.
1513 * ---------------------------------------------------------------------- */
1515 virtual int emitM3RawPrototype(Node *n, const String *cname, const String *m3name) {
1516 String *im_return_type = NewString("");
1517 //String *symname = Getattr(n,"sym:name");
1518 ParmList *l = Getattr(n, "parms");
1520 /* Attach the non-standard typemaps to the parameter list. */
1521 Swig_typemap_attach_parms("m3rawinmode", l, NULL);
1522 Swig_typemap_attach_parms("m3rawintype", l, NULL);
1524 /* Get return types */
1527 String *tm = getMappedTypeNew(n, "m3rawrettype", "");
1529 Printf(im_return_type, "%s", tm);
1531 has_return = hasContent(tm);
1534 /* cname is the original name if 'n' denotes a C function
1535 and it is the relabeled name (sym:name) if 'n' denotes a C++ method or similar */
1536 m3raw_intf.enterBlock(no_block);
1537 Printf(m3raw_intf.f, "\n<* EXTERNAL %s *>\nPROCEDURE %s (", cname, m3name);
1539 // Generate signature for raw interface
1542 writeArgState state;
1543 attachParameterNames(n, "tmap:rawinname", "modula3:rawname", "arg%d");
1544 for (p = skipIgnored(l, "m3rawintype"); p != NULL; p = skipIgnored(p, "m3rawintype")) {
1546 /* Get argument passing mode, should be one of VALUE, VAR, READONLY */
1547 String *mode = Getattr(p, "tmap:m3rawinmode");
1548 String *argname = Getattr(p, "modula3:rawname");
1549 String *im_param_type = getMappedType(p, "m3rawintype");
1550 addImports(m3raw_intf.import, "m3rawintype", p);
1552 writeArg(m3raw_intf.f, state, mode, argname, im_param_type, NIL);
1553 if (im_param_type != NIL) {
1554 p = Getattr(p, "tmap:m3rawintype:next");
1559 writeArg(m3raw_intf.f, state, NIL, NIL, NIL, NIL);
1562 /* Finish M3 raw prototype */
1563 Printf(m3raw_intf.f, ")");
1564 // neither a C wrapper nor a plain C function may throw an exception
1565 //generateThrowsClause(throws_hash, m3raw_intf.f);
1567 Printf(m3raw_intf.f, ": %s", im_return_type);
1569 Printf(m3raw_intf.f, ";\n");
1571 Delete(im_return_type);
1575 /* -----------------------------------------------------------------------
1577 * ----------------------------------------------------------------------- */
1579 virtual int variableWrapper(Node *n) {
1580 Language::variableWrapper(n);
1584 /* -----------------------------------------------------------------------
1585 * globalvariableHandler()
1586 * ----------------------------------------------------------------------- */
1588 virtual int globalvariableHandler(Node *n) {
1589 SwigType *t = Getattr(n, "type");
1592 // Get the variable type
1593 if ((tm = getMappedTypeNew(n, "m3wraptype", ""))) {
1594 substituteClassname(t, tm);
1597 variable_name = Getattr(n, "sym:name");
1598 variable_type = Copy(tm);
1600 // Get the variable type expressed in terms of Modula 3 equivalents of C types
1601 if ((tm = getMappedTypeNew(n, "m3rawtype", ""))) {
1602 m3raw_intf.enterBlock(no_block);
1603 Printf(m3raw_intf.f, "\n<* EXTERNAL *> VAR %s: %s;\n", variable_name, tm);
1605 // Output the property's accessor methods
1607 global_variable_flag = true;
1608 int ret = Language::globalvariableHandler(n);
1609 global_variable_flag = false;
1612 Printf(m3wrap_impl.f, "\n\n");
1618 long getConstNumeric(Node *n) {
1619 String *constnumeric = Getfeature(n, "constnumeric");
1620 String *name = Getattr(n, "name");
1622 if (constnumeric == NIL) {
1623 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Feature 'constnumeric' is necessary to obtain value of %s.\n", name);
1625 } else if (!strToL(constnumeric, numvalue)) {
1626 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number,
1627 "The feature 'constnumeric' of %s specifies value <%s> which is not an integer constant.\n", name, constnumeric);
1634 /* ------------------------------------------------------------------------
1635 * generateIntConstant()
1637 * Considers node as an integer constant definition
1638 * and generate a Modula 3 constant definition.
1639 * ------------------------------------------------------------------------ */
1640 void generateIntConstant(Node *n, String *name) {
1641 String *value = Getattr(n, "value");
1642 String *type = Getfeature(n, "modula3:constint:type");
1643 String *conv = Getfeature(n, "modula3:constint:conv");
1646 name = Getattr(n, "sym:name");
1650 bool isSimpleNum = strToL(value, numvalue);
1652 numvalue = getConstNumeric(n);
1656 if ((conv == NIL) || ((Strcmp(conv, "set:int") != 0) && (Strcmp(conv, "int:set") != 0))) {
1657 /* The original value of the constant has precedence over
1658 'constnumeric' feature since we like to keep
1659 the style (that is the base) of simple numeric constants */
1661 if (hasPrefix(value, "0x")) {
1662 m3value = NewStringf("16_%s", Char(value) + 2);
1663 } else if ((Len(value) > 1) && (*Char(value) == '0')) {
1664 m3value = NewStringf("8_%s", Char(value) + 1);
1666 m3value = Copy(value);
1668 /* If we cannot easily obtain the value of a numeric constant,
1669 we use the results given by a C compiler. */
1671 m3value = Copy(Getfeature(n, "constnumeric"));
1674 // if the value can't be converted, it is ignored
1675 if (convertInt(numvalue, numvalue, conv)) {
1676 m3value = NewStringf("%d", numvalue);
1682 if (m3value != NIL) {
1683 m3wrap_intf.enterBlock(constant);
1684 Printf(m3wrap_intf.f, "%s", name);
1685 if (hasContent(type)) {
1686 Printf(m3wrap_intf.f, ": %s", type);
1688 Printf(m3wrap_intf.f, " = %s;\n", m3value);
1693 /* -----------------------------------------------------------------------
1694 * generateSetConstant()
1696 * Considers node as a set constant definition
1697 * and generate a Modula 3 constant definition.
1698 * ------------------------------------------------------------------------ */
1699 void generateSetConstant(Node *n, String *name) {
1700 String *value = Getattr(n, "value");
1701 String *type = Getfeature(n, "modula3:constset:type");
1702 String *setname = Getfeature(n, "modula3:constset:set");
1703 String *basename = Getfeature(n, "modula3:constset:base");
1704 String *conv = Getfeature(n, "modula3:constset:conv");
1706 m3wrap_intf.enterBlock(constant);
1708 Printf(m3wrap_intf.f, "%s", name);
1710 Printf(m3wrap_intf.f, ":%s ", type);
1712 Printf(m3wrap_intf.f, " = %s{", setname);
1715 if (!strToL(value, numvalue)) {
1716 numvalue = getConstNumeric(n);
1718 convertInt(numvalue, numvalue, conv);
1720 bool isIntType = Strcmp(basename, "CARDINAL") == 0;
1723 Hash *enumeration = Getattr(enumeration_coll, basename);
1724 if (enumeration == NIL) {
1725 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "There is no enumeration <%s> as needed for the set.\n", setname);
1728 items = Getattr(enumeration, "items");
1732 bool gencomma = false;
1734 while (numvalue > 0) {
1735 if ((numvalue & 1) != 0) {
1738 Printv(m3wrap_intf.f, ",", NIL);
1741 Printf(m3wrap_intf.f, "%d", bitpos);
1744 sprintf(bitval, "%d", bitpos);
1745 String *bitname = Getattr(items, bitval);
1746 if (bitname == NIL) {
1747 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Enumeration <%s> has no value <%s>.\n", setname, bitval);
1750 Printv(m3wrap_intf.f, ",", NIL);
1753 Printf(m3wrap_intf.f, "%s.%s", basename, bitname);
1760 Printf(m3wrap_intf.f, "};\n");
1763 void generateConstant(Node *n) {
1764 // any of the special interpretation disables the default behaviour
1765 String *enumitem = Getfeature(n, "modula3:enumitem:name");
1766 String *constset = Getfeature(n, "modula3:constset:name");
1767 String *constint = Getfeature(n, "modula3:constint:name");
1768 if (hasContent(enumitem) || hasContent(constset) || hasContent(constint)) {
1769 if (hasContent(constset)) {
1770 generateSetConstant(n, constset);
1772 if (hasContent(constint)) {
1773 generateIntConstant(n, constint);
1776 String *value = Getattr(n, "value");
1777 String *name = Getattr(n, "sym:name");
1779 name = Getattr(n, "name");
1781 m3wrap_intf.enterBlock(constant);
1782 Printf(m3wrap_intf.f, "%s = %s;\n", name, value);
1787 void generateEnumerationItem(const String *name, const String *value, int numvalue) {
1788 String *oldsymname = Getattr(enumeration_items, value);
1789 if (oldsymname != NIL) {
1790 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "The value <%s> is already assigned to <%s>.\n", value, oldsymname);
1792 Setattr(enumeration_items, value, name);
1793 if (enumeration_max < numvalue) {
1794 enumeration_max = numvalue;
1799 void emitEnumeration(File *file, String *name, Node *n) {
1800 Printf(file, "%s = {", name);
1802 bool gencomma = false;
1803 int max = aToL(Getattr(n, "max"));
1804 Hash *items = Getattr(n, "items");
1805 for (i = 0; i <= max; i++) {
1812 sprintf(numstr, "%d", i);
1813 String *name = Getattr(items, numstr);
1815 Printv(file, name, NIL);
1817 Printf(file, "Dummy%d", i);
1820 Printf(file, "\n};\n");
1823 /* -----------------------------------------------------------------------
1826 * Handles constants and enumeration items.
1827 * ------------------------------------------------------------------------ */
1829 virtual int constantWrapper(Node *n) {
1830 generateConstant(n);
1835 // enumerations are handled like constant definitions
1836 /* -----------------------------------------------------------------------------
1838 * ----------------------------------------------------------------------------- */
1840 virtual int enumDeclaration(Node *n) {
1841 String *symname = nameToModula3(Getattr(n, "sym:name"), true);
1842 enumerationStart(symname);
1843 int result = Language::enumDeclaration(n);
1850 /* -----------------------------------------------------------------------------
1851 * enumvalueDeclaration()
1852 * ----------------------------------------------------------------------------- */
1854 virtual int enumvalueDeclaration(Node *n) {
1855 generateConstant(n);
1857 This call would continue processing in the constantWrapper
1858 which cannot handle values like "RED+1".
1859 return Language::enumvalueDeclaration(n);
1864 /* -----------------------------------------------------------------------------
1868 * imclassbase - base (extends) for the intermediary class
1869 * imclassclassmodifiers - class modifiers for the intermediary class
1870 * imclasscode - text (Modula 3 code) is copied verbatim to the intermediary class
1871 * imclassimports - import statements for the intermediary class
1872 * imclassinterfaces - interface (implements) for the intermediary class
1874 * modulebase - base (extends) for the module class
1875 * moduleclassmodifiers - class modifiers for the module class
1876 * modulecode - text (Modula 3 code) is copied verbatim to the module class
1877 * moduleimports - import statements for the module class
1878 * moduleinterfaces - interface (implements) for the module class
1880 * ----------------------------------------------------------------------------- */
1882 virtual int pragmaDirective(Node *n) {
1884 String *lang = Getattr(n, "lang");
1885 String *code = Getattr(n, "name");
1886 String *value = Getattr(n, "value");
1888 if (Strcmp(lang, "modula3") == 0) {
1890 String *strvalue = NewString(value);
1891 Replaceall(strvalue, "\\\"", "\"");
1893 bool isEnumItem = Strcmp(code, "enumitem") == 0;
1894 bool isSetItem = Strcmp(code, "setitem") == 0;
1896 if (Strcmp(code, "imclassbase") == 0) {
1897 Delete(m3raw_baseclass);
1898 m3raw_baseclass = Copy(strvalue);
1899 } else if (Strcmp(code, "imclassclassmodifiers") == 0) {
1900 Delete(m3raw_class_modifiers);
1901 m3raw_class_modifiers = Copy(strvalue);
1902 } else if (Strcmp(code, "imclasscode") == 0) {
1903 Printf(m3raw_intf.f, "%s\n", strvalue);
1904 } else if (Strcmp(code, "imclassimports") == 0) {
1905 Delete(m3raw_imports);
1906 m3raw_imports = Copy(strvalue);
1907 } else if (Strcmp(code, "imclassinterfaces") == 0) {
1908 Delete(m3raw_interfaces);
1909 m3raw_interfaces = Copy(strvalue);
1910 } else if (Strcmp(code, "modulebase") == 0) {
1911 Delete(module_baseclass);
1912 module_baseclass = Copy(strvalue);
1913 } else if (Strcmp(code, "moduleclassmodifiers") == 0) {
1914 Delete(m3wrap_modifiers);
1915 m3wrap_modifiers = Copy(strvalue);
1916 } else if (Strcmp(code, "modulecode") == 0) {
1917 Printf(m3wrap_impl.f, "%s\n", strvalue);
1918 } else if (Strcmp(code, "moduleimports") == 0) {
1919 Delete(module_imports);
1920 module_imports = Copy(strvalue);
1921 } else if (Strcmp(code, "moduleinterfaces") == 0) {
1922 Delete(module_interfaces);
1923 module_interfaces = Copy(strvalue);
1924 } else if (Strcmp(code, "unsafe") == 0) {
1925 unsafe_module = true;
1926 } else if (Strcmp(code, "library") == 0) {
1927 if (targetlibrary != NULL) {
1928 Delete(targetlibrary);
1930 targetlibrary = Copy(strvalue);
1931 } else if (Strcmp(code, "enumitem") == 0) {
1932 } else if (Strcmp(code, "constset") == 0) {
1933 } else if (Strcmp(code, "constint") == 0) {
1934 } else if (Strcmp(code, "makesetofenum") == 0) {
1935 m3wrap_intf.enterBlock(blocktype);
1936 Printf(m3wrap_intf.f, "%sSet = SET OF %s;\n", value, value);
1938 Swig_warning(WARN_MODULA3_UNKNOWN_PRAGMA, input_file, line_number, "Unrecognized pragma <%s>.\n", code);
1943 return Language::pragmaDirective(n);
1946 void Setfeature(Node *n, const char *feature, const String *value, bool warn = false) {
1947 //printf("tag feature <%s> with value <%s>\n", feature, Char(value));
1948 String *attr = NewStringf("feature:%s", feature);
1949 if ((Setattr(n, attr, value) != 0) && warn) {
1950 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Feature <%s> of %s did already exist.\n", feature, Getattr(n, "name"));
1955 String *Getfeature(Node *n, const char *feature) {
1956 //printf("retrieve feature <%s> with value <%s>\n", feature, Char(value));
1957 String *attr = NewStringf("feature:%s", feature);
1958 String *result = Getattr(n, attr);
1963 bool convertInt(long in, long &out, const String *mode) {
1964 if ((mode == NIL) || (Strcmp(mode, "int:int") == 0) || (Strcmp(mode, "set:set") == 0)) {
1967 } else if (Strcmp(mode, "set:int") == 0) {
1968 return log2(in, out);
1969 } else if (Strcmp(mode, "int:set") == 0) {
1971 return unsigned (in) < (sizeof(out) * 8);
1973 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Unknown integer conversion method <%s>.\n", mode);
1978 void collectEnumerations(Hash *enums, Node *n) {
1979 Node *child = firstChild(n);
1980 while (child != NIL) {
1981 String *name = Getattr(child, "name");
1982 const bool isConstant = Strcmp(nodeType(child), "constant") == 0;
1983 const bool isEnumItem = Strcmp(nodeType(child), "enumitem") == 0;
1984 if (isConstant || isEnumItem) {
1985 //printf("%s%s name %s\n", isConstant?"constant":"", isEnumItem?"enumitem":"", Char(name));
1987 String *m3name = Getfeature(child, "modula3:enumitem:name");
1988 String *m3enum = Getfeature(child, "modula3:enumitem:enum");
1989 String *conv = Getfeature(child, "modula3:enumitem:conv");
1991 if (m3enum != NIL) {
1992 //printf("m3enum %s\n", Char(m3enum));
1993 if (m3name == NIL) {
1999 Hash *enumnode = Getattr(enums, m3enum);
2000 if (enumnode == NIL) {
2001 enumnode = NewHash();
2003 Setattr(enumnode, "items", items);
2004 Setattr(enums, m3enum, enumnode);
2006 String *maxstr = Getattr(enumnode, "max");
2007 if (maxstr != NIL) {
2010 items = Getattr(enumnode, "items");
2013 String *value = Getattr(child, "value");
2014 //printf("value: %s\n", Char(value));
2015 if ((value == NIL) || (!strToL(value, numvalue))) {
2016 value = Getattr(child, "enumvalue");
2017 if ((value == NIL) || (!evalExpr(value, numvalue))) {
2018 numvalue = getConstNumeric(child);
2020 //printf("constnumeric: %s\n", Char(value));
2022 Setattr(constant_values, name, NewStringf("%d", numvalue));
2023 if (convertInt(numvalue, numvalue, conv)) {
2024 String *newvalue = NewStringf("%d", numvalue);
2025 String *oldname = Getattr(items, newvalue);
2026 if (oldname != NIL) {
2027 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "The value <%s> is already assigned to <%s>.\n", value, oldname);
2029 //printf("items %lx, set %s = %s\n", (long) items, Char(newvalue), Char(m3name));
2030 Setattr(items, newvalue, m3name);
2031 if (max < numvalue) {
2034 Setattr(enumnode, "max", NewStringf("%d", max));
2040 collectEnumerations(enums, child);
2041 child = nextSibling(child);
2045 enum const_pragma_type { cpt_none, cpt_constint, cpt_constset, cpt_enumitem };
2047 struct const_id_pattern {
2048 String *prefix, *parentEnum;
2051 void tagConstants(Node *first, String *parentEnum, const const_id_pattern & pat, const String *pragma, List *convdesc) {
2054 String *name = getQualifiedName(n);
2055 bool isConstant = Strcmp(nodeType(n), "constant") == 0;
2056 bool isEnumItem = Strcmp(nodeType(n), "enumitem") == 0;
2057 if ((isConstant || isEnumItem) && ((pat.prefix == NIL) || (hasPrefix(name, pat.prefix))) && ((pat.parentEnum == NIL) || ((parentEnum != NIL)
2060 (pat.parentEnum, parentEnum)
2062 //printf("tag %s\n", Char(name));
2063 String *srctype = Getitem(convdesc, 1);
2064 String *relationstr = Getitem(convdesc, 3);
2065 List *relationdesc = Split(relationstr, ',', 2);
2067 // transform name from C to Modula3 style
2068 String *srcstyle = NIL;
2069 String *newprefix = NIL;
2071 //printf("name conversion <%s>\n", Char(Getitem(convdesc,2)));
2072 List *namedesc = Split(Getitem(convdesc, 2), ',', INT_MAX);
2073 Iterator nameit = First(namedesc);
2074 for (; nameit.item != NIL; nameit = Next(nameit)) {
2075 List *nameassign = Split(nameit.item, '=', 2);
2076 String *tag = Getitem(nameassign, 0);
2077 String *data = Getitem(nameassign, 1);
2078 //printf("name conv <%s> = <%s>\n", Char(tag), Char(data));
2079 if (Strcmp(tag, "srcstyle") == 0) {
2080 srcstyle = Copy(data);
2081 } else if (Strcmp(tag, "prefix") == 0) {
2082 newprefix = Copy(data);
2084 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Unknown name conversion tag <%s> with value <%s>.\n", tag, data);
2090 const char *stem = Char(name);
2091 if (pat.prefix != NIL) {
2092 //printf("pat.prefix %s for %s\n", Char(pat.prefix), Char(name));
2093 stem += Len(pat.prefix);
2096 if (Strcmp(srcstyle, "underscore") == 0) {
2097 if (newprefix != NIL) {
2098 String *newstem = nameToModula3(stem, true);
2099 newname = NewStringf("%s%s", newprefix, newstem);
2102 newname = nameToModula3(stem, true);
2105 if (srcstyle != NIL) {
2106 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Unknown C identifier style <%s>.\n", srcstyle);
2108 newname = Copy(name);
2111 if (Strcmp(pragma, "enumitem") == 0) {
2112 if (Len(relationdesc) != 1) {
2113 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Expected <enumeration>, got <%s>.\n", relationstr);
2115 Setfeature(n, "modula3:enumitem:name", newname, true);
2116 Setfeature(n, "modula3:enumitem:enum", relationstr, true);
2117 Setfeature(n, "modula3:enumitem:conv", NewStringf("%s:int", srctype), true);
2118 } else if (Strcmp(pragma, "constint") == 0) {
2119 if (Len(relationdesc) != 1) {
2120 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Expected <ordinal type>, got <%s>.\n", relationstr);
2122 Setfeature(n, "modula3:constint:name", newname, true);
2123 Setfeature(n, "modula3:constint:type", Getitem(relationdesc, 0), true);
2124 Setfeature(n, "modula3:constint:conv", NewStringf("%s:int", srctype), true);
2125 } else if (Strcmp(pragma, "constset") == 0) {
2126 if (Len(relationdesc) != 2) {
2127 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Expected <set type,base type>, got <%s>.\n", relationstr);
2129 String *settype = Getitem(relationdesc, 0);
2130 Setfeature(n, "modula3:constset:name", newname, true);
2131 //Setfeature(n,"modula3:constset:type",settype,true);
2132 Setfeature(n, "modula3:constset:set", settype, true);
2133 Setfeature(n, "modula3:constset:base", Getitem(relationdesc, 1), true);
2134 Setfeature(n, "modula3:constset:conv", NewStringf("%s:set", srctype), true);
2138 Delete(relationdesc);
2141 if (Strcmp(nodeType(n), "enum") == 0) {
2142 //printf("explore enum %s, qualification %s\n", Char(name), Char(Swig_symbol_qualified(n)));
2143 tagConstants(firstChild(n), name, pat, pragma, convdesc);
2145 tagConstants(firstChild(n), NIL, pat, pragma, convdesc);
2151 void scanForConstPragmas(Node *n) {
2152 Node *child = firstChild(n);
2153 while (child != NIL) {
2154 const String *type = nodeType(child);
2155 if (Strcmp(type, "pragma") == 0) {
2156 const String *lang = Getattr(child, "lang");
2157 const String *code = Getattr(child, "name");
2158 String *value = Getattr(child, "value");
2160 if (Strcmp(lang, "modula3") == 0) {
2161 const_pragma_type cpt = cpt_none;
2162 if (Strcmp(code, "constint") == 0) {
2164 } else if (Strcmp(code, "constset") == 0) {
2166 } else if (Strcmp(code, "enumitem") == 0) {
2169 if (cpt != cpt_none) {
2170 const_id_pattern pat = { NIL, NIL };
2172 List *convdesc = Split(value, ';', 4);
2173 List *patterndesc = Split(Getitem(convdesc, 0), ',', INT_MAX);
2175 for (patternit = First(patterndesc); patternit.item != NIL; patternit = Next(patternit)) {
2176 List *patternassign = Split(patternit.item, '=', 2);
2177 String *tag = Getitem(patternassign, 0);
2178 String *data = Getitem(patternassign, 1);
2179 if (Strcmp(tag, "prefix") == 0) {
2180 pat.prefix = Copy(data);
2181 } else if (Strcmp(tag, "enum") == 0) {
2182 pat.parentEnum = Copy(data);
2184 Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Unknown identification tag <%s> with value <%s>.\n", tag, data);
2186 Delete(patternassign);
2188 tagConstants(child, NIL, pat, code, convdesc);
2190 Delete(patterndesc);
2194 scanForConstPragmas(child);
2195 child = nextSibling(child);
2199 /* -----------------------------------------------------------------------------
2200 * emitProxyClassDefAndCPPCasts()
2201 * ----------------------------------------------------------------------------- */
2203 void emitProxyClassDefAndCPPCasts(Node *n) {
2204 String *c_classname = SwigType_namestr(Getattr(n, "name"));
2205 String *c_baseclass = NULL;
2206 String *baseclass = NULL;
2207 String *c_baseclassname = NULL;
2208 String *classDeclarationName = Getattr(n, "classDeclaration:name");
2210 /* Deal with inheritance */
2211 List *baselist = Getattr(n, "bases");
2212 if (baselist != NIL) {
2213 Iterator base = First(baselist);
2214 c_baseclassname = Getattr(base.item, "name");
2215 baseclass = Copy(getProxyName(c_baseclassname));
2217 c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
2220 if (base.item != NIL) {
2221 Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, input_file,
2223 "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n",
2224 classDeclarationName, Getattr(base.item, "name"));
2228 bool derived = baseclass && getProxyName(c_baseclassname);
2230 baseclass = NewString("");
2232 // Inheritance from pure Modula 3 classes
2233 const String *pure_baseclass = typemapLookup(n, "m3base", classDeclarationName, WARN_NONE);
2234 if (hasContent(pure_baseclass) && hasContent(baseclass)) {
2235 Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, input_file,
2237 "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n", classDeclarationName, pure_baseclass);
2239 // Pure Modula 3 interfaces
2240 const String *pure_interfaces = typemapLookup(n, derived ? "m3interfaces_derived" : "m3interfaces",
2241 classDeclarationName, WARN_NONE);
2243 // Start writing the proxy class
2244 Printv(proxy_class_def, typemapLookup(n, "m3imports", classDeclarationName, WARN_NONE), // Import statements
2245 "\n", typemapLookup(n, "m3classmodifiers", classDeclarationName, WARN_MODULA3_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
2246 " class $m3classname", // Class name and bases
2247 (derived || *Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", baseclass, pure_baseclass, ((derived || *Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces
2248 ", " : "", pure_interfaces, " {\n", " private IntPtr swigCPtr;\n", // Member variables for memory handling
2249 derived ? "" : " protected bool swigCMemOwn;\n", "\n", " ", typemapLookup(n, "m3ptrconstructormodifiers", classDeclarationName, WARN_MODULA3_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers
2250 " $m3classname(IntPtr cPtr, bool cMemoryOwn) ", // Constructor used for wrapping pointers
2252 ": base($imclassname.$m3classnameTo$baseclass(cPtr), cMemoryOwn) {\n"
2253 : "{\n swigCMemOwn = cMemoryOwn;\n", " swigCPtr = cPtr;\n", " }\n", NIL);
2255 if (!have_default_constructor_flag) { // All proxy classes need a constructor
2256 Printv(proxy_class_def, "\n", " protected $m3classname() : this(IntPtr.Zero, false) {\n", " }\n", NIL);
2258 // C++ destructor is wrapped by the Dispose method
2259 // Note that the method name is specified in a typemap attribute called methodname
2260 String *destruct = NewString("");
2261 const String *tm = NULL;
2262 Node *attributes = NewHash();
2263 String *destruct_methodname = NULL;
2265 tm = typemapLookup(n, "m3destruct_derived", classDeclarationName, WARN_NONE, attributes);
2266 destruct_methodname = Getattr(attributes, "tmap:m3destruct_derived:methodname");
2268 tm = typemapLookup(n, "m3destruct", classDeclarationName, WARN_NONE, attributes);
2269 destruct_methodname = Getattr(attributes, "tmap:m3destruct:methodname");
2271 if (!destruct_methodname) {
2272 Swig_error(input_file, line_number, "No methodname attribute defined in m3destruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
2274 // Emit the Finalize and Dispose methods
2277 if (*Char(destructor_call)) {
2278 Printv(proxy_class_def, typemapLookup(n, "m3finalize", classDeclarationName, WARN_NONE), NIL);
2281 Printv(destruct, tm, NIL);
2282 if (*Char(destructor_call))
2283 Replaceall(destruct, "$imcall", destructor_call);
2285 Replaceall(destruct, "$imcall", "throw new MethodAccessException(\"C++ destructor does not have public access\")");
2286 if (*Char(destruct))
2287 Printv(proxy_class_def, "\n public ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n", NIL);
2292 // Emit various other methods
2293 Printv(proxy_class_def, typemapLookup(n, "m3getcptr", classDeclarationName, WARN_MODULA3_TYPEMAP_GETCPTR_UNDEF), // getCPtr method
2294 typemapLookup(n, "m3code", classDeclarationName, WARN_NONE), // extra Modula 3 code
2297 // Substitute various strings into the above template
2298 Replaceall(proxy_class_def, "$m3classname", proxy_class_name);
2299 Replaceall(proxy_class_code, "$m3classname", proxy_class_name);
2301 Replaceall(proxy_class_def, "$baseclass", baseclass);
2302 Replaceall(proxy_class_code, "$baseclass", baseclass);
2304 Replaceall(proxy_class_def, "$imclassname", m3raw_name);
2305 Replaceall(proxy_class_code, "$imclassname", m3raw_name);
2307 // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
2309 Printv(m3raw_cppcasts_code, "\n [DllImport(\"", m3wrap_name, "\", EntryPoint=\"Modula3_", proxy_class_name, "To", baseclass, "\")]\n", NIL);
2310 Printv(m3raw_cppcasts_code, " public static extern IntPtr ", "$m3classnameTo$baseclass(IntPtr objectRef);\n", NIL);
2312 Replaceall(m3raw_cppcasts_code, "$m3classname", proxy_class_name);
2313 Replaceall(m3raw_cppcasts_code, "$baseclass", baseclass);
2315 Printv(upcasts_code,
2316 "SWIGEXPORT long Modula3_$imclazznameTo$imbaseclass",
2317 "(long objectRef) {\n",
2318 " long baseptr = 0;\n" " *($cbaseclass **)&baseptr = *($cclass **)&objectRef;\n" " return baseptr;\n" "}\n", "\n", NIL);
2320 Replaceall(upcasts_code, "$imbaseclass", baseclass);
2321 Replaceall(upcasts_code, "$cbaseclass", c_baseclass);
2322 Replaceall(upcasts_code, "$imclazzname", proxy_class_name);
2323 Replaceall(upcasts_code, "$cclass", c_classname);
2328 /* ----------------------------------------------------------------------
2331 * If necessary create and return the string
2332 * associated with a certain attribute of 'n'.
2333 * ---------------------------------------------------------------------- */
2335 String *getAttrString(Node *n, const char *attr) {
2336 String *str = Getattr(n, attr);
2338 str = NewString("");
2339 Setattr(n, attr, str);
2344 /* ----------------------------------------------------------------------
2345 * getMethodDeclarations()
2347 * If necessary create and return the handle
2348 * where the methods of the current access can be written to.
2349 * 'n' must be a member of a struct or a class.
2350 * ---------------------------------------------------------------------- */
2352 String *getMethodDeclarations(Node *n) {
2353 String *acc_str = Getattr(n, "access");
2355 if (acc_str == NIL) {
2356 methodattr = NewString("modula3:method:public");
2358 methodattr = NewStringf("modula3:method:%s", acc_str);
2360 String *methods = getAttrString(parentNode(n), Char(methodattr));
2365 /* ----------------------------------------------------------------------
2367 * ---------------------------------------------------------------------- */
2369 virtual int classHandler(Node *n) {
2371 File *f_proxy = NULL;
2372 proxy_class_name = Copy(Getattr(n, "sym:name"));
2373 //String *rawname = Getattr(n,"name");
2376 if (!addSymbol(proxy_class_name, n))
2379 if (Cmp(proxy_class_name, m3raw_name) == 0) {
2380 Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name);
2381 SWIG_exit(EXIT_FAILURE);
2384 if (Cmp(proxy_class_name, m3wrap_name) == 0) {
2385 Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name);
2386 SWIG_exit(EXIT_FAILURE);
2389 String *filen = NewStringf("%s%s.m3", Swig_file_dirname(outfile), proxy_class_name);
2390 f_proxy = NewFile(filen, "w", SWIG_output_files());
2392 FileErrorDisplay(filen);
2393 SWIG_exit(EXIT_FAILURE);
2398 emitBanner(f_proxy);
2400 Clear(proxy_class_def);
2401 Clear(proxy_class_code);
2403 have_default_constructor_flag = false;
2404 destructor_call = NewString("");
2407 /* This will invoke memberfunctionHandler, membervariableHandler ...
2408 and finally it may invoke functionWrapper
2409 for wrappers and member variable accessors.
2410 It will invoke Language:constructorDeclaration
2411 which decides whether to call MODULA3::constructorHandler */
2412 Language::classHandler(n);
2415 String *kind = Getattr(n, "kind");
2416 if (Cmp(kind, "struct") == 0) {
2417 String *entries = NewString("");
2419 writeArgState state;
2420 for (child = firstChild(n); child != NIL; child = nextSibling(child)) {
2421 String *childType = nodeType(child);
2422 if (Strcmp(childType, "cdecl") == 0) {
2423 String *member = Getattr(child, "sym:name");
2424 ParmList *pl = Getattr(child, "parms");
2426 // Get the variable type in Modula 3 type equivalents
2427 String *m3ct = getMappedTypeNew(child, "m3rawtype", "");
2429 writeArg(entries, state, NIL, member, m3ct, NIL);
2433 writeArg(entries, state, NIL, NIL, NIL, NIL);
2435 m3raw_intf.enterBlock(blocktype);
2436 Printf(m3raw_intf.f, "%s =\nRECORD\n%sEND;\n", proxy_class_name, entries);
2440 } else if (Cmp(kind, "class") == 0) {
2441 enum access_privilege { acc_public, acc_protected, acc_private };
2442 int max_acc = acc_public;
2444 const char *acc_name[3] = { "public", "protected", "private" };
2447 for (acc = acc_public; acc <= acc_private; acc++) {
2448 String *methodattr = NewStringf("modula3:method:%s", acc_name[acc]);
2449 methods[acc] = Getattr(n, methodattr);
2451 max_acc = max_acc > acc ? max_acc : acc;
2454 /* Determine the name of the base class */
2455 String *baseclassname = NewString("");
2457 List *baselist = Getattr(n, "bases");
2459 /* Look for the first (principal?) base class -
2460 Modula 3 does not support multiple inheritance */
2461 Iterator base = First(baselist);
2462 Append(baseclassname, Getattr(base.item, "sym:name"));
2464 if (base.item != NIL) {
2465 Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, input_file,
2467 "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n",
2468 proxy_class_name, Getattr(base.item, "name"));
2473 /* the private class of the base class and only this
2474 need a pointer to the C++ object */
2475 bool need_private = !hasContent(baseclassname);
2476 max_acc = need_private ? acc_private : max_acc;
2478 /* Declare C++ object as abstract pointer in Modula 3 */
2479 /* The revelation system does not allow us
2480 to imitate the whole class hierarchy of the C++ library,
2481 but at least we can distinguish between classes of different roots. */
2482 if (hasContent(baseclassname)) {
2483 m3raw_intf.enterBlock(blocktype);
2484 Printf(m3raw_intf.f, "%s = %s;\n", proxy_class_name, baseclassname);
2486 m3raw_intf.enterBlock(blocktype);
2487 Printf(m3raw_intf.f, "%s <: ADDRESS;\n", proxy_class_name);
2488 m3raw_impl.enterBlock(revelation);
2489 Printf(m3raw_impl.f, "%s = UNTRACED BRANDED REF RECORD (*Dummy*) END;\n", proxy_class_name);
2493 m3wrap_intf.enterBlock(blocktype);
2494 if (hasContent(methods[acc_public])) {
2495 superclass = NewStringf("%sPublic", proxy_class_name);
2496 } else if (hasContent(baseclassname)) {
2497 superclass = Copy(baseclassname);
2499 superclass = NewString("ROOT");
2501 Printf(m3wrap_intf.f, "%s <: %s;\n", proxy_class_name, superclass);
2505 static const char *acc_m3suffix[] = { "Public", "Protected", "Private" };
2507 for (acc = acc_public; acc <= acc_private; acc++) {
2508 bool process_private = (acc == acc_private) && need_private;
2509 if (hasContent(methods[acc]) || process_private) {
2510 String *subclass = NewStringf("%s%s", proxy_class_name, acc_m3suffix[acc]);
2512 m3wrap_intf.enterBlock(revelation);
2513 Printf(m3wrap_intf.f, "%s <: %s;\n", proxy_class_name, subclass);
2515 if (acc == max_acc) {
2516 m3wrap_intf.enterBlock(revelation);
2517 Printf(m3wrap_intf.f, "%s =\n", proxy_class_name);
2519 m3wrap_intf.enterBlock(blocktype);
2520 Printf(m3wrap_intf.f, "%s =\n", subclass);
2522 Printf(m3wrap_intf.f, "%s BRANDED OBJECT\n", baseclassname);
2523 if (process_private) {
2524 Setattr(m3wrap_intf.import, m3raw_name, "");
2525 Printf(m3wrap_intf.f, "cxxObj:%s.%s;\n", m3raw_name, proxy_class_name);
2527 if (hasContent(methods[acc])) {
2528 Printf(m3wrap_intf.f, "METHODS\n%s", methods[acc]);
2530 if (acc == max_acc) {
2531 String *overrides = Getattr(n, "modula3:override");
2532 Printf(m3wrap_intf.f, "OVERRIDES\n%s", overrides);
2534 Printf(m3wrap_intf.f, "END;\n");
2535 Delete(baseclassname);
2536 baseclassname = subclass;
2541 Delete(methods[acc_public]);
2542 Delete(methods[acc_protected]);
2543 Delete(methods[acc_private]);
2546 Swig_warning(WARN_MODULA3_TYPECONSTRUCTOR_UNKNOWN, input_file, line_number, "Unknown type constructor %s\n", kind);
2552 emitProxyClassDefAndCPPCasts(n);
2554 Printv(f_proxy, proxy_class_def, proxy_class_code, NIL);
2556 Printf(f_proxy, "}\n");
2560 Delete(proxy_class_name);
2561 proxy_class_name = NULL;
2562 Delete(destructor_call);
2563 destructor_call = NULL;
2568 /* ----------------------------------------------------------------------
2569 * memberfunctionHandler()
2570 * ---------------------------------------------------------------------- */
2572 virtual int memberfunctionHandler(Node *n) {
2573 //printf("begin memberfunctionHandler(%s)\n", Char(Getattr(n,"name")));
2574 Setattr(n, "modula3:functype", "method");
2575 Language::memberfunctionHandler(n);
2578 /* Language::memberfunctionHandler will remove the mapped types
2579 that emitM3Wrapper may attach */
2580 ParmList *pl = Getattr(n, "parms");
2581 Swig_typemap_attach_parms("m3wrapinmode", pl, NULL);
2582 Swig_typemap_attach_parms("m3wrapinname", pl, NULL);
2583 Swig_typemap_attach_parms("m3wrapintype", pl, NULL);
2584 Swig_typemap_attach_parms("m3wrapindefault", pl, NULL);
2585 attachParameterNames(n, "tmap:m3wrapinname", "autoname", "arg%d");
2586 String *rettype = getMappedTypeNew(n, "m3wrapouttype", "");
2588 String *methodname = Getattr(n, "sym:name");
2590 if (methodname==NIL) {
2591 methodname = Getattr(n,"name");
2594 String *arguments = createM3Signature(n);
2595 String *storage = Getattr(n, "storage");
2596 String *overridden = Getattr(n, "override");
2597 bool isVirtual = (storage != NIL) && (Strcmp(storage, "virtual") == 0);
2598 bool isOverridden = (overridden != NIL)
2599 && (Strcmp(overridden, "1") == 0);
2600 if ((!isVirtual) || (!isOverridden)) {
2602 String *methods = getMethodDeclarations(n);
2603 Printf(methods, "%s(%s)%s%s;%s\n",
2604 methodname, arguments,
2605 hasContent(rettype) ? ": " : "", hasContent(rettype) ? (const String *) rettype : "", isVirtual ? " (* base method *)" : "");
2608 /* this was attached by functionWrapper
2609 invoked by Language::memberfunctionHandler */
2610 String *fname = Getattr(n, "modula3:funcname");
2611 String *overrides = getAttrString(parentNode(n), "modula3:override");
2612 Printf(overrides, "%s := %s;\n", methodname, fname);
2618 String *overloaded_name = getOverloadedName(n);
2619 String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
2620 Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
2621 Setattr(n, "imfuncname", intermediary_function_name);
2622 proxyClassFunctionHandler(n);
2623 Delete(overloaded_name);
2625 //printf("end memberfunctionHandler(%s)\n", Char(Getattr(n,"name")));
2629 /* ----------------------------------------------------------------------
2630 * staticmemberfunctionHandler()
2631 * ---------------------------------------------------------------------- */
2633 virtual int staticmemberfunctionHandler(Node *n) {
2636 Language::staticmemberfunctionHandler(n);
2639 String *overloaded_name = getOverloadedName(n);
2640 String *intermediary_function_name = Swig_name_member(proxy_class_name, overloaded_name);
2641 Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
2642 Setattr(n, "imfuncname", intermediary_function_name);
2643 proxyClassFunctionHandler(n);
2644 Delete(overloaded_name);
2646 static_flag = false;
2651 /* -----------------------------------------------------------------------------
2652 * proxyClassFunctionHandler()
2654 * Function called for creating a Modula 3 wrapper function around a c++ function in the
2655 * proxy class. Used for both static and non-static C++ class functions.
2656 * C++ class static functions map to Modula 3 static functions.
2657 * Two extra attributes in the Node must be available. These are "proxyfuncname" -
2658 * the name of the Modula 3 class proxy function, which in turn will call "imfuncname" -
2659 * the intermediary (PInvoke) function name in the intermediary class.
2660 * ----------------------------------------------------------------------------- */
2662 void proxyClassFunctionHandler(Node *n) {
2663 SwigType *t = Getattr(n, "type");
2664 ParmList *l = Getattr(n, "parms");
2665 Hash *throws_hash = NewHash();
2666 String *intermediary_function_name = Getattr(n, "imfuncname");
2667 String *proxy_function_name = Getattr(n, "proxyfuncname");
2671 String *imcall = NewString("");
2672 String *return_type = NewString("");
2673 String *function_code = NewString("");
2674 bool setter_flag = false;
2680 if (SwigType_type(Getattr(l, "type")) == T_VOID) {
2685 /* Attach the non-standard typemaps to the parameter list */
2686 Swig_typemap_attach_parms("in", l, NULL);
2687 Swig_typemap_attach_parms("m3wraptype", l, NULL);
2688 Swig_typemap_attach_parms("m3in", l, NULL);
2690 /* Get return types */
2691 if ((tm = getMappedTypeNew(n, "m3wraptype", ""))) {
2692 substituteClassname(t, tm);
2693 Printf(return_type, "%s", tm);
2696 if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
2698 setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(Swig_name_member(proxy_class_name, variable_name)))
2702 /* Start generating the proxy function */
2703 Printf(function_code, " %s ", Getattr(n, "feature:modula3:methodmodifiers"));
2705 Printf(function_code, "static ");
2706 if (Getattr(n, "override"))
2707 Printf(function_code, "override ");
2708 else if (checkAttribute(n, "storage", "virtual"))
2709 Printf(function_code, "virtual ");
2711 Printf(function_code, "%s %s(", return_type, proxy_function_name);
2713 Printv(imcall, m3raw_name, ".", intermediary_function_name, "(", NIL);
2715 Printv(imcall, "swigCPtr", NIL);
2717 emit_mark_varargs(l);
2719 int gencomma = !static_flag;
2721 /* Output each parameter */
2722 for (i = 0, p = l; p; i++) {
2724 /* Ignored varargs */
2725 if (checkAttribute(p, "varargs:ignore", "1")) {
2730 /* Ignored parameters */
2731 if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2732 p = Getattr(p, "tmap:in:next");
2736 /* Ignore the 'this' argument for variable wrappers */
2737 if (!(variable_wrapper_flag && i == 0)) {
2738 SwigType *pt = Getattr(p, "type");
2739 String *param_type = NewString("");
2741 /* Get the Modula 3 parameter type */
2742 if ((tm = getMappedType(p, "m3wraptype"))) {
2743 substituteClassname(pt, tm);
2744 Printf(param_type, "%s", tm);
2748 Printf(imcall, ", ");
2750 String *arg = variable_wrapper_flag ? NewString("value") : makeParameterName(n,
2754 // Use typemaps to transform type used in Modula 3 wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
2755 if ((tm = getMappedType(p, "in"))) {
2756 addThrows(throws_hash, "in", p);
2757 substituteClassname(pt, tm);
2758 Replaceall(tm, "$input", arg);
2759 Printv(imcall, tm, NIL);
2762 /* Add parameter to proxy function */
2764 Printf(function_code, ", ");
2766 Printf(function_code, "%s %s", param_type, arg);
2771 p = Getattr(p, "tmap:in:next");
2774 Printf(imcall, ")");
2775 Printf(function_code, ")");
2777 // Transform return type used in PInvoke function (in intermediary class) to type used in Modula 3 wrapper function (in proxy class)
2778 if ((tm = getMappedTypeNew(n, "m3out", ""))) {
2779 addThrows(throws_hash, "m3out", n);
2780 if (GetFlag(n, "feature:new"))
2781 Replaceall(tm, "$owner", "true");
2783 Replaceall(tm, "$owner", "false");
2784 substituteClassname(t, tm);
2785 Replaceall(tm, "$imcall", imcall);
2788 generateThrowsClause(throws_hash, function_code);
2789 Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string);
2791 if (proxy_flag && wrapping_member_flag && !enum_constant_flag) {
2795 if ((tm = getMappedTypeNew(n, "m3varin", ""))) {
2796 if (GetFlag(n, "feature:new"))
2797 Replaceall(tm, "$owner", "true");
2799 Replaceall(tm, "$owner", "false");
2800 substituteClassname(t, tm);
2801 Replaceall(tm, "$imcall", imcall);
2802 Printf(proxy_class_code, "%s", tm);
2806 if ((tm = getMappedTypeNew(n, "m3varout", ""))) {
2807 if (GetFlag(n, "feature:new"))
2808 Replaceall(tm, "$owner", "true");
2810 Replaceall(tm, "$owner", "false");
2811 substituteClassname(t, tm);
2812 Replaceall(tm, "$imcall", imcall);
2813 Printf(proxy_class_code, "%s", tm);
2817 // Normal function call
2818 Printv(proxy_class_code, function_code, NIL);
2821 Delete(function_code);
2822 Delete(return_type);
2824 Delete(throws_hash);
2827 /* ----------------------------------------------------------------------
2828 * constructorHandler()
2829 * ---------------------------------------------------------------------- */
2831 virtual int constructorHandler(Node *n) {
2832 // this invokes functionWrapper
2833 Language::constructorHandler(n);
2836 ParmList *l = Getattr(n, "parms");
2838 Hash *throws_hash = NewHash();
2839 String *overloaded_name = getOverloadedName(n);
2840 String *imcall = NewString("");
2842 Printf(proxy_class_code, " %s %s(", Getattr(n, "feature:modula3:methodmodifiers"), proxy_class_name);
2843 Printv(imcall, " : this(", m3raw_name, ".", Swig_name_construct(overloaded_name), "(", NIL);
2845 /* Attach the non-standard typemaps to the parameter list */
2846 Swig_typemap_attach_parms("in", l, NULL);
2847 Swig_typemap_attach_parms("m3wraptype", l, NULL);
2848 Swig_typemap_attach_parms("m3in", l, NULL);
2850 emit_mark_varargs(l);
2858 /* Output each parameter */
2859 for (i = 0; p; i++) {
2861 /* Ignored varargs */
2862 if (checkAttribute(p, "varargs:ignore", "1")) {
2867 /* Ignored parameters */
2868 if (checkAttribute(p, "tmap:in:numinputs", "0")) {
2869 p = Getattr(p, "tmap:in:next");
2873 SwigType *pt = Getattr(p, "type");
2874 String *param_type = NewString("");
2876 /* Get the Modula 3 parameter type */
2877 if ((tm = getMappedType(p, "m3wraptype"))) {
2878 substituteClassname(pt, tm);
2879 Printf(param_type, "%s", tm);
2883 Printf(imcall, ", ");
2885 String *arg = makeParameterName(n, p, i);
2887 // Use typemaps to transform type used in Modula 3 wrapper function (in proxy class) to type used in PInvoke function (in intermediary class)
2888 if ((tm = getMappedType(p, "in"))) {
2889 addThrows(throws_hash, "in", p);
2890 substituteClassname(pt, tm);
2891 Replaceall(tm, "$input", arg);
2892 Printv(imcall, tm, NIL);
2895 /* Add parameter to proxy function */
2897 Printf(proxy_class_code, ", ");
2898 Printf(proxy_class_code, "%s %s", param_type, arg);
2903 p = Getattr(p, "tmap:in:next");
2906 Printf(imcall, "), true)");
2908 Printf(proxy_class_code, ")");
2909 Printf(proxy_class_code, "%s", imcall);
2910 generateThrowsClause(throws_hash, proxy_class_code);
2911 Printf(proxy_class_code, " {\n");
2912 Printf(proxy_class_code, " }\n\n");
2914 if (!gencomma) // We must have a default constructor
2915 have_default_constructor_flag = true;
2917 Delete(overloaded_name);
2919 Delete(throws_hash);
2925 /* ----------------------------------------------------------------------
2926 * destructorHandler()
2927 * ---------------------------------------------------------------------- */
2929 virtual int destructorHandler(Node *n) {
2930 Language::destructorHandler(n);
2931 String *symname = Getattr(n, "sym:name");
2934 Printv(destructor_call, m3raw_name, ".", Swig_name_destroy(symname), "(swigCPtr)", NIL);
2939 /* ----------------------------------------------------------------------
2940 * membervariableHandler()
2941 * ---------------------------------------------------------------------- */
2943 virtual int membervariableHandler(Node *n) {
2944 //printf("begin membervariableHandler(%s)\n", Char(Getattr(n,"name")));
2945 SwigType *t = Getattr(n, "type");
2948 // Get the variable type
2949 if ((tm = getMappedTypeNew(n, "m3wraptype", ""))) {
2950 substituteClassname(t, tm);
2953 variable_name = Getattr(n, "sym:name");
2954 //printf("member variable: %s\n", Char(variable_name));
2956 // Output the property's field declaration and accessor methods
2957 Printf(proxy_class_code, " public %s %s {", tm, variable_name);
2959 Setattr(n, "modula3:functype", "accessor");
2960 wrapping_member_flag = true;
2961 variable_wrapper_flag = true;
2962 Language::membervariableHandler(n);
2963 wrapping_member_flag = false;
2964 variable_wrapper_flag = false;
2966 Printf(proxy_class_code, "\n }\n\n");
2969 String *methods = getMethodDeclarations(n);
2970 String *overrides = getAttrString(parentNode(n), "modula3:override");
2971 SwigType *type = Getattr(n, "type");
2972 String *m3name = capitalizeFirst(variable_name);
2973 //String *m3name = nameToModula3(variable_name,true);
2974 if (!SwigType_isconst(type)) {
2976 String *inmode = getMappedTypeNew(n, "m3wrapinmode", "", false);
2977 String *intype = getMappedTypeNew(n, "m3wrapintype", "");
2978 Printf(methods, "set%s(%s val:%s);\n", m3name, (inmode != NIL) ? (const String *) inmode : "", intype);
2981 /* this was attached by functionWrapper
2982 invoked by Language::memberfunctionHandler */
2983 String *fname = Getattr(n, "modula3:setname");
2984 Printf(overrides, "set%s := %s;\n", m3name, fname);
2989 String *outtype = getMappedTypeNew(n, "m3wrapouttype", "");
2990 Printf(methods, "get%s():%s;\n", m3name, outtype);
2993 /* this was attached by functionWrapper
2994 invoked by Language::memberfunctionHandler */
2995 String *fname = Getattr(n, "modula3:getname");
2996 Printf(overrides, "get%s := %s;\n", m3name, fname);
3001 //printf("end membervariableHandler(%s)\n", Char(Getattr(n,"name")));
3006 /* ----------------------------------------------------------------------
3007 * staticmembervariableHandler()
3008 * ---------------------------------------------------------------------- */
3010 virtual int staticmembervariableHandler(Node *n) {
3012 bool static_const_member_flag = (Getattr(n, "value") == 0);
3013 if (static_const_member_flag) {
3014 SwigType *t = Getattr(n, "type");
3017 // Get the variable type
3018 if ((tm = getMappedTypeNew(n, "m3wraptype", ""))) {
3019 substituteClassname(t, tm);
3021 // Output the property's field declaration and accessor methods
3022 Printf(proxy_class_code, " public static %s %s {", tm, Getattr(n, "sym:name"));
3025 variable_name = Getattr(n, "sym:name");
3026 wrapping_member_flag = true;
3028 Language::staticmembervariableHandler(n);
3029 wrapping_member_flag = false;
3030 static_flag = false;
3032 if (static_const_member_flag)
3033 Printf(proxy_class_code, "\n }\n\n");
3038 /* ----------------------------------------------------------------------
3039 * memberconstantHandler()
3040 * ---------------------------------------------------------------------- */
3042 virtual int memberconstantHandler(Node *n) {
3043 variable_name = Getattr(n, "sym:name");
3044 wrapping_member_flag = true;
3045 Language::memberconstantHandler(n);
3046 wrapping_member_flag = false;
3050 /* -----------------------------------------------------------------------------
3051 * getOverloadedName()
3052 * ----------------------------------------------------------------------------- */
3054 String *getOverloadedName(Node *n) {
3055 String *overloaded_name = Copy(Getattr(n, "sym:name"));
3057 if (Getattr(n, "sym:overloaded")) {
3058 Printv(overloaded_name, Getattr(n, "sym:overname"), NIL);
3061 return overloaded_name;
3064 /* -----------------------------------------------------------------------------
3066 * It is also used for set and get methods of global variables.
3067 * ----------------------------------------------------------------------------- */
3069 void emitM3Wrapper(Node *n, const String *func_name) {
3070 SwigType *t = Getattr(n, "type");
3071 ParmList *l = Getattr(n, "parms");
3072 Hash *throws_hash = NewHash();
3073 int num_exceptions = 0;
3074 int num_returns = 0;
3075 String *rawcall = NewString("");
3076 String *reccall = NewString("");
3077 String *local_variables = NewString("");
3078 String *local_constants = NewString("");
3079 String *incheck = NewString("");
3080 String *outcheck = NewString("");
3081 String *setup = NewString("");
3082 String *cleanup = NewString("");
3083 String *outarg = NewString(""); /* don't mix up with 'autark' :-] */
3084 String *storeout = NewString("");
3085 String *result_name = NewString("");
3086 String *return_variables = NewString("");
3087 const char *result_return = "ret";
3088 String *function_code = NewString("");
3089 /*several names for the same function */
3090 String *raw_name = Getattr(n, "name"); /*original C function name */
3091 //String *func_name = Getattr(n,"sym:name"); /*final Modula3 name chosen by the user*/
3092 bool setter_flag = false;
3093 int multiretval = GetFlag(n, "feature:modula3:multiretval");
3096 if (SwigType_type(Getattr(l, "type")) == T_VOID) {
3101 /* Attach the non-standard typemaps to the parameter list */
3102 Swig_typemap_attach_parms("m3wrapargvar", l, NULL);
3103 Swig_typemap_attach_parms("m3wrapargconst", l, NULL);
3104 Swig_typemap_attach_parms("m3wrapargraw", l, NULL);
3105 Swig_typemap_attach_parms("m3wrapargdir", l, NULL);
3106 Swig_typemap_attach_parms("m3wrapinmode", l, NULL);
3107 Swig_typemap_attach_parms("m3wrapinname", l, NULL);
3108 Swig_typemap_attach_parms("m3wrapintype", l, NULL);
3109 Swig_typemap_attach_parms("m3wrapindefault", l, NULL);
3110 Swig_typemap_attach_parms("m3wrapinconv", l, NULL);
3111 Swig_typemap_attach_parms("m3wrapincheck", l, NULL);
3112 Swig_typemap_attach_parms("m3wrapoutname", l, NULL);
3113 Swig_typemap_attach_parms("m3wrapouttype", l, NULL);
3114 Swig_typemap_attach_parms("m3wrapoutconv", l, NULL);
3115 Swig_typemap_attach_parms("m3wrapoutcheck", l, NULL);
3117 attachMappedType(n, "m3wrapretraw");
3118 attachMappedType(n, "m3wrapretname");
3119 attachMappedType(n, "m3wraprettype");
3120 attachMappedType(n, "m3wrapretvar");
3121 attachMappedType(n, "m3wrapretconv");
3122 attachMappedType(n, "m3wrapretcheck");
3124 Swig_typemap_attach_parms("m3wrapfreearg", l, NULL);
3127 Swig_typemap_attach_parms("m3wrapargvar:throws", l, NULL);
3128 Swig_typemap_attach_parms("m3wrapargraw:throws", l, NULL);
3129 Swig_typemap_attach_parms("m3wrapinconv:throws", l, NULL);
3130 Swig_typemap_attach_parms("m3wrapincheck:throws", l, NULL);
3131 Swig_typemap_attach_parms("m3wrapoutconv:throws", l, NULL);
3132 Swig_typemap_attach_parms("m3wrapoutcheck:throws", l, NULL);
3134 attachMappedType(n, "m3wrapretvar:throws");
3135 attachMappedType(n, "m3wrapretconv:throws");
3136 attachMappedType(n, "m3wrapretcheck:throws");
3138 Swig_typemap_attach_parms("m3wrapfreearg:throws", l, NULL);
3141 /* Attach argument names to the parameter list */
3142 /* should be a separate procedure making use of hashes */
3143 attachParameterNames(n, "tmap:m3wrapinname", "autoname", "arg%d");
3145 /* Get return types */
3146 String *result_m3rawtype = Copy(getMappedTypeNew(n, "m3rawrettype", ""));
3147 String *result_m3wraptype = Copy(getMappedTypeNew(n, "m3wraprettype", ""));
3148 bool has_return_raw = hasContent(result_m3rawtype);
3149 bool has_return_m3 = hasContent(result_m3wraptype);
3150 if (has_return_m3) {
3152 //printf("%s: %s\n", Char(func_name),Char(result_m3wraptype));
3155 String *arguments = createM3Signature(n);
3157 /* Create local variables or RECORD fields for return values
3158 and determine return type that might result from a converted VAR argument. */
3160 writeArgState state;
3161 if (multiretval && has_return_m3) {
3162 writeArg(return_variables, state, NIL, NewString(result_return), result_m3wraptype, NIL);
3165 Parm *p = skipIgnored(l, "m3wrapouttype");
3168 String *arg = Getattr(p, "tmap:m3wrapoutname");
3170 arg = Getattr(p, "name");
3173 String *tm = Getattr(p, "tmap:m3wrapouttype");
3175 if (isOutParam(p)) {
3177 if (num_returns == 0) {
3178 Printv(result_name, arg, NIL);
3179 Clear(result_m3wraptype);
3180 Printv(result_m3wraptype, tm, NIL);
3182 Swig_warning(WARN_MODULA3_TYPEMAP_MULTIPLE_RETURN, input_file, line_number,
3183 "Typemap m3wrapargdir set to 'out' for %s implies a RETURN value, but the routine %s has already one.\nUse %%multiretval feature.\n",
3184 SwigType_str(Getattr(p, "type"), 0), raw_name);
3188 addImports(m3wrap_intf.import, "m3wrapouttype", p);
3189 writeArg(return_variables, state, NIL, arg, tm, NIL);
3191 p = skipIgnored(Getattr(p, "tmap:m3wrapouttype:next"), "m3wrapouttype");
3196 writeArg(return_variables, state, NIL, NIL, NIL, NIL);
3199 Printv(result_name, "result", NIL);
3200 Printf(result_m3wraptype, "%sResult", func_name);
3201 m3wrap_intf.enterBlock(blocktype);
3202 Printf(m3wrap_intf.f, "%s =\nRECORD\n%sEND;\n", result_m3wraptype, return_variables);
3203 Printf(local_variables, "%s: %s;\n", result_name, result_m3wraptype);
3205 Append(local_variables, return_variables);
3209 /* Declare local constants e.g. for storing argument names. */
3214 String *arg = Getattr(p, "autoname");
3216 String *tm = Getattr(p, "tmap:m3wrapargconst");
3218 addImports(m3wrap_impl.import, "m3wrapargconst", p);
3219 Replaceall(tm, "$input", arg);
3220 Printv(local_constants, tm, "\n", NIL);
3221 p = Getattr(p, "tmap:m3wrapargconst:next");
3229 /* Declare local variables e.g. for converted input values. */
3231 String *tm = getMappedTypeNew(n, "m3wrapretvar", "", false);
3233 addImports(m3wrap_impl.import, "m3wrapretvar", n);
3234 addThrows(throws_hash, "m3wrapretvar", n);
3235 Printv(local_variables, tm, "\n", NIL);
3241 String *arg = Getattr(p, "autoname");
3243 tm = Getattr(p, "tmap:m3wrapargvar");
3245 /* exceptions that may be raised but can't be catched,
3246 thus we won't count them in num_exceptions */
3247 addImports(m3wrap_impl.import, "m3wrapargvar", p);
3248 addThrows(throws_hash, "m3wrapargvar", p);
3249 Replaceall(tm, "$input", arg);
3250 Printv(local_variables, tm, "\n", NIL);
3251 p = Getattr(p, "tmap:m3wrapargvar:next");
3259 /* Convert input values from Modula 3 to C. */
3264 String *arg = Getattr(p, "autoname");
3266 String *tm = Getattr(p, "tmap:m3wrapinconv");
3268 addImports(m3wrap_impl.import, "m3wrapinconv", p);
3269 num_exceptions += addThrows(throws_hash, "m3wrapinconv", p);
3270 Replaceall(tm, "$input", arg);
3271 Printv(setup, tm, "\n", NIL);
3272 p = Getattr(p, "tmap:m3wrapinconv:next");
3280 /* Generate checks for input value integrity. */
3285 String *arg = Getattr(p, "autoname");
3287 String *tm = Getattr(p, "tmap:m3wrapincheck");
3289 addImports(m3wrap_impl.import, "m3wrapincheck", p);
3290 num_exceptions += addThrows(throws_hash, "m3wrapincheck", p);
3291 Replaceall(tm, "$input", arg);
3292 Printv(incheck, tm, "\n", NIL);
3293 p = Getattr(p, "tmap:m3wrapincheck:next");
3301 Printv(rawcall, m3raw_name, ".", func_name, "(", NIL);
3302 /* Arguments to the raw C function */
3304 bool gencomma = false;
3308 Printf(rawcall, ", ");
3311 addImports(m3wrap_impl.import, "m3wrapargraw", p);
3312 num_exceptions += addThrows(throws_hash, "m3wrapargraw", p);
3314 String *arg = Getattr(p, "autoname");
3315 String *qualarg = NewString("");
3316 if (!isInParam(p)) {
3317 String *tmparg = Getattr(p, "tmap:m3wrapoutname");
3318 if (tmparg != NIL) {
3321 if (multiretval /*&& isOutParam(p) - automatically fulfilled */ ) {
3322 Printf(qualarg, "%s.", result_name);
3325 Append(qualarg, arg);
3326 Setattr(p, "m3outarg", qualarg);
3328 String *tm = Getattr(p, "tmap:m3wrapargraw");
3330 Replaceall(tm, "$input", arg);
3331 Replaceall(tm, "$output", qualarg);
3332 Printv(rawcall, tm, NIL);
3333 p = Getattr(p, "tmap:m3wrapargraw:next");
3335 //Printv(rawcall, Getattr(p,"lname"), NIL);
3336 Printv(rawcall, qualarg, NIL);
3342 Printf(rawcall, ")");
3344 /* Check for error codes and integrity of results */
3346 String *tm = getMappedTypeNew(n, "m3wrapretcheck", "", false);
3348 addImports(m3wrap_impl.import, "m3wrapretcheck", n);
3349 num_exceptions += addThrows(throws_hash, "m3wrapretcheck", n);
3350 Printv(outcheck, tm, "\n", NIL);
3355 tm = Getattr(p, "tmap:m3wrapoutcheck");
3357 String *arg = Getattr(p, "autoname");
3358 String *outarg = Getattr(p, "m3outarg");
3359 addImports(m3wrap_impl.import, "m3wrapoutcheck", p);
3360 num_exceptions += addThrows(throws_hash, "m3wrapoutcheck", p);
3361 //substituteClassname(Getattr(p,"type"), tm);
3362 Replaceall(tm, "$input", arg);
3363 Replaceall(tm, "$output", outarg);
3364 Printv(outcheck, tm, "\n", NIL);
3365 p = Getattr(p, "tmap:m3wrapoutcheck:next");
3372 /* Convert the results to Modula 3 data structures and
3373 put them in the record prepared for returning */
3375 /* m3wrapretconv is processed
3376 when it is clear if there is some output conversion and checking code */
3379 String *tm = Getattr(p, "tmap:m3wrapoutconv");
3381 String *arg = Getattr(p, "autoname");
3382 String *outarg = Getattr(p, "m3outarg");
3383 addImports(m3wrap_impl.import, "m3wrapoutconv", n);
3384 num_exceptions += addThrows(throws_hash, "m3wrapoutconv", p);
3385 //substituteClassname(Getattr(p,"type"), tm);
3386 Replaceall(tm, "$input", arg);
3387 Replaceall(tm, "$output", outarg);
3388 Printf(storeout, "%s := %s;\n", outarg, tm);
3389 p = Getattr(p, "tmap:m3wrapoutconv:next");
3396 /* Generate cleanup code */
3400 String *tm = Getattr(p, "tmap:m3wrapfreearg");
3402 String *arg = Getattr(p, "autoname");
3403 String *outarg = Getattr(p, "m3outarg");
3404 addImports(m3wrap_impl.import, "m3wrapfreearg", p);
3405 num_exceptions += addThrows(throws_hash, "m3wrapfreearg", p);
3406 //substituteClassname(Getattr(p,"type"), tm);
3407 Replaceall(tm, "$input", arg);
3408 Replaceall(tm, "$output", outarg);
3409 Printv(cleanup, tm, "\n", NIL);
3410 p = Getattr(p, "tmap:m3wrapfreearg:next");
3418 /* Currently I don't know how a typemap similar to the original 'out' typemap
3419 could help returning the return value. */
3420 /* Receive result from call to raw library function */
3421 if (!has_return_raw) {
3431 Printf(reccall, "%s;\n", rawcall);
3433 if (hasContent(result_name)) {
3434 Printf(outarg, "RETURN %s;\n", result_name);
3438 arg0 := rawcall(arg1);
3439 result.ret := Convert(arg0);
3445 RETURN Convert(arg0);
3450 String *return_raw = getMappedTypeNew(n, "m3wrapretraw", "", false);
3451 String *return_conv = getMappedTypeNew(n, "m3wrapretconv", "", false);
3453 /* immediate RETURN would skip result checking */
3454 if ((hasContent(outcheck) || hasContent(storeout)
3455 || hasContent(cleanup)) && (!hasContent(result_name))
3456 && (return_raw == NIL)) {
3457 Printv(result_name, "result", NIL);
3458 Printf(local_variables, "%s: %s;\n", result_name, result_m3wraptype);
3461 String *result_lvalue = Copy(result_name);
3463 Printf(result_lvalue, ".%s", result_return);
3465 if (return_raw != NIL) {
3466 Printf(reccall, "%s := %s;\n", return_raw, rawcall);
3467 } else if (hasContent(result_name)) {
3468 Printf(reccall, "%s := %s;\n", result_lvalue, rawcall);
3470 Printf(outarg, "RETURN %s;\n", rawcall);
3472 if (return_conv != NIL) {
3473 addImports(m3wrap_impl.import, "m3wrapretconv", n);
3474 num_exceptions += addThrows(throws_hash, "m3wrapretconv", n);
3475 if (hasContent(result_name)) {
3476 Printf(reccall, "%s := %s;\n", result_lvalue, return_conv);
3477 Printf(outarg, "RETURN %s;\n", result_name);
3479 Printf(outarg, "RETURN %s;\n", return_conv);
3482 if (hasContent(result_name)) {
3483 Printf(outarg, "RETURN %s;\n", result_name);
3489 /* Create procedure header */
3491 String *header = NewStringf("PROCEDURE %s (%s)",
3492 func_name, arguments);
3494 if ((num_returns > 0) || multiretval) {
3495 Printf(header, ": %s", result_m3wraptype);
3497 generateThrowsClause(throws_hash, header);
3499 Append(function_code, header);
3501 m3wrap_intf.enterBlock(no_block);
3502 Printf(m3wrap_intf.f, "%s;\n\n", header);
3506 String *body = NewStringf("%s%s%s%s%s",
3513 String *exc_handler;
3514 if (hasContent(cleanup) && (num_exceptions > 0)) {
3515 exc_handler = NewStringf("TRY\n%sFINALLY\n%sEND;\n", body, cleanup);
3517 exc_handler = NewStringf("%s%s", body, cleanup);
3520 Printf(function_code, " =\n%s%s%s%sBEGIN\n%s%sEND %s;\n\n",
3521 hasContent(local_constants) ? "CONST\n" : "", local_constants,
3522 hasContent(local_variables) ? "VAR\n" : "", local_variables, exc_handler, outarg, func_name);
3524 Delete(exc_handler);
3528 m3wrap_impl.enterBlock(no_block);
3529 if (proxy_flag && global_variable_flag) {
3533 String *tm = getMappedTypeNew(n, "m3varin", "");
3535 if (GetFlag(n, "feature:new")) {
3536 Replaceall(tm, "$owner", "true");
3538 Replaceall(tm, "$owner", "false");
3540 substituteClassname(t, tm);
3541 Replaceall(tm, "$rawcall", rawcall);
3542 Replaceall(tm, "$vartype", variable_type); /* $type is already replaced by some super class */
3543 Replaceall(tm, "$var", variable_name);
3544 Printf(m3wrap_impl.f, "%s", tm);
3548 String *tm = getMappedTypeNew(n, "m3varout", "");
3550 if (GetFlag(n, "feature:new"))
3551 Replaceall(tm, "$owner", "true");
3553 Replaceall(tm, "$owner", "false");
3554 substituteClassname(t, tm);
3555 Replaceall(tm, "$rawcall", rawcall);
3556 Replaceall(tm, "$vartype", variable_type);
3557 Replaceall(tm, "$var", variable_name);
3558 Printf(m3wrap_impl.f, "%s", tm);
3562 // Normal function call
3563 Printv(m3wrap_impl.f, function_code, NIL);
3567 Delete(return_variables);
3568 Delete(local_variables);
3569 Delete(local_constants);
3576 Delete(function_code);
3577 Delete(result_name);
3578 Delete(result_m3wraptype);
3581 Delete(throws_hash);
3584 /*----------------------------------------------------------------------
3585 * replaceSpecialVariables()
3586 *--------------------------------------------------------------------*/
3588 virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
3590 SwigType *type = Getattr(parm, "type");
3591 substituteClassname(type, tm);
3594 /* -----------------------------------------------------------------------------
3595 * substituteClassname()
3597 * Substitute the special variable $m3classname with the proxy class name for classes/structs/unions
3598 * that SWIG knows about.
3599 * Otherwise use the $descriptor name for the Modula 3 class name. Note that the $&m3classname substitution
3600 * is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
3602 * pt - parameter type
3603 * tm - typemap contents that might contain the special variable to be replaced
3605 * tm - typemap contents complete with the special variable substitution
3607 * substitution_performed - flag indicating if a substitution was performed
3608 * ----------------------------------------------------------------------------- */
3610 bool substituteClassname(SwigType *pt, String *tm) {
3611 bool substitution_performed = false;
3612 if (Strstr(tm, "$m3classname") || Strstr(tm, "$&m3classname")) {
3613 String *classname = getProxyName(pt);
3615 Replaceall(tm, "$&m3classname", classname); // getProxyName() works for pointers to classes too
3616 Replaceall(tm, "$m3classname", classname);
3617 } else { // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved.
3618 String *descriptor = NULL;
3619 SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
3621 if (Strstr(tm, "$&m3classname")) {
3622 SwigType_add_pointer(type);
3623 descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type));
3624 Replaceall(tm, "$&m3classname", descriptor);
3625 } else { // $m3classname
3626 descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type));
3627 Replaceall(tm, "$m3classname", descriptor);
3630 // Add to hash table so that the type wrapper classes can be created later
3631 Setattr(swig_types_hash, descriptor, type);
3635 substitution_performed = true;
3637 return substitution_performed;
3640 /* -----------------------------------------------------------------------------
3641 * makeParameterName()
3645 * p - parameter node
3646 * arg_num - parameter argument number
3648 * arg - a unique parameter name
3649 * ----------------------------------------------------------------------------- */
3651 String *makeParameterName(Node *n, Parm *p, int arg_num) {
3653 // Use C parameter name unless it is a duplicate or an empty parameter name
3654 String *pn = Getattr(p, "name");
3656 ParmList *plist = Getattr(n, "parms");
3658 if ((Cmp(pn, Getattr(plist, "name")) == 0))
3660 plist = nextSibling(plist);
3662 String *arg = (!pn || (count > 1)) ? NewStringf("arg%d",
3663 arg_num) : Copy(Getattr(p,
3669 /* -----------------------------------------------------------------------------
3670 * attachParameterNames()
3673 * n - Node of a function declaration
3674 * tmid - attribute name for overriding C argument names,
3675 * e.g. "tmap:m3wrapinname",
3676 * don't forget to attach the mapped types before
3677 * nameid - attribute for attaching the names,
3678 * e.g. "modula3:inname"
3679 * fmt - format for the argument name containing %d
3681 * ----------------------------------------------------------------------------- */
3683 void attachParameterNames(Node *n, const char *tmid, const char *nameid, const char *fmt) {
3684 /* Use C parameter name if present and unique,
3685 otherwise create an 'arg%d' name */
3686 Hash *hash = NewHash();
3687 Parm *p = Getattr(n, "parms");
3690 String *name = Getattr(p, tmid);
3692 name = Getattr(p, "name");
3695 if ((!hasContent(name)) || (Getattr(hash, name) != NIL)) {
3696 newname = NewStringf(fmt, count);
3698 newname = Copy(name);
3700 if (1 == Setattr(hash, newname, "1")) {
3701 Swig_warning(WARN_MODULA3_DOUBLE_ID, input_file, line_number, "Argument '%s' twice.\n", newname);
3703 Setattr(p, nameid, newname);
3711 /* -----------------------------------------------------------------------------
3712 * createM3Signature()
3714 * Create signature of M3 wrapper procedure
3715 * Call attachParameterNames and attach mapped types before!
3716 * m3wrapintype, m3wrapinmode, m3wrapindefault
3717 * ----------------------------------------------------------------------------- */
3719 String *createM3Signature(Node *n) {
3720 String *arguments = NewString("");
3721 Parm *p = skipIgnored(Getattr(n, "parms"), "m3wrapintype");
3722 writeArgState state;
3725 /* Get the M3 parameter type */
3726 String *tm = getMappedType(p, "m3wrapintype");
3729 addImports(m3wrap_intf.import, "m3wrapintype", p);
3730 addImports(m3wrap_impl.import, "m3wrapintype", p);
3731 String *mode = Getattr(p, "tmap:m3wrapinmode");
3732 String *deflt = Getattr(p, "tmap:m3wrapindefault");
3733 String *arg = Getattr(p, "autoname");
3734 SwigType *pt = Getattr(p, "type");
3735 substituteClassname(pt, tm); /* do we need this ? */
3737 writeArg(arguments, state, mode, arg, tm, deflt);
3739 p = skipIgnored(Getattr(p, "tmap:m3wrapintype:next"), "m3wrapintype");
3744 writeArg(arguments, state, NIL, NIL, NIL, NIL);
3748 /* not used any longer
3749 - try SwigType_str if required again */
3751 /* -----------------------------------------------------------------------------
3752 * createCSignature()
3754 * Create signature of C function
3755 * ----------------------------------------------------------------------------- */
3757 String *createCSignature(Node *n) {
3758 String *arguments = NewString("");
3759 bool gencomma = false;
3761 for (p = Getattr(n, "parms"); p != NIL; p = nextSibling(p)) {
3763 Append(arguments, ",");
3766 String *type = Getattr(p, "type");
3767 String *ctype = getMappedTypeNew(type, "ctype");
3768 Append(arguments, ctype);
3774 /* -----------------------------------------------------------------------------
3775 * emitTypeWrapperClass()
3776 * ----------------------------------------------------------------------------- */
3778 void emitTypeWrapperClass(String *classname, SwigType *type) {
3779 Node *n = NewHash();
3780 Setfile(n, input_file);
3781 Setline(n, line_number);
3783 String *filen = NewStringf("%s%s.m3", Swig_file_dirname(outfile), classname);
3784 File *f_swigtype = NewFile(filen, "w", SWIG_output_files());
3786 FileErrorDisplay(filen);
3787 SWIG_exit(EXIT_FAILURE);
3789 String *swigtype = NewString("");
3792 emitBanner(f_swigtype);
3794 // Pure Modula 3 baseclass and interfaces
3795 const String *pure_baseclass = typemapLookup(n, "m3base", type, WARN_NONE);
3796 const String *pure_interfaces = typemapLookup(n, "m3interfaces", type, WARN_NONE);
3799 Printv(swigtype, typemapLookup(n, "m3imports", type, WARN_NONE), // Import statements
3800 "\n", typemapLookup(n, "m3classmodifiers", type, WARN_MODULA3_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers
3801 " class $m3classname", // Class name and bases
3802 *Char(pure_baseclass) ? " : " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces
3803 " : " : "", pure_interfaces, " {\n", " private IntPtr swigCPtr;\n", "\n", " ", typemapLookup(n, "m3ptrconstructormodifiers", type, WARN_MODULA3_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers
3804 " $m3classname(IntPtr cPtr, bool bFutureUse) {\n", // Constructor used for wrapping pointers
3805 " swigCPtr = cPtr;\n", " }\n", "\n", " protected $m3classname() {\n", // Default constructor
3806 " swigCPtr = IntPtr.Zero;\n", " }\n", typemapLookup(n, "m3getcptr", type, WARN_MODULA3_TYPEMAP_GETCPTR_UNDEF), // getCPtr method
3807 typemapLookup(n, "m3code", type, WARN_NONE), // extra Modula 3 code
3810 Replaceall(swigtype, "$m3classname", classname);
3811 Printv(f_swigtype, swigtype, NIL);
3818 /* -----------------------------------------------------------------------------
3820 * n - for input only and must contain info for Getfile(n) and Getline(n) to work
3821 * tmap_method - typemap method name
3822 * type - typemap type to lookup
3823 * warning - warning number to issue if no typemaps found
3824 * typemap_attributes - the typemap attributes are attached to this node and will
3825 * also be used for temporary storage if non null
3826 * return is never NULL, unlike Swig_typemap_lookup()
3827 * ----------------------------------------------------------------------------- */
3829 const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) {
3830 Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
3831 Setattr(node, "type", type);
3832 Setfile(node, Getfile(n));
3833 Setline(node, Getline(n));
3834 const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
3837 if (warning != WARN_NONE)
3838 Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
3840 if (!typemap_attributes)
3845 /* -----------------------------------------------------------------------------
3848 * Add all exceptions to a hash that are associated with the 'typemap'.
3849 * Return number the number of these exceptions.
3850 * ----------------------------------------------------------------------------- */
3852 int addThrows(Hash *throws_hash, const String *typemap, Node *parameter) {
3853 // Get the comma separated throws clause - held in "throws" attribute in the typemap passed in
3855 String *throws_attribute = NewStringf("%s:throws", typemap);
3857 addImports(m3wrap_intf.import, throws_attribute, parameter);
3858 addImports(m3wrap_impl.import, throws_attribute, parameter);
3860 String *throws = getMappedTypeNew(parameter, Char(throws_attribute), "", false);
3861 //printf("got exceptions %s for %s\n", Char(throws), Char(throws_attribute));
3864 // Put the exception classes in the throws clause into a temporary List
3865 List *temp_classes_list = Split(throws, ',', INT_MAX);
3866 len = Len(temp_classes_list);
3868 // Add the exception classes to the node throws list, but don't duplicate if already in list
3869 if (temp_classes_list /*&& hasContent(temp_classes_list) */ ) {
3870 for (Iterator cls = First(temp_classes_list); cls.item != NIL; cls = Next(cls)) {
3871 String *exception_class = NewString(cls.item);
3872 Replaceall(exception_class, " ", ""); // remove spaces
3873 Replaceall(exception_class, "\t", ""); // remove tabs
3874 if (hasContent(exception_class)) {
3875 // $m3classname substitution
3876 SwigType *pt = Getattr(parameter, "type");
3877 substituteClassname(pt, exception_class);
3878 // Don't duplicate the exception class in the throws clause
3879 //printf("add exception %s\n", Char(exception_class));
3880 Setattr(throws_hash, exception_class, "1");
3882 Delete(exception_class);
3885 Delete(temp_classes_list);
3887 Delete(throws_attribute);
3891 /* -----------------------------------------------------------------------------
3892 * generateThrowsClause()
3893 * ----------------------------------------------------------------------------- */
3895 void generateThrowsClause(Hash *throws_hash, String *code) {
3896 // Add the throws clause into code
3897 if (Len(throws_hash) > 0) {
3898 Iterator cls = First(throws_hash);
3899 Printf(code, " RAISES {%s", cls.key);
3900 for (cls = Next(cls); cls.key != NIL; cls = Next(cls)) {
3901 Printf(code, ", %s", cls.key);
3907 /* -----------------------------------------------------------------------------
3910 * Add all imports that are needed for contents of 'typemap'.
3911 * ----------------------------------------------------------------------------- */
3913 void addImports(Hash *imports_hash, const String *typemap, Node *node) {
3914 // Get the comma separated throws clause - held in "throws" attribute in the typemap passed in
3915 String *imports_attribute = NewStringf("%s:import", typemap);
3916 String *imports = getMappedTypeNew(node, Char(imports_attribute), "", false);
3917 //printf("got imports %s for %s\n", Char(imports), Char(imports_attribute));
3919 if (imports != NIL) {
3920 List *import_list = Split(imports, ',', INT_MAX);
3922 // Add the exception classes to the node imports list, but don't duplicate if already in list
3923 if (import_list != NIL) {
3924 for (Iterator imp = First(import_list); imp.item != NIL; imp = Next(imp)) {
3925 List *import_pair = Split(imp.item, ' ', 3);
3926 if (Len(import_pair) == 1) {
3927 Setattr(imports_hash, Getitem(import_pair, 0), "");
3928 } else if ((Len(import_pair) == 3)
3929 && Strcmp(Getitem(import_pair, 1), "AS") == 0) {
3930 Setattr(imports_hash, Getitem(import_pair, 0), Getitem(import_pair, 2));
3932 Swig_warning(WARN_MODULA3_BAD_IMPORT, input_file, line_number,
3933 "Malformed import '%s' for typemap '%s' defined for type '%s'\n", imp, typemap, SwigType_str(Getattr(node, "type"), 0));
3935 Delete(import_pair);
3938 Delete(import_list);
3940 Delete(imports_attribute);
3943 /* -----------------------------------------------------------------------------
3944 * emitImportStatements()
3945 * ----------------------------------------------------------------------------- */
3947 void emitImportStatements(Hash *imports_hash, String *code) {
3948 // Add the imports statements into code
3949 Iterator imp = First(imports_hash);
3950 while (imp.key != NIL) {
3951 Printf(code, "IMPORT %s", imp.key);
3952 String *imp_as = imp.item;
3953 if (hasContent(imp_as)) {
3954 Printf(code, " AS %s", imp_as);
3956 Printf(code, ";\n");
3961 }; /* class MODULA3 */
3963 /* -----------------------------------------------------------------------------
3964 * swig_modula3() - Instantiate module
3965 * ----------------------------------------------------------------------------- */
3967 extern "C" Language *swig_modula3(void) {
3968 return new MODULA3();
3971 /* -----------------------------------------------------------------------------
3972 * Static member variables
3973 * ----------------------------------------------------------------------------- */
3975 const char *MODULA3::usage = (char *) "\
3976 Modula 3 Options (available with -modula3)\n\
3977 -generateconst <file> - generate code for computing numeric values of constants\n\
3978 -generaterename <file> - generate suggestions for %rename\n\
3979 -generatetypemap <file> - generate templates for some basic typemaps\n\
3980 -oldvarnames - old intermediary method names for variable wrappers\n\
3984 -generateconst <file> - stem of the .c source file for computing the numeric values of constants\n\
3985 -generaterename <file> - stem of the .i source file containing %rename suggestions\n\
3986 -generatetypemap <file> - stem of the .i source file containing typemap patterns\n\