special cases and other things in wxPython, and since I plan on making several more, I've decided to put the SWIG sources in wxPython's CVS instead of relying on maintaining patches. This effectivly becomes a fork of an obsolete version of SWIG, :-( but since SWIG 1.3 still doesn't have some things I rely on in 1.1, not to mention that my custom patches would all have to be redone, I felt that this is the easier road to take. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15307 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			622 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			622 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*******************************************************************************
 | |
|  * Simplified Wrapper and Interface Generator  (SWIG)
 | |
|  * 
 | |
|  * Author : David Beazley
 | |
|  *
 | |
|  * Department of Computer Science        
 | |
|  * University of Chicago
 | |
|  * 1100 E 58th Street
 | |
|  * Chicago, IL  60637
 | |
|  * beazley@cs.uchicago.edu
 | |
|  *
 | |
|  * Please read the file LICENSE for the copyright and terms by which SWIG
 | |
|  * can be used and distributed.
 | |
|  *******************************************************************************/
 | |
| 
 | |
| #include "internal.h"
 | |
| #include <ctype.h>
 | |
| 
 | |
| 
 | |
| // -----------------------------------------------------------------------
 | |
| // $Header$
 | |
| //
 | |
| // lang.cxx
 | |
| //
 | |
| // This file contains some default methods for the SWIG language class.   
 | |
| // Default C++ handling is implemented here as well as a few utility functions.
 | |
| //
 | |
| // -----------------------------------------------------------------------
 | |
| 
 | |
| 
 | |
| // -----------------------------------------------------------------
 | |
| // void Language::set_init(char *iname)
 | |
| //
 | |
| // Called to make an initialization function by %init (obsolete)
 | |
| // ----------------------------------------------------------------- 
 | |
| 
 | |
| void Language::set_init(char *iname) {
 | |
|   set_module(iname,0);
 | |
| }
 | |
| 
 | |
| // -----------------------------------------------------------------
 | |
| // void Language::create_command(char *cname, char *iname
 | |
| //
 | |
| // Method for adding a previous wrapped C function.
 | |
| // ----------------------------------------------------------------- 
 | |
| 
 | |
| void Language::create_command(char *, char *) {
 | |
|   fprintf(stderr,"SWIG Warning. No command creation procedure defined.\n");
 | |
|   fprintf(stderr,"C++ inheritance may not work correctly.\n");
 | |
| }
 | |
| 
 | |
| // -----------------------------------------------------------------
 | |
| // void Language::add_native(char *targetlang, char *funcname)
 | |
| //
 | |
| // Method for adding a native function
 | |
| // ----------------------------------------------------------------- 
 | |
| 
 | |
| void
 | |
| Language::add_native(char *, char *funcname) {
 | |
| 
 | |
|   fprintf(stderr,"%s : Line %d.  Adding native function %s not supported (ignored).\n", input_file, line_number, funcname);
 | |
| 
 | |
| }
 | |
| 
 | |
| static char  *ClassName = 0;        // This is the real name of the current class
 | |
| static char  *ClassRename = 0;      // This is non-NULL if the class has been renamed
 | |
| static char  *ClassType = 0;        // Type of class (ie. union, struct, class) 
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::cpp_open_class(char *classname, char *classrename, char *ctype, int strip)
 | |
| //
 | |
| // Open a new C++ class.
 | |
| //
 | |
| // INPUTS:
 | |
| //      classname          = Real name of the C++ class
 | |
| //      classrename        = New name of the class (if %name was used)
 | |
| //      ctype              = Class type (struct, class, union, etc...)
 | |
| //      strip              = Flag indicating whether we should strip the class type off
 | |
| //
 | |
| // This function is in charge of creating a new class.   The SWIG parser has
 | |
| // already processed the entire class definition prior to calling this
 | |
| // function (which should simplify things considerably).
 | |
| //
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_open_class(char *classname, char *classrename, char *ctype, int strip) {
 | |
| 
 | |
|   // Copy the class name
 | |
| 
 | |
|   if (ClassName) delete ClassName;
 | |
|   ClassName = copy_string(classname);
 | |
| 
 | |
|   // Copy the class renaming
 | |
| 
 | |
|   if (ClassRename) delete ClassRename;
 | |
|   if (classrename) {
 | |
|     ClassRename = copy_string(classrename);
 | |
|   } else {
 | |
|     ClassRename = 0;           // No renaming
 | |
|   }
 | |
| 
 | |
|   // Make the class type
 | |
| 
 | |
|   if (ClassType) delete ClassType;
 | |
|   ClassType = new char[strlen(ctype)+2];
 | |
|   if (strip) ClassType[0] = 0;
 | |
|   else sprintf(ClassType,"%s ",ctype);
 | |
| 
 | |
|   if (doc_entry) {
 | |
|     doc_entry->usage = "";
 | |
|     doc_entry->name = copy_string(classname);
 | |
|     doc_entry->usage << "class ";
 | |
|     if (ClassRename) doc_entry->usage << ClassRename;
 | |
|     else doc_entry->usage << ClassName;
 | |
|     doc_entry->cinfo << "created from " << ctype 
 | |
| 		     << " " << classname;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::cpp_close_class()
 | |
| //
 | |
| // Close the current class
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_close_class() {
 | |
| 
 | |
| 
 | |
|   // Doesn't really do anything 
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l)
 | |
| //
 | |
| // Method for adding C++ member function
 | |
| //
 | |
| // INPUTS:
 | |
| //      name        - name of the member function
 | |
| //      iname       - renaming (if given)
 | |
| //      t           - Return datatype
 | |
| //      l           - Parameter list
 | |
| //
 | |
| // By default, we're going to create a function of the form :
 | |
| //
 | |
| //         Foo_bar(this,args)
 | |
| //
 | |
| // Where Foo is the classname, bar is the member name and the this pointer is
 | |
| // explicitly attached to the beginning.
 | |
| //
 | |
| // The renaming only applies to the member function part, not the full classname.
 | |
| //
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_member_func(char *name, char *iname, DataType *t, ParmList *l) {
 | |
|   char       cname[256];       // Name of the C function
 | |
|   char       new_name[256];
 | |
|   char       *prefix;
 | |
| 
 | |
|   // Generate the C wrapper function name and interpreter name of this function
 | |
|   
 | |
|   // Set the classname prefix
 | |
|   if (ClassRename) {
 | |
|     prefix = ClassRename;
 | |
|   } else {
 | |
|     prefix = ClassName;
 | |
|   }
 | |
| 
 | |
|   // Generate the C wrapper name for this method
 | |
|   
 | |
|   if (AddMethods) {
 | |
|     char *bc = cplus_base_class(name);         // Get base class name of this method
 | |
|     if (bc)
 | |
|       strcpy(cname, name_member(name,bc));
 | |
|     else
 | |
|       strcpy(cname, name_member(name,ClassName));
 | |
|   } else {
 | |
|     strcpy(cname, name_member(name,ClassName));
 | |
|   }
 | |
| 
 | |
|   // Create the actual function name
 | |
| 
 | |
|   if (iname) {
 | |
|     strcpy(new_name, name_member(iname, prefix));
 | |
|   } else {
 | |
|     strcpy(new_name, name_member(name,prefix));
 | |
|   }
 | |
| 
 | |
|   // Now do a symbol table lookup on it :
 | |
| 
 | |
|   if (add_symbol(new_name, 0,0)) {
 | |
|     fprintf(stderr,"%s : Line %d. Function %s (member %s) multiply defined (2nd definition ignored).\n",
 | |
| 	    input_file, line_number, cname, name);
 | |
|     return;
 | |
|   }
 | |
|   
 | |
|   // Now produce the resulting wrapper function
 | |
|   if (doc_entry) {
 | |
|     doc_entry->cinfo << "Member : ";
 | |
|   }
 | |
|   cplus_emit_member_func(ClassName, ClassType, ClassRename, name, iname, t, l, AddMethods);
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::cpp_constructor(char *name, char *iname, ParmList *l)
 | |
| //
 | |
| // Method for adding C++ member constructor
 | |
| //
 | |
| // INPUTS:
 | |
| //      name           - Name of the constructor (usually same as classname)
 | |
| //      iname          - Renamed version
 | |
| //      l              - parameters
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_constructor(char *name, char *iname, ParmList *l) {
 | |
| 
 | |
|   char *prefix, *cname;
 | |
| 
 | |
|   if ((strcmp(name,ClassName)) && (!ObjCClass)) {
 | |
|     fprintf(stderr,"%s : Line %d.  Function %s must have a return type.\n", 
 | |
| 	    input_file, line_number, name);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Set the prefix
 | |
| 
 | |
|   if (ClassRename)
 | |
|     prefix = ClassRename;
 | |
|   else
 | |
|     prefix = ClassName;
 | |
| 
 | |
|   if (iname)
 | |
|     cname = name_construct(iname);
 | |
|   else
 | |
|     cname = name_construct(prefix);
 | |
| 
 | |
|   // Add this function to the SWIG symbol table
 | |
| 
 | |
|   if (add_symbol(cname, 0,0)) {
 | |
|     fprintf(stderr,"%s : Line %d. Constructor %s multiply defined (2nd definition ignored).\n",
 | |
| 	    input_file, line_number, cname);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Attach a note to the cinfo field.
 | |
| 
 | |
|   if (doc_entry) 
 | |
|     doc_entry->cinfo << "Constructor: ";
 | |
| 
 | |
|   // Call our default method
 | |
| 
 | |
|   cplus_emit_constructor(ClassName, ClassType, ClassRename, name, iname, l, AddMethods);
 | |
| 
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::cpp_destructor(char *name, char *iname)
 | |
| //
 | |
| // Method for adding C++ member destructor
 | |
| //
 | |
| // INPUT:
 | |
| //     name        -  Name of the destructor (classname)
 | |
| //     iname       -  Renamed destructor
 | |
| //
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_destructor(char *name, char *iname) {
 | |
| 
 | |
|   char *cname;
 | |
| 
 | |
|   if (ClassRename) 
 | |
|     cname = name_destroy(ClassRename);
 | |
|   else
 | |
|     cname = name_destroy(ClassName);
 | |
| 
 | |
|   // Add this function to the SWIG symbol table
 | |
| 
 | |
|   if (add_symbol(cname, 0,0)) {
 | |
|     fprintf(stderr,"%s : Line %d. Destructor %s multiply defined (2nd definition ignored).\n",
 | |
| 	    input_file, line_number, cname);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
| 
 | |
|   // Attach a note to the description
 | |
| 
 | |
|   if (doc_entry)
 | |
|     doc_entry->cinfo << "Destructor: ";
 | |
| 
 | |
|   // Call our default method
 | |
| 
 | |
|   cplus_emit_destructor(ClassName, ClassType, ClassRename, name, iname, AddMethods);
 | |
| 
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::cleanup()
 | |
| //
 | |
| // Perform any necessary cleanup after reaching end of interface file
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_cleanup() {
 | |
| 
 | |
|   // This doesn't do anything (well, not be default)
 | |
| 
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::cpp_inherit(char **baseclass, int mode)
 | |
| //
 | |
| // Inherit attributes from given baseclass.  
 | |
| //
 | |
| // INPUT:
 | |
| //     baseclass       = NULL terminate list of baseclasses
 | |
| //
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_inherit(char **baseclass, int mode) {
 | |
|   
 | |
|   extern void cplus_inherit_members(char *, int);
 | |
|   int    i = 0;
 | |
| 
 | |
|   if (!baseclass) return;
 | |
|   while (baseclass[i]) {
 | |
|     cplus_inherit_members(baseclass[i],mode);
 | |
|     i++;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::cpp_variable(char *name, char *iname, DataType *t)
 | |
| //
 | |
| // Wrap a C++ data member
 | |
| //
 | |
| // INPUTS :
 | |
| //      name       = Name of the C++ member
 | |
| //     iname       = Name as used in the interpreter
 | |
| //         t       = Datatype
 | |
| //
 | |
| // This creates a pair of functions to set/get the variable of a member.
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_variable(char *name, char *iname, DataType *t) {
 | |
|   char *prefix, *cname;
 | |
| 
 | |
|   // Set the class prefix
 | |
|   
 | |
|   if (ClassRename) {
 | |
|     prefix = ClassRename;
 | |
|   } else {
 | |
|     prefix = ClassName;
 | |
|   }
 | |
| 
 | |
|   if (iname)
 | |
|     cname = name_get(name_member(iname,prefix));
 | |
|   else
 | |
|     cname = name_get(name_member(name,prefix));
 | |
| 
 | |
|   // Check the symbol table
 | |
| 
 | |
|   if (add_symbol(cname,(DataType *) 0,(char *) 0)) {
 | |
|     fprintf(stderr,"%s : Line %d. Variable %s multiply defined (2nd definition ignored).\n", input_file, line_number, cname);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Attach a c descriptor
 | |
| 
 | |
|   if (doc_entry)
 | |
|     doc_entry->cinfo << "Member data: ";
 | |
| 
 | |
|   // Create a function to set the value of the variable
 | |
| 
 | |
|   if (!(Status & STAT_READONLY)) {
 | |
|     cplus_emit_variable_set(ClassName, ClassType, ClassRename, name, iname, t, AddMethods);
 | |
|     // Add a new line to the documentation entry
 | |
|     if (doc_entry) doc_entry->usage << "\n";
 | |
|   }
 | |
| 
 | |
|   // Create a function to get the value of a variable
 | |
| 
 | |
|   cplus_emit_variable_get(ClassName,ClassType, ClassRename, name, iname, t, AddMethods);
 | |
| 
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::cpp_static_func(char *name, char *iname, DataType *t, ParmList *l)
 | |
| //
 | |
| // Wrap a static C++ function
 | |
| //
 | |
| // INPUTS:
 | |
| //      name           = Real name of the function
 | |
| //     iname           = New name in interpreter
 | |
| //      t              = Return datatype
 | |
| //      l              = Parameters
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_static_func(char *name, char *iname, DataType *t, ParmList *l) {
 | |
| 
 | |
|   char  *prefix;
 | |
|   char  *mname;
 | |
|   char  *cname;
 | |
| 
 | |
|   // Set the classname prefix
 | |
|   
 | |
|   if (ClassRename) 
 | |
|     prefix = ClassRename;
 | |
|   else
 | |
|     prefix = ClassName;
 | |
| 
 | |
|   // Set the member function name
 | |
| 
 | |
|   if (iname)
 | |
|     mname = iname;
 | |
|   else
 | |
|     mname = name;
 | |
| 
 | |
|   cname = name_member(mname,prefix);
 | |
| 
 | |
|   // Now do a symbol table lookup on it :
 | |
| 
 | |
|   if (add_symbol(cname, 0,0)) {
 | |
|     if (ObjCClass)
 | |
|       fprintf(stderr,"%s : Line %d. class function %s multiply defined (2nd definition ignored).\n",
 | |
| 	      input_file, line_number, cname);
 | |
|     else
 | |
|       fprintf(stderr,"%s : Line %d. static function %s multiply defined (2nd definition ignored).\n",
 | |
| 	      input_file, line_number, cname);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   if (doc_entry) {
 | |
|     if (ObjCClass)
 | |
|       doc_entry->cinfo << "Class method : ";
 | |
|     else
 | |
|       doc_entry->cinfo << "Static member : ";
 | |
|   }
 | |
| 
 | |
|   cplus_emit_static_func(ClassName,ClassType, ClassRename, name, iname, t, l, AddMethods);
 | |
| 
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::cpp_declare_const(char *name, char *iname, DataType *t, char *value)
 | |
| //
 | |
| // Create a C++ constant
 | |
| //
 | |
| // INPUTS :
 | |
| //       name          = Real name of the constant
 | |
| //       iname         = new name
 | |
| //       t             = Datatype
 | |
| //       value         = value as a string
 | |
| //
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_declare_const(char *name, char *iname, DataType *type, char *value)
 | |
| {
 | |
| 
 | |
|   char  *cname;
 | |
|   char  mname[256];
 | |
|   char  *new_value;
 | |
|   char  *prefix;
 | |
| 
 | |
|   // Set the classname prefix
 | |
|   
 | |
|   if (ClassRename) {
 | |
|     prefix = ClassRename;
 | |
|   } else {
 | |
|     prefix = ClassName;
 | |
|   }
 | |
| 
 | |
|   // Set the constant name
 | |
| 
 | |
|   if (iname)
 | |
|     cname = name_member(iname,prefix);
 | |
|   else
 | |
|     cname = name_member(name,prefix);
 | |
| 
 | |
|   // Now do a symbol table lookup on it :
 | |
| 
 | |
|   if (add_symbol(cname, 0,0)) {
 | |
|     fprintf(stderr,"%s : Line %d. Constant %s (member %s) multiply defined (2nd definition ignored).\n",
 | |
| 	    input_file, line_number, cname, name);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Form correct C++ name
 | |
| 
 | |
|   sprintf(mname,"%s::%s",ClassName,name);
 | |
| 
 | |
|   // Declare a constant
 | |
|   if (!value) {
 | |
|     new_value = new char[strlen(ClassName)+strlen(name)+3];
 | |
|     sprintf(new_value,"%s::%s",ClassName,name);
 | |
|   } else {
 | |
|     new_value = value;
 | |
|   }
 | |
| 
 | |
|   lang->declare_const(cname,cname,type, new_value);
 | |
|   
 | |
|   if (!value) {
 | |
|     delete new_value;
 | |
|   }
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::cpp_static_var(char *name, char *iname, DataType *t)
 | |
| //
 | |
| // Wrap a static C++ variable
 | |
| //
 | |
| // INPUT :
 | |
| //      name        = name of the variable
 | |
| //     iname        = interpreter name
 | |
| //         t        = Datatype
 | |
| //
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_static_var(char *name, char *iname, DataType *t) {
 | |
| 
 | |
|   char  *cname;
 | |
|   char  mname[256];
 | |
|   char  *prefix;
 | |
| 
 | |
|   // Set the classname prefix
 | |
|   
 | |
|   if (ClassRename) {
 | |
|     prefix = ClassRename;
 | |
|   } else {
 | |
|     prefix = ClassName;
 | |
|   }
 | |
| 
 | |
|   // Create the variable name
 | |
|   
 | |
|   if (iname) 
 | |
|     cname = name_member(iname,prefix);
 | |
|   else
 | |
|     cname = name_member(name,prefix);
 | |
| 
 | |
|   // Now do a symbol table lookup on it :
 | |
| 
 | |
|   if (add_symbol(cname, 0,0)) {
 | |
|     fprintf(stderr,"%s : Line %d. Variable %s (member %s) multiply defined (2nd definition ignored).\n",
 | |
| 	    input_file, line_number, cname, name);
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   // Form correct C++ name
 | |
| 
 | |
|   sprintf(mname,"%s::%s",ClassName,name);
 | |
| 
 | |
|   if (doc_entry)
 | |
|     doc_entry->cinfo << "Static member : ";
 | |
| 
 | |
|   // Link with this variable
 | |
| 
 | |
|   lang->link_variable(mname,cname,t);
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::cpp_class_decl(char *classtype, char *classrename, char *classname)
 | |
| //
 | |
| // A forward class declaration
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_class_decl(char *, char *, char *) {
 | |
| 
 | |
|   // Does nothing by default
 | |
| 
 | |
| }
 | |
| 
 | |
| // -----------------------------------------------------------------------------
 | |
| // void Language::cpp_pragma(Pragma *plist)
 | |
| //
 | |
| // Handler C++ pragmas
 | |
| // -----------------------------------------------------------------------------
 | |
| 
 | |
| void Language::cpp_pragma(Pragma *) {
 | |
|   // Does nothing by default
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::add_typedef(DataType *t, char *name)
 | |
| //
 | |
| // Process a typedef declaration.
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::add_typedef(DataType *, char *) {
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::pragma(char *target, char *var, char *value)
 | |
| //
 | |
| // A pragma declaration
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::pragma(char *, char *, char *) {
 | |
| 
 | |
|   // Does nothing by default
 | |
| 
 | |
| }
 | |
| 
 | |
| // ---------------------------------------------------------------------------------
 | |
| // void Language::import(char *filename)
 | |
| //
 | |
| // An import directive
 | |
| // ---------------------------------------------------------------------------------
 | |
| 
 | |
| void Language::import(char *) {
 | |
| 
 | |
|   // Does nothing by default
 | |
| 
 | |
| }
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 | |
| 
 |