/*******************************************************************************
* Simplified Wrapper and Interface Generator (SWIG)
*
* Dave Beazley
*
* Department of Computer Science Theoretical Division (T-11)
* University of Utah Los Alamos National Laboratory
* Salt Lake City, Utah 84112 Los Alamos, New Mexico 87545
* beazley@cs.utah.edu beazley@lanl.gov
*
* Copyright (c) 1995-1997
* The University of Utah and the Regents of the University of California
* All Rights Reserved
*
* Permission is hereby granted, without written agreement and without
* license or royalty fees, to use, copy, modify, and distribute this
* software and its documentation for any purpose, provided that
* (1) The above copyright notice and the following two paragraphs
* appear in all copies of the source code and (2) redistributions
* including binaries reproduces these notices in the supporting
* documentation. Substantial modifications to this software may be
* copyrighted by their authors and need not follow the licensing terms
* described here, provided that the new terms are clearly indicated in
* all files where they apply.
*
* IN NO EVENT SHALL THE AUTHOR, THE UNIVERSITY OF CALIFORNIA, THE
* UNIVERSITY OF UTAH OR DISTRIBUTORS OF THIS SOFTWARE BE LIABLE TO ANY
* PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL
* DAMAGES ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
* EVEN IF THE AUTHORS OR ANY OF THE ABOVE PARTIES HAVE BEEN ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
* THE AUTHOR, THE UNIVERSITY OF CALIFORNIA, AND THE UNIVERSITY OF UTAH
* SPECIFICALLY DISCLAIM ANY WARRANTIES,INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND
* THE AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE MAINTENANCE,
* SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
*
*******************************************************************************/
/**********************************************************************
* $Header: /home/beazley/SWIG/SWIG1.2/Modules/RCS/python.cxx,v 1.60 1997/07/27 20:29:59 beazley Exp $
*
* python.cxx
*
* Python module.
**************************************************************************/
#include "swig.h"
#include "python.h"
// Structures for managing doc strings
struct DocString {
DocEntry *de;
char *name;
DocString *next;
};
static int doc_index = 0;
static DocString *doc_strings = 0;
static char *usage = "\
Python Options (available with -python)\n\
-docstring - Produce docstrings (only applies to shadow classes)\n\
-globals name - Set name used to access C global variable ('cvar' by default).\n\
-module name - Set module name\n\
-shadow - Generate shadow classes. \n\n";
static String pragma_include;
// ---------------------------------------------------------------------
// PYTHON::parse_args(int argc, char *argv[])
//
// ---------------------------------------------------------------------
void PYTHON::parse_args(int argc, char *argv[]) {
int i = 1;
sprintf(LibDir,"%s",path);
docstring = 0;
// Look for additional command line options.
for (i = 1; i < argc; i++) {
if (argv[i]) {
if(strcmp(argv[i],"-module") == 0) {
if (argv[i+1]) {
module = new char[strlen(argv[i+1])+2];
strcpy(module, argv[i+1]);
mark_arg(i);
mark_arg(i+1);
i+=1;
} else {
arg_error();
}
} else if (strcmp(argv[i],"-globals") == 0) {
if (argv[i+1]) {
global_name = new char[strlen(argv[i+1])+1];
strcpy(global_name, argv[i+1]);
mark_arg(i);
mark_arg(i+1);
i++;
} else {
arg_error();
}
} else if (strcmp(argv[i],"-shadow") == 0) {
shadow = 1;
mark_arg(i);
} else if (strcmp(argv[i],"-docstring") == 0) {
docstring = 1;
mark_arg(i);
} else if (strcmp(argv[i],"-help") == 0) {
fputs(usage,stderr);
}
}
}
// Create a symbol for this language
add_symbol("SWIGPYTHON",0,0);
// Set name of typemaps
typemap_lang = "python";
}
// ---------------------------------------------------------------------
// PYTHON::parse()
//
// Parse the interface file
// ---------------------------------------------------------------------
void
PYTHON::parse() {
printf("Generating wrappers for Python\n");
headers();
// Run the SWIG parser
yyparse();
}
// ---------------------------------------------------------------------
// PYTHON::set_module(char *mod_name, char **mod_list)
//
// Sets the module name.
// Does nothing if it's already set (so it can be overridden as a command
// line option).
//
//----------------------------------------------------------------------
void PYTHON::set_module(char *mod_name, char **mod_list) {
int i;
// If an "import" method has been set and we're in shadow class mode,
// output a python command to load the module
if (import_file) {
if (!(strcmp(import_file,input_file+strlen(input_file)-strlen(import_file)))) {
if (shadow) {
fprintf(f_shadow,"\nfrom %s import *\n", mod_name);
}
delete import_file;
import_file = 0;
}
}
if (module) return;
module = new char[strlen(mod_name)+1];
strcpy(module,mod_name);
// If there was a mod_list specified, make this incredible hack
if (mod_list) {
modinit << "#define SWIGMODINIT ";
modextern << "#ifdef __cplusplus\n"
<< "extern \"C\" {\n"
<< "#endif\n";
i = 0;
while(mod_list[i]) {
modinit << "swig_add_module(\"" << mod_list[i] << "\",init"
<< mod_list[i] << "); \\\n";
modextern << "extern void init" << mod_list[i] << "();\n";
i++;
}
modextern << "#ifdef __cplusplus\n"
<< "}\n"
<< "#endif\n";
modinit << "/* End of extern module initialization */\n";
}
}
// ---------------------------------------------------------------------
// PYTHON::set_init(char *iname)
//
// Sets the initialization function name.
// Does nothing if it's already set
//
//----------------------------------------------------------------------
void PYTHON::set_init(char *iname) {
set_module(iname,0);
}
// ---------------------------------------------------------------------
// PYTHON::import(char *filename)
//
// Imports a SWIG module as a separate file.
//----------------------------------------------------------------------
void PYTHON::import(char *filename) {
if (import_file) delete import_file;
import_file = copy_string(filename);
}
// ----------------------------------------------------------------------
// PYTHON::add_method(char *name, char *function)
//
// Add some symbols to the methods table
// ----------------------------------------------------------------------
void PYTHON::add_method(char *name, char *function) {
Method *n;
n = new Method;
n->name = new char[strlen(name)+1];
strcpy(n->name,name);
n->function = new char[strlen(function)+1];
strcpy(n->function, function);
n->next = head;
head = n;
}
// ---------------------------------------------------------------------
// PYTHON::print_methods()
//
// Prints out the method array.
// ---------------------------------------------------------------------
void PYTHON::print_methods() {
Method *n;
fprintf(f_wrappers,"static PyMethodDef %sMethods[] = {\n", module);
n = head;
while (n) {
fprintf(f_wrappers,"\t { \"%s\", %s, 1 },\n", n->name, n->function);
n = n->next;
}
fprintf(f_wrappers,"\t { NULL, NULL }\n");
fprintf(f_wrappers,"};\n");
}
// ---------------------------------------------------------------------
// char *PYTHON::add_docstring(DocEntry *de)
//
// Adds a documentation entry to the doc-string generator. Returns a
// unique character symbol that will be used to fill in the doc-string
// at a later time.
// ---------------------------------------------------------------------
char *PYTHON::add_docstring(DocEntry *de) {
DocString *s;
String str;
str = "@doc";
str << doc_index << "@";
s = new DocString();
s->de = de;
s->name = copy_string(str);
s->next = doc_strings;
doc_strings = s;
doc_index++;
return s->name;
}
// ---------------------------------------------------------------------
// PYTHON::headers(void)
//
// ----------------------------------------------------------------------
void PYTHON::headers(void)
{
emit_banner(f_header);
fprintf(f_header,"/* Implementation : PYTHON */\n\n");
fprintf(f_header,"#define SWIGPYTHON\n");
fprintf(f_header,"#include <string.h>\n");
fprintf(f_header,"#include <stdlib.h>\n");
if (!NoInclude) {
if (insert_file("python.swg", f_header) == -1) {
fprintf(stderr,"SWIG : Fatal error. Unable to locate python.swg. (Possible installation problem).\n");
SWIG_exit(1);
}
emit_hex(f_header);
} else {
if (insert_file("pyexp.swg", f_header) == -1) {
fprintf(stderr,"SWIG : Fatal error. Unable to locate pyexp.swg. (Possible installation problem).\n");
SWIG_exit(1);
}
}
}
// --------------------------------------------------------------------
// PYTHON::initialize(void)
//
// This function outputs the starting code for a function to initialize
// your interface. It is only called once by the parser.
//
// ---------------------------------------------------------------------
void PYTHON::initialize(void)
{
char filen[256];
char *temp;
char *oldmodule = 0;
if (!module) {
module = "swig";
fprintf(stderr,"SWIG : *** Warning. No module name specified.\n");
}
// If shadow classing is enabled, we're going to change the module
// name to "modulec"
if (shadow) {
temp = new char[strlen(module)+2];
sprintf(temp,"%sc",module);
oldmodule = module;
module = temp;
}
/* Initialize the C code for the module */
initialize_cmodule();
/* Create a shadow file (if enabled).*/
if (shadow) {
sprintf(filen,"%s%s.py", output_dir, oldmodule);
if ((f_shadow = fopen(filen,"w")) == 0) {
fprintf(stderr,"Unable to open %s\n", filen);
SWIG_exit(0);
}
fprintf(f_shadow,"# This file was created automatically by SWIG.\n");
fprintf(f_shadow,"import %s\n", module);
}
// Dump out external module declarations
if (strlen(modinit.get()) > 0) {
fprintf(f_header,"%s\n",modinit.get());
}
if (strlen(modextern.get()) > 0) {
fprintf(f_header,"%s\n",modextern.get());
}
}
// ---------------------------------------------------------------------
// PYTHON::initialize_cmodule(void)
//
// Initializes the C module.
//
// ---------------------------------------------------------------------
void PYTHON::initialize_cmodule(void)
{
int i;
fprintf(f_header,"#define SWIG_init init%s\n\n", module);
fprintf(f_header,"#define SWIG_name \"%s\"\n", module);
// Output the start of the init function.
// Modify this to use the proper return type and arguments used
// by the target Language
fprintf(f_init,"static PyObject *SWIG_globals;\n");
fprintf(f_init,"#ifdef __cplusplus\n");
fprintf(f_init,"extern \"C\" \n");
fprintf(f_init,"#endif\n");
fprintf(f_init,"SWIGEXPORT(void,init%s)() {\n",module);
fprintf(f_init,"\t PyObject *m, *d;\n");
if (InitNames) {
i = 0;
while (InitNames[i]) {
fprintf(f_init,"\t %s();\n", InitNames[i]);
i++;
}
}
fprintf(f_init,"\t SWIG_globals = SWIG_newvarlink();\n");
fprintf(f_init,"\t m = Py_InitModule(\"%s\", %sMethods);\n", module, module);
fprintf(f_init,"\t d = PyModule_GetDict(m);\n");
}
// ---------------------------------------------------------------------
// PYTHON::close(void)
//
// Called when the end of the interface file is reached. Closes the
// initialization function and performs cleanup as necessary.
// ---------------------------------------------------------------------
void PYTHON::close(void)
{
print_methods();
close_cmodule();
if ((doc_entry) && (module)){
String temp;
temp << "Python Module : ";
if (shadow) {
module[strlen(module)-1] = 0;
}
temp << module;
doc_entry->cinfo << temp;
}
if (shadow) {
String fullshadow;
fullshadow << classes
<< "\n\n#-------------- FUNCTION WRAPPERS ------------------\n\n"
<< func
<< "\n\n#-------------- VARIABLE WRAPPERS ------------------\n\n"
<< vars;
if (strlen(pragma_include) > 0) {
fullshadow << "\n\n#-------------- USER INCLUDE -----------------------\n\n"
<< pragma_include;
}
// Go through all of the docstrings and replace the docstrings
DocString *s;
s = doc_strings;
while (s) {
fullshadow.replace(s->name, s->de->text);
s = s->next;
}
/*
fprintf(f_shadow,"\n\n#-------------- FUNCTION WRAPPERS ------------------\n\n");
fprintf(f_shadow,"%s",func.get());
fprintf(f_shadow,"\n\n#-------------- VARIABLE WRAPPERS ------------------\n\n");
fprintf(f_shadow,"%s",vars.get());
if (strlen(pragma_include) > 0) {
fprintf(f_shadow,"\n\n#-------------- USER INCLUDE -----------------------\n\n");
fprintf(f_shadow,"%s",pragma_include.get());
}
*/
fprintf(f_shadow, "%s", fullshadow.get());
fclose(f_shadow);
}
}
// --------------------------------------------------------------------
// PYTHON::close_cmodule(void)
//
// Called to cleanup the C module code
// --------------------------------------------------------------------
void PYTHON::close_cmodule(void)
{
emit_ptr_equivalence(f_init);
fprintf(f_init,"}\n");
}
// ----------------------------------------------------------------------
// PYTHON::get_pointer(char *iname, char *srcname, char *src, char *target,
// DataType *t, WrapperFunction &f, char *ret)
//
// Emits code to get a pointer and do type checking.
// iname = name of the function/method (used for error messages)
// srcname = Name of source (used for error message reporting).
// src = name of variable where source string is located.
// dest = name of variable where pointer value is stored.
// t = Expected datatype of the parameter
// f = Wrapper function object being used to generate code.
// ret = return code upon failure.
//
// Note : pointers are stored as strings so you first need to get
// a string and then call _swig_get_hex() to extract a point.
//
// This module is pretty ugly, but type checking is kind of nasty
// anyways.
// ----------------------------------------------------------------------
void
PYTHON::get_pointer(char *iname, char *srcname, char *src, char *dest,
DataType *t, String &f, char *ret)
{
// Now get the pointer value from the string and save in dest
f << tab4 << "if (" << src << ") {\n";
f << tab8 << "if (SWIG_GetPtr(" << src << ",(void **) &" << dest << ",";
// If we're passing a void pointer, we give the pointer conversion a NULL
// pointer, otherwise pass in the expected type.
if (t->type == T_VOID) f << "(char *) 0 )) {\n";
else
f << "\"" << t->print_mangle() << "\")) {\n";
// This part handles the type checking according to three different
// levels. 0 = no checking, 1 = warning message, 2 = strict.
switch(TypeStrict) {
case 0: // No type checking
f << tab8 << "}\n";
break;
case 1: // Warning message only
// Change this part to how you want to handle a type-mismatch warning.
// By default, it will just print to stderr.
f << tab8 << tab4 << "fprintf(stderr,\"Warning : type mismatch in " << srcname
<< " of " << iname << ". Expected " << t->print_mangle()
<< ", received %s\\n\"," << src << ");\n"
<< tab8 << "}\n";
break;
case 2: // Super strict mode.
// Change this part to return an error.
f << tab8 << tab4 << "PyErr_SetString(PyExc_TypeError,\"Type error in " << srcname
<< " of " << iname << ". Expected " << t->print_mangle() << ".\");\n"
<< tab8 << "return " << ret << ";\n"
<< tab8 << "}\n";
break;
default :
fprintf(stderr,"SWIG Error. Unknown strictness level\n");
break;
}
f << tab4 << "}\n";
}
// ----------------------------------------------------------------------
// PYTHON::shadow_defargs(Parm *p, ParmList *l, int i, int pcount, int numopt,
// String &code, char *indent)
//
// Internal function for extracting from default arguments on shadow classes.
// Note : the index refers to the arguments in a Python function. C arguments
// that are ignored will not affect the index.
//
// p = Current parameter
// l = Parameter list
// i = Current parameter index
// pcount = Number of parameters
// numopt = Number of default arguments
// code = String object containing output.
// indent = Base indentation
//
// -----------------------------------------------------------------------
void PYTHON::shadow_defargs(Parm *p, ParmList *l, int i, int pcount, int numopt,
String &code, char *indent)
{
int need_translate = 0;
code << indent << "argl = map(None,args)\n";
// Now check for arguments that need translation
while (p) {
// If parameter is ignored, forget it
if (!p->ignore) {
if ((hash.lookup(p->t->name)) && (p->t->is_pointer <= 1)) {
need_translate = 1;
code << indent << "try: " << "argl[" << (i - (pcount-numopt)) << "] = argl["
<< (i-(pcount-numopt)) << "].this\n"
<< indent << "except: pass\n";
}
i++;
}
p = l->get_next();
}
code << indent << "args = tuple(argl)\n";
if (!need_translate) code = "";
}
// ----------------------------------------------------------------------
// PYTHON::emit_function_header()
//
// Return the code to be used as a function header
// ----------------------------------------------------------------------
void PYTHON::emit_function_header(WrapperFunction &emit_to, char *wname)
{
emit_to.def << "static PyObject *" << wname
<< "(PyObject *self, PyObject *args) {";
emit_to.code << tab4 << "self = self;\n";
}
// ----------------------------------------------------------------------
// PYTHON::convert_self()
//
// Called during the function generation process, to determine what to
// use as the "self" variable during the call. Derived classes may emit code
// to convert the real self pointer into a usable pointer.
//
// Returns the name of the variable to use as the self pointer
// ----------------------------------------------------------------------
char *PYTHON::convert_self(WrapperFunction &)
{
// Default behaviour is no translation
return "";
}
// ----------------------------------------------------------------------
// PYTHON::make_funcname_wrapper()
//
// Called to create a name for a wrapper function
// ----------------------------------------------------------------------
char *PYTHON::make_funcname_wrapper(char *fnName)
{
return name_wrapper(fnName,"");
}
// ----------------------------------------------------------------------
// PYTHON::create_command(char *cname, char *iname)
//
// Create a new command in the interpreter. Used for C++ inheritance
// stuff.
// ----------------------------------------------------------------------
void PYTHON::create_command(char *cname, char *iname) {
// Create the name of the wrapper function
char *wname = name_wrapper(cname,"");
// Now register the function with the interpreter.
add_method(iname, wname);
}
// ----------------------------------------------------------------------
// PYTHON::create_function(char *name, char *iname, DataType *d,
// ParmList *l)
//
// This function creates a wrapper function and registers it with the
// interpreter.
//
// Inputs :
// name = actual name of the function that's being wrapped
// iname = name of the function in the interpreter (may be different)
// d = Return datatype of the functions.
// l = A linked list containing function parameter information.
//
// ----------------------------------------------------------------------
void PYTHON::create_function(char *name, char *iname, DataType *d, ParmList *l)
{
Parm *p;
int pcount,i,j;
String wname, self_name, call_name;
char source[64], target[64], temp[256], argnum[20];
char *usage = 0;
WrapperFunction f;
String parse_args;
String arglist;
String get_pointers;
String cleanup, outarg;
String check;
String build;
int have_build = 0;
char *tm;
int numopt = 0;
have_output = 0;
// Make a valid name for this function. This removes special symbols
// that would cause problems in the C compiler.
wname = make_funcname_wrapper(iname);
// Now emit the function declaration for the wrapper function. You
// should modify this to return the appropriate types and use the
// appropriate parameters.
emit_function_header(f, wname);
f.add_local("PyObject *","_resultobj");
// Get the function usage string for later use
usage = usage_func(iname,d,l);
// Write code to extract function parameters.
// This is done in one pass, but we need to construct three independent
// pieces.
// 1. Python format string such as "iis"
// 2. The actual arguments to put values into
// 3. Pointer conversion code.
//
// If there is a type mapping, we will extract the Python argument
// as a raw PyObject and let the user deal with it.
//
pcount = emit_args(d, l, f);
parse_args << tab4 << "if(!PyArg_ParseTuple(args,\"";
i = 0;
j = 0;
numopt = l->numopt(); // Get number of optional arguments
if (numopt) have_defarg = 1;
p = l->get_first();
while (p != 0) {
// Generate source and target strings
sprintf(source,"_obj%d",i);
sprintf(target,"_arg%d",i);
sprintf(argnum,"%d",j+1);
// Only consider this argument if it's not ignored
if (!p->ignore) {
arglist << ",";
// Add an optional argument separator if needed
if (j == pcount-numopt) {
parse_args << "|";
}
// Look for input typemap
if ((tm = typemap_lookup("in","python",p->t,p->name,source,target,&f))) {
parse_args << "O"; // Grab the argument as a raw PyObject
f.add_local("PyObject *",source,"0");
arglist << "&" << source;
if (i >= (pcount-numopt))
get_pointers << tab4 << "if (" << source << ")\n";
get_pointers << tm << "\n";
get_pointers.replace("$argnum", argnum);
get_pointers.replace("$arg",source);
} else {
// Check if this parameter is a pointer. If not, we'll get values
if (!p->t->is_pointer) {
// Extract a parameter by "value"
switch(p->t->type) {
// Handle integers here. Usually this can be done as a single
// case if you appropriate cast things. However, if you have
// special cases, you'll need to add more code.
case T_INT : case T_UINT: case T_SINT:
parse_args << "i";
break;
case T_SHORT: case T_USHORT: case T_SSHORT:
parse_args << "h";
break;
case T_LONG : case T_ULONG: case T_SLONG :
parse_args << "l";
break;
case T_SCHAR : case T_UCHAR :
parse_args << "b";
break;
case T_CHAR:
parse_args << "c";
break;
case T_FLOAT :
parse_args << "f";
break;
case T_DOUBLE:
parse_args << "d";
break;
case T_BOOL:
{
String tempb;
tempb << "tempbool" << i;
parse_args << "i";
f.add_local("int",tempb.get());
get_pointers << tab4 << target << " = " << p->t->print_cast() << " " << tempb << ";\n";
arglist << "&" << tempb;
}
break;
// Void.. Do nothing.
case T_VOID :
break;
// User defined. This is usually invalid. No way to pass a
// complex type by "value". We'll just pass into the unsupported
// datatype case.
case T_USER:
// Unsupported data type
default :
fprintf(stderr,"%s : Line %d. Unable to use type %s as a function argument.\n",input_file, line_number, p->t->print_type());
break;
}
// Emit code for parameter list
if ((p->t->type != T_VOID) && (p->t->type != T_BOOL))
arglist << "&_arg" << i;
} else {
// Is some other kind of variable.
parse_args << "s";
if ((p->t->type == T_CHAR) && (p->t->is_pointer == 1)) {
arglist << "&_arg" << i;
} else {
// Have some sort of pointer variable. Create a temporary local
// variable for the string and read the pointer value into it.
sprintf(source,"_argc%d", i);
sprintf(target,"_arg%d", i);
sprintf(temp,"argument %d",i+1);
f.add_local("char *", source,"0");
arglist << "&" << source;
get_pointer(iname, temp, source, target, p->t, get_pointers, "NULL");
}
}
}
j++;
}
// Check if there was any constraint code
if ((tm = typemap_lookup("check","python",p->t,p->name,source,target))) {
check << tm << "\n";
check.replace("$argnum", argnum);
}
// Check if there was any cleanup code
if ((tm = typemap_lookup("freearg","python",p->t,p->name,target,source))) {
cleanup << tm << "\n";
cleanup.replace("$argnum", argnum);
cleanup.replace("$arg",source);
}
if ((tm = typemap_lookup("argout","python",p->t,p->name,target,"_resultobj"))) {
outarg << tm << "\n";
outarg.replace("$argnum", argnum);
outarg.replace("$arg",source);
have_output++;
}
if ((tm = typemap_lookup("build","python",p->t,p->name,source,target))) {
build << tm << "\n";
have_build = 1;
}
p = l->get_next();
i++;
}
parse_args << ":" << iname << "\""; // No additional arguments
parse_args << arglist << ")) \n"
<< tab8 << "return NULL;\n";
self_name = convert_self(f);
/* Now slap the whole first part of the wrapper function together */
f.code << parse_args << get_pointers << check;
// Special handling for build values
if (have_build) {
char temp1[256];
char temp2[256];
l->sub_parmnames(build); // Replace all parameter names
for (i = 0; i < l->nparms; i++) {
p = l->get(i);
if (strlen(p->name) > 0) {
sprintf(temp1,"_in_%s", p->name);
} else {
sprintf(temp1,"_in_arg%d", i);
}
sprintf(temp2,"_obj%d",i);
build.replaceid(temp1,temp2);
}
f.code << build;
}
// This function emits code to call the real function. Assuming you read
// the parameters in correctly, this will work.
call_name = "";
call_name << self_name << name;
emit_func_call(call_name,d,l,f);
// Now emit code to return the functions return value (if any).
// If there was a result, it was saved in _result.
// If the function is a void type, don't do anything.
if ((tm = typemap_lookup("out","python",d,iname,"_result","_resultobj"))) {
// Yep. Use it instead of the default
f.code << tm << "\n";
} else {
if ((d->type != T_VOID) || (d->is_pointer)) {
// Now have return value, figure out what to do with it.
if (!d->is_pointer) {
// Function returns a "value"
switch(d->type) {
// Return an integer type
case T_INT: case T_SINT: case T_UINT: case T_BOOL:
f.code << tab4 << "_resultobj = Py_BuildValue(\"i\",_result);\n";
break;
case T_SHORT: case T_SSHORT: case T_USHORT:
f.code << tab4 << "_resultobj = Py_BuildValue(\"h\",_result);\n";
break;
case T_LONG : case T_SLONG : case T_ULONG:
f.code << tab4 << "_resultobj = Py_BuildValue(\"l\",_result);\n";
break;
case T_SCHAR: case T_UCHAR :
f.code << tab4 << "_resultobj = Py_BuildValue(\"b\",_result);\n";
break;
// Return a floating point value
case T_DOUBLE :
f.code << tab4 << "_resultobj = Py_BuildValue(\"d\",_result);\n";
break;
case T_FLOAT :
f.code << tab4 << "_resultobj = Py_BuildValue(\"f\",_result);\n";
break;
// Return a single ASCII value. Usually we need to convert
// it to a NULL-terminate string and return that instead.
case T_CHAR :
f.code << tab4 << "_resultobj = Py_BuildValue(\"c\",_result);\n";
break;
case T_USER :
// Return something by value
// We're living dangerously here, but life is short...play hard
// Oops. Need another local variable
f.add_local("char","_ptemp[128]");
d->is_pointer++;
f.code << tab4 << "SWIG_MakePtr(_ptemp, (void *) _result,\""
<< d->print_mangle() << "\");\n";
d->is_pointer--;
// Return a character string containing our pointer.
f.code << tab4 << "_resultobj = Py_BuildValue(\"s\",_ptemp);\n";
break;
default :
fprintf(stderr,"%s: Line %d. Unable to use return type %s in function %s.\n", input_file, line_number, d->print_type(), name);
break;
}
} else {
// Return type is a pointer. We'll see if it's a char * and return
// a string. Otherwise, we'll convert it into a SWIG pointer and return
// that.
if ((d->type == T_CHAR) && (d->is_pointer == 1)) {
// Return a character string
f.code << tab4 << "_resultobj = Py_BuildValue(\"s\", _result);\n";
// If declared as a new object, free the result
} else {
// Build a SWIG pointer.
f.add_local("char","_ptemp[128]");
f.code << tab4 << "SWIG_MakePtr(_ptemp, (char *) _result,\""
<< d->print_mangle() << "\");\n";
// Return a character string containing our pointer.
f.code << tab4 << "_resultobj = Py_BuildValue(\"s\",_ptemp);\n";
}
}
} else {
// no return value and no output args
//if (!have_output) {
f.code << tab4 << "Py_INCREF(Py_None);\n";
f.code << tab4 << "_resultobj = Py_None;\n";
//}
}
}
// Check to see if there were any output arguments, if so we're going to
// create a Python list object out of the current result
f.code << outarg;
// If there was any other cleanup needed, do that
f.code << cleanup;
// Look to see if there is any newfree cleanup code
if (NewObject) {
if ((tm = typemap_lookup("newfree","python",d,iname,"_result",""))) {
f.code << tm << "\n";
}
}
// See if there is any argument cleanup code
if ((tm = typemap_lookup("ret","python",d,iname,"_result",""))) {
// Yep. Use it instead of the default
f.code << tm << "\n";
}
f.code << tab4 << "return _resultobj;\n";
f.code << "}\n";
// Substitute the cleanup code
f.code.replace("$cleanup",cleanup);
// Substitute the function name
f.code.replace("$name",iname);
// Dump the function out
f.print(f_wrappers);
// Now register the function with the interpreter.
add_method(iname, wname);
// Create a documentation entry for this
if (doc_entry) {
static DocEntry *last_doc_entry = 0;
doc_entry->usage << usage;
if (last_doc_entry != doc_entry) {
doc_entry->cinfo << "returns " << d->print_type();
last_doc_entry = doc_entry;
}
}
// ---------------------------------------------------------------------------
// Create a shadow for this function (if enabled and not in a member function)
// ---------------------------------------------------------------------------
if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
String translate;
int need_wrapper = 0;
int have_optional = 0;
// First, we're going to check to see if this function needs modification
p = l->get_first();
while (p) {
if ((!p->ignore) && (hash.lookup(p->t->name)) && (p->t->is_pointer <= 1))
need_wrapper = 1;
p = l->get_next();
}
// Check return code for modification
if ((hash.lookup(d->name)) && (d->is_pointer <=1))
need_wrapper = 1;
// If no modification is needed. We're just going to play some
// symbol table games instead
if (docstring && doc_entry)
need_wrapper = 1;
if (!need_wrapper) {
func << iname << " = " << module << "." << iname << "\n\n";
} else {
func << "def " << iname << "(";
p = l->get_first();
i = 0;
while(p) {
if (!p->ignore) {
if (i >= pcount-numopt) {
have_optional = 1;
func << "*args";
shadow_defargs(p,l,i,pcount,numopt,translate,tab4);
break;
}
func << "arg" << i;
p = l->get_next();
if (p)
if (!p->ignore)
func << ",";
i++;
} else {
p = l->get_next();
if (p)
if ((i > 0) && (!p->ignore))
func << ",";
}
}
func << "):\n";
// Create a docstring for this
if (docstring && doc_entry) {
func << tab4 << "\"\"\"" << add_docstring(doc_entry) << "\"\"\"\n";
}
func << translate;
func << tab4;
// if ((d->type != T_VOID) || (d->is_pointer > 0))
func << "val = ";
// if ((hash.lookup(d->name)) && (d->is_pointer <=1))
// func << (char *) hash.lookup(d->name) << "Ptr(";
// Big, big, big ugly hack. If default arguments are involved, we've got
// to go through a handler function instead. Bleah!
if (have_optional) {
func << "apply(" << module << "." << iname << ",(";
} else {
func << module << "." << iname << "(";
}
p = l->get_first();
i = 0;
while(p) {
if (!p->ignore) {
if (i >= (pcount-numopt)) {
func << ")+args";
break;
}
func << "arg" << i;
if ((hash.lookup(p->t->name)) && (p->t->is_pointer <= 1))
func << ".this";
p = l->get_next();
if (p)
if (!p->ignore)
func << ",";
i++;
} else {
p = l->get_next();
if (p)
if ((i > 0) && (!p->ignore))
func << ",";
}
}
// if ((hash.lookup(d->name)) && (d->is_pointer <=1))
// func << "))\n";
// else
func << ")\n";
// Check to see if return type is an object
if ((hash.lookup(d->name)) && (d->is_pointer <= 1)) {
// If the output of this object has been remapped in any way, we're
// going to return it as a bare object.
if (!typemap_check("out",typemap_lang,d,iname)) {
// If there are output arguments, we are going to return the value
// unchanged. Otherwise, emit some shadow class conversion code.
if (!have_output) {
func << tab4 << "val = " << (char *) hash.lookup(d->name) << "Ptr(val)\n";
if (((hash.lookup(d->name)) && (d->is_pointer < 1)) ||
((hash.lookup(d->name)) && (d->is_pointer == 1) && NewObject))
func << tab4 << "val.thisown = 1\n";
} else {
// Does nothing--returns the value unmolested
}
#ifdef OLD_METHOD
// This is the old behavior. Now obsolete
if (have_output) {
func << tab4 << "val = [" << (char *) hash.lookup(d->name) << "Ptr(val[0])] + val[1:]\n";
if (((hash.lookup(d->name)) && (d->is_pointer < 1)) ||
((hash.lookup(d->name)) && (d->is_pointer == 1) && NewObject))
func << tab4 << "val[0].thisown = 1\n";
} else {
func << tab4 << "val = " << (char *) hash.lookup(d->name) << "Ptr(val)\n";
if (((hash.lookup(d->name)) && (d->is_pointer < 1)) ||
((hash.lookup(d->name)) && (d->is_pointer == 1) && NewObject))
func << tab4 << "val.thisown = 1\n";
}
#endif
}
}
func << tab4 << "return val\n\n";
}
}
}
// -----------------------------------------------------------------------
// PYTHON::link_variable(char *name, char *iname, DataType *d)
//
// Input variables:
// name = the real name of the variable being linked
// iname = Name of the variable in the interpreter (may be different)
// d = Datatype of the variable.
//
// This creates a pair of functions for evaluating/setting the value
// of a variable. These are then added to the special SWIG global
// variable type.
// -----------------------------------------------------------------------
void PYTHON::link_variable(char *name, char *iname, DataType *t) {
char *wname;
static int have_globals = 0;
char *tm;
WrapperFunction getf, setf;
// If this is our first call, add the globals variable to the
// Python dictionary.
if (!have_globals) {
fprintf(f_init,"\t PyDict_SetItemString(d,\"%s\", SWIG_globals);\n",global_name);
have_globals=1;
if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
vars << global_name << " = " << module << "." << global_name << "\n";
}
}
// First make a sanitized version of the function name (in case it's some
// funky C++ thing).
wname = name_wrapper(name,"");
// ---------------------------------------------------------------------
// Create a function for setting the value of the variable
// ---------------------------------------------------------------------
setf.def << "static int " << wname << "_set(PyObject *val) {";
if (!(Status & STAT_READONLY)) {
if ((tm = typemap_lookup("varin","python",t,name,"val",name))) {
setf.code << tm << "\n";
setf.code.replace("$name",iname);
} else {
if ((t->type != T_VOID) || (t->is_pointer)) {
if (!t->is_pointer) {
// Have a real value here
switch(t->type) {
case T_INT: case T_SHORT: case T_LONG :
case T_UINT: case T_USHORT: case T_ULONG:
case T_SINT: case T_SSHORT: case T_SLONG:
case T_SCHAR: case T_UCHAR: case T_BOOL:
// Get an integer value
setf.add_local(t->print_type(), "tval");
setf.code << tab4 << "tval = " << t->print_cast() << "PyInt_AsLong(val);\n"
<< tab4 << "if (PyErr_Occurred()) {\n"
<< tab8 << "PyErr_SetString(PyExc_TypeError,\"C variable '"
<< iname << "'(" << t->print_type() << ")\");\n"
<< tab8 << "return 1; \n"
<< tab4 << "}\n"
<< tab4 << name << " = tval;\n";
break;
case T_FLOAT: case T_DOUBLE:
// Get a floating point value
setf.add_local(t->print_type(), "tval");
setf.code << tab4 << "tval = " << t->print_cast() << "PyFloat_AsDouble(val);\n"
<< tab4 << "if (PyErr_Occurred()) {\n"
<< tab8 << "PyErr_SetString(PyExc_TypeError,\"C variable '"
<< iname << "'(" << t->print_type() << ")\");\n"
<< tab8 << "return 1; \n"
<< tab4 << "}\n"
<< tab4 << name << " = tval;\n";
break;
// A single ascii character
case T_CHAR:
setf.add_local("char *", "tval");
setf.code << tab4 << "tval = (char *) PyString_AsString(val);\n"
<< tab4 << "if (PyErr_Occurred()) {\n"
<< tab8 << "PyErr_SetString(PyExc_TypeError,\"C variable '"
<< iname << "'(" << t->print_type() << ")\");\n"
<< tab8 << "return 1; \n"
<< tab4 << "}\n"
<< tab4 << name << " = *tval;\n";
break;
case T_USER:
setf.add_local("char *", "tval");
t->is_pointer++;
setf.add_local(t->print_type(),"temp");
setf.code << tab4 << "tval = (char *) PyString_AsString(val);\n"
<< tab4 << "if (PyErr_Occurred()) {\n"
<< tab8 << "PyErr_SetString(PyExc_TypeError,\"C variable '"
<< iname << "'(" << t->print_type() << ")\");\n"
<< tab8 << "return 1; \n"
<< tab4 << "}\n";
get_pointer(iname,"value","tval","temp",t,setf.code,"1");
setf.code << tab4 << name << " = *temp;\n";
t->is_pointer--;
break;
default:
fprintf(stderr,"%s : Line %d. Unable to link with type %s.\n", input_file, line_number, t->print_type());
}
} else {
// Parse a pointer value
if ((t->type == T_CHAR) && (t->is_pointer == 1)) {
setf.add_local("char *", "tval");
setf.code << tab4 << "tval = (char *) PyString_AsString(val);\n"
<< tab4 << "if (PyErr_Occurred()) {\n"
<< tab8 << "PyErr_SetString(PyExc_TypeError,\"C variable '"
<< iname << "'(" << t->print_type() << ")\");\n"
<< tab8 << "return 1; \n"
<< tab4 << "}\n";
if (CPlusPlus) {
setf.code << tab4 << "if (" << name << ") delete [] " << name << ";\n"
<< tab4 << name << " = new char[strlen(tval)+1];\n"
<< tab4 << "strcpy(" << name << ",tval);\n";
} else {
setf.code << tab4 << "if (" << name << ") free(" << name << ");\n"
<< tab4 << name << " = (char *) malloc(strlen(tval)+1);\n"
<< tab4 << "strcpy(" << name << ",tval);\n";
}
} else {
// Is a generic pointer value.
setf.add_local("char *", "tval");
setf.add_local(t->print_type(),"temp");
setf.code << tab4 << "tval = (char *) PyString_AsString(val);\n"
<< tab4 << "if (PyErr_Occurred()) {\n"
<< tab8 << "PyErr_SetString(PyExc_TypeError,\"C variable '"
<< iname << "'(" << t->print_type() << ")\");\n"
<< tab8 << "return 1; \n"
<< tab4 << "}\n";
get_pointer(iname,"value","tval","temp",t,setf.code,"1");
setf.code << tab4 << name << " = temp;\n";
}
}
}
}
setf.code << tab4 << "return 0;\n";
} else {
// Is a readonly variable. Issue an error
setf.code << tab4 << "PyErr_SetString(PyExc_TypeError,\"Variable " << iname
<< " is read-only.\");\n"
<< tab4 << "return 1;\n";
}
setf.code << "}\n";
// Dump out function for setting value
setf.print(f_wrappers);
// ----------------------------------------------------------------
// Create a function for getting the value of a variable
// ----------------------------------------------------------------
getf.def << "static PyObject *" << wname << "_get() {";
getf.add_local("PyObject *","pyobj");
if ((tm = typemap_lookup("varout","python",t,name,name,"pyobj"))) {
getf.code << tm << "\n";
getf.code.replace("$name",iname);
} else if ((tm = typemap_lookup("out","python",t,name,name,"pyobj"))) {
getf.code << tm << "\n";
getf.code.replace("$name",iname);
} else {
if ((t->type != T_VOID) || (t->is_pointer)) {
if (!t->is_pointer) {
/* Is a normal datatype */
switch(t->type) {
case T_INT: case T_SINT: case T_UINT:
case T_SHORT: case T_SSHORT: case T_USHORT:
case T_LONG: case T_SLONG: case T_ULONG:
case T_SCHAR: case T_UCHAR: case T_BOOL:
getf.code << tab4 << "pyobj = PyInt_FromLong((long) " << name << ");\n";
break;
case T_FLOAT: case T_DOUBLE:
getf.code << tab4 << "pyobj = PyFloat_FromDouble((double) " << name << ");\n";
break;
case T_CHAR:
getf.add_local("char","ptemp[2]");
getf.code << tab4 << "ptemp[0] = " << name << ";\n"
<< tab4 << "ptemp[1] = 0;\n"
<< tab4 << "pyobj = PyString_FromString(ptemp);\n";
break;
case T_USER:
// Hack this into a pointer
getf.add_local("char", "ptemp[128]");
t->is_pointer++;
getf.code << tab4 << "SWIG_MakePtr(ptemp,(char *) &" << name
<< "," << quote << t->print_mangle() << quote << ");\n"
<< tab4 << "pyobj = PyString_FromString(ptemp);\n";
t->is_pointer--;
break;
default:
fprintf(stderr,"Unable to link with type %s\n", t->print_type());
break;
}
} else {
// Is some sort of pointer value
if ((t->type == T_CHAR) && (t->is_pointer == 1)) {
getf.code << tab4 << "if (" << name << ")\n"
<< tab8 << "pyobj = PyString_FromString(" << name << ");\n"
<< tab4 << "else pyobj = PyString_FromString(\"(NULL)\");\n";
} else {
getf.add_local("char","ptemp[128]");
getf.code << tab4 << "SWIG_MakePtr(ptemp, (char *) " << name << ",\""
<< t->print_mangle() << "\");\n"
<< tab4 << "pyobj = PyString_FromString(ptemp);\n";
}
}
}
}
getf.code << tab4 << "return pyobj;\n"
<< "}\n";
getf.print(f_wrappers);
// Now add this to the variable linking mechanism
fprintf(f_init,"\t SWIG_addvarlink(SWIG_globals,\"%s\",%s_get, %s_set);\n", iname, wname, wname);
// Fill in the documentation entry
if (doc_entry) {
doc_entry->usage << usage_var(iname, t);
doc_entry->cinfo << "Global : " << t->print_type() << " " << name;
}
// ----------------------------------------------------------
// Output a shadow variable. (If applicable and possible)
// ----------------------------------------------------------
if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
if ((hash.lookup(t->name)) && (t->is_pointer <= 1)) {
vars << iname << " = " << (char *) hash.lookup(t->name) << "Ptr(" << module << "." << global_name
<< "." << iname << ")\n";
}
}
}
// -----------------------------------------------------------------------
// PYTHON::declare_const(char *name, char *iname, DataType *type, char *value)
//
// Makes a constant as defined with #define. Constants are added to the
// module's dictionary and are **NOT** guaranteed to be read-only,
// sorry.
//
// ------------------------------------------------------------------------
void PYTHON::declare_const(char *name, char *, DataType *type, char *value) {
char *tm;
// Make a static python object
if ((tm = typemap_lookup("const","python",type,name,value,name))) {
fprintf(f_init,"%s\n",tm);
} else {
if ((type->type == T_USER) && (!type->is_pointer)) {
fprintf(stderr,"%s : Line %d. Unsupported constant value.\n", input_file, line_number);
return;
}
if (type->is_pointer == 0) {
switch(type->type) {
case T_INT:case T_SINT: case T_UINT: case T_BOOL:
case T_SHORT: case T_SSHORT: case T_USHORT:
case T_LONG: case T_SLONG: case T_ULONG:
case T_SCHAR: case T_UCHAR:
fprintf(f_init,"\t PyDict_SetItemString(d,\"%s\", PyInt_FromLong((long) %s));\n",name,value);
break;
case T_DOUBLE:
case T_FLOAT:
fprintf(f_init,"\t PyDict_SetItemString(d,\"%s\", PyFloat_FromDouble((double) %s));\n",name,value);
break;
case T_CHAR :
fprintf(f_init,"\t PyDict_SetItemString(d,\"%s\", PyString_FromString(\"%s\"));\n",name,value);
break;
default:
fprintf(stderr,"%s : Line %d. Unsupported constant value.\n", input_file, line_number);
break;
}
} else {
if ((type->type == T_CHAR) && (type->is_pointer == 1)) {
fprintf(f_init,"\t PyDict_SetItemString(d,\"%s\", PyString_FromString(\"%s\"));\n",name,value);
} else {
// A funky user-defined type. We're going to munge it into a string pointer value
fprintf(f_init,"\t {\n");
fprintf(f_init,"\t\t char %s_char[%d];\n", name, (int) strlen(type->print_mangle()) + 20);
fprintf(f_init,"\t\t SWIG_MakePtr(%s_char, (void *) (%s),\"%s\");\n",
name, value, type->print_mangle());
fprintf(f_init,"\t\t PyDict_SetItemString(d,\"%s\", PyString_FromString(%s_char));\n",name,name);
fprintf(f_init,"\t }\n");
}
}
}
if ((shadow) && (!(shadow & PYSHADOW_MEMBER))) {
vars << name << " = " << module << "." << name << "\n";
}
if (doc_entry) {
doc_entry->usage = "";
doc_entry->usage << usage_const(name,type,value);
doc_entry->cinfo = "";
doc_entry->cinfo << "Constant: " << type->print_type();
}
}
// ----------------------------------------------------------------------
// PYTHON::usage_var(char *iname, DataType *t)
//
// This function produces a string indicating how to use a variable.
// It is called by the documentation system to produce syntactically
// correct documentation entires.
//
// s is a pointer to a character pointer. You should create
// a string and set this pointer to point to it.
// ----------------------------------------------------------------------
char *PYTHON::usage_var(char *iname, DataType *) {
static String temp;
temp = "";
temp << global_name << "." << iname;
// Create result. Don't modify this
return temp.get();
}
// ---------------------------------------------------------------------------
// PYTHON::usage_func(char *iname, DataType *t, ParmList *l)
//
// Produces a string indicating how to call a function in the target
// language.
//
// ---------------------------------------------------------------------------
char *PYTHON::usage_func(char *iname, DataType *, ParmList *l) {
static String temp;
Parm *p;
int i;
temp = "";
temp << iname << "(";
// Now go through and print parameters
// You probably don't need to change this
i = 0;
p = l->get_first();
while (p != 0) {
if (!p->ignore) {
i++;
/* If parameter has been named, use that. Otherwise, just print a type */
if ((p->t->type != T_VOID) || (p->t->is_pointer)) {
if (strlen(p->name) > 0) {
temp << p->name;
} else {
temp << p->t->print_type();
}
}
p = l->get_next();
if (p != 0) {
if (!p->ignore)
temp << ",";
}
} else {
p = l->get_next();
if (p) {
if ((!p->ignore) && (i > 0))
temp << ",";
}
}
}
temp << ")";
// Create result. Don't change this
return temp.get();
}
// ----------------------------------------------------------------------
// PYTHON::usage_const(char *iname, DataType *type, char *value)
//
// Produces a string for a constant. Really about the same as
// usage_var() except we'll indicate the value of the constant.
// ----------------------------------------------------------------------
char *PYTHON::usage_const(char *iname, DataType *, char *value) {
static String temp;
temp = "";
temp << iname << " = " << value;
return temp.get();
}
// -----------------------------------------------------------------------
// PYTHON::add_native(char *name, char *funcname)
//
// Add a native module name to the methods list.
// -----------------------------------------------------------------------
void PYTHON::add_native(char *name, char *funcname) {
add_method(name, funcname);
if (shadow) {
func << name << " = " << module << "." << name << "\n\n";
}
}
// -----------------------------------------------------------------------
// PYTHON::cpp_class_decl(char *name, char *rename, char *type)
//
// Treatment of an empty class definition. Used to handle
// shadow classes across modules.
// -----------------------------------------------------------------------
void PYTHON::cpp_class_decl(char *name, char *rename, char *type) {
char temp[256];
if (shadow) {
hash.add(name,copy_string(rename));
// Add full name of datatype to the hash table
if (strlen(type) > 0) {
sprintf(temp,"%s %s", type, name);
hash.add(temp,copy_string(rename));
}
}
}
// -----------------------------------------------------------------------
// PYTHON::pragma(char *name, char *type)
//
// Pragma directive. Used to do various python specific things
// -----------------------------------------------------------------------
void PYTHON::pragma(char *lang, char *cmd, char *value) {
if (strcmp(lang,"python") == 0) {
if (strcmp(cmd,"CODE") == 0) {
if (shadow) {
fprintf(f_shadow,"%s\n",value);
}
} else if (strcmp(cmd,"code") == 0) {
if (shadow) {
fprintf(f_shadow,"%s\n",value);
}
} else if (strcmp(cmd,"include") == 0) {
if (shadow) {
if (value) {
if (get_file(value,pragma_include) == -1) {
fprintf(stderr,"%s : Line %d. Unable to locate file %s\n", input_file, line_number, value);
}
}
}
} else {
fprintf(stderr,"%s : Line %d. Unrecognized pragma.\n", input_file, line_number);
}
}
}
/*********************************************************************************
*
* $Log: python.cxx,v $
* Revision 1.60 1997/07/27 20:29:59 beazley
* Changes to shadow class mechanism for output typemaps.
*
* Revision 1.59 1997/07/09 03:10:52 beazley
* First cut at eliminating compiler warnings.
*
* Revision 1.58 1997/07/08 05:19:47 beazley
* Fixed bug in shadow-class generation for non-class functions returning
* values via argout typemaps.
*
* Revision 1.57 1997/07/03 03:25:46 beazley
* Fixed some code generation problems with shadow classes and output
* arguments.
*
* Revision 1.56 1997/06/29 19:08:25 beazley
* Changed EXPORT to SWIGEXPORT
*
* Revision 1.55 1997/06/22 20:51:20 beazley
* Minor change to docstring option.
*
* Revision 1.54 1997/06/22 16:53:22 beazley
* Minor changes.
*
* Revision 1.53 1997/06/20 22:37:59 beazley
* Fixed compiler warnings
*
* Revision 1.52 1997/06/17 04:43:10 beazley
* Fixed bugs with %name(). Moved to unified naming scheme.
*
* Revision 1.51 1997/05/28 21:41:21 beazley
* Moved revision history to end.
*
* Revision 1.50 1997/05/24 05:15:52 beazley
* Added the "build" typemap.
*
* Revision 1.49 1997/05/19 19:10:39 beazley
* Fixed bug in native functions and shadow classes.
*
* Revision 1.48 1997/05/19 16:27:52 beazley
* Added a few more typemap variables.
*
* Revision 1.47 1997/05/09 16:29:14 beazley
* Fixed a bug in the "check" typemap.
*
* Revision 1.46 1997/05/08 05:42:21 beazley
* Added $cleanup symbol. Fixed core dump on empty files.
*
* Revision 1.45 1997/05/05 15:52:08 beazley
* A few minor bug fixes in code generation. Added support for
* parameterized typemaps. Bug fixes with "ignore" and "argout"
* typemaps.
*
* Revision 1.44 1997/04/19 21:26:01 beazley
* Added support for %new directive. A few new pragma directives.
*
* Revision 1.43 1997/03/19 23:48:04 beazley
* Changed "constrain" typemap to "check"
*
* Revision 1.42 1997/03/18 22:27:29 beazley
* Added constrain typemap
*
* Revision 1.41 1997/03/16 21:26:58 beazley
* Fixed bug with -c option.
*
* Revision 1.40 1997/03/12 05:03:43 beazley
* Minor bug fixes
*
* Revision 1.39 1997/03/08 23:11:54 beazley
* Minor tweak to code generation and change of ordering in a few spots.
*
* Revision 1.38 1997/03/02 22:40:57 beazley
* Removed warnings. Minor improvements
*
* Revision 1.37 1997/02/19 23:03:42 beazley
* Added create_command() function for C++ optimization.
*
* Revision 1.36 1997/02/16 18:51:51 beazley
* Modified to allowed ignore arguments. Bug fixes to default argument
* handling.
*
* Revision 1.35 1997/01/30 05:51:32 beazley
* Fixed Dec alpha bug with extra space inserted before an endif.
*
* Revision 1.34 1997/01/27 05:13:45 beazley
* Added support for default arguments in shadow classes.
*
* Revision 1.33 1997/01/08 05:43:06 beazley
* Pre 1.1b3 checkin
*
* Revision 1.32 1997/01/06 17:12:03 beazley
* Added support for typemaps. Multiple inheritance.
*
* Revision 1.31 1996/12/26 23:03:19 beazley
* Modified to use new pointer type-checker
*
* Revision 1.30 1996/12/26 04:48:00 beazley
* Added support for %module directive with multiple modules
*
* Revision 1.29 1996/12/03 08:41:26 beazley
* pre-1.1b2 checkin
*
* Revision 1.28 1996/11/12 20:01:57 beazley
* Changes to support new documentation and C++ handling
*
* Revision 1.27 1996/10/23 05:24:33 beazley
* Added support for 'bool' datatype
*
* Revision 1.26 1996/09/26 21:50:17 dmb
* Minor fixes
*
* Revision 1.25 1996/08/29 05:41:00 dmb
* Fixed help message
*
* Revision 1.24 1996/08/27 23:02:21 dmb
* Minor changes to error handling
*
* Revision 1.23 1996/08/25 00:05:13 dmb
* More improvements to shadow classes
*
* Revision 1.22 1996/08/21 16:51:37 dmb
* Cleanup to eliminate warning messages
*
* Revision 1.21 1996/08/21 05:50:28 dmb
* More changes to shadow classes.
*
* Revision 1.20 1996/08/16 04:17:21 dmb
* Added SWIG_name declaration
*
* Revision 1.19 1996/08/12 01:50:03 dmb
* Almost a completely new version. Changed variable linking, constants,
* and added support for new language class structure
*
* Revision 1.18 1996/08/02 02:57:41 dmb
* Modified to use better parameter list functions()
*
* Revision 1.17 1996/07/17 15:06:30 dmb
* Fixed a few more bugs with -strict 1 mode.
*
* Revision 1.16 1996/07/17 14:57:42 dmb
* Fixed bug in -strict 1 pointer type checking mode.
*
* Revision 1.15 1996/06/02 00:14:36 beazley
* Minor fixes
*
* Revision 1.14 1996/05/22 20:20:21 beazley
* Add banner and cleanup functions to headers() and close() functions
*
* Revision 1.13 1996/05/20 23:36:07 beazley
* Added a few more constant datatypes.
*
* Revision 1.12 1996/05/17 05:53:32 beazley
* Added return by value support
*
* Revision 1.11 1996/05/16 03:58:34 beazley
* Fixed bug in function return type error message.
*
* Revision 1.10 1996/05/13 23:45:37 beazley
* Reworked the module/init procedure
*
* Revision 1.9 1996/05/10 23:38:26 beazley
* Minor changes
*
* Revision 1.8 1996/05/07 03:24:10 beazley
* Fixed bug with linking pointer variable types.
*
* Revision 1.7 1996/05/03 05:11:15 dmb
* Fixed up some C++ linking problems.
*
* Revision 1.6 1996/05/01 22:42:01 dmb
* Cleaned up command line option handling.
*
* Revision 1.5 1996/04/13 19:02:05 beazley
* Fixed bug in module system and variable linking.
*
* Revision 1.4 1996/04/09 20:18:35 beazley
* Minor cleanup.
*
* Revision 1.3 1996/04/08 22:09:36 beazley
* Minor cleanup
*
* Revision 1.2 1996/03/28 02:47:14 beazley
* Some bug fixes, etc...
*
* Revision 1.1 1996/03/24 22:15:14 beazley
* Initial revision
*
*********************************************************************************/
syntax highlighted by Code2HTML, v. 0.9.1