/trunk/Source/Modules/ruby.cxx
C++ | 2137 lines | 1935 code | 101 blank | 101 comment | 145 complexity | 98f00cb5c0518d222270d2e3ee10f02c MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
- /* -----------------------------------------------------------------------------
- * 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.
- *
- * ruby.cxx
- *
- * Ruby language module for SWIG.
- * ----------------------------------------------------------------------------- */
- char cvsroot_ruby_cxx[] = "$Id: ruby.cxx 12883 2011-12-22 21:14:09Z wsfulton $";
- #include "swigmod.h"
- #include "cparse.h"
- static int treduce = SWIG_cparse_template_reduce(0);
- #define SWIG_PROTECTED_TARGET_METHODS 1
- #include <ctype.h>
- #include <string.h>
- #include <limits.h> /* for INT_MAX */
- class RClass {
- private:
- String *temp;
- public:
- String *name; /* class name (renamed) */
- String *cname; /* original C class/struct name */
- String *mname; /* Mangled name */
- /**
- * The C variable name used in the SWIG-generated wrapper code to refer to
- * this class; usually it is of the form "SwigClassXXX.klass", where SwigClassXXX
- * is a swig_class struct instance and klass is a member of that struct.
- */
- String *vname;
- /**
- * The C variable name used in the SWIG-generated wrapper code to refer to
- * the module that implements this class's methods (when we're trying to
- * support C++ multiple inheritance). Usually it is of the form
- * "SwigClassClassName.mImpl", where SwigClassXXX is a swig_class struct instance
- * and mImpl is a member of that struct.
- */
- String *mImpl;
- String *type;
- String *prefix;
- String *init;
- int constructor_defined;
- int destructor_defined;
- RClass() {
- temp = NewString("");
- name = NewString("");
- cname = NewString("");
- mname = NewString("");
- vname = NewString("");
- mImpl = NewString("");
- type = NewString("");
- prefix = NewString("");
- init = NewString("");
- constructor_defined = 0;
- destructor_defined = 0;
- }
-
- ~RClass() {
- Delete(name);
- Delete(cname);
- Delete(vname);
- Delete(mImpl);
- Delete(mname);
- Delete(type);
- Delete(prefix);
- Delete(init);
- Delete(temp);
- }
- void set_name(const_String_or_char_ptr cn, const_String_or_char_ptr rn, const_String_or_char_ptr valn) {
- /* Original C/C++ class (or struct) name */
- Clear(cname);
- Append(cname, cn);
- /* Mangled name */
- Delete(mname);
- mname = Swig_name_mangle(cname);
- /* Renamed class name */
- Clear(name);
- Append(name, valn);
- /* Variable name for the VALUE that refers to the Ruby Class object */
- Clear(vname);
- Printf(vname, "SwigClass%s.klass", name);
- /* Variable name for the VALUE that refers to the Ruby Class object */
- Clear(mImpl);
- Printf(mImpl, "SwigClass%s.mImpl", name);
- /* Prefix */
- Clear(prefix);
- Printv(prefix, (rn ? rn : cn), "_", NIL);
- }
- char *strip(const_String_or_char_ptr s) {
- Clear(temp);
- Append(temp, s);
- if (Strncmp(s, prefix, Len(prefix)) == 0) {
- Replaceall(temp, prefix, "");
- }
- return Char(temp);
- }
- };
- /* flags for the make_autodoc function */
- enum autodoc_t {
- AUTODOC_CLASS,
- AUTODOC_CTOR,
- AUTODOC_DTOR,
- AUTODOC_STATICFUNC,
- AUTODOC_FUNC,
- AUTODOC_METHOD,
- AUTODOC_GETTER,
- AUTODOC_SETTER
- };
- static const char *usage = (char *) "\
- Ruby Options (available with -ruby)\n\
- -autorename - Enable renaming of classes and methods to follow Ruby coding standards\n\
- -cppcast - Enable C++ casting operators (default)\n\
- -globalmodule - Wrap everything into the global module\n\
- -initname <name>- Set entry function to Init_<name> (used by `require')\n\
- -minherit - Attempt to support multiple inheritance\n\
- -noautorename - Disable renaming of classes and methods (default)\n\
- -nocppcast - Disable C++ casting operators, useful for generating bugs\n\
- -prefix <name> - Set a prefix <name> to be prepended to all names\n\
- ";
- #define RCLASS(hash, name) (RClass*)(Getattr(hash, name) ? Data(Getattr(hash, name)) : 0)
- #define SET_RCLASS(hash, name, klass) Setattr(hash, name, NewVoid(klass, 0))
- class RUBY:public Language {
- private:
- String *module;
- String *modvar;
- String *feature;
- String *prefix;
- int current;
- Hash *classes; /* key=cname val=RClass */
- RClass *klass; /* Currently processing class */
- Hash *special_methods; /* Python style special method name table */
- File *f_directors;
- File *f_directors_h;
- File *f_directors_helpers;
- File *f_begin;
- File *f_runtime;
- File *f_runtime_h;
- File *f_header;
- File *f_wrappers;
- File *f_init;
- File *f_initbeforefunc;
- bool useGlobalModule;
- bool multipleInheritance;
- // Wrap modes
- enum WrapperMode {
- NO_CPP,
- MEMBER_FUNC,
- CONSTRUCTOR_ALLOCATE,
- CONSTRUCTOR_INITIALIZE,
- DESTRUCTOR,
- MEMBER_VAR,
- CLASS_CONST,
- STATIC_FUNC,
- STATIC_VAR
- };
- /* ------------------------------------------------------------
- * autodoc level declarations
- * ------------------------------------------------------------ */
- enum autodoc_l {
- NO_AUTODOC = -2, // no autodoc
- STRING_AUTODOC = -1, // use provided string
- NAMES_AUTODOC = 0, // only parameter names
- TYPES_AUTODOC = 1, // parameter names and types
- EXTEND_AUTODOC = 2, // extended documentation and parameter names
- EXTEND_TYPES_AUTODOC = 3 // extended documentation and parameter types + names
- };
- autodoc_t last_mode;
- String* last_autodoc;
- autodoc_l autodoc_level(String *autodoc) {
- autodoc_l dlevel = NO_AUTODOC;
- if (autodoc) {
- char *c = Char(autodoc);
- if (c && isdigit(c[0])) {
- dlevel = (autodoc_l) atoi(c);
- } else {
- if (strcmp(c, "extended") == 0) {
- dlevel = EXTEND_AUTODOC;
- } else {
- dlevel = STRING_AUTODOC;
- }
- }
- }
- return dlevel;
- }
- /* ------------------------------------------------------------
- * have_docstring()
- * Check if there is a docstring directive and it has text,
- * or there is an autodoc flag set
- * ------------------------------------------------------------ */
- bool have_docstring(Node *n) {
- String *str = Getattr(n, "feature:docstring");
- return (str && Len(str) > 0) || (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"));
- }
- /* ------------------------------------------------------------
- * docstring()
- * Get the docstring text, stripping off {} if neccessary,
- * and enclose in triple double quotes. If autodoc is also
- * set then it will build a combined docstring.
- * ------------------------------------------------------------ */
- String *docstring(Node *n, autodoc_t ad_type) {
- String *str = Getattr(n, "feature:docstring");
- bool have_ds = (str && Len(str) > 0);
- bool have_auto = (Getattr(n, "feature:autodoc") && !GetFlag(n, "feature:noautodoc"));
- String *autodoc = NULL;
- String *doc = NULL;
- if (have_ds) {
- char *t = Char(str);
- if (*t == '{') {
- Delitem(str, 0);
- Delitem(str, DOH_END);
- }
- }
- if (have_auto) {
- autodoc = make_autodoc(n, ad_type);
- have_auto = (autodoc && Len(autodoc) > 0);
- }
- // If there is more than one line then make docstrings like this:
- //
- // This is line1
- // And here is line2 followed by the rest of them
- //
- // otherwise, put it all on a single line
- //
- if (have_auto && have_ds) { // Both autodoc and docstring are present
- doc = NewString("");
- Printv(doc, "\n", autodoc, "\n", str, NIL);
- } else if (!have_auto && have_ds) { // only docstring
- if (Strchr(str, '\n') == 0) {
- doc = NewString(str);
- } else {
- doc = NewString("");
- Printv(doc, str, NIL);
- }
- } else if (have_auto && !have_ds) { // only autodoc
- if (Strchr(autodoc, '\n') == 0) {
- doc = NewStringf("%s", autodoc);
- } else {
- doc = NewString("");
- Printv(doc, "\n", autodoc, NIL);
- }
- } else
- doc = NewString("");
- // Save the generated strings in the parse tree in case they are used later
- // by post processing tools
- Setattr(n, "ruby:docstring", doc);
- Setattr(n, "ruby:autodoc", autodoc);
- return doc;
- }
- /* -----------------------------------------------------------------------------
- * addMissingParameterNames()
- * For functions that have not had nameless parameters set in the Language class.
- *
- * Inputs:
- * plist - entire parameter list
- * arg_offset - argument number for first parameter
- * Side effects:
- * The "lname" attribute in each parameter in plist will be contain a parameter name
- * ----------------------------------------------------------------------------- */
- void addMissingParameterNames(ParmList *plist, int arg_offset) {
- Parm *p = plist;
- int i = arg_offset;
- while (p) {
- if (!Getattr(p, "lname")) {
- String *pname = Swig_cparm_name(p, i);
- Delete(pname);
- }
- i++;
- p = nextSibling(p);
- }
- }
- /* ------------------------------------------------------------
- * make_autodocParmList()
- * Generate the documentation for the function parameters
- * ------------------------------------------------------------ */
- String *make_autodocParmList(Node *n, bool showTypes) {
- String *doc = NewString("");
- String *pdocs = 0;
- ParmList *plist = CopyParmList(Getattr(n, "parms"));
- Parm *p;
- Parm *pnext;
- int lines = 0;
- int start_arg_num = is_wrapping_class() ? 1 : 0;
- const int maxwidth = 80;
- addMissingParameterNames(plist, start_arg_num); // for $1_name substitutions done in Swig_typemap_attach_parms
- Swig_typemap_attach_parms("in", plist, 0);
- Swig_typemap_attach_parms("doc", plist, 0);
- if (Strcmp(ParmList_protostr(plist), "void") == 0) {
- //No parameters actually
- return doc;
- }
- for (p = plist; p; p = pnext) {
- String *tm = Getattr(p, "tmap:in");
- if (tm) {
- pnext = Getattr(p, "tmap:in:next");
- if (checkAttribute(p, "tmap:in:numinputs", "0")) {
- continue;
- }
- } else {
- pnext = nextSibling(p);
- }
- String *name = 0;
- String *type = 0;
- String *value = 0;
- String *pdoc = Getattr(p, "tmap:doc");
- if (pdoc) {
- name = Getattr(p, "tmap:doc:name");
- type = Getattr(p, "tmap:doc:type");
- value = Getattr(p, "tmap:doc:value");
- }
- // Note: the generated name should be consistent with that in kwnames[]
- name = name ? name : Getattr(p, "name");
- name = name ? name : Getattr(p, "lname");
- name = Swig_name_make(p, 0, name, 0, 0); // rename parameter if a keyword
- type = type ? type : Getattr(p, "type");
- value = value ? value : Getattr(p, "value");
- if (SwigType_isvarargs(type))
- break;
- // Skip the 'self' parameter which in ruby is implicit
- if ( Cmp(name, "self") == 0 )
- continue;
- // Make __p parameters just p (as used in STL)
- Replace( name, "__", "", DOH_REPLACE_FIRST );
- if (Len(doc)) {
- // add a comma to the previous one if any
- Append(doc, ", ");
- // Do we need to wrap a long line?
- if ((Len(doc) - lines * maxwidth) > maxwidth) {
- Printf(doc, "\n%s", tab4);
- lines += 1;
- }
- }
- // Do the param type too?
- Node *nn = classLookup(Getattr(p, "type"));
- String *type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
- if (showTypes)
- Printf(doc, "%s ", type_str);
- Append(doc, name);
- if (pdoc) {
- if (!pdocs)
- pdocs = NewString("Parameters:\n");
- Printf(pdocs, " %s.\n", pdoc);
- }
- if (value) {
- String *new_value = convertValue(value, Getattr(p, "type"));
- if (new_value) {
- value = new_value;
- } else {
- Node *lookup = Swig_symbol_clookup(value, 0);
- if (lookup)
- value = Getattr(lookup, "sym:name");
- }
- Printf(doc, "=%s", value);
- }
- Delete(type_str);
- Delete(name);
- }
- if (pdocs)
- Setattr(n, "feature:pdocs", pdocs);
- Delete(plist);
- return doc;
- }
- /* ------------------------------------------------------------
- * make_autodoc()
- * Build a docstring for the node, using parameter and other
- * info in the parse tree. If the value of the autodoc
- * attribute is "0" then do not include parameter types, if
- * it is "1" (the default) then do. If it has some other
- * value then assume it is supplied by the extension writer
- * and use it directly.
- * ------------------------------------------------------------ */
- String *make_autodoc(Node *n, autodoc_t ad_type) {
- int extended = 0;
- // If the function is overloaded then this funciton is called
- // for the last one. Rewind to the first so the docstrings are
- // in order.
- while (Getattr(n, "sym:previousSibling"))
- n = Getattr(n, "sym:previousSibling");
- Node *pn = Swig_methodclass(n);
- String* super_names = NewString("");
- String* class_name = Getattr(pn, "sym:name") ;
- if ( !class_name ) {
- class_name = NewString("");
- } else {
- class_name = Copy(class_name);
- List *baselist = Getattr(pn, "bases");
- if (baselist && Len(baselist)) {
- Iterator base = First(baselist);
- while (base.item && GetFlag(base.item, "feature:ignore")) {
- base = Next(base);
- }
- int count = 0;
- for ( ;base.item; ++count) {
- if ( count ) Append(super_names, ", ");
- String *basename = Getattr(base.item, "sym:name");
- String* basenamestr = NewString(basename);
- Node* parent = parentNode(base.item);
- while (parent)
- {
- String *parent_name = Copy( Getattr(parent, "sym:name") );
- if ( !parent_name ) {
- Node* mod = Getattr(parent, "module");
- if ( mod )
- parent_name = Copy( Getattr(mod, "name") );
- if ( parent_name )
- (Char(parent_name))[0] = (char)toupper((Char(parent_name))[0]);
- }
- if ( parent_name ) {
- Insert(basenamestr, 0, "::");
- Insert(basenamestr, 0, parent_name);
- Delete(parent_name);
- }
- parent = parentNode(parent);
- }
- Append(super_names, basenamestr );
- Delete(basenamestr);
- base = Next(base);
- }
- }
- }
- String* full_name;
- if ( module ) {
- full_name = NewString(module);
- if (class_name && Len(class_name) > 0)
- Append(full_name, "::");
- }
- else
- full_name = NewString("");
- Append(full_name, class_name);
- String* symname = Getattr(n, "sym:name");
- if ( Getattr( special_methods, symname ) )
- symname = Getattr( special_methods, symname );
- String* methodName = NewString(full_name);
- Append(methodName, symname);
- // Each overloaded function will try to get documented,
- // so we keep the name of the last overloaded function and its type.
- // Documenting just from functionWrapper() is not possible as
- // sym:name has already been changed to include the class name
- if ( last_mode == ad_type && Cmp(methodName, last_autodoc) == 0 ) {
- Delete(full_name);
- Delete(class_name);
- Delete(super_names);
- Delete(methodName);
- return NewString("");
- }
- last_mode = ad_type;
- last_autodoc = Copy(methodName);
- String *doc = NewString("/*\n");
- int counter = 0;
- bool skipAuto = false;
- Node* on = n;
- for ( ; n; ++counter ) {
- String *type_str = NULL;
- skipAuto = false;
- bool showTypes = false;
- String *autodoc = Getattr(n, "feature:autodoc");
- autodoc_l dlevel = autodoc_level(autodoc);
- switch (dlevel) {
- case NO_AUTODOC:
- break;
- case NAMES_AUTODOC:
- showTypes = false;
- break;
- case TYPES_AUTODOC:
- showTypes = true;
- break;
- case EXTEND_AUTODOC:
- extended = 1;
- showTypes = false;
- break;
- case EXTEND_TYPES_AUTODOC:
- extended = 1;
- showTypes = true;
- break;
- case STRING_AUTODOC:
- skipAuto = true;
- break;
- }
- SwigType *type = Getattr(n, "type");
- if (type) {
- if (Strcmp(type, "void") == 0) {
- type_str = NULL;
- } else {
- SwigType *qt = SwigType_typedef_resolve_all(type);
- if (SwigType_isenum(qt)) {
- type_str = NewString("int");
- } else {
- Node *nn = classLookup(type);
- type_str = nn ? Copy(Getattr(nn, "sym:name")) : SwigType_str(type, 0);
- }
- }
- }
- if (counter == 0) {
- switch (ad_type) {
- case AUTODOC_CLASS:
- Printf(doc, " Document-class: %s", full_name);
- if ( Len(super_names) > 0 )
- Printf( doc, " < %s", super_names);
- Append(doc, "\n\n");
- break;
- case AUTODOC_CTOR:
- Printf(doc, " Document-method: %s.new\n\n", full_name);
- break;
- case AUTODOC_DTOR:
- break;
- case AUTODOC_STATICFUNC:
- Printf(doc, " Document-method: %s.%s\n\n", full_name, symname);
- break;
- case AUTODOC_FUNC:
- case AUTODOC_METHOD:
- case AUTODOC_GETTER:
- Printf(doc, " Document-method: %s.%s\n\n", full_name, symname);
- break;
- case AUTODOC_SETTER:
- Printf(doc, " Document-method: %s.%s=\n\n", full_name, symname);
- break;
- }
- }
- if (skipAuto) {
- if ( counter == 0 ) Printf(doc, " call-seq:\n");
- switch( ad_type )
- {
- case AUTODOC_STATICFUNC:
- case AUTODOC_FUNC:
- case AUTODOC_METHOD:
- case AUTODOC_GETTER:
- {
- String *paramList = make_autodocParmList(n, showTypes);
- if (Len(paramList))
- Printf(doc, " %s(%s)", symname, paramList);
- else
- Printf(doc, " %s", symname);
- if (type_str)
- Printf(doc, " -> %s", type_str);
- break;
- }
- case AUTODOC_SETTER:
- {
- Printf(doc, " %s=(x)", symname);
- if (type_str)
- Printf(doc, " -> %s", type_str);
- break;
- }
- default:
- break;
- }
- } else {
- switch (ad_type) {
- case AUTODOC_CLASS:
- {
- // Only do the autodoc if there isn't a docstring for the class
- String *str = Getattr(n, "feature:docstring");
- if (counter == 0 && (str == 0 || Len(str) == 0)) {
- if (CPlusPlus) {
- Printf(doc, " Proxy of C++ %s class", full_name);
- } else {
- Printf(doc, " Proxy of C %s struct", full_name);
- }
- }
- }
- break;
- case AUTODOC_CTOR:
- if (counter == 0)
- Printf(doc, " call-seq:\n");
- if (Strcmp(class_name, symname) == 0) {
- String *paramList = make_autodocParmList(n, showTypes);
- if (Len(paramList))
- Printf(doc, " %s.new(%s)", class_name, paramList);
- else
- Printf(doc, " %s.new", class_name);
- } else {
- Printf(doc, " %s.new(%s)", class_name, make_autodocParmList(n, showTypes));
- }
- break;
- case AUTODOC_DTOR:
- break;
- case AUTODOC_STATICFUNC:
- case AUTODOC_FUNC:
- case AUTODOC_METHOD:
- case AUTODOC_GETTER:
- {
- if (counter == 0)
- Printf(doc, " call-seq:\n");
- String *paramList = make_autodocParmList(n, showTypes);
- if (Len(paramList))
- Printf(doc, " %s(%s)", symname, paramList);
- else
- Printf(doc, " %s", symname);
- if (type_str)
- Printf(doc, " -> %s", type_str);
- break;
- }
- case AUTODOC_SETTER:
- {
- Printf(doc, " call-seq:\n");
- Printf(doc, " %s=(x)", symname);
- if (type_str)
- Printf(doc, " -> %s", type_str);
- break;
- }
- }
- }
- // if it's overloaded then get the next decl and loop around again
- n = Getattr(n, "sym:nextSibling");
- if (n)
- Append(doc, "\n");
- Delete(type_str);
- }
- Printf(doc, "\n\n");
- if (!skipAuto) {
- switch (ad_type) {
- case AUTODOC_CLASS:
- case AUTODOC_DTOR:
- break;
- case AUTODOC_CTOR:
- Printf(doc, "Class constructor.\n");
- break;
- case AUTODOC_STATICFUNC:
- Printf(doc, "A class method.\n");
- break;
- case AUTODOC_FUNC:
- Printf(doc, "A module function.\n");
- break;
- case AUTODOC_METHOD:
- Printf(doc, "An instance method.\n");
- break;
- case AUTODOC_GETTER:
- Printf(doc, "Get value of attribute.\n");
- break;
- case AUTODOC_SETTER:
- Printf(doc, "Set new value for attribute.\n");
- break;
- }
- }
- n = on;
- while ( n ) {
- String *autodoc = Getattr(n, "feature:autodoc");
- autodoc_l dlevel = autodoc_level(autodoc);
- symname = Getattr(n, "sym:name");
- if ( Getattr( special_methods, symname ) )
- symname = Getattr( special_methods, symname );
- switch (dlevel) {
- case NO_AUTODOC:
- case NAMES_AUTODOC:
- case TYPES_AUTODOC:
- extended = 0;
- break;
- case STRING_AUTODOC:
- extended = 2;
- Replaceall( autodoc, "$class", class_name );
- Printv(doc, autodoc, ".", NIL);
- break;
- case EXTEND_AUTODOC:
- case EXTEND_TYPES_AUTODOC:
- extended = 1;
- break;
- }
- if (extended) {
- String *pdocs = Getattr(n, "feature:pdocs");
- if (pdocs) {
- Printv(doc, "\n\n", pdocs, NULL);
- break;
- }
- if ( extended == 2 ) break;
- }
- n = Getattr(n, "sym:nextSibling");
- }
- Append(doc, "\n*/\n");
- Delete(full_name);
- Delete(class_name);
- Delete(super_names);
- Delete(methodName);
- return doc;
- }
- /* ------------------------------------------------------------
- * convertValue()
- * Check if string v can be a Ruby value literal,
- * (eg. number or string), or translate it to a Ruby literal.
- * ------------------------------------------------------------ */
- String *convertValue(String *v, SwigType *t) {
- if (v && Len(v) > 0) {
- char fc = (Char(v))[0];
- if (('0' <= fc && fc <= '9') || '\'' == fc || '"' == fc) {
- /* number or string (or maybe NULL pointer) */
- if (SwigType_ispointer(t) && Strcmp(v, "0") == 0)
- return NewString("None");
- else
- return v;
- }
- if (Strcmp(v, "NULL") == 0)
- return SwigType_ispointer(t) ? NewString("nil") : NewString("0");
- else if (Strcmp(v, "true") == 0 || Strcmp(v, "TRUE") == 0)
- return NewString("true");
- else if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0)
- return NewString("false");
- if (Strcmp(v, "true") == 0 || Strcmp(v, "FALSE") == 0)
- return NewString("True");
- if (Strcmp(v, "false") == 0 || Strcmp(v, "FALSE") == 0)
- return NewString("False");
- }
- return 0;
- }
- public:
- /* ---------------------------------------------------------------------
- * RUBY()
- *
- * Initialize member data
- * --------------------------------------------------------------------- */
- RUBY() {
- module = 0;
- modvar = 0;
- feature = 0;
- prefix = 0;
- last_autodoc = NewString("");
- current = NO_CPP;
- classes = 0;
- klass = 0;
- special_methods = 0;
- f_begin = 0;
- f_runtime = 0;
- f_header = 0;
- f_wrappers = 0;
- f_init = 0;
- f_initbeforefunc = 0;
- useGlobalModule = false;
- multipleInheritance = false;
- director_prot_ctor_code = NewString("");
- Printv(director_prot_ctor_code,
- "if ( $comparison ) { /* subclassed */\n",
- " $director_new \n",
- "} else {\n", " rb_raise(rb_eRuntimeError,\"accessing abstract class or protected constructor\"); \n", " return Qnil;\n", "}\n", NIL);
- director_multiple_inheritance = 0;
- director_language = 1;
- }
- /* ---------------------------------------------------------------------
- * main()
- *
- * Parse command line options and initializes variables.
- * --------------------------------------------------------------------- */
-
- virtual void main(int argc, char *argv[]) {
- int cppcast = 1;
- int autorename = 0;
- /* Set location of SWIG library */
- SWIG_library_directory("ruby");
- /* Look for certain command line options */
- for (int i = 1; i < argc; i++) {
- if (argv[i]) {
- if (strcmp(argv[i], "-initname") == 0) {
- if (argv[i + 1]) {
- char *name = argv[i + 1];
- feature = NewString(name);
- Swig_mark_arg(i);
- Swig_mark_arg(i + 1);
- i++;
- } else {
- Swig_arg_error();
- }
- }
- else if (strcmp(argv[i], "-feature") == 0) {
- fprintf( stderr, "Warning: Ruby -feature option is deprecated, "
- "please use -initname instead.\n");
- if (argv[i + 1]) {
- char *name = argv[i + 1];
- feature = NewString(name);
- Swig_mark_arg(i);
- Swig_mark_arg(i + 1);
- i++;
- } else {
- Swig_arg_error();
- }
- } else if (strcmp(argv[i], "-globalmodule") == 0) {
- useGlobalModule = true;
- Swig_mark_arg(i);
- } else if (strcmp(argv[i], "-minherit") == 0) {
- multipleInheritance = true;
- director_multiple_inheritance = 1;
- Swig_mark_arg(i);
- } else if (strcmp(argv[i], "-cppcast") == 0) {
- cppcast = 1;
- Swig_mark_arg(i);
- } else if (strcmp(argv[i], "-nocppcast") == 0) {
- cppcast = 0;
- Swig_mark_arg(i);
- } else if (strcmp(argv[i], "-autorename") == 0) {
- autorename = 1;
- Swig_mark_arg(i);
- } else if (strcmp(argv[i], "-noautorename") == 0) {
- autorename = 0;
- Swig_mark_arg(i);
- } else if (strcmp(argv[i], "-prefix") == 0) {
- if (argv[i + 1]) {
- char *name = argv[i + 1];
- prefix = NewString(name);
- Swig_mark_arg(i);
- Swig_mark_arg(i + 1);
- i++;
- } else {
- Swig_arg_error();
- }
- } else if (strcmp(argv[i], "-help") == 0) {
- Printf(stdout, "%s\n", usage);
- }
- }
- }
- if (cppcast) {
- /* Turn on cppcast mode */
- Preprocessor_define((DOH *) "SWIG_CPLUSPLUS_CAST", 0);
- }
- if (autorename) {
- /* Turn on the autorename mode */
- Preprocessor_define((DOH *) "SWIG_RUBY_AUTORENAME", 0);
- }
- /* Add a symbol to the parser for conditional compilation */
- Preprocessor_define("SWIGRUBY 1", 0);
- /* Add typemap definitions */
- SWIG_typemap_lang("ruby");
- SWIG_config_file("ruby.swg");
- allow_overloading();
- }
- /**
- * Generate initialization code to define the Ruby module(s),
- * accounting for nested modules as necessary.
- */
- void defineRubyModule() {
- List *modules = Split(module, ':', INT_MAX);
- if (modules != 0 && Len(modules) > 0) {
- String *mv = 0;
- Iterator m;
- m = First(modules);
- while (m.item) {
- if (Len(m.item) > 0) {
- if (mv != 0) {
- Printv(f_init, tab4, modvar, " = rb_define_module_under(", modvar, ", \"", m.item, "\");\n", NIL);
- } else {
- Printv(f_init, tab4, modvar, " = rb_define_module(\"", m.item, "\");\n", NIL);
- mv = NewString(modvar);
- }
- }
- m = Next(m);
- }
- Delete(mv);
- Delete(modules);
- }
- }
- void registerMagicMethods() {
- special_methods = NewHash();
- /* Python->Ruby style special method name. */
- /* Basic */
- Setattr(special_methods, "__repr__", "inspect");
- Setattr(special_methods, "__str__", "to_s");
- Setattr(special_methods, "__cmp__", "<=>");
- Setattr(special_methods, "__hash__", "hash");
- Setattr(special_methods, "__nonzero__", "nonzero?");
- /* Callable */
- Setattr(special_methods, "__call__", "call");
- /* Collection */
- Setattr(special_methods, "__len__", "length");
- Setattr(special_methods, "__getitem__", "[]");
- Setattr(special_methods, "__setitem__", "[]=");
- /* Operators */
- Setattr(special_methods, "__add__", "+");
- Setattr(special_methods, "__pos__", "+@");
- Setattr(special_methods, "__sub__", "-");
- Setattr(special_methods, "__neg__", "-@");
- Setattr(special_methods, "__mul__", "*");
- Setattr(special_methods, "__div__", "/");
- Setattr(special_methods, "__mod__", "%");
- Setattr(special_methods, "__lshift__", "<<");
- Setattr(special_methods, "__rshift__", ">>");
- Setattr(special_methods, "__and__", "&");
- Setattr(special_methods, "__or__", "|");
- Setattr(special_methods, "__xor__", "^");
- Setattr(special_methods, "__invert__", "~");
- Setattr(special_methods, "__lt__", "<");
- Setattr(special_methods, "__le__", "<=");
- Setattr(special_methods, "__gt__", ">");
- Setattr(special_methods, "__ge__", ">=");
- Setattr(special_methods, "__eq__", "==");
- /* Other numeric */
- Setattr(special_methods, "__divmod__", "divmod");
- Setattr(special_methods, "__pow__", "**");
- Setattr(special_methods, "__abs__", "abs");
- Setattr(special_methods, "__int__", "to_i");
- Setattr(special_methods, "__float__", "to_f");
- Setattr(special_methods, "__coerce__", "coerce");
- }
- /* ---------------------------------------------------------------------
- * top()
- * --------------------------------------------------------------------- */
- virtual int top(Node *n) {
- /**
- * See if any Ruby module options have been specified as options
- * to the %module directive.
- */
- Node *swigModule = Getattr(n, "module");
- if (swigModule) {
- Node *options = Getattr(swigModule, "options");
- if (options) {
- if (Getattr(options, "directors")) {
- allow_directors();
- }
- if (Getattr(options, "dirprot")) {
- allow_dirprot();
- }
- if (Getattr(options, "ruby_globalmodule")) {
- useGlobalModule = true;
- }
- if (Getattr(options, "ruby_minherit")) {
- multipleInheritance = true;
- director_multiple_inheritance = 1;
- }
- }
- }
- /* Set comparison with none for ConstructorToFunction */
- setSubclassInstanceCheck(NewStringf("strcmp(rb_obj_classname(self), classname) != 0"));
- // setSubclassInstanceCheck(NewString("CLASS_OF(self) != cFoo.klass"));
- /* Initialize all of the output files */
- String *outfile = Getattr(n, "outfile");
- String *outfile_h = Getattr(n, "outfile_h");
- if (!outfile) {
- Printf(stderr, "Unable to determine outfile\n");
- SWIG_exit(EXIT_FAILURE);
- }
- 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("");
- f_directors_h = NewString("");
- f_directors = NewString("");
- f_directors_helpers = NewString("");
- f_initbeforefunc = NewString("");
- if (directorsEnabled()) {
- if (!outfile_h) {
- Printf(stderr, "Unable to determine outfile_h\n");
- SWIG_exit(EXIT_FAILURE);
- }
- f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
- if (!f_runtime_h) {
- FileErrorDisplay(outfile_h);
- SWIG_exit(EXIT_FAILURE);
- }
- }
- /* 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("director", f_directors);
- Swig_register_filebyname("director_h", f_directors_h);
- Swig_register_filebyname("director_helpers", f_directors_helpers);
- Swig_register_filebyname("initbeforefunc", f_initbeforefunc);
- modvar = 0;
- current = NO_CPP;
- klass = 0;
- classes = NewHash();
- registerMagicMethods();
- Swig_banner(f_begin);
- Printf(f_runtime, "\n");
- Printf(f_runtime, "#define SWIGRUBY\n");
- if (directorsEnabled()) {
- Printf(f_runtime, "#define SWIG_DIRECTORS\n");
- }
- Printf(f_runtime, "\n");
- /* typedef void *VALUE */
- SwigType *value = NewSwigType(T_VOID);
- SwigType_add_pointer(value);
- SwigType_typedef(value, (char *) "VALUE");
- Delete(value);
- /* Set module name */
- set_module(Char(Getattr(n, "name")));
- if (directorsEnabled()) {
- /* Build a version of the module name for use in a C macro name. */
- String *module_macro = Copy(module);
- Replaceall(module_macro, "::", "__");
- Swig_banner(f_directors_h);
- Printf(f_directors_h, "\n");
- Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", module_macro);
- Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", module_macro);
- Printf(f_directors_h, "namespace Swig {\n");
- Printf(f_directors_h, " class Director;\n");
- Printf(f_directors_h, "}\n\n");
- Printf(f_directors_helpers, "/* ---------------------------------------------------\n");
- Printf(f_directors_helpers, " * C++ director class helpers\n");
- Printf(f_directors_helpers, " * --------------------------------------------------- */\n\n");
- Printf(f_directors, "\n\n");
- Printf(f_directors, "/* ---------------------------------------------------\n");
- Printf(f_directors, " * C++ director class methods\n");
- Printf(f_directors, " * --------------------------------------------------- */\n\n");
- if (outfile_h)
- Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
- Delete(module_macro);
- }
- Printf(f_header, "#define SWIG_init Init_%s\n", feature);
- Printf(f_header, "#define SWIG_name \"%s\"\n\n", module);
- Printf(f_header, "static VALUE %s;\n", modvar);
- /* Start generating the initialization function */
- String* docs = docstring(n, AUTODOC_CLASS);
- Printf(f_init, "/*\n%s\n*/", docs );
- Printv(f_init, "\n", "#ifdef __cplusplus\n", "extern \"C\"\n", "#endif\n", "SWIGEXPORT void Init_", feature, "(void) {\n", "size_t i;\n", "\n", NIL);
- Printv(f_init, tab4, "SWIG_InitRuntime();\n", NIL);
- if (!useGlobalModule)
- defineRubyModule();
- Printv(f_init, "\n", "SWIG_InitializeModule(0);\n", "for (i = 0; i < swig_module.size; i++) {\n", "SWIG_define_class(swig_module.types[i]);\n", "}\n", NIL);
- Printf(f_init, "\n");
- /* Initialize code to keep track of objects */
- Printf(f_init, "SWIG_RubyInitializeTrackings();\n");
- Language::top(n);
- if (directorsEnabled()) {
- // Insert director runtime into the f_runtime file (make it occur before %header section)
- Swig_insert_file("director.swg", f_runtime);
- }
- /* Finish off our init function */
- Printf(f_init, "}\n");
- SwigType_emit_type_table(f_runtime, f_wrappers);
- /* Close all of the files */
- Dump(f_runtime, f_begin);
- Dump(f_header, f_begin);
- if (directorsEnabled()) {
- Dump(f_directors_helpers, f_begin);
- Dump(f_directors, f_begin);
- Dump(f_directors_h, f_runtime_h);
- Printf(f_runtime_h, "\n");
- Printf(f_runtime_h, "#endif\n");
- Close(f_runtime_h);
- }
- Dump(f_wrappers, f_begin);
- Dump(f_initbeforefunc, f_begin);
- Wrapper_pretty_print(f_init, f_begin);
- Delete(f_header);
- Delete(f_wrappers);
- Delete(f_init);
- Delete(f_initbeforefunc);
- Close(f_begin);
- Delete(f_runtime);
- Delete(f_begin);
- return SWIG_OK;
- }
- /* -----------------------------------------------------------------------------
- * importDirective()
- * ----------------------------------------------------------------------------- */
- virtual int importDirective(Node *n) {
- String *modname = Getattr(n, "module");
- if (modname) {
- if (prefix) {
- Insert(modname, 0, prefix);
- }
- List *modules = Split(modname, ':', INT_MAX);
- if (modules && Len(modules) > 0) {
- modname = NewString("");
- String *last = NULL;
- Iterator m = First(modules);
- while (m.item) {
- if (Len(m.item) > 0) {
- if (last) {
- Append(modname, "/");
- }
- Append(modname, m.item);
- last = m.item;
- }
- m = Next(m);
- }
- Printf(f_init, "rb_require(\"%s\");\n", modname);
- Delete(modname);
- }
- Delete(modules);
- }
- return Language::importDirective(n);
- }
- /* ---------------------------------------------------------------------
- * set_module(const char *mod_name)
- *
- * Sets the module name. Does nothing if it's already set (so it can
- * be overridden as a command line option).
- *---------------------------------------------------------------------- */
- void set_module(const char *s) {
- String *mod_name = NewString(s);
- if (module == 0) {
- /* Start with the empty string */
- module = NewString("");
- if (prefix) {
- Insert(mod_name, 0, prefix);
- }
- /* Account for nested modules */
- List *modules = Split(mod_name, ':', INT_MAX);
- if (modules != 0 && Len(modules) > 0) {
- String *last = 0;
- Iterator m = First(modules);
- while (m.item) {
- if (Len(m.item) > 0) {
- String *cap = NewString(m.item);
- (Char(cap))[0] = (char)toupper((Char(cap))[0]);
- if (last != 0) {
- Append(module, "::");
- }
- Append(module, cap);
- last = m.item;
- }
- m = Next(m);
- }
- if (feature == 0) {
- feature = Copy(last);
- }
- (Char(last))[0] = (char)toupper((Char(last))[0]);
- modvar = NewStringf("m%s", last);
- Delete(modules);
- }
- }
- Delete(mod_name);
- }
- /* --------------------------------------------------------------------------
- * nativeWrapper()
- * -------------------------------------------------------------------------- */
- virtual int nativeWrapper(Node *n) {
- String *funcname = Getattr(n, "wrap:name");
- Swig_warning(WARN_LANG_NATIVE_UNIMPL, input_file, line_number, "Adding native function %s not supported (ignored).\n", funcname);
- return SWIG_NOWRAP;
- }
- /**
- * Process the comma-separated list of aliases (if any).
- */
- void defineAliases(Node *n, const_String_or_char_ptr iname) {
- String *aliasv = Getattr(n, "feature:alias");
- if (aliasv) {
- List *aliases = Split(aliasv, ',', INT_MAX);
- if (aliases && Len(aliases) > 0) {
- Iterator alias = First(aliases);
- while (alias.item) {
- if (Len(alias.item) > 0) {
- if (multipleInheritance) {
- Printv(klass->init, tab4, "rb_define_alias(", klass->mImpl, ", \"", alias.item, "\", \"", iname, "\");\n", NIL);
- } else {
- Printv(klass->init, tab4, "rb_define_alias(", klass->vname, ", \"", alias.item, "\", \"", iname, "\");\n", NIL);
- }
- }
- alias = Next(alias);
- }
- }
- Delete(aliases);
- }
- }
- /* ---------------------------------------------------------------------
- * create_command(Node *n, char *iname)
- *
- * Creates a new command from a C function.
- * iname = Name of function in scripting language
- *
- * A note about what "protected" and "private" mean in Ruby:
- *
- * A private method is accessible only within the class or its subclasses,
- * and it is callable only in "function form", with 'self' (implicit or
- * explicit) as a receiver.
- *
- * A protected method is callable only from within its class, but unlike
- * a private method, it can be called with a receiver other than self, such
- * as another instance of the same class.
- * --------------------------------------------------------------------- */
- void create_command(Node *n, const_String_or_char_ptr iname) {
- String *alloc_func = Swig_name_wrapper(iname);
- String *wname = Swig_name_wrapper(iname);
- if (CPlusPlus) {
- Insert(wname, 0, "VALUEFUNC(");
- Append(wname, ")");
- }
- if (current != NO_CPP)
- iname = klass->strip(iname);
- if (Getattr(special_methods, iname)) {
- iname = GetChar(special_methods, iname);
- }
- String *s = NewString("");
- String *temp = NewString("");
- #ifdef SWIG_PROTECTED_TARGET_METHODS
- const char *rb_define_method = is_public(n) ? "rb_define_method" : "rb_define_protected_method";
- #else
- const char *rb_define_method = "rb_define_method";
- #endif
- switch (current) {
- case MEMBER_FUNC:
- {
- if (multipleInheritance) {
- Printv(klass->init, tab4, rb_define_method, "(", klass->mImpl, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
- } else {
- Printv(klass->init, tab4, rb_define_method, "(", klass->vname, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
- }
- }
- break;
- case CONSTRUCTOR_ALLOCATE:
- Printv(s, tab4, "rb_define_alloc_func(", klass->vname, ", ", alloc_func, ");\n", NIL);
- Replaceall(klass->init, "$allocator", s);
- break;
- case CONSTRUCTOR_INITIALIZE:
- Printv(s, tab4, rb_define_method, "(", klass->vname, ", \"initialize\", ", wname, ", -1);\n", NIL);
- Replaceall(klass->init, "$initializer", s);
- break;
- case MEMBER_VAR:
- Append(temp, iname);
- /* Check for _set or _get at the end of the name. */
- if (Len(temp) > 4) {
- const char *p = Char(temp) + (Len(temp) - 4);
- if (strcmp(p, "_set") == 0) {
- Delslice(temp, Len(temp) - 4, DOH_END);
- Append(temp, "=");
- } else if (strcmp(p, "_get") == 0) {
- Delslice(temp, Len(temp) - 4, DOH_END);
- }
- }
- if (multipleInheritance) {
- Printv(klass->init, tab4, "rb_define_method(", klass->mImpl, ", \"", temp, "\", ", wname, ", -1);\n", NIL);
- } else {
- Printv(klass->init, tab4, "rb_define_method(", klass->vname, ", \"", temp, "\", ", wname, ", -1);\n", NIL);
- }
- break;
- case STATIC_FUNC:
- Printv(klass->init, tab4, "rb_define_singleton_method(", klass->vname, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
- break;
- case NO_CPP:
- if (!useGlobalModule) {
- Printv(s, tab4, "rb_define_module_function(", modvar, ", \"", iname, "\", ", wname, ", -1);\n", NIL);
- Printv(f_init, s, NIL);
- } else {
- Printv(s, tab4, "rb_define_global_function(\"", iname, "\", ", wname, ", -1);\n", NIL);
- Printv(f_init, s, NIL);
- }
- break;
- case DESTRUCTOR:
- case CLASS_CONST:
- case STATIC_VAR:
- assert(false); // Should not have gotten here for these types
- default:
- assert(false);
- }
- defineAliases(n, iname);
- Delete(temp);
- Delete(s);
- Delete(wname);
- Delete(alloc_func);
- }
- /* ---------------------------------------------------------------------
- * applyInputTypemap()
- *
- * Look up the appropriate "in" typemap for this parameter (p),
- * substitute the correct strings for the $target and $input typemap
- * parameters, and dump the resulting code to the wrapper file.
- * --------------------------------------------------------------------- */
- Parm *applyInputTypemap(Parm *p, String *ln, String *source, Wrapper *f, String *symname) {
- String *tm;
- SwigType *pt = Getattr(p, "type");
- if ((tm = Getattr(p, "tmap:in"))) {
- Replaceall(tm, "$target", ln);
- Replaceall(tm, "$source", source);
- Replaceall(tm, "$input", source);
- Replaceall(tm, "$symname", symname);
- if (Getattr(p, "wrap:disown") || (Getattr(p, "tmap:in:disown"))) {
- Replaceall(tm, "$disown", "SWIG_POINTER_DISOWN");
- } else {
- Replaceall(tm, "$disown", "0");
- }
- Setattr(p, "emit:input", Copy(source));
- Printf(f->code, "%s\n", tm);
- p = Getattr(p, "tmap:in:next");
- } else {
- Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
- p = nextSibling(p);
- }
- return p;
- }
- Parm *skipIgnoredArgs(Parm *p) {
- while (checkAttribute(p, "tmap:in:numinputs", "0")) {
- p = Getattr(p, "tmap:in:next");
- }
- return p;
- }
- /* ---------------------------------------------------------------------
- * marshalInputArgs()
- *
- * Process all of the arguments passed into the scripting language
- * method and convert them into C/C++ function arguments using the
- * supplied typemaps.
- * --------------------------------------------------------------------- */
- void marshalInputArgs(Node *n, ParmList *l, int numarg, int numreq, String *kwargs, bool allow_kwargs, Wrapper *f) {
- int i;
- Parm *p;
- String *tm;
- String *source;
- String *target;
- source = NewString("");
- target = NewString("");
- bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n));
- /**
- * The 'start' value indicates which of the C/C++ function arguments
- * produced here corresponds to the first value in Ruby's argv[] array.
- * The value of start is either zero or one. If start is zero, then
- * the first argument (with name arg1) is based on the value of argv[0].
- * If start is one, then arg1 is based on the value of argv[1].
- */
- int start = (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) ? 1 : 0;
- int varargs = emit_isvarargs(l);
- Printf(kwargs, "{ ");
- for (i = 0, p = l; i < numarg; i++) {
- p = skipIgnoredArgs(p);
- String *pn = Getattr(p, "name");
- String *ln = Getattr(p, "lname");
- /* Produce string representation of source argument */
- Clear(source);
- /* First argument is a special case */
- if (i == 0) {
- Printv(source, (start == 0) ? "argv[0]" : "self", NIL);
- } else {
- Printf(source, "argv[%d]", i - start);
- }
- /* Produce string representation of target argument */
- Clear(target);
- Printf(target, "%s", Char(ln));
- if (i >= (numreq)) { /* Check if parsing an optional argument */
- Printf(f->code, " if (argc > %d) {\n", i - start);
- }
- /* Record argument name for keyword argument handling */
- if (Len(pn)) {
- Printf(kwargs, "\"%s\",", pn);
- } else {
- Printf(kwargs, "\"arg%d\",", i + 1);
- }
- /* Look for an input typemap */
- p = applyInputTypemap(p, ln, source, f, Getattr(n, "name"));
- if (i >= numreq) {
- Printf(f->code, "}\n");
- }
- }
- /* Finish argument marshalling */
- Printf(kwargs, " NULL }");
- if (allow_kwargs) {
- Printv(f->locals, tab4, "const char *kwnames[] = ", kwargs, ";\n", NIL);
- }
- /* Trailing varargs */
- if (varargs) {
- if (p && (tm = Getattr(p, "tmap:in"))) {
- Clear(source);
- Printf(source, "argv[%d]", i - start);
- Replaceall(tm, "$input", source);
- Setattr(p, "emit:input", Copy(source));
- Printf(f->code, "if (argc > %d) {\n", i - start);
- Printv(f->code, tm, "\n", NIL);
- Printf(f->code, "}\n");
- }
- }
- Delete(source);
- Delete(target);
- }
- /* ---------------------------------------------------------------------
- * insertConstraintCheckingCode(ParmList *l, Wrapper *f)
- *
- * Checks each of the parameters in the parameter list for a "check"
- * typemap and (if it finds one) inserts the typemapping code into
- * the function wrapper.
- * --------------------------------------------------------------------- */
- void insertConstraintCheckingCode(ParmList *l, Wrapper *f) {
- Parm *p;
- String *tm;
- for (p = l; p;) {
- if ((tm = Getattr(p, "tmap:check"))) {
- Replaceall(tm, "$target", Getattr(p, "lname"));
- Printv(f->code, tm, "\n", NIL);
- p = Getattr(p, "tmap:check:next");
- } else {
- p = nextSibling(p);
- }
- }
- }
- /* ---------------------------------------------------------------------
- * insertCleanupCode(ParmList *l, String *cleanup)
- *
- * Checks each of the parameters in the parameter list for a "freearg"
- * typemap and (if it finds one) inserts the typemapping code into
- * the function wrapper.
- * --------------------------------------------------------------------- */
- void insertCleanupCode(ParmList *l, String *cleanup) {
- String *tm;
- for (Parm *p = l; p;) {
- if ((tm = Getattr(p, "tmap:freearg"))) {
- if (Len(tm) != 0) {
- Replaceall(tm, "$source", Getattr(p, "lname"));
- Printv(cleanup, tm, "\n", NIL);
- }
- p = Getattr(p, "tmap:freearg:next");
- } else {
- p = nextSibling(p);
- }
- }
- }
- /* ---------------------------------------------------------------------
- * insertArgOutputCode(ParmList *l, String *outarg, int& need_result)
- *
- * Checks each of the parameters in the parameter list for a "argout"
- * typemap and (if it finds one) inserts the typemapping code into
- * the function wrapper.
- * --------------------------------------------------------------------- */
- void insertArgOutputCode(ParmList *l, String *outarg, int &need_result) {
- String *tm;
- for (Parm *p = l; p;) {
- if ((tm = Getattr(p, "tmap:argout"))) {
- Replaceall(tm, "$source", Getattr(p, "lname"));
- Replaceall(tm, "$target", "vresult");
- Replaceall(tm, "$result", "vresult");
- Replaceall(tm, "$arg", Getattr(p, "emit:input"));
- Replaceall(tm, "$input", Getattr(p, "emit:input"));
- Printv(outarg, tm, "\n", NIL);
- need_result += 1;
- p = Getattr(p, "tmap:argout:next");
- } else {
- p = nextSibling(p);
- }
- }
- }
- /* ---------------------------------------------------------------------
- * validIdentifier()
- *
- * Is this a valid identifier in the scripting language?
- * Ruby method names can include any combination of letters, numbers
- * and underscores. A Ruby method name may optionally end with
- * a question mark ("?"), exclamation point ("!") or equals sign ("=").
- *
- * Methods whose names end with question marks are, by convention,
- * predicate methods that return true or false (e.g. Array#empty?).
- *
- * Methods whose names end with exclamation points are, by convention,
- * called bang methods that modify the instance in place (e.g. Array#sort!).
- *
- * Methods whose names end with an equals sign are attribute setters
- * (e.g. Thread#critical=).
- * --------------------------------------------------------------------- */
- virtual int validIdentifier(String *s) {
- char *c = Char(s);
- while (*c) {
- if (!(isalnum(*c) || (*c == '_') || (*c == '?') || (*c == '!') || (*c == '=')))
- return 0;
- c++;
- }
- return 1;
- }
- /* ---------------------------------------------------------------------
- * functionWrapper()
- *
- * Create a function declaration and register it with the interpreter.
- * --------------------------------------------------------------------- */
- virtual int functionWrapper(Node *n) {
- String *nodeType;
- bool destructor;
- String *symname = Copy(Getattr(n, "sym:name"));
- SwigType *t = Getattr(n, "type");
- ParmList *l = Getattr(n, "parms");
- int director_method = 0;
- String *tm;
- int need_result = 0;
- /* Ruby needs no destructor wrapper */
- if (current == DESTRUCTOR)
- return SWIG_NOWRAP;
- nodeType = Getattr(n, "nodeType");
- destructor = (!Cmp(nodeType, "destructor"));
- /* If the C++ class constructor is overloaded, we only want to
- * write out the "new" singleton method once since it is always
- * the same. (It's the "initialize" method that will handle the
- * overloading). */
- if (current == CONSTRUCTOR_ALLOCATE && Swig_symbol_isoverloaded(n) && Getattr(n, "sym:nextSibling") != 0)
- return SWIG_OK;
- String *overname = 0;
- if (Getattr(n, "sym:overloaded")) {
- overname = Getattr(n, "sym:overname");
- } else {
- if (!addSymbol(symname, n))
- return SWIG_ERROR;
- }
- String *cleanup = NewString("");
- String *outarg = NewString("");
- String *kwargs = NewString("");
- Wrapper *f = NewWrapper();
- /* Rename predicate methods */
- if (GetFlag(n, "feature:predicate")) {
- Append(symname, "?");
- }
- /* Rename bang methods */
- if (GetFlag(n, "feature:bang")) {
- Append(symname, "!");
- }
- /* Determine the name of the SWIG wrapper function */
- String *wname = Swig_name_wrapper(symname);
- if (overname && current != CONSTRUCTOR_ALLOCATE) {
- Append(wname, overname);
- }
- /* Emit arguments */
- if (current != CONSTRUCTOR_ALLOCATE) {
- emit_parameter_variables(l, f);
- }
- /* Attach standard typemaps */
- if (current != CONSTRUCTOR_ALLOCATE) {
- emit_attach_parmmaps(l, f);
- }
- Setattr(n, "wrap:parms", l);
- /* Get number of arguments */
- int numarg = emit_num_arguments(l);
- int numreq = emit_num_required(l);
- int varargs = emit_isvarargs(l);
- bool allow_kwargs = GetFlag(n, "feature:kwargs") ? true : false;
- bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n));
- int start = (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) ? 1 : 0;
- /* Now write the wrapper function itself */
- if (current == CONSTRUCTOR_ALLOCATE) {
- Printf(f->def, "#ifdef HAVE_RB_DEFINE_ALLOC_FUNC\n");
- Printv(f->def, "SWIGINTERN VALUE\n", wname, "(VALUE self) {", NIL);
- Printf(f->def, "#else\n");
- Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL);
- Printf(f->def, "#endif\n");
- } else if (current == CONSTRUCTOR_INITIALIZE) {
- Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL);
- if (!varargs) {
- Printf(f->code, "if ((argc < %d) || (argc > %d)) ", numreq - start, numarg - start);
- } else {
- Printf(f->code, "if (argc < %d) ", numreq - start);
- }
- Printf(f->code, "{rb_raise(rb_eArgError, \"wrong # of arguments(%%d for %d)\",argc); SWIG_fail;}\n", numreq - start);
- } else {
- if ( current == NO_CPP )
- {
- String* docs = docstring(n, AUTODOC_FUNC);
- Printf(f_wrappers, "%s", docs);
- Delete(docs);
- }
- Printv(f->def, "SWIGINTERN VALUE\n", wname, "(int argc, VALUE *argv, VALUE self) {", NIL);
- if (!varargs) {
- Printf(f->code, "if ((argc < %d) || (argc > %d)) ", numreq - start, numarg - start);
- } else {
- Printf(f->code, "if (argc < %d) ", numreq - start);
- }
- Printf(f->code, "{rb_raise(rb_eArgError, \"wrong # of arguments(%%d for %d)\",argc); SWIG_fail;}\n", numreq - start);
- }
- /* Now walk the function parameter list and generate code */
- /* to get arguments */
- if (current != CONSTRUCTOR_ALLOCATE) {
- marshalInputArgs(n, l, numarg, numreq, kwargs, allow_kwargs, f);
- }
- // FIXME?
- if (ctor_director) {
- numarg--;
- numreq--;
- }
- /* Insert constraint checking code */
- insertConstraintCheckingCode(l, f);
- /* Insert cleanup code */
- insertCleanupCode(l, cleanup);
- /* Insert argument output code */
- insertArgOutputCode(l, outarg, need_result);
- /* if the object is a director, and the method call originated from its
- * underlying Ruby object, resolve the call by going up the c++
- * inheritance chain. otherwise try to resolve the method in python.
- * without this check an infinite loop is set up between the director and
- * shadow class method calls.
- */
- // NOTE: this code should only be inserted if this class is the
- // base class of a director class. however, in general we haven't
- // yet analyzed all classes derived from this one to see if they are
- // directors. furthermore, this class may be used as the base of
- // a director class defined in a completely different module at a
- // later time, so this test must be included whether or not directorbase
- // is true. we do skip this code if directors have not been enabled
- // at the command line to preserve source-level compatibility with
- // non-polymorphic swig. also, if this wrapper is for a smart-pointer
- // method, there is no need to perform the test since the calling object
- // (the smart-pointer) and the director object (the "pointee") are
- // distinct.
- director_method = is_member_director(n) && !is_smart_pointer() && !destructor;
- if (director_method) {
- Wrapper_add_local(f, "director", "Swig::Director *director = 0");
- Printf(f->code, "director = dynamic_cast<Swig::Director *>(arg1);\n");
- Wrapper_add_local(f, "upcall", "bool upcall = false");
- Append(f->code, "upcall = (director && (director->swig_get_self() == self));\n");
- }
- /* Now write code to make the function call */
- if (current != CONSTRUCTOR_ALLOCATE) {
- if (current == CONSTRUCTOR_INITIALIZE) {
- Node *pn = Swig_methodclass(n);
- String *symname = Getattr(pn, "sym:name");
- String *action = Getattr(n, "wrap:action");
- if (directorsEnabled()) {
- String *classname = NewStringf("const char *classname SWIGUNUSED = \"%s::%s\"", module, symname);
- Wrapper_add_local(f, "classname", classname);
- }
- if (action) {
- Printf(action, "\nDATA_PTR(self) = %s;", Swig_cresult_name());
- if (GetFlag(pn, "feature:trackobjects")) {
- Printf(action, "\nSWIG_RubyAddTracking(%s, self);", Swig_cresult_name());
- }
- }
- }
- /* Emit the function call */
- if (director_method) {
- Printf(f->code, "try {\n");
- }
- Setattr(n, "wrap:name", wname);
- Swig_director_emit_dynamic_cast(n, f);
- String *actioncode = emit_action(n);
- if (director_method) {
- Printf(actioncode, "} catch (Swig::DirectorException& e) {\n");
- Printf(actioncode, " rb_exc_raise(e.getError());\n");
- Printf(actioncode, " SWIG_fail;\n");
- Printf(actioncode, "}\n");
- }
- /* Return value if necessary */
- if (SwigType_type(t) != T_VOID && current != CONSTRUCTOR_INITIALIZE) {
- need_result = 1;
- if (GetFlag(n, "feature:predicate")) {
- Printv(actioncode, tab4, "vresult = (", Swig_cresult_name(), " ? Qtrue : Qfalse);\n", NIL);
- } else {
- tm = Swig_typemap_lookup_out("out", n, Swig_cresult_name(), f, actioncode);
- actioncode = 0;
- if (tm) {
- Replaceall(tm, "$result", "vresult");
- Replaceall(tm, "$source", Swig_cresult_name());
- Replaceall(tm, "$target", "vresult");
- if (GetFlag(n, "feature:new"))
- Replaceall(tm, "$owner", "SWIG_POINTER_OWN");
- else
- Replaceall(tm, "$owner", "0");
- #if 1
- // FIXME: this will not try to unwrap directors returned as non-director
- // base class pointers!
- /* New addition to unwrap director return values so that the original
- * Ruby object is returned instead.
- */
- bool unwrap = false;
- String *decl = Getattr(n, "decl");
- int is_pointer = SwigType_ispointer_return(decl);
- int is_reference = SwigType_isreference_return(decl);
- if (is_pointer || is_reference) {
- String *type = Getattr(n, "type");
- Node *parent = Swig_methodclass(n);
- Node *modname = Getattr(parent, "module");
- Node *target = Swig_directormap(modname, type);
- if (target)
- unwrap = true;
- }
- if (unwrap) {
- Wrapper_add_local(f, "director", "Swig::Director *director = 0");
- Printf(f->code, "director = dynamic_cast<Swig::Director *>(%s);\n", Swig_cresult_name());
- Printf(f->code, "if (director) {\n");
- Printf(f->code, " vresult = director->swig_get_self();\n");
- Printf(f->code, "} else {\n");
- Printf(f->code, "%s\n", tm);
- Printf(f->code, "}\n");
- director_method = 0;
- } else {
- Printf(f->code, "%s\n", tm);
- }
- #else
- Printf(f->code, "%s\n", tm);
- #endif
- Delete(tm);
- } else {
- Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s.\n", SwigType_str(t, 0));
- }
- }
- }
- if (actioncode) {
- Append(f->code, actioncode);
- Delete(actioncode);
- }
- emit_return_variable(n, t, f);
- }
- /* Extra code needed for new and initialize methods */
- if (current == CONSTRUCTOR_ALLOCATE) {
- need_result = 1;
- Printf(f->code, "VALUE vresult = SWIG_NewClassInstance(self, SWIGTYPE%s);\n", Char(SwigType_manglestr(t)));
- Printf(f->code, "#ifndef HAVE_RB_DEFINE_ALLOC_FUNC\n");
- Printf(f->code, "rb_obj_call_init(vresult, argc, argv);\n");
- Printf(f->code, "#endif\n");
- } else if (current == CONSTRUCTOR_INITIALIZE) {
- need_result = 1;
- }
- else
- {
- if ( need_result > 1 ) {
- if ( SwigType_type(t) == T_VOID )
- Printf(f->code, "vresult = rb_ary_new();\n");
- else
- {
- Printf(f->code, "if (vresult == Qnil) vresult = rb_ary_new();\n");
- Printf(f->code, "else vresult = SWIG_Ruby_AppendOutput( "
- "rb_ary_new(), vresult);\n");
- }
- }
- }
- /* Dump argument output code; */
- Printv(f->code, outarg, NIL);
- /* Dump the argument cleanup code */
- int need_cleanup = (current != CONSTRUCTOR_ALLOCATE) && (Len(cleanup) != 0);
- if (need_cleanup) {
- Printv(f->code, cleanup, NIL);
- }
- /* Look for any remaining cleanup. This processes the %new directive */
- if (current != CONSTRUCTOR_ALLOCATE && GetFlag(n, "feature:new")) {
- tm = Swig_typemap_lookup("newfree", n, Swig_cresult_name(), 0);
- if (tm) {
- Replaceall(tm, "$source", Swig_cresult_name());
- Printv(f->code, tm, "\n", NIL);
- Delete(tm);
- }
- }
- /* Special processing on return value. */
- tm = Swig_typemap_lookup("ret", n, Swig_cresult_name(), 0);
- if (tm) {
- Replaceall(tm, "$source", Swig_cresult_name());
- Printv(f->code, tm, NIL);
- Delete(tm);
- }
- if (director_method) {
- if ((tm = Swig_typemap_lookup("directorfree", n, Swig_cresult_name(), 0))) {
- Replaceall(tm, "$input", Swig_cresult_name());
- Replaceall(tm, "$result", "vresult");
- Printf(f->code, "%s\n", tm);
- }
- }
- /* Wrap things up (in a manner of speaking) */
- if (need_result) {
- if (current == CONSTRUCTOR_ALLOCATE) {
- Printv(f->code, tab4, "return vresult;\n", NIL);
- } else if (current == CONSTRUCTOR_INITIALIZE) {
- Printv(f->code, tab4, "return self;\n", NIL);
- Printv(f->code, "fail:\n", NIL);
- if (need_cleanup) {
- Printv(f->code, cleanup, NIL);
- }
- Printv(f->code, tab4, "return Qnil;\n", NIL);
- } else {
- Wrapper_add_local(f, "vresult", "VALUE vresult = Qnil");
- Printv(f->code, tab4, "return vresult;\n", NIL);
- Printv(f->code, "fail:\n", NIL);
- if (need_cleanup) {
- Printv(f->code, cleanup, NIL);
- }
- Printv(f->code, tab4, "return Qnil;\n", NIL);
- }
- } else {
- Printv(f->code, tab4, "return Qnil;\n", NIL);
- Printv(f->code, "fail:\n", NIL);
- if (need_cleanup) {
- Printv(f->code, cleanup, NIL);
- }
- Printv(f->code, tab4, "return Qnil;\n", NIL);
- }
- Printf(f->code, "}\n");
- /* Substitute the cleanup code */
- Replaceall(f->code, "$cleanup", cleanup);
- /* Substitute the function name */
- Replaceall(f->code, "$symname", symname);
- /* Emit the function */
- Wrapper_print(f, f_wrappers);
- /* Now register the function with the interpreter */
- if (!Swig_symbol_isoverloaded(n)) {
- create_command(n, symname);
- } else {
- if (current == CONSTRUCTOR_ALLOCATE) {
- create_command(n, symname);
- } else {
- if (!Getattr(n, "sym:nextSibling"))
- dispatchFunction(n);
- }
- }
- Delete(kwargs);
- Delete(cleanup);
- Delete(outarg);
- DelWrapper(f);
- Delete(symname);
- return SWIG_OK;
- }
- /* ------------------------------------------------------------
- * dispatchFunction()
- * ------------------------------------------------------------ */
- void dispatchFunction(Node *n) {
- /* Last node in overloaded chain */
- int maxargs;
- String *tmp = NewString("");
- String *dispatch = Swig_overload_dispatch(n, "return %s(nargs, args, self);", &maxargs);
- /* Generate a dispatch wrapper for all overloaded functions */
- Wrapper *f = NewWrapper();
- String *symname = Getattr(n, "sym:name");
- String *wname = Swig_name_wrapper(symname);
- Printv(f->def, "SWIGINTERN VALUE ", wname, "(int nargs, VALUE *args, VALUE self) {", NIL);
- Wrapper_add_local(f, "argc", "int argc");
- bool ctor_director = (current == CONSTRUCTOR_INITIALIZE && Swig_directorclass(n));
- if (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) {
- Printf(tmp, "VALUE argv[%d]", maxargs + 1);
- } else {
- Printf(tmp, "VALUE argv[%d]", maxargs);
- }
- Wrapper_add_local(f, "argv", tmp);
- Wrapper_add_local(f, "ii", "int ii");
- if (current == MEMBER_FUNC || current == MEMBER_VAR || ctor_director) {
- maxargs += 1;
- Printf(f->code, "argc = nargs + 1;\n");
- Printf(f->code, "argv[0] = self;\n");
- Printf(f->code, "if (argc > %d) SWIG_fail;\n", maxargs);
- Printf(f->code, "for (ii = 1; (ii < argc); ++ii) {\n");
- Printf(f->code, "argv[ii] = args[ii-1];\n");
- Printf(f->code, "}\n");
- } else {
- Printf(f->code, "argc = nargs;\n");
- Printf(f->code, "if (argc > %d) SWIG_fail;\n", maxargs);
- Printf(f->code, "for (ii = 0; (ii < argc); ++ii) {\n");
- Printf(f->code, "argv[ii] = args[ii];\n");
- Printf(f->code, "}\n");
- }
- Replaceall(dispatch, "$args", "nargs, args, self");
- Printv(f->code, dispatch, "\n", NIL);
-
- // Generate prototype list, go to first node
- Node *sibl = n;
- String* type = SwigType_str(Getattr(sibl,"type"),NULL);
- while (Getattr(sibl, "sym:previousSibling"))
- sibl = Getattr(sibl, "sym:previousSibling"); // go all the way up
- // Constructors will be treated specially
- const bool isCtor = Cmp(Getattr(sibl,"feature:new"), "1") == 0;
- const bool isMethod = ( Cmp(Getattr(sibl, "ismember"), "1") == 0 &&
- (!isCtor) );
- // Construct real method name
- String* methodName = NewString("");
- if ( isMethod ) {
- // Sometimes a method node has no parent (SF#3034054).
- // This value is used in an exception message, so just skip the class
- // name in this case so at least we don't segfault. This is probably
- // just working around a problem elsewhere though.
- Node *parent_node = parentNode(sibl);
- if (parent_node)
- Printv( methodName, Getattr(parent_node,"sym:name"), ".", NIL );
- }
- Append( methodName, Getattr(sibl,"sym:name" ) );
- if ( isCtor ) Append( methodName, ".new" );
- // Generate prototype list
- String *protoTypes = NewString("");
- do {
- Append( protoTypes, "\n\" ");
- if ( !isCtor ) Printv( protoTypes, type, " ", NIL );
- Printv(protoTypes, methodName, NIL );
- Parm* p = Getattr(sibl, "wrap:parms");
- if (p && (current == MEMBER_FUNC || current == MEMBER_VAR ||
- ctor_director) )
- p = nextSibling(p); // skip self
- Append( protoTypes, "(" );
- while(p)
- {
- Append( protoTypes, SwigType_str(Getattr(p,"type"), Getattr(p,"name")) );
- if ( ( p = nextSibling(p)) ) Append(protoTypes, ", ");
- }
- Append( protoTypes, ")\\n\"" );
- } while ((sibl = Getattr(sibl, "sym:nextSibling")));
- Ap