| /* ----------------------------------------------------------------------------- |
| * This file is part of SWIG, which is licensed as a whole under version 3 |
| * (or any later version) of the GNU General Public License. Some additional |
| * terms also apply to certain portions of SWIG. The full details of the SWIG |
| * license and copyrights can be found in the LICENSE and COPYRIGHT files |
| * included with the SWIG source code as distributed by the SWIG developers |
| * and at http://www.swig.org/legal.html. |
| * |
| * modula3.cxx |
| * |
| * Modula3 language module for SWIG. |
| * ----------------------------------------------------------------------------- */ |
| |
| /* |
| Text formatted with |
| indent -sob -br -ce -nut -npsl |
| */ |
| |
| /* |
| Report: |
| - It's not a good concept to use member variables or global variables |
| for passing parameters to functions. |
| It's not a good concept to use functions of superclasses for specific services. |
| E.g. For SWIG this means: Generating accessor functions for member variables |
| is the most common but no general task to be processed in membervariableHandler. |
| Better provide a service function which generates accessor function code |
| and equip this service function with all parameters needed for input (parse node) |
| and output (generated code). |
| - How can I make globalvariableHandler not to generate |
| interface functions to two accessor functions |
| (that don't exist) ? |
| - How can I generate a typemap that turns every C reference argument into |
| its Modula 3 counterpart, that is |
| void test(Complex &z); |
| PROCEDURE test(VAR z:Complex); |
| - neither $*n_mangle nor $*n_type nor $*n_ltype return the type without |
| pointer converted to Modula3 equivalent, |
| $*n_mangle is the variant closest to what I expect |
| - using a typemap like |
| typemap(m3wrapintype) int * %{VAR $1_name: INTEGER%} |
| has the advantages: |
| - one C parameter can be turned into multiple M3 parameters |
| - the argument can be renamed |
| - using typemaps like |
| typemap(m3wrapinmode) int * "VAR" |
| typemap(m3wrapintype) int * "INTEGER" |
| has the advantages: |
| - multiple parameters with same type and default value can be bundled |
| - more conform to the other language modules |
| - Where takes the reduction of multi-typemaps place? |
| How can I preserve all parameters for functions of the intermediary class? |
| The answer is Getattrs(n,"tmap:m3rawintype:next") |
| - Char() can be used to transform a String to (char *) |
| which can be used for output with printf |
| - What is the while (checkAttribute()) loop in functionWrapper good for? |
| Appearently for skipping (numinputs=0) typemaps. |
| - SWIGTYPE const * - typemap is ignored, whereas |
| SWIGTYPE * - typemap is invoked, why? |
| Had it been (const SWIGTYPE *) instead? |
| - enumeration items should definitely be equipped |
| with its plain numerical value |
| One could add tag 'numvalue' in CParse/parser.y, |
| but it is still possible that someone declares an |
| enumeration using a symbolic constant. |
| I have quickly hacked |
| that the successive number is assigned |
| if "enumvalue" has suffix "+1". |
| The ultimate solution would be to generate a C program |
| which includes the header and outputs all constants. |
| This program might be compiled and run |
| by 'make' or by SWIG and the resulting output is fed back to SWIG. |
| - It's a bad idea to interpret feature value "" |
| 'disable feature' because the value "" |
| might be sensible in case of feature:modula3:oldprefix. |
| - What's the difference between "sym:name" and "name" ? |
| "name" is the original name and |
| "sym:name" is probably modified by the user using %rename |
| - Is it possible for 'configure' to find out if m3pp is installed |
| and to invoke it for generated Modula3 files? |
| - It would be better to separate an arguments purpose and its name, |
| because an output variable with name "OUTPUT" is not very descriptive. |
| In case of PLPlot this could be solved by typedefs |
| that assign special purposes to the array types. |
| - Can one interpret $n_basetype as the identifier matched with SWIGTYPE ? |
| |
| SWIG's odds: |
| - arguments of type (Node *) for SWIG functions |
| should be most often better (const Node *): |
| Swig_symbol_qualified, Getattr, nodeType, parentNode |
| - unique identifier style instead of |
| NewString, Getattr, firstChild |
| - 'class'.name is qualified, |
| 'enum'.name and 'enumitem'.name is not |
| - Swig_symbol_qualified() returns NIL for enumeration nodes |
| |
| - Is there a function that creates a C representation of a SWIG type string? |
| |
| ToDo: |
| - create WeakRefs only for resources returned by function marked with %newobject |
| -> part of output conversion |
| - clean typemap conception |
| - should a multi-typemap for m3wrapouttype skip the corresponding input parameters? |
| when yes - How to handle inout-arguments? In this case like in-argument. |
| - C++ classes |
| - C++ exceptions |
| - allow for moving RECORD and OBJECT definitions |
| to separate files, with the main type called T |
| - call-back functions |
| - special option: fast access to class members by pointer arithmetic, |
| member offsets can be determined by a C++ program that print them. |
| - emit enumeration definitions when its first item is declared, |
| currently enumerations are emitted at the beginning of the file |
| |
| Done: |
| - addThrow should convert the typemap by itself |
| - not possible because routine for attaching mapped types to parameter nodes |
| won't work for the function node |
| - turning error codes into exceptions |
| -> part of output value checking |
| - create WeakRefs for resources allocated by the library |
| -> part of output conversion |
| - TRY..FINALLY..END; can be omitted |
| - if there is no m3wrapfreearg |
| - no exception can be raised in the body (empty RAISES) list |
| */ |
| |
| #include "swigmod.h" |
| |
| #include <limits.h> // for INT_MAX |
| #include <ctype.h> |
| |
| #define USAGE_ARG_DIR "m3wrapargdir typemap expect values: in, out, inout\n" |
| |
| class MODULA3:public Language { |
| public: |
| enum block_type { no_block, constant, variable, blocktype, revelation }; |
| |
| private: |
| struct M3File { |
| String *f; |
| Hash *import; |
| block_type bt; |
| /* VC++ 6 doesn't allow the access to 'no_block' |
| if it is a private member of MODULA3 class */ |
| M3File():f(NewString("")), import(NewHash()), bt(no_block) { |
| } |
| ~M3File() { |
| Delete(f); |
| Delete(import); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * enterBlock() |
| * |
| * Make sure that a given declaration is written to the right declaration block, |
| * that is constants are written after "CONST" and so on ... |
| * ----------------------------------------------------------------------------- */ |
| void enterBlock(block_type newbt) { |
| static const char *ident[] = { "", "\nCONST\n", "\nVAR\n", "\nTYPE\n", "\nREVEAL\n" }; |
| #ifdef DEBUG |
| if ((bt < 0) || (4 < bt)) { |
| printf("bt %d out of range\n", bt); |
| } |
| #endif |
| if (newbt != bt) { |
| Append(f, ident[newbt]); |
| bt = newbt; |
| } |
| } |
| |
| }; |
| |
| static const char *usage; |
| const String *empty_string; |
| |
| Hash *swig_types_hash; |
| File *f_begin; |
| File *f_runtime; |
| File *f_header; |
| File *f_wrappers; |
| File *f_init; |
| |
| bool proxy_flag; // Flag for generating proxy classes |
| bool have_default_constructor_flag; |
| bool native_function_flag; // Flag for when wrapping a native function |
| bool enum_constant_flag; // Flag for when wrapping an enum or constant |
| bool static_flag; // Flag for when wrapping a static functions or member variables |
| bool variable_wrapper_flag; // Flag for when wrapping a nonstatic member variable |
| bool wrapping_member_flag; // Flag for when wrapping a member variable/enum/const |
| bool global_variable_flag; // Flag for when wrapping a global variable |
| bool old_variable_names; // Flag for old style variable names in the intermediary class |
| bool unsafe_module; |
| |
| String *m3raw_name; // raw interface name |
| M3File m3raw_intf; // raw interface |
| M3File m3raw_impl; // raw implementation (usually empty) |
| String *m3wrap_name; // wrapper module |
| M3File m3wrap_intf; |
| M3File m3wrap_impl; |
| String *m3makefile; |
| String *targetlibrary; |
| String *proxy_class_def; |
| String *proxy_class_code; |
| String *proxy_class_name; |
| String *variable_name; //Name of a variable being wrapped |
| String *variable_type; //Type of this variable |
| Hash *enumeration_coll; //Collection of all enumerations. |
| /* The items are nodes with members: |
| "items" - hash of with key 'itemname' and content 'itemvalue' |
| "max" - maximum value in item list |
| */ |
| String *constant_values; |
| String *constantfilename; |
| String *renamefilename; |
| String *typemapfilename; |
| String *m3raw_imports; //intermediary class imports from %pragma |
| String *module_imports; //module imports from %pragma |
| String *m3raw_baseclass; //inheritance for intermediary class class from %pragma |
| String *module_baseclass; //inheritance for module class from %pragma |
| String *m3raw_interfaces; //interfaces for intermediary class class from %pragma |
| String *module_interfaces; //interfaces for module class from %pragma |
| String *m3raw_class_modifiers; //class modifiers for intermediary class overriden by %pragma |
| String *m3wrap_modifiers; //class modifiers for module class overriden by %pragma |
| String *upcasts_code; //C++ casts for inheritance hierarchies C++ code |
| String *m3raw_cppcasts_code; //C++ casts up inheritance hierarchies intermediary class code |
| String *destructor_call; //C++ destructor call if any |
| String *outfile; |
| |
| enum type_additions { none, pointer, reference }; |
| |
| public: |
| |
| /* ----------------------------------------------------------------------------- |
| * MODULA3() |
| * ----------------------------------------------------------------------------- */ |
| |
| MODULA3(): |
| empty_string(NewString("")), |
| swig_types_hash(NULL), |
| f_begin(NULL), |
| f_runtime(NULL), |
| f_header(NULL), |
| f_wrappers(NULL), |
| f_init(NULL), |
| proxy_flag(true), |
| have_default_constructor_flag(false), |
| native_function_flag(false), |
| enum_constant_flag(false), |
| static_flag(false), |
| variable_wrapper_flag(false), |
| wrapping_member_flag(false), |
| global_variable_flag(false), |
| old_variable_names(false), |
| unsafe_module(false), |
| m3raw_name(NULL), |
| m3raw_intf(), |
| m3raw_impl(), |
| m3wrap_name(NULL), |
| m3wrap_intf(), |
| m3wrap_impl(), |
| m3makefile(NULL), |
| targetlibrary(NULL), |
| proxy_class_def(NULL), |
| proxy_class_code(NULL), |
| proxy_class_name(NULL), |
| variable_name(NULL), |
| variable_type(NULL), |
| enumeration_coll(NULL), |
| constant_values(NULL), |
| constantfilename(NULL), |
| renamefilename(NULL), |
| typemapfilename(NULL), |
| m3raw_imports(NULL), |
| module_imports(NULL), |
| m3raw_baseclass(NULL), |
| module_baseclass(NULL), |
| m3raw_interfaces(NULL), |
| module_interfaces(NULL), |
| m3raw_class_modifiers(NULL), |
| m3wrap_modifiers(NULL), |
| upcasts_code(NULL), |
| m3raw_cppcasts_code(NULL), |
| destructor_call(NULL), |
| outfile(NULL) { |
| } |
| |
| /************** some utility functions ***************/ |
| |
| /* ----------------------------------------------------------------------------- |
| * getMappedType() |
| * |
| * Return the type of 'p' mapped by 'map'. |
| * Print a standard warning if 'p' can't be mapped. |
| * ----------------------------------------------------------------------------- */ |
| |
| String *getMappedType(Node *p, const char *map) { |
| String *mapattr = NewString("tmap:"); |
| Append(mapattr, map); |
| |
| String *tm = Getattr(p, mapattr); |
| if (tm == NIL) { |
| Swig_warning(WARN_MODULA3_TYPEMAP_TYPE_UNDEF, input_file, line_number, |
| "No '%s' typemap defined for type '%s'\n", map, SwigType_str(Getattr(p, "type"), 0)); |
| } |
| Delete(mapattr); |
| return tm; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * getMappedTypeNew() |
| * |
| * Similar to getMappedType but uses Swig_type_lookup_new. |
| * ----------------------------------------------------------------------------- */ |
| |
| String *getMappedTypeNew(Node *n, const char *map, const char *lname = "", bool warn = true) { |
| String *tm = Swig_typemap_lookup(map, n, lname, 0); |
| if ((tm == NIL) && warn) { |
| Swig_warning(WARN_MODULA3_TYPEMAP_TYPE_UNDEF, input_file, line_number, |
| "No '%s' typemap defined for type '%s'\n", map, SwigType_str(Getattr(n, "type"), 0)); |
| } |
| return tm; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * attachMappedType() |
| * |
| * Obtain the type mapped by 'map' and attach it to the node |
| * ----------------------------------------------------------------------------- */ |
| |
| void attachMappedType(Node *n, const char *map, const char *lname = "") { |
| String *tm = Swig_typemap_lookup(map, n, lname, 0); |
| if (tm != NIL) { |
| String *attr = NewStringf("tmap:%s", map); |
| Setattr(n, attr, tm); |
| Delete(attr); |
| } |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * skipIgnored() |
| * |
| * Skip all parameters that have 'numinputs=0' |
| * with respect to a given typemap. |
| * ----------------------------------------------------------------------------- */ |
| |
| Node *skipIgnored(Node *p, const char *map) { |
| String *niattr = NewStringf("tmap:%s:numinputs", map); |
| String *nextattr = NewStringf("tmap:%s:next", map); |
| |
| while ((p != NIL) && checkAttribute(p, niattr, "0")) { |
| p = Getattr(p, nextattr); |
| } |
| |
| Delete(nextattr); |
| Delete(niattr); |
| return p; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * isInParam() |
| * isOutParam() |
| * |
| * Check if the parameter is intended for input or for output. |
| * ----------------------------------------------------------------------------- */ |
| |
| bool isInParam(Node *p) { |
| String *dir = Getattr(p, "tmap:m3wrapargdir"); |
| //printf("dir for %s: %s\n", Char(Getattr(p,"name")), Char(dir)); |
| if ((dir == NIL) || (Strcmp(dir, "in") == 0) |
| || (Strcmp(dir, "inout") == 0)) { |
| return true; |
| } else if (Strcmp(dir, "out") == 0) { |
| return false; |
| } else { |
| printf("%s", USAGE_ARG_DIR); |
| return false; |
| } |
| } |
| |
| bool isOutParam(Node *p) { |
| String *dir = Getattr(p, "tmap:m3wrapargdir"); |
| if ((dir == NIL) || (Strcmp(dir, "in") == 0)) { |
| return false; |
| } else if ((Strcmp(dir, "out") == 0) || (Strcmp(dir, "inout") == 0)) { |
| return true; |
| } else { |
| printf("%s", USAGE_ARG_DIR); |
| return false; |
| } |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * printAttrs() |
| * |
| * For debugging: Show all attributes of a node and their values. |
| * ----------------------------------------------------------------------------- */ |
| void printAttrs(Node *n) { |
| Iterator it; |
| for (it = First(n); it.key != NIL; it = Next(it)) { |
| printf("%s = %s\n", Char(it.key), Char(Getattr(n, it.key))); |
| } |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * hasPrefix() |
| * |
| * Check if a string have a given prefix. |
| * ----------------------------------------------------------------------------- */ |
| bool hasPrefix(const String *str, const String *prefix) { |
| int len_prefix = Len(prefix); |
| return (Len(str) > len_prefix) |
| && (Strncmp(str, prefix, len_prefix) == 0); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * getQualifiedName() |
| * |
| * Return fully qualified identifier of n. |
| * ----------------------------------------------------------------------------- */ |
| #if 0 |
| // Swig_symbol_qualified returns NIL for enumeration nodes |
| String *getQualifiedName(Node *n) { |
| String *qual = Swig_symbol_qualified(n); |
| String *name = Getattr(n, "name"); |
| if (hasContent(qual)) { |
| return NewStringf("%s::%s", qual, name); |
| } else { |
| return name; |
| } |
| } |
| #else |
| String *getQualifiedName(Node *n) { |
| String *name = Copy(Getattr(n, "name")); |
| n = parentNode(n); |
| while (n != NIL) { |
| const String *type = nodeType(n); |
| if ((Strcmp(type, "class") == 0) || (Strcmp(type, "struct") == 0) || (Strcmp(type, "namespace") == 0)) { |
| String *newname = NewStringf("%s::%s", Getattr(n, "name"), name); |
| Delete(name); |
| //name = newname; |
| // Hmpf, the class name is already qualified. |
| return newname; |
| } |
| n = parentNode(n); |
| } |
| //printf("qualified name: %s\n", Char(name)); |
| return name; |
| } |
| #endif |
| |
| /* ----------------------------------------------------------------------------- |
| * nameToModula3() |
| * |
| * Turn usual C identifiers like "this_is_an_identifier" |
| * into usual Modula 3 identifier like "thisIsAnIdentifier" |
| * ----------------------------------------------------------------------------- */ |
| String *nameToModula3(const String *sym, bool leadingCap) { |
| int len_sym = Len(sym); |
| char *csym = Char(sym); |
| char *m3sym = new char[len_sym + 1]; |
| int i, j; |
| bool cap = leadingCap; |
| for (i = 0, j = 0; j < len_sym; j++) { |
| char c = csym[j]; |
| if ((c == '_') || (c == ':')) { |
| cap = true; |
| } else { |
| if (isdigit(c)) { |
| m3sym[i] = c; |
| cap = true; |
| } else { |
| if (cap) { |
| m3sym[i] = (char)toupper(c); |
| } else { |
| m3sym[i] = (char)tolower(c); |
| } |
| cap = false; |
| } |
| i++; |
| } |
| } |
| m3sym[i] = 0; |
| String *result = NewString(m3sym); |
| delete[]m3sym; |
| return result; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * capitalizeFirst() |
| * |
| * Make the first character upper case. |
| * ----------------------------------------------------------------------------- */ |
| String *capitalizeFirst(const String *str) { |
| return NewStringf("%c%s", toupper(*Char(str)), Char(str) + 1); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * prefixedNameToModula3() |
| * |
| * If feature modula3:oldprefix and modula3:newprefix is present |
| * and the C identifier has leading 'oldprefix' |
| * then it is replaced by the 'newprefix'. |
| * The rest is converted to Modula style. |
| * ----------------------------------------------------------------------------- */ |
| String *prefixedNameToModula3(Node *n, const String *sym, bool leadingCap) { |
| String *oldPrefix = Getattr(n, "feature:modula3:oldprefix"); |
| String *newPrefix = Getattr(n, "feature:modula3:newprefix"); |
| String *result = NewString(""); |
| char *short_sym = Char(sym); |
| // if at least one prefix feature is present |
| // the replacement takes place |
| if ((oldPrefix != NIL) || (newPrefix != NIL)) { |
| if ((oldPrefix == NIL) || hasPrefix(sym, oldPrefix)) { |
| short_sym += Len(oldPrefix); |
| if (newPrefix != NIL) { |
| Append(result, newPrefix); |
| } |
| } |
| } |
| String *suffix = nameToModula3(short_sym, leadingCap || hasContent(newPrefix)); |
| Append(result, suffix); |
| Delete(suffix); |
| return result; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * hasContent() |
| * |
| * Check if the string exists and contains something. |
| * ----------------------------------------------------------------------------- */ |
| bool hasContent(const String *str) { |
| return (str != NIL) && (Strcmp(str, "") != 0); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * openWriteFile() |
| * |
| * Caution: The file must be freshly allocated and will be destroyed |
| * by this routine. |
| * ----------------------------------------------------------------------------- */ |
| |
| File *openWriteFile(String *name) { |
| File *file = NewFile(name, "w", SWIG_output_files()); |
| if (!file) { |
| FileErrorDisplay(name); |
| SWIG_exit(EXIT_FAILURE); |
| } |
| Delete(name); |
| return file; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * aToL() |
| * |
| * like atol but with additional user warning |
| * ----------------------------------------------------------------------------- */ |
| |
| long aToL(const String *value) { |
| char *endptr; |
| long numvalue = strtol(Char(value), &endptr, 0); |
| if (*endptr != 0) { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "The string <%s> does not denote a numeric value.\n", value); |
| } |
| return numvalue; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * strToL() |
| * |
| * like strtol but returns if the conversion was successful |
| * ----------------------------------------------------------------------------- */ |
| |
| bool strToL(const String *value, long &numvalue) { |
| char *endptr; |
| numvalue = strtol(Char(value), &endptr, 0); |
| return (*endptr == 0); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * evalExpr() |
| * |
| * Evaluate simple expression as they may occur in "enumvalue" attributes. |
| * ----------------------------------------------------------------------------- */ |
| |
| bool evalExpr(String *value, long &numvalue) { |
| // Split changes file status of String and thus cannot receive 'const' strings |
| //printf("evaluate <%s>\n", Char(value)); |
| List *summands = Split(value, '+', INT_MAX); |
| Iterator sm = First(summands); |
| numvalue = 0; |
| for (; sm.item != NIL; sm = Next(sm)) { |
| String *smvalue = Getattr(constant_values, sm.item); |
| long smnumvalue; |
| if (smvalue != NIL) { |
| if (!strToL(smvalue, smnumvalue)) { |
| //printf("evaluation: abort 0 <%s>\n", Char(smvalue)); |
| return false; |
| } |
| } else { |
| if (!strToL(sm.item, smnumvalue)) { |
| //printf("evaluation: abort 1 <%s>\n", Char(sm)); |
| return false; |
| } |
| } |
| numvalue += smnumvalue; |
| } |
| //printf("evaluation: return %ld\n", numvalue); |
| return true; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * log2() |
| * |
| * Determine the position of the single bit of a power of two. |
| * Returns true if the given number is a power of two. |
| * ----------------------------------------------------------------------------- */ |
| |
| bool log2(long n, long &exp) { |
| exp = 0; |
| while (n > 0) { |
| if ((n & 1) != 0) { |
| return n == 1; |
| } |
| exp++; |
| n >>= 1; |
| } |
| return false; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * writeArg |
| * |
| * Write a function argument or RECORD entry definition. |
| * Bundles arguments of same type and default value. |
| * 'name.next==NIL' denotes the end of the entry or argument list. |
| * ----------------------------------------------------------------------------- */ |
| |
| bool equalNilStr(const String *str0, const String *str1) { |
| if (str0 == NIL) { |
| return (str1 == NIL); |
| //return (str0==NIL) == (str1==NIL); |
| } else { |
| return (str1 != NIL) && (Cmp(str0, str1) == 0); |
| //return Cmp(str0,str1)==0; |
| } |
| } |
| |
| struct writeArgState { |
| String *mode, *name, *type, *value; |
| bool hold; |
| writeArgState():mode(NIL), name(NIL), type(NIL), value(NIL), hold(false) { |
| } |
| }; |
| |
| void writeArg(File *f, writeArgState & state, String *mode, String *name, String *type, String *value) { |
| /* skip the first argument, |
| only store the information for the next call in this case */ |
| if (state.name != NIL) { |
| if ((!state.hold) && (state.mode != NIL)) { |
| Printf(f, "%s ", state.mode); |
| } |
| if ((name != NIL) && equalNilStr(state.mode, mode) && equalNilStr(state.type, type) && (state.value == NIL) && (value == NIL) |
| /* the same expression may have different values |
| due to side effects of the called function */ |
| /*equalNilStr(state.value,value) */ |
| ) { |
| Printf(f, "%s, ", state.name); |
| state.hold = true; |
| } else { |
| Append(f, state.name); |
| if (state.type != NIL) { |
| Printf(f, ": %s", state.type); |
| } |
| if (state.value != NIL) { |
| Printf(f, ":= %s", state.value); |
| } |
| Append(f, ";\n"); |
| state.hold = false; |
| } |
| } |
| /* at the next call the current argument will be the previous one */ |
| state.mode = mode; |
| state.name = name; |
| state.type = type; |
| state.value = value; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * getProxyName() |
| * |
| * Test to see if a type corresponds to something wrapped with a proxy class |
| * Return NULL if not otherwise the proxy class name |
| * ----------------------------------------------------------------------------- */ |
| |
| String *getProxyName(SwigType *t) { |
| if (proxy_flag) { |
| Node *n = classLookup(t); |
| if (n) { |
| return Getattr(n, "sym:name"); |
| } |
| } |
| return NULL; |
| } |
| |
| /*************** language processing ********************/ |
| |
| /* ------------------------------------------------------------ |
| * main() |
| * ------------------------------------------------------------ */ |
| |
| virtual void main(int argc, char *argv[]) { |
| |
| SWIG_library_directory("modula3"); |
| |
| // Look for certain command line options |
| for (int i = 1; i < argc; i++) { |
| if (argv[i]) { |
| if (strcmp(argv[i], "-generateconst") == 0) { |
| if (argv[i + 1]) { |
| constantfilename = NewString(argv[i + 1]); |
| Swig_mark_arg(i); |
| Swig_mark_arg(i + 1); |
| i++; |
| } else { |
| Swig_arg_error(); |
| } |
| } else if (strcmp(argv[i], "-generaterename") == 0) { |
| if (argv[i + 1]) { |
| renamefilename = NewString(argv[i + 1]); |
| Swig_mark_arg(i); |
| Swig_mark_arg(i + 1); |
| i++; |
| } else { |
| Swig_arg_error(); |
| } |
| } else if (strcmp(argv[i], "-generatetypemap") == 0) { |
| if (argv[i + 1]) { |
| typemapfilename = NewString(argv[i + 1]); |
| Swig_mark_arg(i); |
| Swig_mark_arg(i + 1); |
| i++; |
| } else { |
| Swig_arg_error(); |
| } |
| } else if (strcmp(argv[i], "-noproxy") == 0) { |
| Swig_mark_arg(i); |
| proxy_flag = false; |
| } else if (strcmp(argv[i], "-oldvarnames") == 0) { |
| Swig_mark_arg(i); |
| old_variable_names = true; |
| } else if (strcmp(argv[i], "-help") == 0) { |
| Printf(stdout, "%s\n", usage); |
| } |
| } |
| } |
| |
| // Add a symbol to the parser for conditional compilation |
| Preprocessor_define("SWIGMODULA3 1", 0); |
| |
| // Add typemap definitions |
| SWIG_typemap_lang("modula3"); |
| SWIG_config_file("modula3.swg"); |
| |
| allow_overloading(); |
| } |
| |
| /* --------------------------------------------------------------------- |
| * top() |
| * --------------------------------------------------------------------- */ |
| |
| virtual int top(Node *n) { |
| if (hasContent(constantfilename) || hasContent(renamefilename) || hasContent(typemapfilename)) { |
| int result = SWIG_OK; |
| if (hasContent(constantfilename)) { |
| result = generateConstantTop(n) && result; |
| } |
| if (hasContent(renamefilename)) { |
| result = generateRenameTop(n) && result; |
| } |
| if (hasContent(typemapfilename)) { |
| result = generateTypemapTop(n) && result; |
| } |
| return result; |
| } else { |
| return generateM3Top(n); |
| } |
| } |
| |
| void scanConstant(File *file, Node *n) { |
| Node *child = firstChild(n); |
| while (child != NIL) { |
| String *constname = NIL; |
| String *type = nodeType(child); |
| if ((Strcmp(type, "enumitem") == 0) |
| || (Strcmp(type, "constant") == 0)) { |
| #if 1 |
| constname = getQualifiedName(child); |
| #else |
| constname = Getattr(child, "value"); |
| if ((!hasContent(constname)) |
| || (('0' <= *Char(constname)) && (*Char(constname) <= '9'))) { |
| constname = Getattr(child, "name"); |
| } |
| #endif |
| } |
| if (constname != NIL) { |
| Printf(file, " printf(\"%%%%constnumeric(%%Lg) %s;\\n\", (long double)%s);\n", constname, constname); |
| } |
| scanConstant(file, child); |
| child = nextSibling(child); |
| } |
| } |
| |
| int generateConstantTop(Node *n) { |
| File *file = openWriteFile(NewStringf("%s.c", constantfilename)); |
| if (CPlusPlus) { |
| Printf(file, "#include <cstdio>\n"); |
| } else { |
| Printf(file, "#include <stdio.h>\n"); |
| } |
| Printf(file, "#include \"%s\"\n", input_file); |
| Printf(file, "\n"); |
| Printf(file, "int main (int argc, char *argv[]) {\n"); |
| Printf(file, "\ |
| /*This progam must work for floating point numbers and integers.\n\ |
| Thus all numbers are converted to double precision floating point format.*/\n"); |
| scanConstant(file, n); |
| Printf(file, " return 0;\n"); |
| Printf(file, "}\n"); |
| Delete(file); |
| return SWIG_OK; |
| } |
| |
| void scanRename(File *file, Node *n) { |
| Node *child = firstChild(n); |
| while (child != NIL) { |
| String *type = nodeType(child); |
| if (Strcmp(type, "cdecl") == 0) { |
| ParmList *p = Getattr(child, "parms"); |
| if (p != NIL) { |
| String *name = getQualifiedName(child); |
| String *m3name = nameToModula3(name, true); |
| /*don't know how to get the original C type identifiers */ |
| //String *arguments = createCSignature (child); |
| Printf(file, "%%rename(\"%s\") %s;\n", m3name, name); |
| /*Printf(file, "%%rename(\"%s\") %s %s(%s);\n", |
| m3name, Getattr(n,"type"), name, arguments); */ |
| Delete(name); |
| Delete(m3name); |
| //Delete (arguments); |
| } |
| } |
| scanRename(file, child); |
| child = nextSibling(child); |
| } |
| } |
| |
| int generateRenameTop(Node *n) { |
| File *file = openWriteFile(NewStringf("%s.i", renamefilename)); |
| Printf(file, "\ |
| /* This file was generated from %s\n\ |
| by SWIG with option -generaterename. */\n\ |
| \n", input_file); |
| scanRename(file, n); |
| Delete(file); |
| return SWIG_OK; |
| } |
| |
| void scanTypemap(File *file, Node *n) { |
| Node *child = firstChild(n); |
| while (child != NIL) { |
| String *type = nodeType(child); |
| //printf("nodetype %s\n", Char(type)); |
| String *storage = Getattr(child, "storage"); |
| if ((Strcmp(type, "class") == 0) || ((Strcmp(type, "cdecl") == 0) && (storage != NIL) |
| && (Strcmp(storage, "typedef") == 0))) { |
| String *name = getQualifiedName(child); |
| String *m3name = nameToModula3(name, true); |
| Printf(file, "%%typemap(\"m3wrapintype\") %s %%{%s%%}\n", name, m3name); |
| Printf(file, "%%typemap(\"m3rawintype\") %s %%{%s%%}\n", name, m3name); |
| Printf(file, "\n"); |
| } |
| scanTypemap(file, child); |
| child = nextSibling(child); |
| } |
| } |
| |
| int generateTypemapTop(Node *n) { |
| File *file = openWriteFile(NewStringf("%s.i", typemapfilename)); |
| Printf(file, "\ |
| /* This file was generated from %s\n\ |
| by SWIG with option -generatetypemap. */\n\ |
| \n", input_file); |
| scanTypemap(file, n); |
| Delete(file); |
| return SWIG_OK; |
| } |
| |
| int generateM3Top(Node *n) { |
| /* Initialize all of the output files */ |
| outfile = Getattr(n, "outfile"); |
| |
| f_begin = NewFile(outfile, "w", SWIG_output_files()); |
| if (!f_begin) { |
| FileErrorDisplay(outfile); |
| SWIG_exit(EXIT_FAILURE); |
| } |
| f_runtime = NewString(""); |
| f_init = NewString(""); |
| f_header = NewString(""); |
| f_wrappers = NewString(""); |
| |
| m3makefile = NewString(""); |
| |
| /* Register file targets with the SWIG file handler */ |
| Swig_register_filebyname("header", f_header); |
| Swig_register_filebyname("wrapper", f_wrappers); |
| Swig_register_filebyname("begin", f_begin); |
| Swig_register_filebyname("runtime", f_runtime); |
| Swig_register_filebyname("init", f_init); |
| |
| Swig_register_filebyname("m3rawintf", m3raw_intf.f); |
| Swig_register_filebyname("m3rawimpl", m3raw_impl.f); |
| Swig_register_filebyname("m3wrapintf", m3wrap_intf.f); |
| Swig_register_filebyname("m3wrapimpl", m3wrap_impl.f); |
| Swig_register_filebyname("m3makefile", m3makefile); |
| |
| swig_types_hash = NewHash(); |
| |
| String *name = Getattr(n, "name"); |
| // Make the intermediary class and module class names. The intermediary class name can be set in the module directive. |
| Node *optionsnode = Getattr(Getattr(n, "module"), "options"); |
| if (optionsnode != NIL) { |
| String *m3raw_name_tmp = Getattr(optionsnode, "m3rawname"); |
| if (m3raw_name_tmp != NIL) { |
| m3raw_name = Copy(m3raw_name_tmp); |
| } |
| } |
| if (m3raw_name == NIL) { |
| m3raw_name = NewStringf("%sRaw", name); |
| } |
| Setattr(m3wrap_impl.import, m3raw_name, ""); |
| |
| m3wrap_name = Copy(name); |
| |
| proxy_class_def = NewString(""); |
| proxy_class_code = NewString(""); |
| m3raw_baseclass = NewString(""); |
| m3raw_interfaces = NewString(""); |
| m3raw_class_modifiers = NewString(""); // package access only to the intermediary class by default |
| m3raw_imports = NewString(""); |
| m3raw_cppcasts_code = NewString(""); |
| m3wrap_modifiers = NewString("public"); |
| module_baseclass = NewString(""); |
| module_interfaces = NewString(""); |
| module_imports = NewString(""); |
| upcasts_code = NewString(""); |
| |
| Swig_banner(f_begin); |
| |
| Printf(f_runtime, "\n\n#ifndef SWIGMODULA3\n#define SWIGMODULA3\n#endif\n\n"); |
| |
| Swig_name_register("wrapper", "Modula3_%f"); |
| if (old_variable_names) { |
| Swig_name_register("set", "set_%n%v"); |
| Swig_name_register("get", "get_%n%v"); |
| } |
| |
| Printf(f_wrappers, "\n#ifdef __cplusplus\n"); |
| Printf(f_wrappers, "extern \"C\" {\n"); |
| Printf(f_wrappers, "#endif\n\n"); |
| |
| constant_values = NewHash(); |
| scanForConstPragmas(n); |
| enumeration_coll = NewHash(); |
| collectEnumerations(enumeration_coll, n); |
| |
| /* Emit code */ |
| Language::top(n); |
| |
| // Generate m3makefile |
| // This will be unnecessary if SWIG is invoked from Quake. |
| { |
| File *file = openWriteFile(NewStringf("%sm3makefile", SWIG_output_directory())); |
| |
| Printf(file, "%% automatically generated quake file for %s\n\n", name); |
| |
| /* Write the fragments written by '%insert' |
| collected while 'top' processed the parse tree */ |
| Printv(file, m3makefile, NIL); |
| |
| Printf(file, "import(\"libm3\")\n"); |
| //Printf(file, "import_lib(\"%s\",\"/usr/lib\")\n", name); |
| Printf(file, "module(\"%s\")\n", m3raw_name); |
| Printf(file, "module(\"%s\")\n\n", m3wrap_name); |
| |
| if (targetlibrary != NIL) { |
| Printf(file, "library(\"%s\")\n", targetlibrary); |
| } else { |
| Printf(file, "library(\"m3%s\")\n", name); |
| } |
| Delete(file); |
| } |
| |
| // Generate the raw interface |
| { |
| File *file = openWriteFile(NewStringf("%s%s.i3", SWIG_output_directory(), m3raw_name)); |
| |
| emitBanner(file); |
| |
| Printf(file, "INTERFACE %s;\n\n", m3raw_name); |
| |
| emitImportStatements(m3raw_intf.import, file); |
| Printf(file, "\n"); |
| |
| // Write the interface generated within 'top' |
| Printv(file, m3raw_intf.f, NIL); |
| |
| Printf(file, "\nEND %s.\n", m3raw_name); |
| Delete(file); |
| } |
| |
| // Generate the raw module |
| { |
| File *file = openWriteFile(NewStringf("%s%s.m3", SWIG_output_directory(), m3raw_name)); |
| |
| emitBanner(file); |
| |
| Printf(file, "MODULE %s;\n\n", m3raw_name); |
| |
| emitImportStatements(m3raw_impl.import, file); |
| Printf(file, "\n"); |
| |
| // will be empty usually |
| Printv(file, m3raw_impl.f, NIL); |
| |
| Printf(file, "BEGIN\nEND %s.\n", m3raw_name); |
| Delete(file); |
| } |
| |
| // Generate the interface for the comfort wrappers |
| { |
| File *file = openWriteFile(NewStringf("%s%s.i3", SWIG_output_directory(), m3wrap_name)); |
| |
| emitBanner(file); |
| |
| Printf(file, "INTERFACE %s;\n", m3wrap_name); |
| |
| emitImportStatements(m3wrap_intf.import, file); |
| Printf(file, "\n"); |
| |
| { |
| Iterator it = First(enumeration_coll); |
| if (it.key != NIL) { |
| Printf(file, "TYPE\n"); |
| } |
| for (; it.key != NIL; it = Next(it)) { |
| Printf(file, "\n"); |
| emitEnumeration(file, it.key, it.item); |
| } |
| } |
| |
| // Add the wrapper methods |
| Printv(file, m3wrap_intf.f, NIL); |
| |
| // Finish off the class |
| Printf(file, "\nEND %s.\n", m3wrap_name); |
| Delete(file); |
| } |
| |
| // Generate the wrapper routines implemented in Modula 3 |
| { |
| File *file = openWriteFile(NewStringf("%s%s.m3", SWIG_output_directory(), m3wrap_name)); |
| |
| emitBanner(file); |
| |
| if (unsafe_module) { |
| Printf(file, "UNSAFE "); |
| } |
| Printf(file, "MODULE %s;\n\n", m3wrap_name); |
| |
| emitImportStatements(m3wrap_impl.import, file); |
| Printf(file, "\n"); |
| |
| // Add the wrapper methods |
| Printv(file, m3wrap_impl.f, NIL); |
| |
| Printf(file, "\nBEGIN\nEND %s.\n", m3wrap_name); |
| Delete(file); |
| } |
| |
| if (upcasts_code) |
| Printv(f_wrappers, upcasts_code, NIL); |
| |
| Printf(f_wrappers, "#ifdef __cplusplus\n"); |
| Printf(f_wrappers, "}\n"); |
| Printf(f_wrappers, "#endif\n"); |
| |
| // Output a Modula 3 type wrapper class for each SWIG type |
| for (Iterator swig_type = First(swig_types_hash); swig_type.item != NIL; swig_type = Next(swig_type)) { |
| emitTypeWrapperClass(swig_type.key, swig_type.item); |
| } |
| |
| Delete(swig_types_hash); |
| swig_types_hash = NULL; |
| Delete(constant_values); |
| constant_values = NULL; |
| Delete(enumeration_coll); |
| enumeration_coll = NULL; |
| Delete(m3raw_name); |
| m3raw_name = NULL; |
| Delete(m3raw_baseclass); |
| m3raw_baseclass = NULL; |
| Delete(m3raw_interfaces); |
| m3raw_interfaces = NULL; |
| Delete(m3raw_class_modifiers); |
| m3raw_class_modifiers = NULL; |
| Delete(m3raw_imports); |
| m3raw_imports = NULL; |
| Delete(m3raw_cppcasts_code); |
| m3raw_cppcasts_code = NULL; |
| Delete(proxy_class_def); |
| proxy_class_def = NULL; |
| Delete(proxy_class_code); |
| proxy_class_code = NULL; |
| Delete(m3wrap_name); |
| m3wrap_name = NULL; |
| Delete(m3wrap_modifiers); |
| m3wrap_modifiers = NULL; |
| Delete(targetlibrary); |
| targetlibrary = NULL; |
| Delete(module_baseclass); |
| module_baseclass = NULL; |
| Delete(module_interfaces); |
| module_interfaces = NULL; |
| Delete(module_imports); |
| module_imports = NULL; |
| Delete(upcasts_code); |
| upcasts_code = NULL; |
| Delete(constantfilename); |
| constantfilename = NULL; |
| Delete(renamefilename); |
| renamefilename = NULL; |
| Delete(typemapfilename); |
| typemapfilename = NULL; |
| |
| /* Close all of the files */ |
| Dump(f_runtime, f_begin); |
| Dump(f_header, f_begin); |
| Dump(f_wrappers, f_begin); |
| Wrapper_pretty_print(f_init, f_begin); |
| Delete(f_header); |
| Delete(f_wrappers); |
| Delete(f_init); |
| Delete(f_runtime); |
| Delete(f_begin); |
| return SWIG_OK; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * emitBanner() |
| * ----------------------------------------------------------------------------- */ |
| |
| void emitBanner(File *f) { |
| Printf(f, "(*******************************************************************************\n"); |
| Swig_banner_target_lang(f, " *"); |
| Printf(f, "*******************************************************************************)\n\n"); |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * nativeWrapper() |
| * ---------------------------------------------------------------------- */ |
| |
| virtual int nativeWrapper(Node *n) { |
| String *wrapname = Getattr(n, "wrap:name"); |
| |
| if (!addSymbol(wrapname, n)) |
| return SWIG_ERROR; |
| |
| if (Getattr(n, "type")) { |
| Swig_save("nativeWrapper", n, "name", NIL); |
| Setattr(n, "name", wrapname); |
| native_function_flag = true; |
| functionWrapper(n); |
| Swig_restore(n); |
| native_function_flag = false; |
| } else { |
| Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name")); |
| } |
| |
| return SWIG_OK; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * functionWrapper() |
| * ---------------------------------------------------------------------- */ |
| |
| virtual int functionWrapper(Node *n) { |
| String *type = nodeType(n); |
| String *funcType = Getattr(n, "modula3:functype"); |
| String *rawname = Getattr(n, "name"); |
| String *symname = Getattr(n, "sym:name"); |
| String *capname = capitalizeFirst(symname); |
| //String *wname = Swig_name_wrapper(symname); |
| |
| //printf("function: %s\n", Char(symname)); |
| //printf(" purpose: %s\n", Char(funcType)); |
| |
| if (Strcmp(type, "cdecl") == 0) { |
| if (funcType == NIL) { |
| // no wrapper needed for plain functions |
| emitM3RawPrototype(n, rawname, symname); |
| emitM3Wrapper(n, symname); |
| } else if (Strcmp(funcType, "method") == 0) { |
| Setattr(n, "modula3:funcname", capname); |
| emitCWrapper(n, capname); |
| emitM3RawPrototype(n, capname, capname); |
| emitM3Wrapper(n, capname); |
| } else if (Strcmp(funcType, "accessor") == 0) { |
| /* |
| * Generate the proxy class properties for public member variables. |
| * Not for enums and constants. |
| */ |
| if (proxy_flag && wrapping_member_flag && !enum_constant_flag) { |
| // Capitalize the first letter in the function name |
| Setattr(n, "proxyfuncname", capname); |
| Setattr(n, "imfuncname", symname); |
| if (hasPrefix(capname, "Set")) { |
| Setattr(n, "modula3:setname", capname); |
| } else { |
| Setattr(n, "modula3:getname", capname); |
| } |
| |
| emitCWrapper(n, capname); |
| emitM3RawPrototype(n, capname, capname); |
| emitM3Wrapper(n, capname); |
| //proxyClassFunctionHandler(n); |
| } |
| #ifdef DEBUG |
| } else { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Function type <%s> unknown.\n", Char(funcType)); |
| #endif |
| } |
| } else if ((Strcmp(type, "constructor") == 0) || (Strcmp(type, "destructor") == 0)) { |
| emitCWrapper(n, capname); |
| emitM3RawPrototype(n, capname, capname); |
| emitM3Wrapper(n, capname); |
| } |
| // a Java relict |
| #if 0 |
| if (!(proxy_flag && is_wrapping_class()) && !enum_constant_flag) { |
| emitM3Wrapper(n, capname); |
| } |
| #endif |
| |
| Delete(capname); |
| |
| return SWIG_OK; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * emitCWrapper() |
| * |
| * Generate the wrapper in C which calls C++ methods. |
| * ---------------------------------------------------------------------- */ |
| |
| virtual int emitCWrapper(Node *n, const String *wname) { |
| String *rawname = Getattr(n, "name"); |
| String *c_return_type = NewString(""); |
| String *cleanup = NewString(""); |
| String *outarg = NewString(""); |
| String *body = NewString(""); |
| Hash *throws_hash = NewHash(); |
| ParmList *l = Getattr(n, "parms"); |
| SwigType *t = Getattr(n, "type"); |
| String *symname = Getattr(n, "sym:name"); |
| |
| if (!Getattr(n, "sym:overloaded")) { |
| if (!addSymbol(wname, n)) { |
| return SWIG_ERROR; |
| } |
| } |
| // A new wrapper function object |
| Wrapper *f = NewWrapper(); |
| |
| /* Attach the non-standard typemaps to the parameter list. */ |
| Swig_typemap_attach_parms("ctype", l, f); |
| |
| /* Get return types */ |
| { |
| String *tm = getMappedTypeNew(n, "ctype", ""); |
| if (tm != NIL) { |
| Printf(c_return_type, "%s", tm); |
| } |
| } |
| |
| bool is_void_return = (Cmp(c_return_type, "void") == 0); |
| if (!is_void_return) { |
| Wrapper_add_localv(f, "cresult", c_return_type, "cresult = 0", NIL); |
| } |
| |
| Printv(f->def, " SWIGEXPORT ", c_return_type, " ", wname, "(", NIL); |
| |
| // Emit all of the local variables for holding arguments. |
| emit_parameter_variables(l, f); |
| |
| /* Attach the standard typemaps */ |
| emit_attach_parmmaps(l, f); |
| Setattr(n, "wrap:parms", l); |
| |
| // Generate signature and argument conversion for C wrapper |
| { |
| Parm *p; |
| attachParameterNames(n, "tmap:name", "c:wrapname", "m3arg%d"); |
| bool gencomma = false; |
| for (p = skipIgnored(l, "in"); p; p = skipIgnored(p, "in")) { |
| |
| String *arg = Getattr(p, "c:wrapname"); |
| { |
| /* Get the ctype types of the parameter */ |
| String *c_param_type = getMappedType(p, "ctype"); |
| // Add parameter to C function |
| Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL); |
| Delete(c_param_type); |
| gencomma = true; |
| } |
| |
| // Get typemap for this argument |
| String *tm = getMappedType(p, "in"); |
| if (tm != NIL) { |
| addThrows(throws_hash, "in", p); |
| Replaceall(tm, "$input", arg); |
| Setattr(p, "emit:input", arg); /*??? */ |
| Printf(f->code, "%s\n", tm); |
| p = Getattr(p, "tmap:in:next"); |
| } else { |
| p = nextSibling(p); |
| } |
| } |
| } |
| |
| /* Insert constraint checking code */ |
| { |
| Parm *p; |
| for (p = l; p;) { |
| String *tm = Getattr(p, "tmap:check"); |
| if (tm != NIL) { |
| addThrows(throws_hash, "check", p); |
| Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */ |
| Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */ |
| Replaceall(tm, "$input", Getattr(p, "emit:input")); |
| Printv(f->code, tm, "\n", NIL); |
| p = Getattr(p, "tmap:check:next"); |
| } else { |
| p = nextSibling(p); |
| } |
| } |
| } |
| |
| /* Insert cleanup code */ |
| { |
| Parm *p; |
| for (p = l; p;) { |
| String *tm = Getattr(p, "tmap:freearg"); |
| if (tm != NIL) { |
| addThrows(throws_hash, "freearg", p); |
| Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */ |
| Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */ |
| Replaceall(tm, "$input", Getattr(p, "emit:input")); |
| Printv(cleanup, tm, "\n", NIL); |
| p = Getattr(p, "tmap:freearg:next"); |
| } else { |
| p = nextSibling(p); |
| } |
| } |
| } |
| |
| /* Insert argument output code */ |
| { |
| Parm *p; |
| for (p = l; p;) { |
| String *tm = Getattr(p, "tmap:argout"); |
| if (tm != NIL) { |
| addThrows(throws_hash, "argout", p); |
| Replaceall(tm, "$source", Getattr(p, "emit:input")); /* deprecated */ |
| Replaceall(tm, "$target", Getattr(p, "lname")); /* deprecated */ |
| Replaceall(tm, "$arg", Getattr(p, "emit:input")); /* deprecated? */ |
| Replaceall(tm, "$result", "cresult"); |
| Replaceall(tm, "$input", Getattr(p, "emit:input")); |
| Printv(outarg, tm, "\n", NIL); |
| p = Getattr(p, "tmap:argout:next"); |
| } else { |
| p = nextSibling(p); |
| } |
| } |
| } |
| |
| // Get any Modula 3 exception classes in the throws typemap |
| ParmList *throw_parm_list = NULL; |
| if ((throw_parm_list = Getattr(n, "catchlist"))) { |
| Swig_typemap_attach_parms("throws", throw_parm_list, f); |
| Parm *p; |
| for (p = throw_parm_list; p; p = nextSibling(p)) { |
| addThrows(throws_hash, "throws", p); |
| } |
| } |
| |
| Setattr(n, "wrap:name", wname); |
| |
| // Now write code to make the function call |
| if (!native_function_flag) { |
| String *actioncode = emit_action(n); |
| |
| /* Return value if necessary */ |
| String *tm; |
| if ((tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode))) { |
| addThrows(throws_hash, "out", n); |
| Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */ |
| Replaceall(tm, "$target", "cresult"); /* deprecated */ |
| Replaceall(tm, "$result", "cresult"); |
| Printf(f->code, "%s", tm); |
| if (hasContent(tm)) |
| Printf(f->code, "\n"); |
| } else { |
| 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); |
| } |
| emit_return_variable(n, t, f); |
| } |
| |
| /* Output argument output code */ |
| Printv(f->code, outarg, NIL); |
| |
| /* Output cleanup code */ |
| Printv(f->code, cleanup, NIL); |
| |
| /* Look to see if there is any newfree cleanup code */ |
| if (GetFlag(n, "feature:new")) { |
| String *tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0); |
| if (tm != NIL) { |
| addThrows(throws_hash, "newfree", n); |
| Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */ |
| Printf(f->code, "%s\n", tm); |
| } |
| } |
| |
| /* See if there is any return cleanup code */ |
| if (!native_function_flag) { |
| String *tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0); |
| if (tm != NIL) { |
| Replaceall(tm, "$source", Swig_cresult_name()); /* deprecated */ |
| Printf(f->code, "%s\n", tm); |
| } |
| } |
| |
| /* Finish C wrapper */ |
| Printf(f->def, ") {"); |
| |
| if (!is_void_return) |
| Printv(f->code, " return cresult;\n", NIL); |
| Printf(f->code, "}\n"); |
| |
| /* Substitute the cleanup code */ |
| Replaceall(f->code, "$cleanup", cleanup); |
| |
| /* Substitute the function name */ |
| Replaceall(f->code, "$symname", symname); |
| |
| if (!is_void_return) { |
| Replaceall(f->code, "$null", "0"); |
| } else { |
| Replaceall(f->code, "$null", ""); |
| } |
| |
| /* Dump the function out */ |
| if (!native_function_flag) { |
| Wrapper_print(f, f_wrappers); |
| } |
| |
| Delete(c_return_type); |
| Delete(cleanup); |
| Delete(outarg); |
| Delete(body); |
| Delete(throws_hash); |
| DelWrapper(f); |
| return SWIG_OK; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * emitM3RawPrototype() |
| * |
| * Generate an EXTERNAL procedure declaration in Modula 3 |
| * which is the interface to an existing C routine or a C wrapper. |
| * ---------------------------------------------------------------------- */ |
| |
| virtual int emitM3RawPrototype(Node *n, const String *cname, const String *m3name) { |
| String *im_return_type = NewString(""); |
| //String *symname = Getattr(n,"sym:name"); |
| ParmList *l = Getattr(n, "parms"); |
| |
| /* Attach the non-standard typemaps to the parameter list. */ |
| Swig_typemap_attach_parms("m3rawinmode", l, NULL); |
| Swig_typemap_attach_parms("m3rawintype", l, NULL); |
| |
| /* Get return types */ |
| bool has_return; |
| { |
| String *tm = getMappedTypeNew(n, "m3rawrettype", ""); |
| if (tm != NIL) { |
| Printf(im_return_type, "%s", tm); |
| } |
| has_return = hasContent(tm); |
| } |
| |
| /* cname is the original name if 'n' denotes a C function |
| and it is the relabeled name (sym:name) if 'n' denotes a C++ method or similar */ |
| m3raw_intf.enterBlock(no_block); |
| Printf(m3raw_intf.f, "\n<* EXTERNAL %s *>\nPROCEDURE %s (", cname, m3name); |
| |
| // Generate signature for raw interface |
| { |
| Parm *p; |
| writeArgState state; |
| attachParameterNames(n, "tmap:rawinname", "modula3:rawname", "arg%d"); |
| for (p = skipIgnored(l, "m3rawintype"); p; p = skipIgnored(p, "m3rawintype")) { |
| |
| /* Get argument passing mode, should be one of VALUE, VAR, READONLY */ |
| String *mode = Getattr(p, "tmap:m3rawinmode"); |
| String *argname = Getattr(p, "modula3:rawname"); |
| String *im_param_type = getMappedType(p, "m3rawintype"); |
| addImports(m3raw_intf.import, "m3rawintype", p); |
| |
| writeArg(m3raw_intf.f, state, mode, argname, im_param_type, NIL); |
| if (im_param_type != NIL) { |
| p = Getattr(p, "tmap:m3rawintype:next"); |
| } else { |
| p = nextSibling(p); |
| } |
| } |
| writeArg(m3raw_intf.f, state, NIL, NIL, NIL, NIL); |
| } |
| |
| /* Finish M3 raw prototype */ |
| Printf(m3raw_intf.f, ")"); |
| // neither a C wrapper nor a plain C function may throw an exception |
| //generateThrowsClause(throws_hash, m3raw_intf.f); |
| if (has_return) { |
| Printf(m3raw_intf.f, ": %s", im_return_type); |
| } |
| Printf(m3raw_intf.f, ";\n"); |
| |
| Delete(im_return_type); |
| return SWIG_OK; |
| } |
| |
| /* ----------------------------------------------------------------------- |
| * variableWrapper() |
| * ----------------------------------------------------------------------- */ |
| |
| virtual int variableWrapper(Node *n) { |
| Language::variableWrapper(n); |
| return SWIG_OK; |
| } |
| |
| /* ----------------------------------------------------------------------- |
| * globalvariableHandler() |
| * ----------------------------------------------------------------------- */ |
| |
| virtual int globalvariableHandler(Node *n) { |
| SwigType *t = Getattr(n, "type"); |
| String *tm; |
| |
| // Get the variable type |
| if ((tm = getMappedTypeNew(n, "m3wraptype", ""))) { |
| substituteClassname(t, tm); |
| } |
| |
| variable_name = Getattr(n, "sym:name"); |
| variable_type = Copy(tm); |
| |
| // Get the variable type expressed in terms of Modula 3 equivalents of C types |
| if ((tm = getMappedTypeNew(n, "m3rawtype", ""))) { |
| m3raw_intf.enterBlock(no_block); |
| Printf(m3raw_intf.f, "\n<* EXTERNAL *> VAR %s: %s;\n", variable_name, tm); |
| } |
| // Output the property's accessor methods |
| /* |
| global_variable_flag = true; |
| int ret = Language::globalvariableHandler(n); |
| global_variable_flag = false; |
| */ |
| |
| Printf(m3wrap_impl.f, "\n\n"); |
| |
| //return ret; |
| return 1; |
| } |
| |
| long getConstNumeric(Node *n) { |
| String *constnumeric = Getfeature(n, "constnumeric"); |
| String *name = Getattr(n, "name"); |
| long numvalue; |
| if (constnumeric == NIL) { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Feature 'constnumeric' is necessary to obtain value of %s.\n", name); |
| return 0; |
| } else if (!strToL(constnumeric, numvalue)) { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, |
| "The feature 'constnumeric' of %s specifies value <%s> which is not an integer constant.\n", name, constnumeric); |
| return 0; |
| } else { |
| return numvalue; |
| } |
| } |
| |
| /* ------------------------------------------------------------------------ |
| * generateIntConstant() |
| * |
| * Considers node as an integer constant definition |
| * and generate a Modula 3 constant definition. |
| * ------------------------------------------------------------------------ */ |
| void generateIntConstant(Node *n, String *name) { |
| String *value = Getattr(n, "value"); |
| String *type = Getfeature(n, "modula3:constint:type"); |
| String *conv = Getfeature(n, "modula3:constint:conv"); |
| |
| if (name == NIL) { |
| name = Getattr(n, "sym:name"); |
| } |
| |
| long numvalue; |
| bool isSimpleNum = strToL(value, numvalue); |
| if (!isSimpleNum) { |
| numvalue = getConstNumeric(n); |
| } |
| |
| String *m3value; |
| if ((conv == NIL) || ((Strcmp(conv, "set:int") != 0) && (Strcmp(conv, "int:set") != 0))) { |
| /* The original value of the constant has precedence over |
| 'constnumeric' feature since we like to keep |
| the style (that is the base) of simple numeric constants */ |
| if (isSimpleNum) { |
| if (hasPrefix(value, "0x")) { |
| m3value = NewStringf("16_%s", Char(value) + 2); |
| } else if ((Len(value) > 1) && (*Char(value) == '0')) { |
| m3value = NewStringf("8_%s", Char(value) + 1); |
| } else { |
| m3value = Copy(value); |
| } |
| /* If we cannot easily obtain the value of a numeric constant, |
| we use the results given by a C compiler. */ |
| } else { |
| m3value = Copy(Getfeature(n, "constnumeric")); |
| } |
| } else { |
| // if the value can't be converted, it is ignored |
| if (convertInt(numvalue, numvalue, conv)) { |
| m3value = NewStringf("%d", numvalue); |
| } else { |
| m3value = NIL; |
| } |
| } |
| |
| if (m3value != NIL) { |
| m3wrap_intf.enterBlock(constant); |
| Printf(m3wrap_intf.f, "%s", name); |
| if (hasContent(type)) { |
| Printf(m3wrap_intf.f, ": %s", type); |
| } |
| Printf(m3wrap_intf.f, " = %s;\n", m3value); |
| Delete(m3value); |
| } |
| } |
| |
| /* ----------------------------------------------------------------------- |
| * generateSetConstant() |
| * |
| * Considers node as a set constant definition |
| * and generate a Modula 3 constant definition. |
| * ------------------------------------------------------------------------ */ |
| void generateSetConstant(Node *n, String *name) { |
| String *value = Getattr(n, "value"); |
| String *type = Getfeature(n, "modula3:constset:type"); |
| String *setname = Getfeature(n, "modula3:constset:set"); |
| String *basename = Getfeature(n, "modula3:constset:base"); |
| String *conv = Getfeature(n, "modula3:constset:conv"); |
| |
| m3wrap_intf.enterBlock(constant); |
| |
| Printf(m3wrap_intf.f, "%s", name); |
| if (type != NIL) { |
| Printf(m3wrap_intf.f, ":%s ", type); |
| } |
| Printf(m3wrap_intf.f, " = %s{", setname); |
| |
| long numvalue = 0; |
| if (!strToL(value, numvalue)) { |
| numvalue = getConstNumeric(n); |
| } |
| convertInt(numvalue, numvalue, conv); |
| |
| bool isIntType = Strcmp(basename, "CARDINAL") == 0; |
| Hash *items = NIL; |
| if (!isIntType) { |
| Hash *enumeration = Getattr(enumeration_coll, basename); |
| if (enumeration == NIL) { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "There is no enumeration <%s> as needed for the set.\n", setname); |
| isIntType = true; |
| } else { |
| items = Getattr(enumeration, "items"); |
| } |
| } |
| |
| bool gencomma = false; |
| int bitpos = 0; |
| while (numvalue > 0) { |
| if ((numvalue & 1) != 0) { |
| if (isIntType) { |
| if (gencomma) { |
| Printv(m3wrap_intf.f, ",", NIL); |
| } |
| gencomma = true; |
| Printf(m3wrap_intf.f, "%d", bitpos); |
| } else { |
| char bitval[15]; |
| sprintf(bitval, "%d", bitpos); |
| String *bitname = Getattr(items, bitval); |
| if (bitname == NIL) { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Enumeration <%s> has no value <%s>.\n", setname, bitval); |
| } else { |
| if (gencomma) { |
| Printv(m3wrap_intf.f, ",", NIL); |
| } |
| gencomma = true; |
| Printf(m3wrap_intf.f, "%s.%s", basename, bitname); |
| } |
| } |
| } |
| numvalue >>= 1; |
| bitpos++; |
| } |
| Printf(m3wrap_intf.f, "};\n"); |
| } |
| |
| void generateConstant(Node *n) { |
| // any of the special interpretation disables the default behaviour |
| String *enumitem = Getfeature(n, "modula3:enumitem:name"); |
| String *constset = Getfeature(n, "modula3:constset:name"); |
| String *constint = Getfeature(n, "modula3:constint:name"); |
| if (hasContent(enumitem) || hasContent(constset) || hasContent(constint)) { |
| if (hasContent(constset)) { |
| generateSetConstant(n, constset); |
| } |
| if (hasContent(constint)) { |
| generateIntConstant(n, constint); |
| } |
| } else { |
| String *value = Getattr(n, "value"); |
| String *name = Getattr(n, "sym:name"); |
| if (name == NIL) { |
| name = Getattr(n, "name"); |
| } |
| m3wrap_intf.enterBlock(constant); |
| Printf(m3wrap_intf.f, "%s = %s;\n", name, value); |
| } |
| } |
| |
| void emitEnumeration(File *file, String *name, Node *n) { |
| Printf(file, "%s = {", name); |
| int i; |
| bool gencomma = false; |
| int max = aToL(Getattr(n, "max")); |
| Hash *items = Getattr(n, "items"); |
| for (i = 0; i <= max; i++) { |
| if (gencomma) { |
| Printf(file, ","); |
| } |
| Printf(file, "\n"); |
| gencomma = true; |
| char numstr[15]; |
| sprintf(numstr, "%d", i); |
| String *name = Getattr(items, numstr); |
| if (name != NIL) { |
| Printv(file, name, NIL); |
| } else { |
| Printf(file, "Dummy%d", i); |
| } |
| } |
| Printf(file, "\n};\n"); |
| } |
| |
| /* ----------------------------------------------------------------------- |
| * constantWrapper() |
| * |
| * Handles constants and enumeration items. |
| * ------------------------------------------------------------------------ */ |
| |
| virtual int constantWrapper(Node *n) { |
| generateConstant(n); |
| return SWIG_OK; |
| } |
| |
| #if 0 |
| // enumerations are handled like constant definitions |
| /* ----------------------------------------------------------------------------- |
| * enumDeclaration() |
| * ----------------------------------------------------------------------------- */ |
| |
| virtual int enumDeclaration(Node *n) { |
| String *symname = nameToModula3(Getattr(n, "sym:name"), true); |
| enumerationStart(symname); |
| int result = Language::enumDeclaration(n); |
| enumerationStop(); |
| Delete(symname); |
| return result; |
| } |
| #endif |
| |
| /* ----------------------------------------------------------------------------- |
| * enumvalueDeclaration() |
| * ----------------------------------------------------------------------------- */ |
| |
| virtual int enumvalueDeclaration(Node *n) { |
| generateConstant(n); |
| /* |
| This call would continue processing in the constantWrapper |
| which cannot handle values like "RED+1". |
| return Language::enumvalueDeclaration(n); |
| */ |
| return SWIG_OK; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * pragmaDirective() |
| * |
| * Valid Pragmas: |
| * imclassbase - base (extends) for the intermediary class |
| * imclassclassmodifiers - class modifiers for the intermediary class |
| * imclasscode - text (Modula 3 code) is copied verbatim to the intermediary class |
| * imclassimports - import statements for the intermediary class |
| * imclassinterfaces - interface (implements) for the intermediary class |
| * |
| * modulebase - base (extends) for the module class |
| * moduleclassmodifiers - class modifiers for the module class |
| * modulecode - text (Modula 3 code) is copied verbatim to the module class |
| * moduleimports - import statements for the module class |
| * moduleinterfaces - interface (implements) for the module class |
| * |
| * ----------------------------------------------------------------------------- */ |
| |
| virtual int pragmaDirective(Node *n) { |
| if (!ImportMode) { |
| String *lang = Getattr(n, "lang"); |
| String *code = Getattr(n, "name"); |
| String *value = Getattr(n, "value"); |
| |
| if (Strcmp(lang, "modula3") == 0) { |
| |
| String *strvalue = NewString(value); |
| Replaceall(strvalue, "\\\"", "\""); |
| /* |
| bool isEnumItem = Strcmp(code, "enumitem") == 0; |
| bool isSetItem = Strcmp(code, "setitem") == 0; |
| */ |
| if (Strcmp(code, "imclassbase") == 0) { |
| Delete(m3raw_baseclass); |
| m3raw_baseclass = Copy(strvalue); |
| } else if (Strcmp(code, "imclassclassmodifiers") == 0) { |
| Delete(m3raw_class_modifiers); |
| m3raw_class_modifiers = Copy(strvalue); |
| } else if (Strcmp(code, "imclasscode") == 0) { |
| Printf(m3raw_intf.f, "%s\n", strvalue); |
| } else if (Strcmp(code, "imclassimports") == 0) { |
| Delete(m3raw_imports); |
| m3raw_imports = Copy(strvalue); |
| } else if (Strcmp(code, "imclassinterfaces") == 0) { |
| Delete(m3raw_interfaces); |
| m3raw_interfaces = Copy(strvalue); |
| } else if (Strcmp(code, "modulebase") == 0) { |
| Delete(module_baseclass); |
| module_baseclass = Copy(strvalue); |
| } else if (Strcmp(code, "moduleclassmodifiers") == 0) { |
| Delete(m3wrap_modifiers); |
| m3wrap_modifiers = Copy(strvalue); |
| } else if (Strcmp(code, "modulecode") == 0) { |
| Printf(m3wrap_impl.f, "%s\n", strvalue); |
| } else if (Strcmp(code, "moduleimports") == 0) { |
| Delete(module_imports); |
| module_imports = Copy(strvalue); |
| } else if (Strcmp(code, "moduleinterfaces") == 0) { |
| Delete(module_interfaces); |
| module_interfaces = Copy(strvalue); |
| } else if (Strcmp(code, "unsafe") == 0) { |
| unsafe_module = true; |
| } else if (Strcmp(code, "library") == 0) { |
| if (targetlibrary) { |
| Delete(targetlibrary); |
| } |
| targetlibrary = Copy(strvalue); |
| } else if (Strcmp(code, "enumitem") == 0) { |
| } else if (Strcmp(code, "constset") == 0) { |
| } else if (Strcmp(code, "constint") == 0) { |
| } else if (Strcmp(code, "makesetofenum") == 0) { |
| m3wrap_intf.enterBlock(blocktype); |
| Printf(m3wrap_intf.f, "%sSet = SET OF %s;\n", value, value); |
| } else { |
| Swig_warning(WARN_MODULA3_UNKNOWN_PRAGMA, input_file, line_number, "Unrecognized pragma <%s>.\n", code); |
| } |
| Delete(strvalue); |
| } |
| } |
| return Language::pragmaDirective(n); |
| } |
| |
| void Setfeature(Node *n, const char *feature, const String *value, bool warn = false) { |
| //printf("tag feature <%s> with value <%s>\n", feature, Char(value)); |
| String *attr = NewStringf("feature:%s", feature); |
| if ((Setattr(n, attr, value) != 0) && warn) { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Feature <%s> of %s did already exist.\n", feature, Getattr(n, "name")); |
| } |
| Delete(attr); |
| } |
| |
| String *Getfeature(Node *n, const char *feature) { |
| //printf("retrieve feature <%s> with value <%s>\n", feature, Char(value)); |
| String *attr = NewStringf("feature:%s", feature); |
| String *result = Getattr(n, attr); |
| Delete(attr); |
| return result; |
| } |
| |
| bool convertInt(long in, long &out, const String *mode) { |
| if ((mode == NIL) || (Strcmp(mode, "int:int") == 0) || (Strcmp(mode, "set:set") == 0)) { |
| out = in; |
| return true; |
| } else if (Strcmp(mode, "set:int") == 0) { |
| return log2(in, out); |
| } else if (Strcmp(mode, "int:set") == 0) { |
| out = 1L << in; |
| return unsigned (in) < (sizeof(out) * 8); |
| } else { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Unknown integer conversion method <%s>.\n", mode); |
| return false; |
| } |
| } |
| |
| void collectEnumerations(Hash *enums, Node *n) { |
| Node *child = firstChild(n); |
| while (child != NIL) { |
| String *name = Getattr(child, "name"); |
| const bool isConstant = Strcmp(nodeType(child), "constant") == 0; |
| const bool isEnumItem = Strcmp(nodeType(child), "enumitem") == 0; |
| if (isConstant || isEnumItem) { |
| //printf("%s%s name %s\n", isConstant?"constant":"", isEnumItem?"enumitem":"", Char(name)); |
| { |
| String *m3name = Getfeature(child, "modula3:enumitem:name"); |
| String *m3enum = Getfeature(child, "modula3:enumitem:enum"); |
| String *conv = Getfeature(child, "modula3:enumitem:conv"); |
| |
| if (m3enum != NIL) { |
| //printf("m3enum %s\n", Char(m3enum)); |
| if (m3name == NIL) { |
| m3name = name; |
| } |
| |
| long max = -1; |
| Hash *items; |
| Hash *enumnode = Getattr(enums, m3enum); |
| if (enumnode == NIL) { |
| enumnode = NewHash(); |
| items = NewHash(); |
| Setattr(enumnode, "items", items); |
| Setattr(enums, m3enum, enumnode); |
| } else { |
| String *maxstr = Getattr(enumnode, "max"); |
| if (maxstr != NIL) { |
| max = aToL(maxstr); |
| } |
| items = Getattr(enumnode, "items"); |
| } |
| long numvalue; |
| String *value = Getattr(child, "value"); |
| //printf("value: %s\n", Char(value)); |
| if ((value == NIL) || (!strToL(value, numvalue))) { |
| value = Getattr(child, "enumvalue"); |
| if ((value == NIL) || (!evalExpr(value, numvalue))) { |
| numvalue = getConstNumeric(child); |
| } |
| //printf("constnumeric: %s\n", Char(value)); |
| } |
| Setattr(constant_values, name, NewStringf("%d", numvalue)); |
| if (convertInt(numvalue, numvalue, conv)) { |
| String *newvalue = NewStringf("%d", numvalue); |
| String *oldname = Getattr(items, newvalue); |
| if (oldname != NIL) { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "The value <%s> is already assigned to <%s>.\n", value, oldname); |
| } |
| //printf("items %p, set %s = %s\n", items, Char(newvalue), Char(m3name)); |
| Setattr(items, newvalue, m3name); |
| if (max < numvalue) { |
| max = numvalue; |
| } |
| Setattr(enumnode, "max", NewStringf("%d", max)); |
| } |
| } |
| } |
| } |
| |
| collectEnumerations(enums, child); |
| child = nextSibling(child); |
| } |
| } |
| |
| enum const_pragma_type { cpt_none, cpt_constint, cpt_constset, cpt_enumitem }; |
| |
| struct const_id_pattern { |
| String *prefix, *parentEnum; |
| }; |
| |
| void tagConstants(Node *first, String *parentEnum, const const_id_pattern & pat, const String *pragma, List *convdesc) { |
| Node *n = first; |
| while (n != NIL) { |
| String *name = getQualifiedName(n); |
| bool isConstant = Strcmp(nodeType(n), "constant") == 0; |
| bool isEnumItem = Strcmp(nodeType(n), "enumitem") == 0; |
| if ((isConstant || isEnumItem) && ((pat.prefix == NIL) || (hasPrefix(name, pat.prefix))) && ((pat.parentEnum == NIL) || ((parentEnum != NIL) |
| && |
| (Strcmp |
| (pat.parentEnum, parentEnum) |
| == 0)))) { |
| //printf("tag %s\n", Char(name)); |
| String *srctype = Getitem(convdesc, 1); |
| String *relationstr = Getitem(convdesc, 3); |
| List *relationdesc = Split(relationstr, ',', 2); |
| |
| // transform name from C to Modula3 style |
| String *srcstyle = NIL; |
| String *newprefix = NIL; |
| { |
| //printf("name conversion <%s>\n", Char(Getitem(convdesc,2))); |
| List *namedesc = Split(Getitem(convdesc, 2), ',', INT_MAX); |
| Iterator nameit = First(namedesc); |
| for (; nameit.item != NIL; nameit = Next(nameit)) { |
| List *nameassign = Split(nameit.item, '=', 2); |
| String *tag = Getitem(nameassign, 0); |
| String *data = Getitem(nameassign, 1); |
| //printf("name conv <%s> = <%s>\n", Char(tag), Char(data)); |
| if (Strcmp(tag, "srcstyle") == 0) { |
| srcstyle = Copy(data); |
| } else if (Strcmp(tag, "prefix") == 0) { |
| newprefix = Copy(data); |
| } else { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Unknown name conversion tag <%s> with value <%s>.\n", tag, data); |
| } |
| Delete(nameassign); |
| } |
| Delete(namedesc); |
| } |
| const char *stem = Char(name); |
| if (pat.prefix != NIL) { |
| //printf("pat.prefix %s for %s\n", Char(pat.prefix), Char(name)); |
| stem += Len(pat.prefix); |
| } |
| String *newname; |
| if (srcstyle && Strcmp(srcstyle, "underscore") == 0) { |
| if (newprefix != NIL) { |
| String *newstem = nameToModula3(stem, true); |
| newname = NewStringf("%s%s", newprefix, newstem); |
| Delete(newstem); |
| } else { |
| newname = nameToModula3(stem, true); |
| } |
| } else { |
| if (srcstyle != NIL) { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Unknown C identifier style <%s>.\n", srcstyle); |
| } |
| newname = Copy(name); |
| } |
| |
| if (Strcmp(pragma, "enumitem") == 0) { |
| if (Len(relationdesc) != 1) { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Expected <enumeration>, got <%s>.\n", relationstr); |
| } |
| Setfeature(n, "modula3:enumitem:name", newname, true); |
| Setfeature(n, "modula3:enumitem:enum", relationstr, true); |
| Setfeature(n, "modula3:enumitem:conv", NewStringf("%s:int", srctype), true); |
| } else if (Strcmp(pragma, "constint") == 0) { |
| if (Len(relationdesc) != 1) { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Expected <ordinal type>, got <%s>.\n", relationstr); |
| } |
| Setfeature(n, "modula3:constint:name", newname, true); |
| Setfeature(n, "modula3:constint:type", Getitem(relationdesc, 0), true); |
| Setfeature(n, "modula3:constint:conv", NewStringf("%s:int", srctype), true); |
| } else if (Strcmp(pragma, "constset") == 0) { |
| if (Len(relationdesc) != 2) { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Expected <set type,base type>, got <%s>.\n", relationstr); |
| } |
| String *settype = Getitem(relationdesc, 0); |
| Setfeature(n, "modula3:constset:name", newname, true); |
| //Setfeature(n,"modula3:constset:type",settype,true); |
| Setfeature(n, "modula3:constset:set", settype, true); |
| Setfeature(n, "modula3:constset:base", Getitem(relationdesc, 1), true); |
| Setfeature(n, "modula3:constset:conv", NewStringf("%s:set", srctype), true); |
| } |
| |
| Delete(newname); |
| Delete(relationdesc); |
| } |
| |
| if (Strcmp(nodeType(n), "enum") == 0) { |
| //printf("explore enum %s, qualification %s\n", Char(name), Char(Swig_symbol_qualified(n))); |
| tagConstants(firstChild(n), name, pat, pragma, convdesc); |
| } else { |
| tagConstants(firstChild(n), NIL, pat, pragma, convdesc); |
| } |
| n = nextSibling(n); |
| } |
| } |
| |
| void scanForConstPragmas(Node *n) { |
| Node *child = firstChild(n); |
| while (child != NIL) { |
| const String *type = nodeType(child); |
| if (Strcmp(type, "pragma") == 0) { |
| const String *lang = Getattr(child, "lang"); |
| const String *code = Getattr(child, "name"); |
| String *value = Getattr(child, "value"); |
| |
| if (Strcmp(lang, "modula3") == 0) { |
| const_pragma_type cpt = cpt_none; |
| if (Strcmp(code, "constint") == 0) { |
| cpt = cpt_constint; |
| } else if (Strcmp(code, "constset") == 0) { |
| cpt = cpt_constset; |
| } else if (Strcmp(code, "enumitem") == 0) { |
| cpt = cpt_enumitem; |
| } |
| if (cpt != cpt_none) { |
| const_id_pattern pat = { NIL, NIL }; |
| |
| List *convdesc = Split(value, ';', 4); |
| List *patterndesc = Split(Getitem(convdesc, 0), ',', INT_MAX); |
| Iterator patternit; |
| for (patternit = First(patterndesc); patternit.item != NIL; patternit = Next(patternit)) { |
| List *patternassign = Split(patternit.item, '=', 2); |
| String *tag = Getitem(patternassign, 0); |
| String *data = Getitem(patternassign, 1); |
| if (Strcmp(tag, "prefix") == 0) { |
| pat.prefix = Copy(data); |
| } else if (Strcmp(tag, "enum") == 0) { |
| pat.parentEnum = Copy(data); |
| } else { |
| Swig_warning(WARN_MODULA3_BAD_ENUMERATION, input_file, line_number, "Unknown identification tag <%s> with value <%s>.\n", tag, data); |
| } |
| Delete(patternassign); |
| } |
| tagConstants(child, NIL, pat, code, convdesc); |
| |
| Delete(patterndesc); |
| } |
| } |
| } |
| scanForConstPragmas(child); |
| child = nextSibling(child); |
| } |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * emitProxyClassDefAndCPPCasts() |
| * ----------------------------------------------------------------------------- */ |
| |
| void emitProxyClassDefAndCPPCasts(Node *n) { |
| String *c_classname = SwigType_namestr(Getattr(n, "name")); |
| String *c_baseclass = NULL; |
| String *baseclass = NULL; |
| String *c_baseclassname = NULL; |
| String *name = Getattr(n, "name"); |
| |
| /* Deal with inheritance */ |
| List *baselist = Getattr(n, "bases"); |
| if (baselist) { |
| Iterator base = First(baselist); |
| while (base.item) { |
| if (!GetFlag(base.item, "feature:ignore")) { |
| String *baseclassname = Getattr(base.item, "name"); |
| if (!c_baseclassname) { |
| c_baseclassname = baseclassname; |
| baseclass = Copy(getProxyName(baseclassname)); |
| if (baseclass) |
| c_baseclass = SwigType_namestr(baseclassname); |
| } else { |
| /* Warn about multiple inheritance for additional base class(es) */ |
| String *proxyclassname = Getattr(n, "classtypeobj"); |
| Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, Getfile(n), Getline(n), |
| "Warning for %s, base %s ignored. Multiple inheritance is not supported in Modula 3.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname)); |
| } |
| } |
| base = Next(base); |
| } |
| } |
| |
| bool derived = baseclass && getProxyName(c_baseclassname); |
| if (!baseclass) |
| baseclass = NewString(""); |
| |
| // Inheritance from pure Modula 3 classes |
| const String *pure_baseclass = typemapLookup(n, "m3base", name, WARN_NONE); |
| if (hasContent(pure_baseclass) && hasContent(baseclass)) { |
| Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, Getfile(n), Getline(n), |
| "Warning for %s, base %s ignored. Multiple inheritance is not supported in Modula 3.\n", name, pure_baseclass); |
| } |
| // Pure Modula 3 interfaces |
| const String *pure_interfaces = typemapLookup(n, derived ? "m3interfaces_derived" : "m3interfaces", |
| name, WARN_NONE); |
| |
| // Start writing the proxy class |
| Printv(proxy_class_def, typemapLookup(n, "m3imports", name, WARN_NONE), // Import statements |
| "\n", typemapLookup(n, "m3classmodifiers", name, WARN_MODULA3_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers |
| " class $m3classname", // Class name and bases |
| (derived || *Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", baseclass, pure_baseclass, ((derived || *Char(pure_baseclass)) && *Char(pure_interfaces)) ? // Interfaces |
| ", " : "", pure_interfaces, " {\n", " private IntPtr swigCPtr;\n", // Member variables for memory handling |
| derived ? "" : " protected bool swigCMemOwn;\n", "\n", " ", typemapLookup(n, "m3ptrconstructormodifiers", name, WARN_MODULA3_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers |
| " $m3classname(IntPtr cPtr, bool cMemoryOwn) ", // Constructor used for wrapping pointers |
| derived ? |
| ": base($imclassname.$m3classnameTo$baseclass(cPtr), cMemoryOwn) {\n" |
| : "{\n swigCMemOwn = cMemoryOwn;\n", " swigCPtr = cPtr;\n", " }\n", NIL); |
| |
| if (!have_default_constructor_flag) { // All proxy classes need a constructor |
| Printv(proxy_class_def, "\n", " protected $m3classname() : this(IntPtr.Zero, false) {\n", " }\n", NIL); |
| } |
| // C++ destructor is wrapped by the Dispose method |
| // Note that the method name is specified in a typemap attribute called methodname |
| String *destruct = NewString(""); |
| const String *tm = NULL; |
| Node *attributes = NewHash(); |
| String *destruct_methodname = NULL; |
| if (derived) { |
| tm = typemapLookup(n, "m3destruct_derived", name, WARN_NONE, attributes); |
| destruct_methodname = Getattr(attributes, "tmap:m3destruct_derived:methodname"); |
| } else { |
| tm = typemapLookup(n, "m3destruct", name, WARN_NONE, attributes); |
| destruct_methodname = Getattr(attributes, "tmap:m3destruct:methodname"); |
| } |
| if (!destruct_methodname) { |
| Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in m3destruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name); |
| } |
| // Emit the Finalize and Dispose methods |
| if (tm) { |
| // Finalize method |
| if (*Char(destructor_call)) { |
| Printv(proxy_class_def, typemapLookup(n, "m3finalize", name, WARN_NONE), NIL); |
| } |
| // Dispose method |
| Printv(destruct, tm, NIL); |
| if (*Char(destructor_call)) |
| Replaceall(destruct, "$imcall", destructor_call); |
| else |
| Replaceall(destruct, "$imcall", "throw new MethodAccessException(\"C++ destructor does not have public access\")"); |
| if (*Char(destruct)) |
| Printv(proxy_class_def, "\n public ", derived ? "override" : "virtual", " void ", destruct_methodname, "() ", destruct, "\n", NIL); |
| } |
| Delete(attributes); |
| Delete(destruct); |
| |
| // Emit various other methods |
| Printv(proxy_class_def, typemapLookup(n, "m3getcptr", name, WARN_MODULA3_TYPEMAP_GETCPTR_UNDEF), // getCPtr method |
| typemapLookup(n, "m3code", name, WARN_NONE), // extra Modula 3 code |
| "\n", NIL); |
| |
| // Substitute various strings into the above template |
| Replaceall(proxy_class_def, "$m3classname", proxy_class_name); |
| Replaceall(proxy_class_code, "$m3classname", proxy_class_name); |
| |
| Replaceall(proxy_class_def, "$baseclass", baseclass); |
| Replaceall(proxy_class_code, "$baseclass", baseclass); |
| |
| Replaceall(proxy_class_def, "$imclassname", m3raw_name); |
| Replaceall(proxy_class_code, "$imclassname", m3raw_name); |
| |
| // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy) |
| if (derived) { |
| Printv(m3raw_cppcasts_code, "\n [DllImport(\"", m3wrap_name, "\", EntryPoint=\"Modula3_", proxy_class_name, "To", baseclass, "\")]\n", NIL); |
| Printv(m3raw_cppcasts_code, " public static extern IntPtr ", "$m3classnameTo$baseclass(IntPtr objectRef);\n", NIL); |
| |
| Replaceall(m3raw_cppcasts_code, "$m3classname", proxy_class_name); |
| Replaceall(m3raw_cppcasts_code, "$baseclass", baseclass); |
| |
| Printv(upcasts_code, |
| "SWIGEXPORT long Modula3_$imclazznameTo$imbaseclass", |
| "(long objectRef) {\n", |
| " long baseptr = 0;\n" " *($cbaseclass **)&baseptr = *($cclass **)&objectRef;\n" " return baseptr;\n" "}\n", "\n", NIL); |
| |
| Replaceall(upcasts_code, "$imbaseclass", baseclass); |
| Replaceall(upcasts_code, "$cbaseclass", c_baseclass); |
| Replaceall(upcasts_code, "$imclazzname", proxy_class_name); |
| Replaceall(upcasts_code, "$cclass", c_classname); |
| } |
| Delete(baseclass); |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * getAttrString() |
| * |
| * If necessary create and return the string |
| * associated with a certain attribute of 'n'. |
| * ---------------------------------------------------------------------- */ |
| |
| String *getAttrString(Node *n, const char *attr) { |
| String *str = Getattr(n, attr); |
| if (str == NIL) { |
| str = NewString(""); |
| Setattr(n, attr, str); |
| } |
| return str; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * getMethodDeclarations() |
| * |
| * If necessary create and return the handle |
| * where the methods of the current access can be written to. |
| * 'n' must be a member of a struct or a class. |
| * ---------------------------------------------------------------------- */ |
| |
| String *getMethodDeclarations(Node *n) { |
| String *acc_str = Getattr(n, "access"); |
| String *methodattr; |
| if (acc_str == NIL) { |
| methodattr = NewString("modula3:method:public"); |
| } else { |
| methodattr = NewStringf("modula3:method:%s", acc_str); |
| } |
| String *methods = getAttrString(parentNode(n), Char(methodattr)); |
| Delete(methodattr); |
| return methods; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * classHandler() |
| * ---------------------------------------------------------------------- */ |
| |
| virtual int classHandler(Node *n) { |
| |
| File *f_proxy = NULL; |
| proxy_class_name = Copy(Getattr(n, "sym:name")); |
| //String *rawname = Getattr(n,"name"); |
| |
| if (proxy_flag) { |
| if (!addSymbol(proxy_class_name, n)) |
| return SWIG_ERROR; |
| |
| if (Cmp(proxy_class_name, m3raw_name) == 0) { |
| Printf(stderr, "Class name cannot be equal to intermediary class name: %s\n", proxy_class_name); |
| SWIG_exit(EXIT_FAILURE); |
| } |
| |
| if (Cmp(proxy_class_name, m3wrap_name) == 0) { |
| Printf(stderr, "Class name cannot be equal to module class name: %s\n", proxy_class_name); |
| SWIG_exit(EXIT_FAILURE); |
| } |
| |
| String *filen = NewStringf("%s%s.m3", SWIG_output_directory(), proxy_class_name); |
| f_proxy = NewFile(filen, "w", SWIG_output_files()); |
| if (!f_proxy) { |
| FileErrorDisplay(filen); |
| SWIG_exit(EXIT_FAILURE); |
| } |
| Delete(filen); |
| filen = NULL; |
| |
| emitBanner(f_proxy); |
| |
| Clear(proxy_class_def); |
| Clear(proxy_class_code); |
| |
| have_default_constructor_flag = false; |
| destructor_call = NewString(""); |
| } |
| |
| /* This will invoke memberfunctionHandler, membervariableHandler ... |
| and finally it may invoke functionWrapper |
| for wrappers and member variable accessors. |
| It will invoke Language:constructorDeclaration |
| which decides whether to call MODULA3::constructorHandler */ |
| Language::classHandler(n); |
| |
| { |
| String *kind = Getattr(n, "kind"); |
| if (Cmp(kind, "struct") == 0) { |
| String *entries = NewString(""); |
| Node *child; |
| writeArgState state; |
| for (child = firstChild(n); child != NIL; child = nextSibling(child)) { |
| String *childType = nodeType(child); |
| if (Strcmp(childType, "cdecl") == 0) { |
| String *member = Getattr(child, "sym:name"); |
| ParmList *pl = Getattr(child, "parms"); |
| if (pl == NIL) { |
| // Get the variable type in Modula 3 type equivalents |
| String *m3ct = getMappedTypeNew(child, "m3rawtype", ""); |
| |
| writeArg(entries, state, NIL, member, m3ct, NIL); |
| } |
| } |
| } |
| writeArg(entries, state, NIL, NIL, NIL, NIL); |
| |
| m3raw_intf.enterBlock(blocktype); |
| Printf(m3raw_intf.f, "%s =\nRECORD\n%sEND;\n", proxy_class_name, entries); |
| |
| Delete(entries); |
| |
| } else if (Cmp(kind, "class") == 0) { |
| enum access_privilege { acc_public, acc_protected, acc_private }; |
| int max_acc = acc_public; |
| |
| const char *acc_name[3] = { "public", "protected", "private" }; |
| String *methods[3]; |
| int acc; |
| for (acc = acc_public; acc <= acc_private; acc++) { |
| String *methodattr = NewStringf("modula3:method:%s", acc_name[acc]); |
| methods[acc] = Getattr(n, methodattr); |
| Delete(methodattr); |
| max_acc = max_acc > acc ? max_acc : acc; |
| } |
| |
| /* Determine the name of the base class */ |
| String *baseclassname = NewString(""); |
| { |
| List *baselist = Getattr(n, "bases"); |
| if (baselist) { |
| /* Look for the first (principal?) base class - |
| Modula 3 does not support multiple inheritance */ |
| Iterator base = First(baselist); |
| if (base.item) { |
| Append(baseclassname, Getattr(base.item, "sym:name")); |
| base = Next(base); |
| if (base.item) { |
| Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, Getfile(n), Getline(n), |
| "Warning for %s, base %s ignored. Multiple inheritance is not supported in Modula 3.\n", |
| proxy_class_name, Getattr(base.item, "name")); |
| } |
| } |
| } |
| } |
| |
| /* the private class of the base class and only this |
| need a pointer to the C++ object */ |
| bool need_private = !hasContent(baseclassname); |
| max_acc = need_private ? acc_private : max_acc; |
| |
| /* Declare C++ object as abstract pointer in Modula 3 */ |
| /* The revelation system does not allow us |
| to imitate the whole class hierarchy of the C++ library, |
| but at least we can distinguish between classes of different roots. */ |
| if (hasContent(baseclassname)) { |
| m3raw_intf.enterBlock(blocktype); |
| Printf(m3raw_intf.f, "%s = %s;\n", proxy_class_name, baseclassname); |
| } else { |
| m3raw_intf.enterBlock(blocktype); |
| Printf(m3raw_intf.f, "%s <: ADDRESS;\n", proxy_class_name); |
| m3raw_impl.enterBlock(revelation); |
| Printf(m3raw_impl.f, "%s = UNTRACED BRANDED REF RECORD (*Dummy*) END;\n", proxy_class_name); |
| } |
| |
| String *superclass; |
| m3wrap_intf.enterBlock(blocktype); |
| if (hasContent(methods[acc_public])) { |
| superclass = NewStringf("%sPublic", proxy_class_name); |
| } else if (hasContent(baseclassname)) { |
| superclass = Copy(baseclassname); |
| } else { |
| superclass = NewString("ROOT"); |
| } |
| Printf(m3wrap_intf.f, "%s <: %s;\n", proxy_class_name, superclass); |
| Delete(superclass); |
| |
| { |
| static const char *acc_m3suffix[] = { "Public", "Protected", "Private" }; |
| int acc; |
| for (acc = acc_public; acc <= acc_private; acc++) { |
| bool process_private = (acc == acc_private) && need_private; |
| if (hasContent(methods[acc]) || process_private) { |
| String *subclass = NewStringf("%s%s", proxy_class_name, acc_m3suffix[acc]); |
| /* |
| m3wrap_intf.enterBlock(revelation); |
| Printf(m3wrap_intf.f, "%s <: %s;\n", proxy_class_name, subclass); |
| */ |
| if (acc == max_acc) { |
| m3wrap_intf.enterBlock(revelation); |
| Printf(m3wrap_intf.f, "%s =\n", proxy_class_name); |
| } else { |
| m3wrap_intf.enterBlock(blocktype); |
| Printf(m3wrap_intf.f, "%s =\n", subclass); |
| } |
| Printf(m3wrap_intf.f, "%s BRANDED OBJECT\n", baseclassname); |
| if (process_private) { |
| Setattr(m3wrap_intf.import, m3raw_name, ""); |
| Printf(m3wrap_intf.f, "cxxObj:%s.%s;\n", m3raw_name, proxy_class_name); |
| } |
| if (hasContent(methods[acc])) { |
| Printf(m3wrap_intf.f, "METHODS\n%s", methods[acc]); |
| } |
| if (acc == max_acc) { |
| String *overrides = Getattr(n, "modula3:override"); |
| Printf(m3wrap_intf.f, "OVERRIDES\n%s", overrides); |
| } |
| Printf(m3wrap_intf.f, "END;\n"); |
| Delete(baseclassname); |
| baseclassname = subclass; |
| } |
| } |
| } |
| |
| Delete(methods[acc_public]); |
| Delete(methods[acc_protected]); |
| Delete(methods[acc_private]); |
| |
| } else { |
| Swig_warning(WARN_MODULA3_TYPECONSTRUCTOR_UNKNOWN, input_file, line_number, "Unknown type constructor %s\n", kind); |
| } |
| } |
| |
| if (proxy_flag) { |
| |
| emitProxyClassDefAndCPPCasts(n); |
| |
| Printv(f_proxy, proxy_class_def, proxy_class_code, NIL); |
| |
| Printf(f_proxy, "}\n"); |
| Delete(f_proxy); |
| f_proxy = NULL; |
| |
| Delete(proxy_class_name); |
| proxy_class_name = NULL; |
| Delete(destructor_call); |
| destructor_call = NULL; |
| } |
| return SWIG_OK; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * memberfunctionHandler() |
| * ---------------------------------------------------------------------- */ |
| |
| virtual int memberfunctionHandler(Node *n) { |
| //printf("begin memberfunctionHandler(%s)\n", Char(Getattr(n,"name"))); |
| Setattr(n, "modula3:functype", "method"); |
| Language::memberfunctionHandler(n); |
| |
| { |
| /* Language::memberfunctionHandler will remove the mapped types |
| that emitM3Wrapper may attach */ |
| ParmList *pl = Getattr(n, "parms"); |
| Swig_typemap_attach_parms("m3wrapinmode", pl, NULL); |
| Swig_typemap_attach_parms("m3wrapinname", pl, NULL); |
| Swig_typemap_attach_parms("m3wrapintype", pl, NULL); |
| Swig_typemap_attach_parms("m3wrapindefault", pl, NULL); |
| attachParameterNames(n, "tmap:m3wrapinname", "autoname", "arg%d"); |
| String *rettype = getMappedTypeNew(n, "m3wrapouttype", ""); |
| |
| String *methodname = Getattr(n, "sym:name"); |
| /* |
| if (methodname==NIL) { |
| methodname = Getattr(n,"name"); |
| } |
| */ |
| String *arguments = createM3Signature(n); |
| String *storage = Getattr(n, "storage"); |
| String *overridden = Getattr(n, "override"); |
| bool isVirtual = (storage != NIL) && (Strcmp(storage, "virtual") == 0); |
| bool isOverridden = (overridden != NIL) |
| && (Strcmp(overridden, "1") == 0); |
| if ((!isVirtual) || (!isOverridden)) { |
| { |
| String *methods = getMethodDeclarations(n); |
| Printf(methods, "%s(%s)%s%s;%s\n", |
| methodname, arguments, |
| hasContent(rettype) ? ": " : "", hasContent(rettype) ? (const String *) rettype : "", isVirtual ? " (* base method *)" : ""); |
| } |
| { |
| /* this was attached by functionWrapper |
| invoked by Language::memberfunctionHandler */ |
| String *fname = Getattr(n, "modula3:funcname"); |
| String *overrides = getAttrString(parentNode(n), "modula3:override"); |
| Printf(overrides, "%s := %s;\n", methodname, fname); |
| } |
| } |
| } |
| |
| if (proxy_flag) { |
| String *overloaded_name = getOverloadedName(n); |
| String *intermediary_function_name = Swig_name_member(NSPACE_TODO, proxy_class_name, overloaded_name); |
| Setattr(n, "proxyfuncname", Getattr(n, "sym:name")); |
| Setattr(n, "imfuncname", intermediary_function_name); |
| proxyClassFunctionHandler(n); |
| Delete(overloaded_name); |
| } |
| //printf("end memberfunctionHandler(%s)\n", Char(Getattr(n,"name"))); |
| return SWIG_OK; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * staticmemberfunctionHandler() |
| * ---------------------------------------------------------------------- */ |
| |
| virtual int staticmemberfunctionHandler(Node *n) { |
| |
| static_flag = true; |
| Language::staticmemberfunctionHandler(n); |
| |
| if (proxy_flag) { |
| String *overloaded_name = getOverloadedName(n); |
| String *intermediary_function_name = Swig_name_member(NSPACE_TODO, proxy_class_name, overloaded_name); |
| Setattr(n, "proxyfuncname", Getattr(n, "sym:name")); |
| Setattr(n, "imfuncname", intermediary_function_name); |
| proxyClassFunctionHandler(n); |
| Delete(overloaded_name); |
| } |
| static_flag = false; |
| |
| return SWIG_OK; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * proxyClassFunctionHandler() |
| * |
| * Function called for creating a Modula 3 wrapper function around a c++ function in the |
| * proxy class. Used for both static and non-static C++ class functions. |
| * C++ class static functions map to Modula 3 static functions. |
| * Two extra attributes in the Node must be available. These are "proxyfuncname" - |
| * the name of the Modula 3 class proxy function, which in turn will call "imfuncname" - |
| * the intermediary (PInvoke) function name in the intermediary class. |
| * ----------------------------------------------------------------------------- */ |
| |
| void proxyClassFunctionHandler(Node *n) { |
| SwigType *t = Getattr(n, "type"); |
| ParmList *l = Getattr(n, "parms"); |
| Hash *throws_hash = NewHash(); |
| String *intermediary_function_name = Getattr(n, "imfuncname"); |
| String *proxy_function_name = Getattr(n, "proxyfuncname"); |
| String *tm; |
| Parm *p; |
| int i; |
| String *imcall = NewString(""); |
| String *return_type = NewString(""); |
| String *function_code = NewString(""); |
| bool setter_flag = false; |
| |
| if (!proxy_flag) |
| return; |
| |
| if (l) { |
| if (SwigType_type(Getattr(l, "type")) == T_VOID) { |
| l = nextSibling(l); |
| } |
| } |
| |
| /* Attach the non-standard typemaps to the parameter list */ |
| Swig_typemap_attach_parms("in", l, NULL); |
| Swig_typemap_attach_parms("m3wraptype", l, NULL); |
| Swig_typemap_attach_parms("m3in", l, NULL); |
| |
| /* Get return types */ |
| if ((tm = getMappedTypeNew(n, "m3wraptype", ""))) { |
| substituteClassname(t, tm); |
| Printf(return_type, "%s", tm); |
| } |
| |
| if (proxy_flag && wrapping_member_flag && !enum_constant_flag) { |
| // Properties |
| setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(NSPACE_TODO, Swig_name_member(NSPACE_TODO, proxy_class_name, variable_name))) |
| == 0); |
| } |
| |
| /* Start generating the proxy function */ |
| Printf(function_code, " %s ", Getattr(n, "feature:modula3:methodmodifiers")); |
| if (static_flag) |
| Printf(function_code, "static "); |
| if (Getattr(n, "override")) |
| Printf(function_code, "override "); |
| else if (checkAttribute(n, "storage", "virtual")) |
| Printf(function_code, "virtual "); |
| |
| Printf(function_code, "%s %s(", return_type, proxy_function_name); |
| |
| Printv(imcall, m3raw_name, ".", intermediary_function_name, "(", NIL); |
| if (!static_flag) |
| Printv(imcall, "swigCPtr", NIL); |
| |
| emit_mark_varargs(l); |
| |
| int gencomma = !static_flag; |
| |
| /* Output each parameter */ |
| for (i = 0, p = l; p; i++) { |
| |
| /* Ignored varargs */ |
| if (checkAttribute(p, "varargs:ignore", "1")) { |
| p = nextSibling(p); |
| continue; |
| } |
| |
| /* Ignored parameters */ |
| if (checkAttribute(p, "tmap:in:numinputs", "0")) { |
| p = Getattr(p, "tmap:in:next"); |
| continue; |
| } |
| |
| /* Ignore the 'this' argument for variable wrappers */ |
| if (!(variable_wrapper_flag && i == 0)) { |
| SwigType *pt = Getattr(p, "type"); |
| String *param_type = NewString(""); |
| |
| /* Get the Modula 3 parameter type */ |
| if ((tm = getMappedType(p, "m3wraptype"))) { |
| substituteClassname(pt, tm); |
| Printf(param_type, "%s", tm); |
| } |
| |
| if (gencomma) |
| Printf(imcall, ", "); |
| |
| String *arg = variable_wrapper_flag ? NewString("value") : makeParameterName(n, |
| p, |
| i); |
| |
| // Use typemaps to transform type used in Modula 3 wrapper function (in proxy class) to type used in PInvoke function (in intermediary class) |
| if ((tm = getMappedType(p, "in"))) { |
| addThrows(throws_hash, "in", p); |
| substituteClassname(pt, tm); |
| Replaceall(tm, "$input", arg); |
| Printv(imcall, tm, NIL); |
| } |
| |
| /* Add parameter to proxy function */ |
| if (gencomma >= 2) |
| Printf(function_code, ", "); |
| gencomma = 2; |
| Printf(function_code, "%s %s", param_type, arg); |
| |
| Delete(arg); |
| Delete(param_type); |
| } |
| p = Getattr(p, "tmap:in:next"); |
| } |
| |
| Printf(imcall, ")"); |
| Printf(function_code, ")"); |
| |
| // Transform return type used in PInvoke function (in intermediary class) to type used in Modula 3 wrapper function (in proxy class) |
| if ((tm = getMappedTypeNew(n, "m3out", ""))) { |
| addThrows(throws_hash, "m3out", n); |
| if (GetFlag(n, "feature:new")) |
| Replaceall(tm, "$owner", "true"); |
| else |
| Replaceall(tm, "$owner", "false"); |
| substituteClassname(t, tm); |
| Replaceall(tm, "$imcall", imcall); |
| } |
| |
| generateThrowsClause(throws_hash, function_code); |
| Printf(function_code, " %s\n\n", tm ? (const String *) tm : empty_string); |
| |
| if (proxy_flag && wrapping_member_flag && !enum_constant_flag) { |
| // Properties |
| if (setter_flag) { |
| // Setter method |
| if ((tm = getMappedTypeNew(n, "m3varin", ""))) { |
| if (GetFlag(n, "feature:new")) |
| Replaceall(tm, "$owner", "true"); |
| else |
| Replaceall(tm, "$owner", "false"); |
| substituteClassname(t, tm); |
| Replaceall(tm, "$imcall", imcall); |
| Printf(proxy_class_code, "%s", tm); |
| } |
| } else { |
| // Getter method |
| if ((tm = getMappedTypeNew(n, "m3varout", ""))) { |
| if (GetFlag(n, "feature:new")) |
| Replaceall(tm, "$owner", "true"); |
| else |
| Replaceall(tm, "$owner", "false"); |
| substituteClassname(t, tm); |
| Replaceall(tm, "$imcall", imcall); |
| Printf(proxy_class_code, "%s", tm); |
| } |
| } |
| } else { |
| // Normal function call |
| Printv(proxy_class_code, function_code, NIL); |
| } |
| |
| Delete(function_code); |
| Delete(return_type); |
| Delete(imcall); |
| Delete(throws_hash); |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * constructorHandler() |
| * ---------------------------------------------------------------------- */ |
| |
| virtual int constructorHandler(Node *n) { |
| // this invokes functionWrapper |
| Language::constructorHandler(n); |
| |
| if (proxy_flag) { |
| ParmList *l = Getattr(n, "parms"); |
| |
| Hash *throws_hash = NewHash(); |
| String *overloaded_name = getOverloadedName(n); |
| String *imcall = NewString(""); |
| |
| Printf(proxy_class_code, " %s %s(", Getattr(n, "feature:modula3:methodmodifiers"), proxy_class_name); |
| Printv(imcall, " : this(", m3raw_name, ".", Swig_name_construct(NSPACE_TODO, overloaded_name), "(", NIL); |
| |
| /* Attach the non-standard typemaps to the parameter list */ |
| Swig_typemap_attach_parms("in", l, NULL); |
| Swig_typemap_attach_parms("m3wraptype", l, NULL); |
| Swig_typemap_attach_parms("m3in", l, NULL); |
| |
| emit_mark_varargs(l); |
| |
| int gencomma = 0; |
| |
| String *tm; |
| Parm *p = l; |
| int i; |
| |
| /* Output each parameter */ |
| for (i = 0; p; i++) { |
| |
| /* Ignored varargs */ |
| if (checkAttribute(p, "varargs:ignore", "1")) { |
| p = nextSibling(p); |
| continue; |
| } |
| |
| /* Ignored parameters */ |
| if (checkAttribute(p, "tmap:in:numinputs", "0")) { |
| p = Getattr(p, "tmap:in:next"); |
| continue; |
| } |
| |
| SwigType *pt = Getattr(p, "type"); |
| String *param_type = NewString(""); |
| |
| /* Get the Modula 3 parameter type */ |
| if ((tm = getMappedType(p, "m3wraptype"))) { |
| substituteClassname(pt, tm); |
| Printf(param_type, "%s", tm); |
| } |
| |
| if (gencomma) |
| Printf(imcall, ", "); |
| |
| String *arg = makeParameterName(n, p, i); |
| |
| // Use typemaps to transform type used in Modula 3 wrapper function (in proxy class) to type used in PInvoke function (in intermediary class) |
| if ((tm = getMappedType(p, "in"))) { |
| addThrows(throws_hash, "in", p); |
| substituteClassname(pt, tm); |
| Replaceall(tm, "$input", arg); |
| Printv(imcall, tm, NIL); |
| } |
| |
| /* Add parameter to proxy function */ |
| if (gencomma) |
| Printf(proxy_class_code, ", "); |
| Printf(proxy_class_code, "%s %s", param_type, arg); |
| gencomma = 1; |
| |
| Delete(arg); |
| Delete(param_type); |
| p = Getattr(p, "tmap:in:next"); |
| } |
| |
| Printf(imcall, "), true)"); |
| |
| Printf(proxy_class_code, ")"); |
| Printf(proxy_class_code, "%s", imcall); |
| generateThrowsClause(throws_hash, proxy_class_code); |
| Printf(proxy_class_code, " {\n"); |
| Printf(proxy_class_code, " }\n\n"); |
| |
| if (!gencomma) // We must have a default constructor |
| have_default_constructor_flag = true; |
| |
| Delete(overloaded_name); |
| Delete(imcall); |
| Delete(throws_hash); |
| } |
| |
| return SWIG_OK; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * destructorHandler() |
| * ---------------------------------------------------------------------- */ |
| |
| virtual int destructorHandler(Node *n) { |
| Language::destructorHandler(n); |
| String *symname = Getattr(n, "sym:name"); |
| |
| if (proxy_flag) { |
| Printv(destructor_call, m3raw_name, ".", Swig_name_destroy(NSPACE_TODO, symname), "(swigCPtr)", NIL); |
| } |
| return SWIG_OK; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * membervariableHandler() |
| * ---------------------------------------------------------------------- */ |
| |
| virtual int membervariableHandler(Node *n) { |
| //printf("begin membervariableHandler(%s)\n", Char(Getattr(n,"name"))); |
| SwigType *t = Getattr(n, "type"); |
| String *tm; |
| |
| // Get the variable type |
| if ((tm = getMappedTypeNew(n, "m3wraptype", ""))) { |
| substituteClassname(t, tm); |
| } |
| |
| variable_name = Getattr(n, "sym:name"); |
| //printf("member variable: %s\n", Char(variable_name)); |
| |
| // Output the property's field declaration and accessor methods |
| Printf(proxy_class_code, " public %s %s {", tm, variable_name); |
| |
| Setattr(n, "modula3:functype", "accessor"); |
| wrapping_member_flag = true; |
| variable_wrapper_flag = true; |
| Language::membervariableHandler(n); |
| wrapping_member_flag = false; |
| variable_wrapper_flag = false; |
| |
| Printf(proxy_class_code, "\n }\n\n"); |
| |
| { |
| String *methods = getMethodDeclarations(n); |
| String *overrides = getAttrString(parentNode(n), "modula3:override"); |
| SwigType *type = Getattr(n, "type"); |
| String *m3name = capitalizeFirst(variable_name); |
| //String *m3name = nameToModula3(variable_name,true); |
| if (!SwigType_isconst(type)) { |
| { |
| String *inmode = getMappedTypeNew(n, "m3wrapinmode", "", false); |
| String *intype = getMappedTypeNew(n, "m3wrapintype", ""); |
| Printf(methods, "set%s(%s val:%s);\n", m3name, (inmode != NIL) ? (const String *) inmode : "", intype); |
| } |
| { |
| /* this was attached by functionWrapper |
| invoked by Language::memberfunctionHandler */ |
| String *fname = Getattr(n, "modula3:setname"); |
| Printf(overrides, "set%s := %s;\n", m3name, fname); |
| } |
| } |
| { |
| { |
| String *outtype = getMappedTypeNew(n, "m3wrapouttype", ""); |
| Printf(methods, "get%s():%s;\n", m3name, outtype); |
| } |
| { |
| /* this was attached by functionWrapper |
| invoked by Language::memberfunctionHandler */ |
| String *fname = Getattr(n, "modula3:getname"); |
| Printf(overrides, "get%s := %s;\n", m3name, fname); |
| } |
| } |
| Delete(m3name); |
| } |
| //printf("end membervariableHandler(%s)\n", Char(Getattr(n,"name"))); |
| |
| return SWIG_OK; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * staticmembervariableHandler() |
| * ---------------------------------------------------------------------- */ |
| |
| virtual int staticmembervariableHandler(Node *n) { |
| |
| bool static_const_member_flag = (Getattr(n, "value") == 0); |
| if (static_const_member_flag) { |
| SwigType *t = Getattr(n, "type"); |
| String *tm; |
| |
| // Get the variable type |
| if ((tm = getMappedTypeNew(n, "m3wraptype", ""))) { |
| substituteClassname(t, tm); |
| } |
| // Output the property's field declaration and accessor methods |
| Printf(proxy_class_code, " public static %s %s {", tm, Getattr(n, "sym:name")); |
| } |
| |
| variable_name = Getattr(n, "sym:name"); |
| wrapping_member_flag = true; |
| static_flag = true; |
| Language::staticmembervariableHandler(n); |
| wrapping_member_flag = false; |
| static_flag = false; |
| |
| if (static_const_member_flag) |
| Printf(proxy_class_code, "\n }\n\n"); |
| |
| return SWIG_OK; |
| } |
| |
| /* ---------------------------------------------------------------------- |
| * memberconstantHandler() |
| * ---------------------------------------------------------------------- */ |
| |
| virtual int memberconstantHandler(Node *n) { |
| variable_name = Getattr(n, "sym:name"); |
| wrapping_member_flag = true; |
| Language::memberconstantHandler(n); |
| wrapping_member_flag = false; |
| return SWIG_OK; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * getOverloadedName() |
| * ----------------------------------------------------------------------------- */ |
| |
| String *getOverloadedName(Node *n) { |
| String *overloaded_name = Copy(Getattr(n, "sym:name")); |
| |
| if (Getattr(n, "sym:overloaded")) { |
| Printv(overloaded_name, Getattr(n, "sym:overname"), NIL); |
| } |
| |
| return overloaded_name; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * emitM3Wrapper() |
| * It is also used for set and get methods of global variables. |
| * ----------------------------------------------------------------------------- */ |
| |
| void emitM3Wrapper(Node *n, const String *func_name) { |
| SwigType *t = Getattr(n, "type"); |
| ParmList *l = Getattr(n, "parms"); |
| Hash *throws_hash = NewHash(); |
| int num_exceptions = 0; |
| int num_returns = 0; |
| String *rawcall = NewString(""); |
| String *reccall = NewString(""); |
| String *local_variables = NewString(""); |
| String *local_constants = NewString(""); |
| String *incheck = NewString(""); |
| String *outcheck = NewString(""); |
| String *setup = NewString(""); |
| String *cleanup = NewString(""); |
| String *outarg = NewString(""); /* don't mix up with 'autark' :-] */ |
| String *storeout = NewString(""); |
| String *result_name = NewString(""); |
| String *return_variables = NewString(""); |
| const char *result_return = "ret"; |
| String *function_code = NewString(""); |
| /*several names for the same function */ |
| String *raw_name = Getattr(n, "name"); /*original C function name */ |
| //String *func_name = Getattr(n,"sym:name"); /*final Modula3 name chosen by the user*/ |
| bool setter_flag = false; |
| int multiretval = GetFlag(n, "feature:modula3:multiretval"); |
| |
| if (l) { |
| if (SwigType_type(Getattr(l, "type")) == T_VOID) { |
| l = nextSibling(l); |
| } |
| } |
| |
| /* Attach the non-standard typemaps to the parameter list */ |
| Swig_typemap_attach_parms("m3wrapargvar", l, NULL); |
| Swig_typemap_attach_parms("m3wrapargconst", l, NULL); |
| Swig_typemap_attach_parms("m3wrapargraw", l, NULL); |
| Swig_typemap_attach_parms("m3wrapargdir", l, NULL); |
| Swig_typemap_attach_parms("m3wrapinmode", l, NULL); |
| Swig_typemap_attach_parms("m3wrapinname", l, NULL); |
| Swig_typemap_attach_parms("m3wrapintype", l, NULL); |
| Swig_typemap_attach_parms("m3wrapindefault", l, NULL); |
| Swig_typemap_attach_parms("m3wrapinconv", l, NULL); |
| Swig_typemap_attach_parms("m3wrapincheck", l, NULL); |
| Swig_typemap_attach_parms("m3wrapoutname", l, NULL); |
| Swig_typemap_attach_parms("m3wrapouttype", l, NULL); |
| Swig_typemap_attach_parms("m3wrapoutconv", l, NULL); |
| Swig_typemap_attach_parms("m3wrapoutcheck", l, NULL); |
| |
| attachMappedType(n, "m3wrapretraw"); |
| attachMappedType(n, "m3wrapretname"); |
| attachMappedType(n, "m3wraprettype"); |
| attachMappedType(n, "m3wrapretvar"); |
| attachMappedType(n, "m3wrapretconv"); |
| attachMappedType(n, "m3wrapretcheck"); |
| |
| Swig_typemap_attach_parms("m3wrapfreearg", l, NULL); |
| |
| /* |
| Swig_typemap_attach_parms("m3wrapargvar:throws", l, NULL); |
| Swig_typemap_attach_parms("m3wrapargraw:throws", l, NULL); |
| Swig_typemap_attach_parms("m3wrapinconv:throws", l, NULL); |
| Swig_typemap_attach_parms("m3wrapincheck:throws", l, NULL); |
| Swig_typemap_attach_parms("m3wrapoutconv:throws", l, NULL); |
| Swig_typemap_attach_parms("m3wrapoutcheck:throws", l, NULL); |
| |
| attachMappedType(n, "m3wrapretvar:throws"); |
| attachMappedType(n, "m3wrapretconv:throws"); |
| attachMappedType(n, "m3wrapretcheck:throws"); |
| |
| Swig_typemap_attach_parms("m3wrapfreearg:throws", l, NULL); |
| */ |
| |
| /* Attach argument names to the parameter list */ |
| /* should be a separate procedure making use of hashes */ |
| attachParameterNames(n, "tmap:m3wrapinname", "autoname", "arg%d"); |
| |
| /* Get return types */ |
| String *result_m3rawtype = Copy(getMappedTypeNew(n, "m3rawrettype", "")); |
| String *result_m3wraptype = Copy(getMappedTypeNew(n, "m3wraprettype", "")); |
| bool has_return_raw = hasContent(result_m3rawtype); |
| bool has_return_m3 = hasContent(result_m3wraptype); |
| if (has_return_m3) { |
| num_returns++; |
| //printf("%s: %s\n", Char(func_name),Char(result_m3wraptype)); |
| } |
| |
| String *arguments = createM3Signature(n); |
| |
| /* Create local variables or RECORD fields for return values |
| and determine return type that might result from a converted VAR argument. */ |
| { |
| writeArgState state; |
| if (multiretval && has_return_m3) { |
| writeArg(return_variables, state, NIL, NewString(result_return), result_m3wraptype, NIL); |
| } |
| |
| Parm *p = skipIgnored(l, "m3wrapouttype"); |
| while (p != NIL) { |
| |
| String *arg = Getattr(p, "tmap:m3wrapoutname"); |
| if (arg == NIL) { |
| arg = Getattr(p, "name"); |
| } |
| |
| String *tm = Getattr(p, "tmap:m3wrapouttype"); |
| if (tm != NIL) { |
| if (isOutParam(p)) { |
| if (!multiretval) { |
| if (num_returns == 0) { |
| Printv(result_name, arg, NIL); |
| Clear(result_m3wraptype); |
| Printv(result_m3wraptype, tm, NIL); |
| } else { |
| Swig_warning(WARN_MODULA3_TYPEMAP_MULTIPLE_RETURN, input_file, line_number, |
| "Typemap m3wrapargdir set to 'out' for %s implies a RETURN value, but the routine %s has already one.\nUse %%multiretval feature.\n", |
| SwigType_str(Getattr(p, "type"), 0), raw_name); |
| } |
| } |
| num_returns++; |
| addImports(m3wrap_intf.import, "m3wrapouttype", p); |
| writeArg(return_variables, state, NIL, arg, tm, NIL); |
| } |
| p = skipIgnored(Getattr(p, "tmap:m3wrapouttype:next"), "m3wrapouttype"); |
| } else { |
| p = nextSibling(p); |
| } |
| } |
| writeArg(return_variables, state, NIL, NIL, NIL, NIL); |
| |
| if (multiretval) { |
| Printv(result_name, Swig_cresult_name(), NIL); |
| Printf(result_m3wraptype, "%sResult", func_name); |
| m3wrap_intf.enterBlock(blocktype); |
| Printf(m3wrap_intf.f, "%s =\nRECORD\n%sEND;\n", result_m3wraptype, return_variables); |
| Printf(local_variables, "%s: %s;\n", result_name, result_m3wraptype); |
| } else { |
| Append(local_variables, return_variables); |
| } |
| } |
| |
| /* Declare local constants e.g. for storing argument names. */ |
| { |
| Parm *p = l; |
| while (p != NIL) { |
| |
| String *arg = Getattr(p, "autoname"); |
| |
| String *tm = Getattr(p, "tmap:m3wrapargconst"); |
| if (tm != NIL) { |
| addImports(m3wrap_impl.import, "m3wrapargconst", p); |
| Replaceall(tm, "$input", arg); |
| Printv(local_constants, tm, "\n", NIL); |
| p = Getattr(p, "tmap:m3wrapargconst:next"); |
| } else { |
| p = nextSibling(p); |
| } |
| |
| } |
| } |
| |
| /* Declare local variables e.g. for converted input values. */ |
| { |
| String *tm = getMappedTypeNew(n, "m3wrapretvar", "", false); |
| if (tm != NIL) { |
| addImports(m3wrap_impl.import, "m3wrapretvar", n); |
| addThrows(throws_hash, "m3wrapretvar", n); |
| Printv(local_variables, tm, "\n", NIL); |
| } |
| |
| Parm *p = l; |
| while (p != NIL) { |
| |
| String *arg = Getattr(p, "autoname"); |
| |
| tm = Getattr(p, "tmap:m3wrapargvar"); |
| if (tm != NIL) { |
| /* exceptions that may be raised but can't be catched, |
| thus we won't count them in num_exceptions */ |
| addImports(m3wrap_impl.import, "m3wrapargvar", p); |
| addThrows(throws_hash, "m3wrapargvar", p); |
| Replaceall(tm, "$input", arg); |
| Printv(local_variables, tm, "\n", NIL); |
| p = Getattr(p, "tmap:m3wrapargvar:next"); |
| } else { |
| p = nextSibling(p); |
| } |
| |
| } |
| } |
| |
| /* Convert input values from Modula 3 to C. */ |
| { |
| Parm *p = l; |
| while (p != NIL) { |
| |
| String *arg = Getattr(p, "autoname"); |
| |
| String *tm = Getattr(p, "tmap:m3wrapinconv"); |
| if (tm != NIL) { |
| addImports(m3wrap_impl.import, "m3wrapinconv", p); |
| num_exceptions += addThrows(throws_hash, "m3wrapinconv", p); |
| Replaceall(tm, "$input", arg); |
| Printv(setup, tm, "\n", NIL); |
| p = Getattr(p, "tmap:m3wrapinconv:next"); |
| } else { |
| p = nextSibling(p); |
| } |
| |
| } |
| } |
| |
| /* Generate checks for input value integrity. */ |
| { |
| Parm *p = l; |
| while (p != NIL) { |
| |
| String *arg = Getattr(p, "autoname"); |
| |
| String *tm = Getattr(p, "tmap:m3wrapincheck"); |
| if (tm != NIL) { |
| addImports(m3wrap_impl.import, "m3wrapincheck", p); |
| num_exceptions += addThrows(throws_hash, "m3wrapincheck", p); |
| Replaceall(tm, "$input", arg); |
| Printv(incheck, tm, "\n", NIL); |
| p = Getattr(p, "tmap:m3wrapincheck:next"); |
| } else { |
| p = nextSibling(p); |
| } |
| |
| } |
| } |
| |
| Printv(rawcall, m3raw_name, ".", func_name, "(", NIL); |
| /* Arguments to the raw C function */ |
| { |
| bool gencomma = false; |
| Parm *p = l; |
| while (p != NIL) { |
| if (gencomma) { |
| Printf(rawcall, ", "); |
| } |
| gencomma = true; |
| addImports(m3wrap_impl.import, "m3wrapargraw", p); |
| num_exceptions += addThrows(throws_hash, "m3wrapargraw", p); |
| |
| String *arg = Getattr(p, "autoname"); |
| String *qualarg = NewString(""); |
| if (!isInParam(p)) { |
| String *tmparg = Getattr(p, "tmap:m3wrapoutname"); |
| if (tmparg != NIL) { |
| arg = tmparg; |
| } |
| if (multiretval /*&& isOutParam(p) - automatically fulfilled */ ) { |
| Printf(qualarg, "%s.", result_name); |
| } |
| } |
| Append(qualarg, arg); |
| Setattr(p, "m3outarg", qualarg); |
| |
| String *tm = Getattr(p, "tmap:m3wrapargraw"); |
| if (tm != NIL) { |
| Replaceall(tm, "$input", arg); |
| Replaceall(tm, "$output", qualarg); |
| Printv(rawcall, tm, NIL); |
| p = Getattr(p, "tmap:m3wrapargraw:next"); |
| } else { |
| //Printv(rawcall, Getattr(p,"lname"), NIL); |
| Printv(rawcall, qualarg, NIL); |
| p = nextSibling(p); |
| } |
| Delete(qualarg); |
| } |
| } |
| Printf(rawcall, ")"); |
| |
| /* Check for error codes and integrity of results */ |
| { |
| String *tm = getMappedTypeNew(n, "m3wrapretcheck", "", false); |
| if (tm != NIL) { |
| addImports(m3wrap_impl.import, "m3wrapretcheck", n); |
| num_exceptions += addThrows(throws_hash, "m3wrapretcheck", n); |
| Printv(outcheck, tm, "\n", NIL); |
| } |
| |
| Parm *p = l; |
| while (p != NIL) { |
| tm = Getattr(p, "tmap:m3wrapoutcheck"); |
| if (tm != NIL) { |
| String *arg = Getattr(p, "autoname"); |
| String *outarg = Getattr(p, "m3outarg"); |
| addImports(m3wrap_impl.import, "m3wrapoutcheck", p); |
| num_exceptions += addThrows(throws_hash, "m3wrapoutcheck", p); |
| //substituteClassname(Getattr(p,"type"), tm); |
| Replaceall(tm, "$input", arg); |
| Replaceall(tm, "$output", outarg); |
| Printv(outcheck, tm, "\n", NIL); |
| p = Getattr(p, "tmap:m3wrapoutcheck:next"); |
| } else { |
| p = nextSibling(p); |
| } |
| } |
| } |
| |
| /* Convert the results to Modula 3 data structures and |
| put them in the record prepared for returning */ |
| { |
| /* m3wrapretconv is processed |
| when it is clear if there is some output conversion and checking code */ |
| Parm *p = l; |
| while (p != NIL) { |
| String *tm = Getattr(p, "tmap:m3wrapoutconv"); |
| if (tm != NIL) { |
| String *arg = Getattr(p, "autoname"); |
| String *outarg = Getattr(p, "m3outarg"); |
| addImports(m3wrap_impl.import, "m3wrapoutconv", n); |
| num_exceptions += addThrows(throws_hash, "m3wrapoutconv", p); |
| //substituteClassname(Getattr(p,"type"), tm); |
| Replaceall(tm, "$input", arg); |
| Replaceall(tm, "$output", outarg); |
| Printf(storeout, "%s := %s;\n", outarg, tm); |
| p = Getattr(p, "tmap:m3wrapoutconv:next"); |
| } else { |
| p = nextSibling(p); |
| } |
| } |
| } |
| |
| /* Generate cleanup code */ |
| { |
| Parm *p = l; |
| while (p != NIL) { |
| String *tm = Getattr(p, "tmap:m3wrapfreearg"); |
| if (tm != NIL) { |
| String *arg = Getattr(p, "autoname"); |
| String *outarg = Getattr(p, "m3outarg"); |
| addImports(m3wrap_impl.import, "m3wrapfreearg", p); |
| num_exceptions += addThrows(throws_hash, "m3wrapfreearg", p); |
| //substituteClassname(Getattr(p,"type"), tm); |
| Replaceall(tm, "$input", arg); |
| Replaceall(tm, "$output", outarg); |
| Printv(cleanup, tm, "\n", NIL); |
| p = Getattr(p, "tmap:m3wrapfreearg:next"); |
| } else { |
| p = nextSibling(p); |
| } |
| } |
| } |
| |
| { |
| /* Currently I don't know how a typemap similar to the original 'out' typemap |
| could help returning the return value. */ |
| /* Receive result from call to raw library function */ |
| if (!has_return_raw) { |
| /* |
| rawcall(arg1); |
| result.val := arg1; |
| RETURN result; |
| */ |
| /* |
| rawcall(arg1); |
| RETURN arg1; |
| */ |
| Printf(reccall, "%s;\n", rawcall); |
| |
| if (hasContent(result_name)) { |
| Printf(outarg, "RETURN %s;\n", result_name); |
| } |
| } else { |
| /* |
| arg0 := rawcall(arg1); |
| result.ret := Convert(arg0); |
| result.val := arg1; |
| RETURN result; |
| */ |
| /* |
| arg0 := rawcall(); |
| RETURN Convert(arg0); |
| */ |
| /* |
| RETURN rawcall(); |
| */ |
| String *return_raw = getMappedTypeNew(n, "m3wrapretraw", "", false); |
| String *return_conv = getMappedTypeNew(n, "m3wrapretconv", "", false); |
| |
| /* immediate RETURN would skip result checking */ |
| if ((hasContent(outcheck) || hasContent(storeout) |
| || hasContent(cleanup)) && (!hasContent(result_name)) |
| && (return_raw == NIL)) { |
| Printv(result_name, Swig_cresult_name(), NIL); |
| Printf(local_variables, "%s: %s;\n", result_name, result_m3wraptype); |
| } |
| |
| String *result_lvalue = Copy(result_name); |
| if (multiretval) { |
| Printf(result_lvalue, ".%s", result_return); |
| } |
| if (return_raw != NIL) { |
| Printf(reccall, "%s := %s;\n", return_raw, rawcall); |
| } else if (hasContent(result_name)) { |
| Printf(reccall, "%s := %s;\n", result_lvalue, rawcall); |
| } else { |
| Printf(outarg, "RETURN %s;\n", rawcall); |
| } |
| if (return_conv != NIL) { |
| addImports(m3wrap_impl.import, "m3wrapretconv", n); |
| num_exceptions += addThrows(throws_hash, "m3wrapretconv", n); |
| if (hasContent(result_name)) { |
| Printf(reccall, "%s := %s;\n", result_lvalue, return_conv); |
| Printf(outarg, "RETURN %s;\n", result_name); |
| } else { |
| Printf(outarg, "RETURN %s;\n", return_conv); |
| } |
| } else { |
| if (hasContent(result_name)) { |
| Printf(outarg, "RETURN %s;\n", result_name); |
| } |
| } |
| } |
| } |
| |
| /* Create procedure header */ |
| { |
| String *header = NewStringf("PROCEDURE %s (%s)", |
| func_name, arguments); |
| |
| if ((num_returns > 0) || multiretval) { |
| Printf(header, ": %s", result_m3wraptype); |
| } |
| generateThrowsClause(throws_hash, header); |
| |
| Append(function_code, header); |
| |
| m3wrap_intf.enterBlock(no_block); |
| Printf(m3wrap_intf.f, "%s;\n\n", header); |
| } |
| |
| { |
| String *body = NewStringf("%s%s%s%s%s", |
| incheck, |
| setup, |
| reccall, |
| outcheck, |
| storeout); |
| |
| String *exc_handler; |
| if (hasContent(cleanup) && (num_exceptions > 0)) { |
| exc_handler = NewStringf("TRY\n%sFINALLY\n%sEND;\n", body, cleanup); |
| } else { |
| exc_handler = NewStringf("%s%s", body, cleanup); |
| } |
| |
| Printf(function_code, " =\n%s%s%s%sBEGIN\n%s%sEND %s;\n\n", |
| hasContent(local_constants) ? "CONST\n" : "", local_constants, |
| hasContent(local_variables) ? "VAR\n" : "", local_variables, exc_handler, outarg, func_name); |
| |
| Delete(exc_handler); |
| Delete(body); |
| } |
| |
| m3wrap_impl.enterBlock(no_block); |
| if (proxy_flag && global_variable_flag) { |
| setter_flag = (Cmp(Getattr(n, "sym:name"), Swig_name_set(NSPACE_TODO, variable_name)) == 0); |
| // Properties |
| if (setter_flag) { |
| // Setter method |
| String *tm = getMappedTypeNew(n, "m3varin", ""); |
| if (tm != NIL) { |
| if (GetFlag(n, "feature:new")) { |
| Replaceall(tm, "$owner", "true"); |
| } else { |
| Replaceall(tm, "$owner", "false"); |
| } |
| substituteClassname(t, tm); |
| Replaceall(tm, "$rawcall", rawcall); |
| Replaceall(tm, "$vartype", variable_type); /* $type is already replaced by some super class */ |
| Replaceall(tm, "$var", variable_name); |
| Printf(m3wrap_impl.f, "%s", tm); |
| } |
| } else { |
| // Getter method |
| String *tm = getMappedTypeNew(n, "m3varout", ""); |
| if (tm != NIL) { |
| if (GetFlag(n, "feature:new")) |
| Replaceall(tm, "$owner", "true"); |
| else |
| Replaceall(tm, "$owner", "false"); |
| substituteClassname(t, tm); |
| Replaceall(tm, "$rawcall", rawcall); |
| Replaceall(tm, "$vartype", variable_type); |
| Replaceall(tm, "$var", variable_name); |
| Printf(m3wrap_impl.f, "%s", tm); |
| } |
| } |
| } else { |
| // Normal function call |
| Printv(m3wrap_impl.f, function_code, NIL); |
| } |
| |
| Delete(arguments); |
| Delete(return_variables); |
| Delete(local_variables); |
| Delete(local_constants); |
| Delete(outarg); |
| Delete(incheck); |
| Delete(outcheck); |
| Delete(setup); |
| Delete(cleanup); |
| Delete(storeout); |
| Delete(function_code); |
| Delete(result_name); |
| Delete(result_m3wraptype); |
| Delete(reccall); |
| Delete(rawcall); |
| Delete(throws_hash); |
| } |
| |
| /*---------------------------------------------------------------------- |
| * replaceSpecialVariables() |
| *--------------------------------------------------------------------*/ |
| |
| virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) { |
| (void)method; |
| SwigType *type = Getattr(parm, "type"); |
| substituteClassname(type, tm); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * substituteClassname() |
| * |
| * Substitute the special variable $m3classname with the proxy class name for classes/structs/unions |
| * that SWIG knows about. |
| * Otherwise use the $descriptor name for the Modula 3 class name. Note that the $&m3classname substitution |
| * is the same as a $&descriptor substitution, ie one pointer added to descriptor name. |
| * Inputs: |
| * pt - parameter type |
| * tm - typemap contents that might contain the special variable to be replaced |
| * Outputs: |
| * tm - typemap contents complete with the special variable substitution |
| * Return: |
| * substitution_performed - flag indicating if a substitution was performed |
| * ----------------------------------------------------------------------------- */ |
| |
| bool substituteClassname(SwigType *pt, String *tm) { |
| bool substitution_performed = false; |
| if (Strstr(tm, "$m3classname") || Strstr(tm, "$&m3classname")) { |
| String *classname = getProxyName(pt); |
| if (classname) { |
| Replaceall(tm, "$&m3classname", classname); // getProxyName() works for pointers to classes too |
| Replaceall(tm, "$m3classname", classname); |
| } else { // use $descriptor if SWIG does not know anything about this type. Note that any typedefs are resolved. |
| String *descriptor = NULL; |
| SwigType *type = Copy(SwigType_typedef_resolve_all(pt)); |
| |
| if (Strstr(tm, "$&m3classname")) { |
| SwigType_add_pointer(type); |
| descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type)); |
| Replaceall(tm, "$&m3classname", descriptor); |
| } else { // $m3classname |
| descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type)); |
| Replaceall(tm, "$m3classname", descriptor); |
| } |
| |
| // Add to hash table so that the type wrapper classes can be created later |
| Setattr(swig_types_hash, descriptor, type); |
| Delete(descriptor); |
| Delete(type); |
| } |
| substitution_performed = true; |
| } |
| return substitution_performed; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * attachParameterNames() |
| * |
| * Inputs: |
| * n - Node of a function declaration |
| * tmid - attribute name for overriding C argument names, |
| * e.g. "tmap:m3wrapinname", |
| * don't forget to attach the mapped types before |
| * nameid - attribute for attaching the names, |
| * e.g. "modula3:inname" |
| * fmt - format for the argument name containing %d |
| * e.g. "arg%d" |
| * ----------------------------------------------------------------------------- */ |
| |
| void attachParameterNames(Node *n, const char *tmid, const char *nameid, const char *fmt) { |
| /* Use C parameter name if present and unique, |
| otherwise create an 'arg%d' name */ |
| Hash *hash = NewHash(); |
| Parm *p = Getattr(n, "parms"); |
| int count = 0; |
| while (p != NIL) { |
| String *name = Getattr(p, tmid); |
| if (name == NIL) { |
| name = Getattr(p, "name"); |
| } |
| String *newname; |
| if ((!hasContent(name)) || (Getattr(hash, name) != NIL)) { |
| newname = NewStringf(fmt, count); |
| } else { |
| newname = Copy(name); |
| } |
| if (1 == Setattr(hash, newname, "1")) { |
| Swig_warning(WARN_MODULA3_DOUBLE_ID, input_file, line_number, "Argument '%s' twice.\n", newname); |
| } |
| Setattr(p, nameid, newname); |
| // Delete(newname); |
| p = nextSibling(p); |
| count++; |
| } |
| Delete(hash); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * createM3Signature() |
| * |
| * Create signature of M3 wrapper procedure |
| * Call attachParameterNames and attach mapped types before! |
| * m3wrapintype, m3wrapinmode, m3wrapindefault |
| * ----------------------------------------------------------------------------- */ |
| |
| String *createM3Signature(Node *n) { |
| String *arguments = NewString(""); |
| Parm *p = skipIgnored(Getattr(n, "parms"), "m3wrapintype"); |
| writeArgState state; |
| while (p != NIL) { |
| |
| /* Get the M3 parameter type */ |
| String *tm = getMappedType(p, "m3wrapintype"); |
| if (tm != NIL) { |
| if (isInParam(p)) { |
| addImports(m3wrap_intf.import, "m3wrapintype", p); |
| addImports(m3wrap_impl.import, "m3wrapintype", p); |
| String *mode = Getattr(p, "tmap:m3wrapinmode"); |
| String *deflt = Getattr(p, "tmap:m3wrapindefault"); |
| String *arg = Getattr(p, "autoname"); |
| SwigType *pt = Getattr(p, "type"); |
| substituteClassname(pt, tm); /* do we need this ? */ |
| |
| writeArg(arguments, state, mode, arg, tm, deflt); |
| } |
| p = skipIgnored(Getattr(p, "tmap:m3wrapintype:next"), "m3wrapintype"); |
| } else { |
| p = nextSibling(p); |
| } |
| } |
| writeArg(arguments, state, NIL, NIL, NIL, NIL); |
| return (arguments); |
| } |
| |
| /* not used any longer |
| - try SwigType_str if required again */ |
| #if 0 |
| /* ----------------------------------------------------------------------------- |
| * createCSignature() |
| * |
| * Create signature of C function |
| * ----------------------------------------------------------------------------- */ |
| |
| String *createCSignature(Node *n) { |
| String *arguments = NewString(""); |
| bool gencomma = false; |
| Node *p; |
| for (p = Getattr(n, "parms"); p != NIL; p = nextSibling(p)) { |
| if (gencomma) { |
| Append(arguments, ","); |
| } |
| gencomma = true; |
| String *type = Getattr(p, "type"); |
| String *ctype = getMappedTypeNew(type, "ctype"); |
| Append(arguments, ctype); |
| } |
| return arguments; |
| } |
| #endif |
| |
| /* ----------------------------------------------------------------------------- |
| * emitTypeWrapperClass() |
| * ----------------------------------------------------------------------------- */ |
| |
| void emitTypeWrapperClass(String *classname, SwigType *type) { |
| Node *n = NewHash(); |
| Setfile(n, input_file); |
| Setline(n, line_number); |
| |
| String *filen = NewStringf("%s%s.m3", SWIG_output_directory(), classname); |
| File *f_swigtype = NewFile(filen, "w", SWIG_output_files()); |
| if (!f_swigtype) { |
| FileErrorDisplay(filen); |
| SWIG_exit(EXIT_FAILURE); |
| } |
| String *swigtype = NewString(""); |
| |
| // Emit banner name |
| emitBanner(f_swigtype); |
| |
| // Pure Modula 3 baseclass and interfaces |
| const String *pure_baseclass = typemapLookup(n, "m3base", type, WARN_NONE); |
| const String *pure_interfaces = typemapLookup(n, "m3interfaces", type, WARN_NONE); |
| |
| // Emit the class |
| Printv(swigtype, typemapLookup(n, "m3imports", type, WARN_NONE), // Import statements |
| "\n", typemapLookup(n, "m3classmodifiers", type, WARN_MODULA3_TYPEMAP_CLASSMOD_UNDEF), // Class modifiers |
| " class $m3classname", // Class name and bases |
| *Char(pure_baseclass) ? " : " : "", pure_baseclass, *Char(pure_interfaces) ? // Interfaces |
| " : " : "", pure_interfaces, " {\n", " private IntPtr swigCPtr;\n", "\n", " ", typemapLookup(n, "m3ptrconstructormodifiers", type, WARN_MODULA3_TYPEMAP_PTRCONSTMOD_UNDEF), // pointer constructor modifiers |
| " $m3classname(IntPtr cPtr, bool bFutureUse) {\n", // Constructor used for wrapping pointers |
| " swigCPtr = cPtr;\n", " }\n", "\n", " protected $m3classname() {\n", // Default constructor |
| " swigCPtr = IntPtr.Zero;\n", " }\n", typemapLookup(n, "m3getcptr", type, WARN_MODULA3_TYPEMAP_GETCPTR_UNDEF), // getCPtr method |
| typemapLookup(n, "m3code", type, WARN_NONE), // extra Modula 3 code |
| "}\n", "\n", NIL); |
| |
| Replaceall(swigtype, "$m3classname", classname); |
| Printv(f_swigtype, swigtype, NIL); |
| |
| Delete(f_swigtype); |
| Delete(filen); |
| Delete(swigtype); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * typemapLookup() |
| * n - for input only and must contain info for Getfile(n) and Getline(n) to work |
| * tmap_method - typemap method name |
| * type - typemap type to lookup |
| * warning - warning number to issue if no typemaps found |
| * typemap_attributes - the typemap attributes are attached to this node and will |
| * also be used for temporary storage if non null |
| * return is never NULL, unlike Swig_typemap_lookup() |
| * ----------------------------------------------------------------------------- */ |
| |
| const String *typemapLookup(Node *n, const_String_or_char_ptr tmap_method, SwigType *type, int warning, Node *typemap_attributes = 0) { |
| Node *node = !typemap_attributes ? NewHash() : typemap_attributes; |
| Setattr(node, "type", type); |
| Setfile(node, Getfile(n)); |
| Setline(node, Getline(n)); |
| const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0); |
| if (!tm) { |
| tm = empty_string; |
| if (warning != WARN_NONE) |
| Swig_warning(warning, Getfile(n), Getline(n), "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0)); |
| } |
| if (!typemap_attributes) |
| Delete(node); |
| return tm; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * addThrows() |
| * |
| * Add all exceptions to a hash that are associated with the 'typemap'. |
| * Return number the number of these exceptions. |
| * ----------------------------------------------------------------------------- */ |
| |
| int addThrows(Hash *throws_hash, const String *typemap, Node *parameter) { |
| // Get the comma separated throws clause - held in "throws" attribute in the typemap passed in |
| int len = 0; |
| String *throws_attribute = NewStringf("%s:throws", typemap); |
| |
| addImports(m3wrap_intf.import, throws_attribute, parameter); |
| addImports(m3wrap_impl.import, throws_attribute, parameter); |
| |
| String *throws = getMappedTypeNew(parameter, Char(throws_attribute), "", false); |
| //printf("got exceptions %s for %s\n", Char(throws), Char(throws_attribute)); |
| |
| if (throws) { |
| // Put the exception classes in the throws clause into a temporary List |
| List *temp_classes_list = Split(throws, ',', INT_MAX); |
| len = Len(temp_classes_list); |
| |
| // Add the exception classes to the node throws list, but don't duplicate if already in list |
| if (temp_classes_list /*&& hasContent(temp_classes_list) */ ) { |
| for (Iterator cls = First(temp_classes_list); cls.item != NIL; cls = Next(cls)) { |
| String *exception_class = NewString(cls.item); |
| Replaceall(exception_class, " ", ""); // remove spaces |
| Replaceall(exception_class, "\t", ""); // remove tabs |
| if (hasContent(exception_class)) { |
| // $m3classname substitution |
| SwigType *pt = Getattr(parameter, "type"); |
| substituteClassname(pt, exception_class); |
| // Don't duplicate the exception class in the throws clause |
| //printf("add exception %s\n", Char(exception_class)); |
| Setattr(throws_hash, exception_class, "1"); |
| } |
| Delete(exception_class); |
| } |
| } |
| Delete(temp_classes_list); |
| } |
| Delete(throws_attribute); |
| return len; |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * generateThrowsClause() |
| * ----------------------------------------------------------------------------- */ |
| |
| void generateThrowsClause(Hash *throws_hash, String *code) { |
| // Add the throws clause into code |
| if (Len(throws_hash) > 0) { |
| Iterator cls = First(throws_hash); |
| Printf(code, " RAISES {%s", cls.key); |
| for (cls = Next(cls); cls.key != NIL; cls = Next(cls)) { |
| Printf(code, ", %s", cls.key); |
| } |
| Printf(code, "}"); |
| } |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * addImports() |
| * |
| * Add all imports that are needed for contents of 'typemap'. |
| * ----------------------------------------------------------------------------- */ |
| |
| void addImports(Hash *imports_hash, const String *typemap, Node *node) { |
| // Get the comma separated throws clause - held in "throws" attribute in the typemap passed in |
| String *imports_attribute = NewStringf("%s:import", typemap); |
| String *imports = getMappedTypeNew(node, Char(imports_attribute), "", false); |
| //printf("got imports %s for %s\n", Char(imports), Char(imports_attribute)); |
| |
| if (imports != NIL) { |
| List *import_list = Split(imports, ',', INT_MAX); |
| |
| // Add the exception classes to the node imports list, but don't duplicate if already in list |
| if (import_list != NIL) { |
| for (Iterator imp = First(import_list); imp.item != NIL; imp = Next(imp)) { |
| List *import_pair = Split(imp.item, ' ', 3); |
| if (Len(import_pair) == 1) { |
| Setattr(imports_hash, Getitem(import_pair, 0), ""); |
| } else if ((Len(import_pair) == 3) |
| && Strcmp(Getitem(import_pair, 1), "AS") == 0) { |
| Setattr(imports_hash, Getitem(import_pair, 0), Getitem(import_pair, 2)); |
| } else { |
| Swig_warning(WARN_MODULA3_BAD_IMPORT, input_file, line_number, |
| "Malformed import '%s' for typemap '%s' defined for type '%s'\n", imp, typemap, SwigType_str(Getattr(node, "type"), 0)); |
| } |
| Delete(import_pair); |
| } |
| } |
| Delete(import_list); |
| } |
| Delete(imports_attribute); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * emitImportStatements() |
| * ----------------------------------------------------------------------------- */ |
| |
| void emitImportStatements(Hash *imports_hash, String *code) { |
| // Add the imports statements into code |
| Iterator imp = First(imports_hash); |
| while (imp.key != NIL) { |
| Printf(code, "IMPORT %s", imp.key); |
| String *imp_as = imp.item; |
| if (hasContent(imp_as)) { |
| Printf(code, " AS %s", imp_as); |
| } |
| Printf(code, ";\n"); |
| imp = Next(imp); |
| } |
| } |
| |
| }; /* class MODULA3 */ |
| |
| /* ----------------------------------------------------------------------------- |
| * swig_modula3() - Instantiate module |
| * ----------------------------------------------------------------------------- */ |
| |
| extern "C" Language *swig_modula3(void) { |
| return new MODULA3(); |
| } |
| |
| /* ----------------------------------------------------------------------------- |
| * Static member variables |
| * ----------------------------------------------------------------------------- */ |
| |
| const char *MODULA3::usage = "\ |
| Modula 3 Options (available with -modula3)\n\ |
| -generateconst <file> - Generate code for computing numeric values of constants\n\ |
| -generaterename <file> - Generate suggestions for %rename\n\ |
| -generatetypemap <file> - Generate templates for some basic typemaps\n\ |
| -oldvarnames - Old intermediary method names for variable wrappers\n\ |
| \n"; |
| |
| /* |
| -generateconst <file> - stem of the .c source file for computing the numeric values of constants\n\ |
| -generaterename <file> - stem of the .i source file containing %rename suggestions\n\ |
| -generatetypemap <file> - stem of the .i source file containing typemap patterns\n\ |
| */ |