| /* ----------------------------------------------------------------------------- |
| * cplus.cxx |
| * |
| * This file contains code for C++ support in SWIG1.1. Beware! |
| * |
| * Author(s) : David Beazley (beazley@cs.uchicago.edu) |
| * |
| * Copyright (C) 1998-2000. The University of Chicago |
| * Copyright (C) 1995-1998. The University of Utah and The Regents of the |
| * University of California. |
| * |
| * See the file LICENSE for information on usage and redistribution. |
| * ----------------------------------------------------------------------------- */ |
| |
| #include "internal.h" |
| extern "C" { |
| #include "swig.h" |
| } |
| |
| static char cvstag[] = "$Header$"; |
| |
| /******************************************************************************* |
| * Note: |
| * |
| * The control flow in this module is completely insane. But here's the |
| * rough outline. |
| * |
| * Stage 1 : SWIG Parsing |
| * cplus_open_class() - Open up a new class |
| * cplus_* - Add members to class |
| * cplus_inherit() - Inherit from base classes |
| * cplus_class_close() - Close class |
| * |
| * ... |
| * cplus_open_class() |
| * ... |
| * cplus_class_close() |
| * |
| * ... and so on, until the end of the file |
| * |
| * After stage 1, all classes have been read, but nothing has been |
| * sent to the language module yet. |
| * |
| * Stage 2 : Code generation |
| * For each class we've saved, do this : |
| * lang->cpp_open_class() - Open class |
| * lang->cpp_* - Emit members |
| * lang->cpp_inherit() - Inherit |
| * lang->cpp_close_class() - Close class |
| * |
| * This two-stage approach solves a number of problems related to working |
| * with multiple files, mutually referenced classes, add adding methods. |
| * Just keep in mind that all C++ code is emitted *after* an entire SWIG |
| * file has been parsed. |
| * |
| * Improved code generation and inheritance of added methods (2/18/97): |
| * |
| * Each C++ declaration now has an associated function name attached to it. |
| * For example : |
| * |
| * class Foo { |
| * void bar(); |
| * } |
| * |
| * Generates a member function "bar()" with a accessor function named |
| * "Foo_bar()". We will use this recorded accessor function to generate |
| * better code for inheritance. For example : |
| * |
| * class Foo2 : public Foo { |
| * |
| * ... |
| * } |
| * |
| * Will create a function called "Foo2_bar()" that is really mapped |
| * onto the base-class method "Foo_bar()". This should improve |
| * code generation substantially. |
| * |
| * Tricky stuff : |
| * - Each target language is responsible for naming wrapper |
| * functions. |
| * |
| *******************************************************************************/ |
| |
| |
| // Some status variables |
| |
| static int Inherit_mode = 0; // Set if we're inheriting members |
| static char *ccode = 0; // Set to optional C code (if available) |
| static DOHHash *localtypes = 0; // Localtype hash |
| static int abstract =0; // Status bit set during code generation |
| int IsVirtual = 0; |
| |
| static int cpp_id = 0; |
| |
| // Forward references |
| |
| void cplus_member_func(char *, char *, SwigType *, ParmList *, int); |
| void cplus_constructor(char *, char *, ParmList *); |
| void cplus_destructor(char *, char *); |
| void cplus_variable(char *, char *, SwigType *); |
| void cplus_static_func(char *, char *, SwigType *, ParmList *); |
| void cplus_declare_const(char *, char *, SwigType *, char *); |
| void cplus_static_var(char *, char *, SwigType *); |
| void cplus_inherit_decl(char **); |
| |
| // ----------------------------------------------------------------------------- |
| // void add_local_type(char *type, char *classname) |
| // void add_local_type(SwigType *type, char *classname) |
| // |
| // Adds a new datatype to the local datatype hash. This is used to handle |
| // datatypes defined within a class. |
| // ----------------------------------------------------------------------------- |
| |
| static void add_local_type(char *type, char *classname) { |
| char str[1024]; |
| if (!localtypes) return; // No hash table initialized, ignore this |
| sprintf(str,"%s::%s",classname,type); |
| Setattr(localtypes,type,str); |
| } |
| |
| void add_local_type(SwigType *type, char *classname) { |
| add_local_type(Char(type),classname); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void update_local_type(SwigType *type) |
| // |
| // Checks to see whether this datatype is part of a class definition. If so, |
| // we update the type-name by appending the class prefix to it. Uses the |
| // name stored in current_class unless unavailable. |
| // ----------------------------------------------------------------------------- |
| |
| static void update_local_type(SwigType *type) { |
| |
| char *newname = 0; |
| |
| // Lookup the datatype in the hash table |
| |
| if (!localtypes) return; |
| |
| newname = GetChar(localtypes,SwigType_base(type)); |
| if (newname) { |
| SwigType_setbase(type,newname); |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void update_parms(ParmList *l) |
| // |
| // Updates all of the parameters in a parameter list with the proper C++ prefix |
| // (if neccessary). |
| // ----------------------------------------------------------------------------- |
| |
| static void update_parms(ParmList *p) { |
| while (p) { |
| SwigType *pt = Gettype(p); |
| DOHString *pvalue = Getvalue(p); |
| |
| update_local_type(pt); |
| |
| // Check for default arguments |
| |
| if ((pvalue) && (localtypes)) { |
| char *s; |
| s = (char *) GetChar(localtypes,pvalue); |
| if (s) { |
| Setvalue(p,s); |
| } |
| } |
| p = Getnext(p); |
| } |
| } |
| |
| // ----------------------------------------------------------------------- |
| // class CPP_member |
| // |
| // Base class for various kinds of C++ members |
| // ----------------------------------------------------------------------- |
| class CPP_member { |
| public: |
| char *name; // Name of the member |
| char *iname; // Name of member in the interpreter |
| int is_static; // Is this a static member? |
| int is_virtual; // Is this virtual? |
| int new_method; // Is this a new method (added by SWIG)? |
| int line; // What line number was this member on |
| char *file; // What file was this in? |
| char *code; // Was there any supplied code? |
| char *base; // Base class where this was defined |
| int inherited; // Was this member inherited? |
| CPP_member *next; // Next member (for building linked lists) |
| int id; // type id when created |
| String *signature; |
| |
| CPP_member() { |
| signature = 0; |
| is_static = 0; |
| is_virtual = 0; |
| base = 0; |
| code = 0; |
| file = 0; |
| next = 0; |
| } |
| virtual void inherit(int) { }; // Inheritance rule (optional) |
| virtual void emit() = 0; // Emit rule |
| }; |
| |
| // ---------------------------------------------------------------------- |
| // class CPP_function : public CPP_member |
| // |
| // Structure for handling a C++ member function |
| // ---------------------------------------------------------------------- |
| |
| class CPP_function : public CPP_member { |
| public: |
| SwigType *ret_type; |
| ParmList *parms; |
| int new_object; |
| |
| CPP_function(char *n, char *i, SwigType *t, ParmList *l, int s, int v = 0) { |
| name = Swig_copy_string(n); |
| iname = Swig_copy_string(i); |
| ret_type = Copy(t); |
| parms = CopyParmList(l); |
| is_static = s; |
| is_virtual = v; |
| new_method = AddMethods; |
| new_object = NewObject; |
| inherited = Inherit_mode; |
| next = 0; |
| line = line_number; |
| file = input_file; |
| signature = NewStringf("%s(%s)", n, ParmList_str(l)); |
| id = cpp_id; |
| if (AddMethods) { |
| if (strlen(Char(CCode))) |
| code = Swig_copy_string(Char(CCode)); |
| else |
| code = 0; |
| } else { |
| code = 0; |
| } |
| } |
| void inherit(int mode) { |
| if (mode & INHERIT_FUNC) { |
| // Set up the proper addmethods mode and provide C code (if provided) |
| int oldaddmethods = AddMethods; |
| int oldnewobject = NewObject; |
| AddMethods = new_method; |
| NewObject = new_object; |
| Clear(CCode); |
| Append(CCode,code); |
| if (is_static) { |
| cplus_static_func(name, iname, ret_type, parms); |
| } else { |
| cplus_member_func(name, iname, ret_type, parms, is_virtual); |
| } |
| AddMethods = oldaddmethods; |
| NewObject = oldnewobject; |
| Clear(CCode); |
| } |
| } |
| void emit() { |
| ParmList *l; |
| SwigType *t; |
| AddMethods = new_method; |
| NewObject = new_object; |
| line_number = line; // Restore line and file |
| input_file = file; |
| ccode = code; |
| IsVirtual = is_virtual; |
| |
| // Make a copy of the parameter list and upgrade its types |
| |
| l = CopyParmList(parms); |
| t = Copy(ret_type); |
| update_parms(l); |
| update_local_type(t); |
| if (is_static) { |
| lang->cpp_static_func(name, iname, t, l); |
| } else { |
| lang->cpp_member_func(name, iname, t, l); |
| } |
| Delete(l); |
| Delete(t); |
| IsVirtual = 0; |
| } |
| }; |
| |
| // -------------------------------------------------------------------------- |
| // class CPP_constructor : public CPP_member |
| // |
| // Class for holding a C++ constructor definition. |
| // -------------------------------------------------------------------------- |
| |
| class CPP_constructor : public CPP_member { |
| public: |
| ParmList *parms; |
| CPP_constructor(char *n, char *i, ParmList *l) { |
| name = Swig_copy_string(n); |
| iname = Swig_copy_string(i); |
| parms = CopyParmList(l); |
| new_method = AddMethods; |
| inherited = 0; |
| next = 0; |
| line = line_number; |
| file = input_file; |
| id = 0; |
| if (AddMethods) { |
| if (strlen(Char(CCode))) |
| code = Swig_copy_string(Char(CCode)); |
| else |
| code = 0; |
| } else { |
| code = 0; |
| } |
| } |
| void emit() { |
| if (1) { |
| ParmList *l; |
| AddMethods = new_method; |
| line_number = line; |
| input_file = file; |
| ccode = code; |
| |
| if (abstract) return; |
| // Make a copy of the parameter list and upgrade its types |
| |
| l = CopyParmList(parms); |
| update_parms(l); |
| lang->cpp_constructor(name,iname,l); |
| Delete(l); |
| } |
| } |
| }; |
| |
| |
| // -------------------------------------------------------------------------- |
| // class CPP_destructor : public CPP_member |
| // |
| // Class for holding a destructor definition |
| // -------------------------------------------------------------------------- |
| |
| class CPP_destructor : public CPP_member { |
| public: |
| |
| CPP_destructor(char *n, char *i) { |
| name = Swig_copy_string(n); |
| iname = Swig_copy_string(i); |
| new_method = AddMethods; |
| next = 0; |
| inherited = 0; |
| line = line_number; |
| file = input_file; |
| id = 0; |
| if (AddMethods) { |
| if (strlen(Char(CCode))) |
| code = Swig_copy_string(Char(CCode)); |
| else |
| code = 0; |
| } else { |
| code = 0; |
| } |
| |
| } |
| |
| void inherit(int mode) { |
| // Set up the proper addmethods mode and provide C code (if provided) |
| int oldaddmethods = AddMethods; |
| AddMethods = new_method; |
| Clear(CCode); |
| Append(CCode,code); |
| cplus_destructor(name,iname); |
| AddMethods = oldaddmethods; |
| Clear(CCode); |
| } |
| |
| void emit() { |
| AddMethods = new_method; |
| line_number = line; |
| input_file = file; |
| ccode = code; |
| lang->cpp_destructor(name, iname); |
| } |
| }; |
| |
| // ------------------------------------------------------------------------- |
| // class CPP_variable : public CPP_member |
| // |
| // Class for a managing a data member |
| // ------------------------------------------------------------------------- |
| |
| class CPP_variable : public CPP_member { |
| public: |
| SwigType *type; |
| int status; |
| CPP_variable(char *n, char *i, SwigType *t, int s) { |
| name = Swig_copy_string(n); |
| iname = Swig_copy_string(i); |
| type = Copy(t); |
| is_static = s; |
| status = Status; |
| next = 0; |
| new_method = AddMethods; |
| line = line_number; |
| file = input_file; |
| if (Inherit_mode) { |
| id = cpp_id; |
| } else { |
| id = 0; |
| } |
| code = 0; |
| inherited = 0; |
| } |
| |
| // Emit code for this |
| |
| void emit() { |
| SwigType *t; |
| int old_status = Status; |
| AddMethods = new_method; |
| Status = status; |
| line_number = line; |
| input_file = file; |
| ccode = code; |
| |
| t = Copy(type); |
| update_local_type(t); |
| /* Check to see if it's read-only */ |
| if (SwigType_isarray(t) || SwigType_isconst(t)) { |
| if (!(Swig_typemap_search("memberin",t,name))) |
| Status = Status | STAT_READONLY; |
| } |
| |
| if (!is_static) { |
| lang->cpp_variable(name,iname,t); |
| } else { |
| lang->cpp_static_var(name,iname,t); |
| } |
| Status = old_status; |
| Delete(t); |
| } |
| |
| // Inherit into another class |
| |
| void inherit(int mode) { |
| int oldstatus = Status; |
| Status = status; |
| if (mode & INHERIT_VAR) { |
| if (!is_static) { |
| int oldaddmethods = AddMethods; |
| AddMethods = new_method; |
| Clear(CCode); |
| Append(CCode,code); |
| cplus_variable(name,iname,type); |
| AddMethods = oldaddmethods; |
| Clear(CCode); |
| } else { |
| cplus_static_var(name,iname,type); |
| } |
| } |
| Status = oldstatus; |
| } |
| }; |
| |
| // ------------------------------------------------------------------------- |
| // class CPP_constant : public CPP_member |
| // |
| // Class for managing constant values |
| // ------------------------------------------------------------------------- |
| |
| class CPP_constant : public CPP_member { |
| public: |
| char *value; |
| SwigType *type; |
| CPP_constant(char *n, char *i, SwigType *t, char *v) { |
| name = Swig_copy_string(n); |
| iname = Swig_copy_string(i); |
| type = Copy(t); |
| value = Swig_copy_string(v); |
| new_method = AddMethods; |
| next = 0; |
| line = line_number; |
| file = input_file; |
| if (Inherit_mode) |
| id = cpp_id; |
| else |
| id = 0; |
| code = 0; |
| inherited = 0; |
| } |
| |
| void emit() { |
| AddMethods = new_method; |
| line_number = line; |
| input_file = file; |
| ccode = code; |
| lang->cpp_declare_const(name,iname,type,value); |
| } |
| |
| void inherit(int mode) { |
| if (mode & INHERIT_CONST) |
| cplus_declare_const(name, iname, type, value); |
| } |
| }; |
| |
| // ---------------------------------------------------------------------- |
| // class CPP_class |
| // |
| // Class for managing class members (internally) |
| // ---------------------------------------------------------------------- |
| |
| static char *inherit_base_class = 0; |
| |
| class CPP_class { |
| public: |
| char *classname; // Real class name |
| char *classrename; // New name of class (if applicable) |
| char *classtype; // class type (struct, union, class) |
| int strip; // Strip off class declarator |
| int wextern; // Value of extern wrapper variable for this class |
| int have_constructor; // Status bit indicating if we've seen a constructor |
| int have_destructor; // Status bit indicating if a destructor has been seen |
| int is_abstract; // Status bit indicating if this is an abstract class |
| int generate_default; // Generate default constructors |
| int objective_c; // Set if this is an objective C class |
| int error; // Set if this class can't be generated |
| int line; // Line number |
| char **baseclass; // Base classes (if any) |
| DOHHash *local; // Hash table for local types |
| void *scope; // Local scope hash table |
| CPP_member *members; // Linked list of members |
| CPP_class *next; // Next class |
| static CPP_class *classlist; // List of all classes stored |
| Pragma *pragmas; // Class pragmas |
| |
| CPP_class(char *name, char *ctype) { |
| CPP_class *c; |
| classname = Swig_copy_string(name); |
| classtype = Swig_copy_string(ctype); |
| classrename = 0; |
| baseclass = 0; |
| local = NewHash(); // Create hash table for storing local datatypes |
| scope = 0; |
| error = 0; |
| pragmas = 0; |
| line = line_number; |
| |
| // Walk down class list and add to end |
| |
| c = classlist; |
| if (c) { |
| while (c->next) { |
| c = c->next; |
| } |
| c->next = this; |
| } else { |
| classlist = this; |
| } |
| next = 0; |
| members = 0; |
| strip = 0; |
| wextern = WrapExtern; |
| have_constructor = 0; |
| have_destructor = 0; |
| is_abstract = 0; |
| generate_default = GenerateDefault; |
| objective_c = ObjCClass; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| // Add a new C++ member to this class |
| // ------------------------------------------------------------------------------ |
| |
| void add_member(CPP_member *m) { |
| CPP_member *cm; |
| |
| // Set base class where this was defined |
| if (inherit_base_class) |
| m->base = inherit_base_class; |
| else |
| m->base = classname; |
| if (!members) { |
| members = m; |
| return; |
| } |
| cm = members; |
| while (cm->next) { |
| cm = cm->next; |
| } |
| cm->next = m; |
| } |
| // ------------------------------------------------------------------------------ |
| // Search for a member with the given name. Returns the member on success, 0 on failure |
| // ------------------------------------------------------------------------------ |
| |
| CPP_member *search_member(char *name) { |
| CPP_member *m; |
| char *c; |
| m = members; |
| while (m) { |
| c = m->iname ? m->iname : m->name; |
| if (strcmp(c,name) == 0) return m; |
| m = m->next; |
| } |
| return 0; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| // Inherit. Put all the declarations associated with this class into the current |
| // ------------------------------------------------------------------------------ |
| |
| void inherit_decls(int mode) { |
| CPP_member *m; |
| m = members; |
| while (m) { |
| inherit_base_class = m->base; |
| cpp_id = m->id; |
| m->inherit(mode); |
| m = m->next; |
| } |
| inherit_base_class = 0; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| // Emit all of the declarations associated with this class |
| // ------------------------------------------------------------------------------ |
| |
| void emit_decls() { |
| CPP_member *m = members; |
| abstract = is_abstract; |
| /* Printf(stdout,"class %s. Abstract = %d\n", classname, is_abstract); */ |
| while (m) { |
| cpp_id = m->id; |
| m->emit(); |
| m = m->next; |
| } |
| } |
| |
| // ------------------------------------------------------------------------------ |
| // Search for a given class in the list |
| // ------------------------------------------------------------------------------ |
| |
| static CPP_class *search(char *name) { |
| CPP_class *c; |
| c = classlist; |
| if (!name) return 0; |
| while (c) { |
| if (strcmp(name,c->classname) == 0) return c; |
| c = c->next; |
| } |
| return 0; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| // Add default constructors and destructors |
| // |
| // ------------------------------------------------------------------------------ |
| |
| void create_default() { |
| if (!generate_default) return; |
| |
| // Try to generate a constructor if not available. |
| Clear(CCode); |
| AddMethods = 0; |
| if ((!have_constructor) && (1)) { |
| cplus_constructor(classname,0,0); |
| }; |
| |
| if (!have_destructor) { |
| cplus_destructor(classname,0); |
| } |
| } |
| |
| // ------------------------------------------------------------------------------ |
| // Dump *all* of the classes saved out to the various |
| // language modules (this does what cplus_close_class used to do) |
| // ------------------------------------------------------------------------------ |
| static void create_all(); |
| }; |
| |
| CPP_class *CPP_class::classlist = 0; |
| static CPP_class *current_class; |
| |
| void CPP_class::create_all() { |
| CPP_class *c; |
| c = classlist; |
| while (c) { |
| if (!c->error) { |
| current_class = c; |
| localtypes = c->local; |
| if ((!c->wextern) && (c->classtype)) { |
| ObjCClass = c->objective_c; |
| lang->cpp_open_class(c->classname,c->classrename,c->classtype,c->strip); |
| lang->cpp_pragma(c->pragmas); |
| c->create_default(); |
| if (c->baseclass) |
| cplus_inherit_decl(c->baseclass); |
| c->emit_decls(); |
| lang->cpp_close_class(); |
| } |
| // Force brute patch to produce the proper casting code |
| // between "local" classes and "external" ones when |
| // %import is used. |
| else if ( (c->wextern) && (c->classtype) ) { |
| SwigType *t; |
| t = NewString(c->classname); |
| SwigType_add_pointer(t); |
| SwigType_remember(t); |
| Delete(t); |
| } |
| } |
| c = c->next; |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // char *cplus_base_class(char *name) |
| // |
| // Given a member name, return the base class that it belongs to. |
| // ----------------------------------------------------------------------------- |
| |
| char *cplus_base_class(char *name) { |
| CPP_member *m = current_class->search_member(name); |
| if (m) { |
| return m->base; |
| } |
| return 0; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_open_class(char *name, char *rname, char *ctype) |
| // |
| // Opens up a new C++ class. If rname is given, we'll be renaming the |
| // class. This also sets up some basic type equivalence for the |
| // type checker. |
| // |
| // Inputs : |
| // name = Name of the class |
| // rname = New name of the class (using %name() directive) |
| // ctype = Class type ("class","struct", or "union") |
| // |
| // Side Effects : |
| // Creates a new class obect internally. |
| // Added type-mappings to the SWIG type-checker module. |
| // Sets a number of internal state variables for later use. |
| // |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_open_class(char *name, char *rname, char *ctype) { |
| |
| char temp[256]; |
| CPP_class *c; |
| |
| // Add some symbol table management here |
| |
| // Search for a previous class definition |
| |
| c = CPP_class::search(name); |
| if (c) { |
| if (c->classtype) { |
| // Hmmm. We already seem to have defined this class so we'll |
| // create a new class object for whatever reason |
| current_class = new CPP_class(name, ctype); |
| } else { |
| // Looks like a reference was made to this class earlier |
| // somehow, but no other information is known. We'll |
| // make it our current class and fix it up a bit |
| current_class = c; |
| c->classtype = Swig_copy_string(ctype); |
| } |
| } else { |
| // Create a new class |
| current_class = new CPP_class(name, ctype); |
| } |
| |
| // Set localtypes hash to our current class |
| |
| localtypes = current_class->local; |
| |
| // If renaming the class, set the new name |
| |
| if (rname) { |
| current_class->classrename = Swig_copy_string(rname); |
| } |
| |
| // Make a typedef for both long and short versions of this datatype |
| |
| if (name) { |
| if (strlen(name)) { |
| if (strlen(ctype) > 0) { |
| sprintf(temp,"%s %s", ctype, name); |
| // typeeq_derived(temp,name,0); // Map "struct foo" to "foo" |
| //typeeq_derived(name,temp,0); // Map "foo" to "struct foo" |
| } |
| } |
| } |
| |
| AddMethods = 0; // Reset add methods flag |
| |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_set_class(char *name) |
| // |
| // This function sets the current class to a given name. If the class |
| // doesn't exist, this function will create one. If it already exists, |
| // we'll just use that. |
| // |
| // This function is used primarily to add or manipulate an already |
| // existing class, but in a different location. For example : |
| // |
| // %include "class.h" // Grab some classes |
| // ... |
| // %addmethods MyClass { // Add some members for shadow classes |
| // ... members ... |
| // } |
| // |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_set_class(char *name) { |
| |
| CPP_class *c; |
| |
| // Look for a previous class definition |
| |
| c = CPP_class::search(name); |
| if (c) { |
| current_class = c; |
| localtypes = c->local; |
| } else { |
| Printf(stderr,"%s:%d: Warning class %s undefined.\n",input_file,line_number,name); |
| current_class = new CPP_class(name,0); |
| localtypes = current_class->local; |
| } |
| }; |
| |
| // This function closes a class open with cplus_set_class() |
| |
| void cplus_unset_class() { |
| current_class = 0; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_class_close(char *name) |
| // |
| // Close a C++ class definition. Up to this point, we've only been collecting |
| // member definitions. This function merely closes the class object and |
| // stores it in a list. All classes are dumped after processing has completed. |
| // |
| // If name is non-null, it means that the name of the class has actually been |
| // set after all of the definitions. For example : |
| // |
| // typedef struct { |
| // double x,y,z |
| // } Vector; |
| // |
| // If this is the case, we'll use that as our classname and datatype. |
| // Otherwise, we'll just go with the classname and classtype set earlier. |
| // |
| // Inputs : name = optional "new name" for the class. |
| // |
| // Output : None |
| // |
| // Side Effects : Resets internal variables. Saves class in internal list. |
| // Registers the class with the language module, but doesn't |
| // emit any code. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_class_close(char *name) { |
| |
| if (name) { |
| // The name of our class suddenly changed by typedef. Fix things up |
| current_class->classname = Swig_copy_string(name); |
| |
| // This flag indicates that the class needs to have it's type stripped off |
| current_class->strip = 1; |
| } |
| |
| // If we're in C++ or Objective-C mode. We're going to drop the class specifier |
| |
| if ((CPlusPlus) || (ObjCClass)) { |
| current_class->strip = 1; |
| } |
| |
| // Register our class with the target language module, but otherwise |
| // don't do anything yet. |
| |
| char *iname; |
| if (current_class->classrename) iname = current_class->classrename; |
| else iname = current_class->classname; |
| |
| lang->cpp_class_decl(current_class->classname, iname, current_class->classtype); |
| |
| // Clear current class variable and reset |
| current_class = 0; |
| localtypes = 0; |
| |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_abort(void) |
| // |
| // Voids the current class--some kind of unrecoverable parsing error occurred. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_abort(void) { |
| current_class->error = 1; |
| current_class = 0; |
| localtypes = 0; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_cleanup(void) |
| // |
| // This function is called after all parsing has been completed. It dumps all |
| // of the stored classes out to the language module. |
| // |
| // Inputs : None |
| // |
| // Output : None |
| // |
| // Side Effects : Emits all C++ wrapper code. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_cleanup(void) { |
| |
| // Dump all classes created at once (yikes!) |
| |
| CPP_class::create_all(); |
| lang->cpp_cleanup(); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_inherit(int count, char **baseclass) |
| // |
| // Inherit from a baseclass. This function only really registers |
| // the inheritance, but doesn't do anything with it yet. |
| // |
| // Inputs : baseclass = A NULL terminated array of strings with the names |
| // of baseclasses. For multiple inheritance, there |
| // will be multiple entries in this list. |
| // |
| // Output : None |
| // |
| // Side Effects : Sets the baseclass variable of the current class. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_inherit(int count, char **baseclass) { |
| int i; |
| |
| // printf("Inheriting : count = %d, baseclass = %x\n",count,baseclass); |
| // If there are baseclasses, make copy of them |
| if (count) { |
| current_class->baseclass = (char **) new char*[count+1]; |
| for (i = 0; i < count; i++) |
| current_class->baseclass[i] = Swig_copy_string(baseclass[i]); |
| current_class->baseclass[i] = 0; |
| } else { |
| baseclass = 0; |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // cplus_generate_types(char **baseclass) |
| // |
| // Generates the type-mappings between the current class and any associated |
| // base classes. This is done by performing a depth first search of the |
| // class hierarchy. Functions for performing correct type-casting are |
| // generated for each base-derived class pair. |
| // |
| // Inputs : baseclass = NULL terminated list of base classes |
| // |
| // Output : None |
| // |
| // Side Effects : Emits pointer conversion functions. Registers type-mappings |
| // with the type checking module. |
| // |
| // ----------------------------------------------------------------------------- |
| |
| static DOHHash *convert = 0; // Hash table of conversion functions |
| |
| void cplus_generate_types(char **baseclass) { |
| CPP_class *bc; |
| int i; |
| DOHString *cfunc; |
| DOHString *temp3; |
| char temp1[512], temp2[512]; |
| |
| if (!baseclass) { |
| return; |
| } |
| |
| if (!convert) convert = NewHash(); |
| |
| // Generate type-conversion functions and type-equivalence |
| cfunc = NewString(""); |
| temp3 = NewString(""); |
| i = 0; |
| while(baseclass[i]) { |
| Clear(cfunc); |
| |
| bc = CPP_class::search(baseclass[i]); |
| if (bc) { |
| // Generate a conversion function (but only for C++) |
| |
| if (!current_class->objective_c) { |
| Clear(temp3); |
| Printv(temp3, "Swig", current_class->classname, "To", bc->classname,0); |
| |
| if (!Getattr(convert,temp3)) { |
| SetVoid(convert,temp3,(void*) 1); |
| |
| // Write a function for casting derived type to parent class |
| |
| #ifdef OLD |
| Printv(cfunc, |
| "static void *Swig", current_class->classname, "To", bc->classname, |
| "(void *ptr) {\n", |
| tab4, current_class->classname, " *src;\n", |
| tab4, bc->classname, " *dest;\n", |
| tab4, "src = (", current_class->classname, " *) ptr;\n", |
| tab4, "dest = (", bc->classname, " *) src;\n", |
| tab4, "return (void *) dest;\n", |
| "}\n", |
| 0); |
| Printf(f_wrappers,"%s\n",Char(cfunc)); |
| #endif |
| } |
| } else { |
| Clear(temp3); |
| Printf(temp3,"0"); |
| } |
| |
| // Make a type-equivalence allowing derived classes to be used in functions of the |
| |
| if (strlen(current_class->classtype) > 0) { |
| sprintf(temp1,"%s %s", current_class->classtype, current_class->classname); |
| sprintf(temp2,"%s %s", bc->classtype, bc->classname); |
| |
| // Add various equivalences to the pointer table |
| |
| // typeeq_derived(bc->classname, current_class->classname,Char(temp3)); |
| // typeeq_derived(temp2, current_class->classname,Char(temp3)); |
| // typeeq_derived(temp2, temp1,Char(temp3)); |
| // typeeq_derived(bc->classname, temp1,Char(temp3)); |
| } else { |
| // typeeq_derived(bc->classname, current_class->classname,Char(temp3)); |
| } |
| // DataType_record_base(current_class->classname, bc->classname); |
| SwigType_inherit(current_class->classname, bc->classname); |
| // Now traverse the hierarchy some more |
| cplus_generate_types(bc->baseclass); |
| } |
| i++; |
| } |
| Delete(temp3); |
| Delete(cfunc); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_inherit_decl(char **baseclass) |
| // |
| // This function is called internally to handle inheritance between classes. |
| // Basically, we're going to generate type-checking information and call |
| // out to the target language to handle the inheritance. |
| // |
| // This function is only called when emitting classes to the language modules |
| // (after all parsing has been complete). |
| // |
| // Inputs : baseclass = NULL terminated list of base-class names. |
| // |
| // Output : None |
| // |
| // Side Effects : Generates type-mappings. Calls the language-specific |
| // inheritance function. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_inherit_decl(char **baseclass) { |
| |
| // If not base-classes, bail out |
| |
| if (!baseclass) return; |
| |
| Inherit_mode = 1; |
| lang->cpp_inherit(baseclass); // Pass inheritance onto the various languages |
| Inherit_mode = 0; |
| |
| // Create type-information for class hierarchy |
| |
| cplus_generate_types(baseclass); |
| } |
| // ----------------------------------------------------------------------------- |
| // void cplus_inherit_members(char *baseclass, int mode) |
| // |
| // Inherits members from a class. This is called by specific language modules |
| // to bring in members from base classes. It may or may not be called. |
| // |
| // This function is called with a *single* base-class, not multiple classes |
| // like other functions. To do multiple inheritance, simply call this |
| // with each of the associated base classes. |
| // |
| // Inputs : |
| // baseclass = Name of baseclass |
| // mode = Inheritance handling flags |
| // INHERIT_FUNC - Import functions in base class |
| // INHERIT_VAR - Import variables in base class |
| // INHERIT_CONST - Inherit constants |
| // INHERIT_ALL - Inherit everything (grossly inefficient) |
| // |
| // Output : None |
| // |
| // Side Effects : Imports methods from base-classes into derived classes. |
| // |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_inherit_members(char *baseclass, int mode) { |
| CPP_class *bc; |
| |
| bc = CPP_class::search(baseclass); |
| if (bc) { |
| bc->inherit_decls(mode); |
| } else { |
| Printf(stderr,"%s:%d: Warning. Base class %s undefined (ignored).\n", input_file, current_class->line, baseclass); |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_member_func(char *name, char *iname, DataType *type, ParmList *, is_virtual) |
| // |
| // Parser entry point to creating a C++ member function. This function primarily |
| // just records the function and does a few symbol table checks. |
| // |
| // Inputs : |
| // name = Real name of the member function |
| // iname = Renamed version (may be NULL) |
| // type = Return datatype |
| // l = Parameter list |
| // is_virtual = Set if this is a pure virtual function (ignored) |
| // |
| // Output : None |
| // |
| // Side Effects : |
| // Adds member function to current class. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_member_func(char *name, char *iname, SwigType *type, ParmList *l, |
| int is_virtual) { |
| |
| CPP_function *f; |
| char *temp_iname; |
| |
| // First, figure out if we're renaming this function or not |
| |
| if (!iname) |
| temp_iname = name; |
| else |
| temp_iname = iname; |
| |
| // If we're in inherit mode, we need to check for duplicates. |
| // Issue a warning. |
| |
| if (Inherit_mode) { |
| CPP_member *m = current_class->search_member(temp_iname); |
| if (m) { |
| /* The current member is already part of the class. However, we might be |
| able to make some "optimizations" if it's virtual */ |
| |
| if ((is_virtual) && (m->is_virtual)) { |
| if (m->signature) { |
| /* Printf(stdout,"Member : %s, %d, '%s'\n", m->name, m->is_virtual, m->signature); */ |
| String *ns = NewStringf("%s(%s)", name, ParmList_str(l)); |
| if (Cmp(ns,m->signature) == 0) { |
| m->base = Swig_copy_string(inherit_base_class); |
| } |
| } |
| } |
| return; |
| } |
| } |
| |
| // Add it to our C++ class list |
| |
| f = new CPP_function(name,temp_iname,type,l,0,is_virtual); |
| current_class->add_member(f); |
| |
| // If this is a pure virtual function, the class is abstract |
| |
| if (is_virtual == PURE_VIRTUAL) |
| current_class->is_abstract = 1; |
| |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_constructor(char *name, char *iname, ParmList *l) |
| // |
| // Parser entry point for creating a constructor. |
| // |
| // Inputs : |
| // name = Real name of the constructor (usually the same as the class) |
| // iname = Renamed version (may be NULL) |
| // l = Parameter list |
| // |
| // Output : None |
| // |
| // Side Effects : |
| // Adds a constructor to the current class. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_constructor(char *name, char *iname, ParmList *l) { |
| |
| CPP_constructor *c; |
| |
| // May want to check the naming scheme here |
| |
| c = new CPP_constructor(name,iname,l); |
| current_class->add_member(c); |
| current_class->have_constructor = 1; |
| |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_destructor(char *name, char *iname) |
| // |
| // Parser entry point for adding a destructor. |
| // |
| // Inputs : |
| // name = Real name of the destructor (usually same as class name) |
| // iname = Renamed version (may be NULL) |
| // |
| // Output : None |
| // |
| // Side Effects : |
| // Adds a destructor to the current class |
| // |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_destructor(char *name, char *iname) { |
| |
| CPP_destructor *d; |
| |
| if (current_class->have_destructor) return; |
| d = new CPP_destructor(name,iname); |
| current_class->add_member(d); |
| current_class->have_destructor = 1; |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_variable(char *name, char *iname, SwigType *t) |
| // |
| // Parser entry point for creating a new member variable. |
| // |
| // Inputs : |
| // name = name of the variable |
| // iname = Renamed version (may be NULL) |
| // t = SwigType |
| // |
| // Output : None |
| // |
| // Side Effects : |
| // Adds a member variable to the current class |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_variable(char *name, char *iname, SwigType *t) { |
| |
| CPP_variable *v; |
| char *temp_iname; |
| |
| // If we're in inherit mode, we need to check for duplicates. |
| |
| if (iname) |
| temp_iname = iname; |
| else |
| temp_iname = name; |
| |
| if (Inherit_mode) { |
| if (current_class->search_member(temp_iname)) { |
| return; |
| } |
| } |
| |
| v = new CPP_variable(name,iname,t,0); |
| current_class->add_member(v); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_static_func(char *name, char *iname, SwigType *type, ParmList *l) |
| // |
| // Parser entry point for creating a new static member function. |
| // |
| // Inputs : |
| // name = Real name of the function |
| // iname = Renamed version (may be NULL) |
| // type = Return SwigType |
| // l = Parameter list |
| // |
| // Output : None |
| // |
| // Side Effects : |
| // Adds a static function to the current class. |
| // |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_static_func(char *name, char *iname, SwigType *type, ParmList *l) { |
| |
| char *temp_iname; |
| |
| // If we're in inherit mode, we need to check for duplicates. |
| |
| if (iname) temp_iname = iname; |
| else temp_iname = name; |
| |
| if (Inherit_mode) { |
| if (current_class->search_member(iname)) { |
| // Have a duplication |
| return; |
| } |
| } |
| |
| CPP_function *f = new CPP_function(name, temp_iname, type, l, 1); |
| current_class->add_member(f); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_declare_const(char *name, char *iname, SwigType *type, char *value) |
| // |
| // Parser entry point for creating a C++ constant (usually contained in an |
| // enum). |
| // |
| // Inputs : |
| // name = Real name of the constant |
| // iname = Renamed constant (may be NULL) |
| // type = Datatype of the constant |
| // value = String representation of the value |
| // |
| // Output : None |
| // |
| // Side Effects : |
| // Adds a constant to the current class. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_declare_const(char *name, char *iname, SwigType *type, char *value) { |
| |
| char *temp_iname; |
| |
| if (iname) temp_iname = iname; |
| else temp_iname = name; |
| |
| // If we're in inherit mode, we need to check for duplicates. |
| // Possibly issue a warning or perhaps a remapping |
| |
| if (Inherit_mode) { |
| if (current_class->search_member(temp_iname)) { |
| return; |
| } |
| } |
| |
| CPP_constant *c = new CPP_constant(name, temp_iname, type, value); |
| current_class->add_member(c); |
| |
| // Add this symbol to local scope of a class |
| add_local_type(name, current_class->classname); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_static_var(char *name, char *iname, SwigType *type) |
| // |
| // Parser entry point for adding a static variable |
| // |
| // Inputs : |
| // name = Name of the member |
| // iname = Renamed version (may be NULL) |
| // type = Datatype |
| // |
| // Output : None |
| // |
| // Side Effects : |
| // Adds a static variable to the current class. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_static_var(char *name, char *iname, SwigType *type) { |
| |
| char *temp_iname; |
| |
| if (iname) temp_iname = iname; |
| else temp_iname = name; |
| |
| // If we're in inherit mode, we need to check for duplicates. |
| // Possibly issue a warning or perhaps a remapping |
| |
| if (Inherit_mode) { |
| if (current_class->search_member(temp_iname)) { |
| return; |
| } |
| } |
| |
| CPP_variable *v = new CPP_variable(name, temp_iname, type, 1); |
| current_class->add_member(v); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // cplus_add_pragma(char *lang, char *name, char *value) |
| // |
| // Add a pragma to a class |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_add_pragma(char *lang, char *name, char *value) |
| { |
| Pragma *pp; |
| Pragma *p = new Pragma; |
| p->filename = NewString(input_file); |
| p->lang = NewString(lang); |
| p->name = NewString(name); |
| p->value = NewString(value); |
| p->next = 0; |
| p->lineno = line_number; |
| |
| if (!current_class->pragmas) { |
| current_class->pragmas = p; |
| return; |
| } |
| pp = current_class->pragmas; |
| while (pp->next) { |
| pp = pp->next; |
| } |
| pp->next = p; |
| } |
| |
| // ------------------------------------------------------------------------------ |
| // C++/Objective-C code generation functions |
| // |
| // The following functions are responsible for generating the wrapper functions |
| // for C++ and Objective-C methods and variables. These functions are usually |
| // called by specific language modules, but individual language modules can |
| // choose to do something else. |
| // |
| // The C++ module sets a number of internal state variables before emitting various |
| // pieces of code. These variables are often checked implicitly by these |
| // procedures even though nothing is passed on the command line. |
| // |
| // The code generator tries to be somewhat intelligent about what its doing. |
| // The member_hash Hash table keeps track of wrapped members and is used for |
| // sharing code between base and derived classes. |
| // ----------------------------------------------------------------------------- |
| |
| static DOHHash *member_hash = 0; // Hash wrapping member function wrappers to scripting wrappers |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_emit_member_func(char *classname, char *classtype, char *classrename, |
| // char *mname, char *mrename, SwigType *type, |
| // ParmList *l, int mode) |
| // |
| // This is a generic function to produce a C wrapper around a C++ member function. |
| // This function does the following : |
| // |
| // 1. Create a C wrapper function |
| // 2. Wrap the C wrapper function like a normal C function in SWIG |
| // 3. Add the function to the scripting language |
| // 4. Fill in the documentation entry |
| // |
| // Specific languages can choose to provide a different mechanism, but this |
| // function is used to provide a low-level C++ interface. |
| // |
| // The mode variable determines whether to create a new function or only to |
| // add it to the interpreter. This is used to support the %addmethods directive |
| // |
| // mode = 0 : Create a wrapper and add it (the normal mode) |
| // mode = 1 : Assume wrapper was already made and add it to the |
| // interpreter (%addmethods mode) |
| // |
| // Wrapper functions are usually created as follows : |
| // |
| // class Foo { |
| // int bar(args) |
| // } |
| // |
| // becomes .... |
| // Foo_bar(Foo *obj, args) { |
| // obj->bar(args); |
| // } |
| // |
| // if %addmethods mode is set AND there is supporting C code detected, make |
| // a function from it. The object is always called 'obj'. |
| // |
| // Then we wrap Foo_bar(). The name "Foo_bar" is actually contained in the parameter |
| // cname. This is so language modules can provide their own names (possibly for |
| // function overloading). |
| // |
| // This function makes no internal checks of the SWIG symbol table. This is |
| // up to the caller. |
| // |
| // Objective-C support (added 5/24/97) : |
| // |
| // If the class member function is part of an objective-C interface, everything |
| // works the same except that we change the calling mechanism to issue an |
| // Objective-C message. |
| // |
| // Optimizations (added 12/31/97) : |
| // |
| // For automatically generated wrapper functions. We now generate macros such |
| // as |
| // #define Foo_bar(a,b,c) (a->bar(b,c)) |
| // |
| // This should make the wrappers a little faster as well as reducing the amount |
| // of wrapper code. |
| // |
| // Inputs : |
| // classname = Name of C++ class |
| // classtype = Type of class (struct, union, class) |
| // classrename = Renamed class (if any) |
| // mname = Member name |
| // mrename = Renamed member |
| // type = Return type of the function |
| // l = Parameter list |
| // mode = addmethods mode |
| // |
| // Output : None |
| // |
| // Side Effects : |
| // Creates C accessor function in the wrapper file. |
| // Calls the language module to create a wrapper function. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_emit_member_func(char *classname, char *classtype, char *classrename, |
| char *mname, char *mrename, SwigType *type, ParmList *l, |
| int mode) { |
| |
| Wrapper *w; |
| char iname[512]; |
| char fullname[512]; |
| DOHString *key; |
| char *prev_wrap = 0; |
| |
| key = NewString(""); |
| |
| if (classtype) { |
| sprintf(fullname,"%s%s", classtype, classname); |
| } else { |
| strcpy(fullname, classname); |
| } |
| |
| w = Swig_cmethod_wrapper(fullname, mname, type, l, ccode); |
| |
| if (!classrename) classrename = classname; |
| if (!mrename) mrename = mname; |
| |
| strcpy(iname, Char(Swig_name_member(classrename, mrename))); |
| |
| if (!member_hash) member_hash = NewHash(); |
| |
| char *bc = cplus_base_class(mrename); |
| if (!bc || (strlen(bc) == 0)) { |
| bc = classname; |
| } |
| |
| /* Printf(key,"%s+%s",Wrapper_Getname(w), ParmList_protostr(l));*/ |
| Printf(key,"%s+%s", Swig_name_member(bc,mrename), ParmList_protostr(l)); |
| /* Printf(stdout,"virtual = %d, bc = %s, mkey = %s\n", IsVirtual, bc, key); */ |
| |
| if (Getattr(member_hash,key)) { |
| prev_wrap = GetChar(member_hash,key); |
| } else { |
| Setattr(member_hash,key,iname); |
| } |
| |
| if (!prev_wrap) { |
| if (mode && ccode) { |
| /* Produce an actual C wrapper */ |
| Wrapper_print(w,f_wrappers); |
| } else if (!mode) { |
| /* Nah. Just produce a string that does the work for us */ |
| emit_set_action(Swig_cmethod_call(mname, Wrapper_Getparms(w))); |
| } |
| lang->create_function(Wrapper_Getname(w), iname, Wrapper_Gettype(w), Wrapper_Getparms(w)); |
| DelWrapper(w); |
| } else { |
| lang->create_command(prev_wrap, iname); |
| } |
| Delete(key); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_emit_static_func(char *classname, char *classtype, char *classrename, |
| // char *mname, char *mrename, SwigType *type, |
| // ParmList *l, int mode) |
| // |
| // This is a generic function to produce a wrapper for a C++ static member function |
| // or an Objective-C class method. |
| // |
| // Specific languages can choose to provide a different mechanism, but this |
| // function is used to provide a low-level C++ interface. |
| // |
| // The mode variable determines whether to create a new function or only to |
| // add it to the interpreter. This is used to support the %addmethods directive |
| // |
| // mode = 0 : Create a wrapper and add it (the normal mode) |
| // mode = 1 : Assume wrapper was already made and add it to the |
| // interpreter (%addmethods mode) |
| // |
| // Wrapper functions are usually created as follows : |
| // |
| // class Foo { |
| // static int bar(args) |
| // } |
| // |
| // becomes a command called Foo_bar() |
| // |
| // if %addmethods mode is set AND there is supporting C code detected, make |
| // a function from it. |
| // |
| // Then we wrap Foo_bar(). The name "Foo_bar" is actually contained in the parameter |
| // cname. This is so language modules can provide their own names (possibly for |
| // function overloading). |
| // |
| // This function makes no internal checks of the SWIG symbol table. This is |
| // up to the caller. |
| // |
| // Inputs : |
| // classname = Name of C++ class |
| // classtype = Type of class (struct, union, class) |
| // classrename = Renamed version of class (optional) |
| // mname = Member name |
| // mrename = Renamed member (optional) |
| // type = Return type of the function |
| // l = Parameter list |
| // mode = addmethods mode |
| // |
| // Output : None |
| // |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_emit_static_func(char *classname, char *, char *classrename, |
| char *mname, char *mrename, SwigType *type, ParmList *l, |
| int mode) { |
| |
| char cname[512], iname[512]; |
| DOHString *key; |
| char *prev_wrap = 0; |
| |
| key = NewString(""); |
| |
| // Generate a function name for the member function |
| |
| if (!mrename) mrename = mname; |
| char *bc = cplus_base_class(mname); |
| |
| if (!bc) bc = classname; |
| if (strlen(bc) == 0) bc = classname; |
| |
| // Generate the name of the C wrapper function |
| if ((!mode) && (!ObjCClass)) { |
| sprintf(cname,"%s::%s", bc, mname); |
| } else { |
| strcpy(cname,Char(Swig_name_member(bc,mname))); |
| } |
| |
| // Generate the scripting name of this function |
| if (!classrename) classrename = classname; |
| strcpy(iname,Char(Swig_name_member(classrename, mrename))); |
| |
| // Perform a hash table lookup to see if we've wrapped anything like this before |
| Printf(key,"%s+%s",cname, ParmList_str(l)); |
| if (!member_hash) member_hash = NewHash(); |
| if (Getattr(member_hash,key)) { |
| prev_wrap = GetChar(member_hash,key); |
| } else { |
| Setattr(member_hash,key,iname); |
| } |
| |
| if (!prev_wrap) { |
| if (!mode) { |
| // Not an added method and not objective C, just wrap it |
| lang->create_function(cname,iname, type, l); |
| } else { |
| if (!ccode) { |
| strcpy(cname, Char(Swig_name_member(classname,mname))); |
| lang->create_function(cname,iname, type, l); |
| } else { |
| Wrapper *w = Swig_cfunction_wrapper(cname, type, l, ccode); |
| Wrapper_print(w,f_wrappers); |
| lang->create_function(cname,iname, Wrapper_Gettype(w), Wrapper_Getparms(w)); |
| DelWrapper(w); |
| } |
| } |
| } else { |
| // Already wrapped this function. Just hook up to it. |
| lang->create_command(prev_wrap, iname); |
| } |
| Delete(key); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_emit_destructor(char *classname, char *classtype, char *classrename, |
| // char *mname, char *mrename, int mode) |
| // |
| // Emit a C wrapper around a C++ destructor. |
| // |
| // Usually this function is used to do the following : |
| // class Foo { |
| // ... |
| // ~Foo(); |
| // } |
| // |
| // becomes .... |
| // void delete_Foo(Foo *f) { |
| // delete f; |
| // } |
| // |
| // Then we wrap delete_Foo(). |
| // |
| // Inputs : |
| // classname = Name of the C++ class |
| // classtype = Type of class (struct,class,union) |
| // classrename = Renamed class (optional) |
| // mname = Name of the destructor |
| // mrename = Name of the function in the interpreter |
| // mode = addmethods mode (0 or 1) |
| // |
| // Output : None |
| // |
| // Side Effects : |
| // Creates a destructor function and wraps it. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_emit_destructor(char *classname, char *classtype, char *classrename, |
| char *mname, char *mrename, int mode) |
| { |
| Wrapper *w; |
| char cname[512],iname[512]; |
| char fclassname[512]; |
| |
| if (!classrename) classrename = classname; |
| |
| strcpy(cname,Char(Swig_name_destroy(classname))); |
| if (mrename) |
| strcpy(iname, Char(Swig_name_destroy(mrename))); |
| else |
| strcpy(iname, Char(Swig_name_destroy(classrename))); |
| |
| sprintf(fclassname,"%s%s", classtype, classname); |
| if (CPlusPlus) { |
| w = Swig_cppdestructor_wrapper(fclassname,ccode); |
| } else { |
| w = Swig_cdestructor_wrapper(fclassname, ccode); |
| } |
| if (mode && ccode) { |
| Wrapper_print(w,f_wrappers); |
| lang->create_function(Wrapper_Getname(w),iname,Wrapper_Gettype(w), Wrapper_Getparms(w)); |
| } else if (mode) { |
| lang->create_function(Wrapper_Getname(w),iname,Wrapper_Gettype(w), Wrapper_Getparms(w)); |
| } else { |
| if (CPlusPlus) |
| emit_set_action(Swig_cppdestructor_call()); |
| else |
| emit_set_action(Swig_cdestructor_call()); |
| lang->create_function(cname, iname, Wrapper_Gettype(w), Wrapper_Getparms(w)); |
| } |
| DelWrapper(w); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_emit_constructor(char *classname, char *classtype, char *classrename, |
| // char *mname, char *mrename, ParmList *l, int mode) |
| // |
| // Creates a C wrapper around a C++ constructor |
| // |
| // Inputs : |
| // classname = name of class |
| // classtype = type of class (struct,class,union) |
| // classrename = Renamed class (optional) |
| // mname = Name of constructor |
| // mrename = Renamed constructor (optional) |
| // l = Parameter list |
| // mode = addmethods mode |
| // |
| // Output : None |
| // |
| // Side Effects : |
| // Creates a C wrapper and calls the language module to wrap it. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_emit_constructor(char *classname, char *classtype, char *classrename, |
| char *mname, char *mrename, ParmList *l, int mode) |
| { |
| char cname[512],iname[512]; |
| char fclassname[512]; |
| Wrapper *w; |
| // Construct names for the function |
| |
| if (!classrename) classrename = classname; |
| strcpy(cname,Char(Swig_name_construct(classname))); |
| if (mrename) |
| strcpy(iname, Char(Swig_name_construct(mrename))); |
| else |
| strcpy(iname, Char(Swig_name_construct(classrename))); |
| |
| sprintf(fclassname,"%s%s", classtype, classname); |
| |
| if (CPlusPlus) { |
| w = Swig_cppconstructor_wrapper(fclassname, l, ccode); |
| } else { |
| w = Swig_cconstructor_wrapper(fclassname, l, ccode); |
| } |
| |
| if (!mode) { |
| if (CPlusPlus) { |
| emit_set_action(Swig_cppconstructor_call(fclassname, l)); |
| } else { |
| emit_set_action(Swig_cconstructor_call(fclassname)); |
| } |
| } else { |
| if (ccode) { |
| Wrapper_print(w,f_wrappers); |
| } |
| } |
| lang->create_function(Wrapper_Getname(w), iname, Wrapper_Gettype(w), Wrapper_Getparms(w)); |
| DelWrapper(w); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_emit_variable_get(char *classname, char *classtype, char *classrename, |
| // char *mname, char *mrename, SwigType *type, int mode) |
| // |
| // Writes a C wrapper to extract a data member |
| // |
| // Usually this function works as follows : |
| // |
| // class Foo { |
| // double x; |
| // } |
| // |
| // becomes : |
| // |
| // double Foo_x_get(Foo *obj) { |
| // return obj->x; |
| // } |
| // |
| // Optimization : 12/31/97 |
| // |
| // Now emits a macro like this : |
| // |
| // #define Foo_x_get(obj) (obj->x) |
| // |
| // Inputs : |
| // classname = name of C++ class |
| // classtype = type of class (struct, class, union) |
| // classrename = Renamed class |
| // mname = Member name |
| // mrename = Renamed member |
| // type = Datatype of the member |
| // mode = Addmethods mode |
| // |
| // Output : None |
| // |
| // Side Effects : |
| // Creates a C accessor function and calls the language module |
| // to make a wrapper around it. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_emit_variable_get(char *classname, char *classtype, char *classrename, |
| char *mname, char *mrename, SwigType *type, int mode) { |
| |
| char cname[512],iname[512], fclassname[512]; |
| char key[512]; |
| char *prev_wrap = 0; |
| Wrapper *w; |
| |
| // First generate a proper name for the get function |
| |
| // Get the base class of this member |
| if (!mrename) mrename = mname; |
| |
| char *bc = cplus_base_class(mrename); |
| if (!bc) bc = classname; |
| if (strlen(bc) == 0) bc = classname; |
| |
| // Generate the name of the C wrapper function (is always the same, regardless |
| // of renaming). |
| |
| strcpy(cname, Char(Swig_name_get(Swig_name_member(bc,mname)))); |
| |
| // Generate the scripting name of this function |
| if (!classrename) classrename = classname; |
| strcpy(iname, Char(Swig_name_get(Swig_name_member(classrename,mrename)))); |
| |
| // Now check to see if we have already wrapped a variable like this. |
| |
| strcpy(key,cname); |
| if (!member_hash) member_hash = NewHash(); |
| if (Getattr(member_hash,key)) { |
| prev_wrap = GetChar(member_hash,key); |
| } else { |
| Setattr(member_hash,key,iname); |
| } |
| |
| sprintf(fclassname,"%s%s", classtype, classname); |
| w = Swig_cmemberget_wrapper(fclassname,mname,type,ccode); |
| |
| // Only generate code if already existing wrapper doesn't exist |
| if (!prev_wrap) { |
| if ((mode) && (ccode)) { |
| Wrapper_print(w,f_wrappers); |
| } else if (!mode) { |
| emit_set_action(Swig_cmemberget_call(mname, type)); |
| } |
| lang->create_function(Wrapper_Getname(w),iname, Wrapper_Gettype(w), Wrapper_Getparms(w)); |
| } else { |
| // Already wrapped this function. Just patch it up |
| lang->create_command(prev_wrap,iname); |
| } |
| DelWrapper(w); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_emit_variable_set(char *classname, char *classtype, char *mname, |
| // char *cname, char *iname, SwigType *type, int mode) |
| // |
| // Writes a C wrapper to set a data member |
| // |
| // Usually this function works as follows : |
| // |
| // class Foo { |
| // double x; |
| // } |
| // |
| // becomes : |
| // |
| // double Foo_x_set(Foo *obj, double value) { |
| // return (obj->x = value); |
| // } |
| // |
| // Need to handle special cases for char * and for user defined types. |
| // |
| // 1. char * |
| // |
| // Will free previous contents (if any) and allocate |
| // new storage. Could be risky, but it's a reasonably |
| // natural thing to do. |
| // |
| // 2. User_Defined |
| // Will assign value from a pointer. |
| // Will return a pointer to current value. |
| // |
| // |
| // Optimization, now defined as a C preprocessor macro |
| // |
| // Inputs : |
| // classname = name of C++ class |
| // classtype = type of class (struct, class, union) |
| // mname = Member name |
| // cname = Name of the C function for this (ie. Foo_bar_get) |
| // iname = Interpreter name of ths function |
| // type = Datatype of the member |
| // mode = Addmethods mode |
| // |
| // Output : None |
| // |
| // Side Effects : |
| // Creates a C accessor function and calls the language module |
| // to wrap it. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_emit_variable_set(char *classname, char *classtype, char *classrename, |
| char *mname, char *mrename, SwigType *type, int mode) { |
| |
| char cname[512], iname[512]; |
| char key[512]; |
| char fclassname[512]; |
| char *prev_wrap = 0; |
| Wrapper *w; |
| // Get the base class of this member |
| if (!mrename) mrename = mname; |
| |
| char *bc = cplus_base_class(mrename); |
| if (!bc) bc = classname; |
| if (strlen(bc) == 0) bc = classname; |
| |
| // Generate the name of the C wrapper function (is always the same, regardless |
| // of renaming). |
| |
| strcpy(cname, Char(Swig_name_set(Swig_name_member(bc,mname)))); |
| |
| if (!classrename) classrename = classname; |
| strcpy(iname, Char(Swig_name_set(Swig_name_member(classrename, mrename)))); |
| |
| |
| // Now check to see if we have already wrapped a variable like this. |
| |
| strcpy(key,cname); |
| if (!member_hash) member_hash = NewHash(); |
| if (Getattr(member_hash,key)) { |
| prev_wrap = GetChar(member_hash,key); |
| } else { |
| Setattr(member_hash,key,iname); |
| } |
| |
| sprintf(fclassname,"%s%s",classtype,classname); |
| w = Swig_cmemberset_wrapper(fclassname,mname,type,ccode); |
| |
| // Only generate code if already existing wrapper doesn't exist |
| |
| if (!prev_wrap) { |
| if ((mode) && (ccode)) { |
| Wrapper_print(w,f_wrappers); |
| } else if (!mode) { |
| /* Check for a member in typemap here */ |
| String *target = NewStringf("%s->%s", Swig_cparm_name(0,0),mname); |
| char *tm = Swig_typemap_lookup("memberin",type,mname,Swig_cparm_name(0,1),target,0); |
| if (!tm) |
| emit_set_action(Swig_cmemberset_call(mname,type)); |
| else |
| emit_set_action(tm); |
| Delete(target); |
| } |
| lang->create_function(Wrapper_Getname(w),iname, Wrapper_Gettype(w), Wrapper_Getparms(w)); |
| } else { |
| lang->create_command(prev_wrap,iname); |
| } |
| DelWrapper(w); |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_register_type(char *typename) |
| // |
| // Registers a datatype name to be associated with the current class. This |
| // typename is placed into a local hash table for later use. For example : |
| // |
| // class foo { |
| // public: |
| // enum ENUM { ... }; |
| // typedef double Real; |
| // void bar(ENUM a, Real b); |
| // } |
| // |
| // Then we need to access bar using fully qualified type names such as |
| // |
| // void wrap_bar(foo::ENUM a, foo::Real b) { |
| // bar(a,b); |
| // } |
| // |
| // Inputs : name of the datatype. |
| // |
| // Output : None |
| // |
| // Side Effects : Adds datatype to localtypes. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_register_type(char *tname) { |
| if (current_class) |
| add_local_type(tname, current_class->classname); |
| }; |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_register_scope(void *h) |
| // |
| // Saves the scope associated with a particular class. It will be needed |
| // later if anything inherits from us. |
| // |
| // Inputs : Hash table h containing the scope |
| // |
| // Output : None |
| // |
| // Side Effects : Saves h with current class |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_register_scope(void *h) { |
| if (current_class) { |
| current_class->scope = h; |
| } |
| } |
| |
| // ----------------------------------------------------------------------------- |
| // void cplus_inherit_scope(int count, char **baseclass) |
| // |
| // Given a list of base classes, this function extracts their former scopes |
| // and merges them with the current scope. This is needed to properly handle |
| // inheritance. |
| // |
| // Inputs : baseclass = NULL terminated array of base-class names |
| // |
| // Output : None |
| // |
| // Side Effects : Updates current scope with new symbols. |
| // |
| // Copies any special symbols if needed. |
| // ----------------------------------------------------------------------------- |
| |
| void cplus_inherit_scope(int count, char **baseclass) { |
| CPP_class *bc; |
| int i; |
| char *val; |
| DOH *key; |
| if (count && current_class) { |
| for (i = 0; i < count; i++) { |
| bc = CPP_class::search(baseclass[i]); |
| if (bc) { |
| if (bc->scope) { |
| SwigType_merge_scope(bc->scope,0); |
| } |
| if (bc->local) { |
| // Copy local symbol table |
| key = Firstkey(bc->local); |
| while (key) { |
| val = GetChar(bc->local,key); |
| Setattr(localtypes,key,val); |
| key = Nextkey(bc->local); |
| } |
| } |
| } |
| } |
| } |
| } |
| |