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
		
			
				
	
	
		
			830 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			830 lines
		
	
	
		
			21 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"
 | 
						|
/*******************************************************************************
 | 
						|
 * $Header$
 | 
						|
 *
 | 
						|
 * File : emit.cxx
 | 
						|
 *
 | 
						|
 * This file contains some useful functions for emitting code that would be
 | 
						|
 * common to all of the interface languages.  Mainly this function deals with
 | 
						|
 * declaring functions external, creating lists of arguments, and making
 | 
						|
 * function calls.
 | 
						|
 *******************************************************************************/
 | 
						|
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
// void emit_banner(FILE *f)
 | 
						|
// 
 | 
						|
// Emits the SWIG identifying banner in the wrapper file
 | 
						|
//
 | 
						|
// Inputs : f   = FILE handle
 | 
						|
//
 | 
						|
// Output : None
 | 
						|
//
 | 
						|
// Side Effects : None
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
 | 
						|
void emit_banner(FILE *f) {
 | 
						|
 | 
						|
  extern char *get_time();
 | 
						|
  extern char fn_header[];
 | 
						|
 | 
						|
  fprintf(f,
 | 
						|
"/*\n\
 | 
						|
 * FILE : %s\n\
 | 
						|
 * \n\
 | 
						|
 * This file was automatically generated by :\n\
 | 
						|
 * Simplified Wrapper and Interface Generator (SWIG)\n\
 | 
						|
 * Version %d.%d %s\n\
 | 
						|
 * \n\
 | 
						|
 * Portions Copyright (c) 1995-1998\n\
 | 
						|
 * The University of Utah and The Regents of the University of California.\n\
 | 
						|
 * Permission is granted to distribute this file in any manner provided\n\
 | 
						|
 * this notice remains intact.\n\
 | 
						|
 * \n\
 | 
						|
 * Do not make changes to this file--changes will be lost!\n\
 | 
						|
 *\n\
 | 
						|
 */\n\n", fn_header, SWIG_MAJOR_VERSION, SWIG_MINOR_VERSION, SWIG_SPIN);
 | 
						|
 | 
						|
  fprintf(f,"\n#define SWIGCODE\n");
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
// emit_extern_var(char *decl, DataType *t, int extern_type, FILE *f)
 | 
						|
// 
 | 
						|
// Emits an external variables declaration.   Extern_type defines the
 | 
						|
// type of external declaration.  Currently, only C/C++ declarations
 | 
						|
// are allowed, but this might be extended to allow Fortran linkage
 | 
						|
// someday
 | 
						|
//
 | 
						|
// Inputs :
 | 
						|
//          decl        = Name of the declaration
 | 
						|
//          t           = Datatype
 | 
						|
//          extern_type = Numeric code indicating type of extern
 | 
						|
//                              0   - No "extern"
 | 
						|
//                              1,2 -  Normal extern (C/C++)
 | 
						|
//          f           = FILE handle
 | 
						|
//
 | 
						|
// Output : None
 | 
						|
//
 | 
						|
// Side Effects : None
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
 | 
						|
void emit_extern_var(char *decl, DataType *t, int extern_type, FILE *f) {
 | 
						|
  char *arr = 0;
 | 
						|
 | 
						|
  if (t->arraystr) arr = t->arraystr;
 | 
						|
  else arr = "";
 | 
						|
 | 
						|
  switch(extern_type) {
 | 
						|
 | 
						|
  case 0:
 | 
						|
    // No extern.  Just a forward reference
 | 
						|
    if (t->arraystr)
 | 
						|
      t->is_pointer--;
 | 
						|
 | 
						|
    if (t->is_reference) {
 | 
						|
      t->is_pointer--;
 | 
						|
      fprintf(f,"%s& %s%s; \n", t->print_full(), decl, arr);
 | 
						|
      t->is_pointer++;
 | 
						|
    } else {
 | 
						|
      fprintf(f,"%s %s%s; \n", t->print_full(), decl,arr);
 | 
						|
    }
 | 
						|
    if (t->arraystr)
 | 
						|
      t->is_pointer++;
 | 
						|
    break;
 | 
						|
  case 1: case 2:
 | 
						|
    if (t->arraystr)
 | 
						|
      t->is_pointer--;
 | 
						|
 | 
						|
    // Normal C/C++ extern
 | 
						|
//    fprintf(f,"#line %d \"%s\"\n", line_number, input_file);
 | 
						|
    if (t->is_reference) {
 | 
						|
      t->is_pointer--;
 | 
						|
      fprintf(f,"extern %s& %s%s; \n", t->print_full(), decl,arr);
 | 
						|
      t->is_pointer++;
 | 
						|
    } else {
 | 
						|
      fprintf(f,"extern %s %s%s; \n", t->print_full(), decl,arr);
 | 
						|
    }
 | 
						|
    if (t->arraystr)
 | 
						|
      t->is_pointer++;
 | 
						|
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
// emit_extern_func(char *decl, DataType *t, ParmList *L, int extern_type,
 | 
						|
//                  FILE *f)
 | 
						|
//
 | 
						|
// Emits an external function declaration (similiar to emit_extern_var).
 | 
						|
// 
 | 
						|
// Inputs : 
 | 
						|
//          decl        = Name of declaration
 | 
						|
//          t           = Return datatype
 | 
						|
//          L           = parameter list
 | 
						|
//          extern_type = Type of extern
 | 
						|
//                           0 - No "extern"
 | 
						|
//                           1 - extern
 | 
						|
//                           2 - extern "C"
 | 
						|
//                           3 - Function declaration (with arg names)
 | 
						|
//          f           = FILE Handle
 | 
						|
//
 | 
						|
// Output : None
 | 
						|
//
 | 
						|
// Side Effects : None
 | 
						|
// 
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
 | 
						|
void emit_extern_func(char *decl, DataType *t, ParmList *L, int extern_type, FILE *f) {
 | 
						|
 | 
						|
  switch(extern_type) {
 | 
						|
  case 0:
 | 
						|
    if (t->is_reference) {
 | 
						|
	t->is_pointer--;
 | 
						|
	fprintf(f,"%s&", t->print_full());
 | 
						|
	t->is_pointer++;
 | 
						|
    } else {
 | 
						|
      fprintf(f,"%s", t->print_full());
 | 
						|
    }
 | 
						|
    
 | 
						|
    fprintf(f,"%s(", decl);
 | 
						|
    L->print_types(f);
 | 
						|
    fprintf(f,");\n");
 | 
						|
    break;
 | 
						|
  case 1:
 | 
						|
    // Normal C/C++ extern
 | 
						|
//    fprintf(f,"#line %d \"%s\"\n", line_number, input_file);
 | 
						|
    if (t->is_reference) {
 | 
						|
	t->is_pointer--;
 | 
						|
	fprintf(f,"extern %s&", t->print_full());
 | 
						|
	t->is_pointer++;
 | 
						|
    } else {
 | 
						|
      fprintf(f,"extern %s", t->print_full());
 | 
						|
    }
 | 
						|
    fprintf(f,"%s(", decl);
 | 
						|
    L->print_types(f);
 | 
						|
    fprintf(f,");\n");
 | 
						|
    break;
 | 
						|
  case 2:
 | 
						|
    // A C++ --- > C Extern
 | 
						|
//    fprintf(f,"#line %d \"%s\"\n", line_number, input_file);
 | 
						|
    if (t->is_reference) {
 | 
						|
	t->is_pointer--;
 | 
						|
	fprintf(f,"extern \"C\" %s&", t->print_full());
 | 
						|
	t->is_pointer++;
 | 
						|
    } else {
 | 
						|
      fprintf(f,"extern \"C\" %s", t->print_full());
 | 
						|
    }
 | 
						|
    fprintf(f,"%s(", decl);
 | 
						|
    L->print_types(f);
 | 
						|
    fprintf(f,");\n");
 | 
						|
    break;
 | 
						|
  case 3:
 | 
						|
    // A function declaration (for inlining )
 | 
						|
    if (t->is_reference) {
 | 
						|
	t->is_pointer--;
 | 
						|
	fprintf(f,"%s&", t->print_full());
 | 
						|
	t->is_pointer++;
 | 
						|
    } else {
 | 
						|
      fprintf(f,"%s", t->print_full());
 | 
						|
    }
 | 
						|
    
 | 
						|
    fprintf(f,"%s(", decl);
 | 
						|
    L->print_args(f);
 | 
						|
    fprintf(f,")\n");
 | 
						|
    break;
 | 
						|
  default:
 | 
						|
    break;
 | 
						|
  }
 | 
						|
}  
 | 
						|
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
// char *emit_local(int i)
 | 
						|
//
 | 
						|
// Returns the name of local variable for parameter i
 | 
						|
//
 | 
						|
// Inputs : i      = Parameter number
 | 
						|
//
 | 
						|
// Output : NULL terminated ASCII string
 | 
						|
//
 | 
						|
// Side Effects : Result is left in a static local variable.
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
 | 
						|
char *emit_local(int i) {
 | 
						|
  static char arg[64];
 | 
						|
 | 
						|
  sprintf(arg,"_arg%d", i);
 | 
						|
  return arg;
 | 
						|
}
 | 
						|
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
// int emit_args(char *d, DataType *rt, ParmList *l, FILE *f)
 | 
						|
//
 | 
						|
// Creates a list of variable declarations for both the return value
 | 
						|
// and function parameters.
 | 
						|
//
 | 
						|
// The return value is always called _result and arguments label as
 | 
						|
// _arg0, _arg1, _arg2, etc...
 | 
						|
//
 | 
						|
// Returns the number of parameters associated with a function.
 | 
						|
// 
 | 
						|
// Inputs :
 | 
						|
//          d     = Name of function
 | 
						|
//          rt    = Return type
 | 
						|
//          l     = Parameter list
 | 
						|
//          f     = FILE Handle
 | 
						|
//
 | 
						|
// Output : Number of function arguments 
 | 
						|
//
 | 
						|
// Side Effects : None
 | 
						|
//
 | 
						|
// Note : This function is obsolete.  Use emit_args below...
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
 | 
						|
int emit_args(DataType *rt, ParmList *l, FILE *f) {
 | 
						|
 | 
						|
  Parm *p;
 | 
						|
  int   i;
 | 
						|
  char  temp[64];
 | 
						|
  String def;
 | 
						|
  char  *tm;
 | 
						|
 | 
						|
  // Declare the return variable
 | 
						|
 | 
						|
  if ((rt->type != T_VOID) || (rt->is_pointer)) {
 | 
						|
    if ((rt->type == T_USER) && (!rt->is_pointer)) {
 | 
						|
 | 
						|
      // Special case for return by "value"
 | 
						|
 | 
						|
      rt->is_pointer++;
 | 
						|
      fprintf(f,"\t %s _result;\n", rt->print_type());
 | 
						|
      rt->is_pointer--;
 | 
						|
    } else {
 | 
						|
 | 
						|
      // Normal return value
 | 
						|
 | 
						|
      fprintf(f,"\t %s _result;\n", rt->print_type());
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Emit function arguments
 | 
						|
 | 
						|
  i = 0;
 | 
						|
  p = l->get_first();
 | 
						|
  while (p != 0) {
 | 
						|
    if ((p->t->type != T_VOID) || (p->t->is_pointer))  {
 | 
						|
      sprintf(temp,"_arg%d", i);
 | 
						|
      if (p->defvalue) {
 | 
						|
	if ((p->t->is_reference) || ((p->t->type == T_USER) && (p->call_type == CALL_REFERENCE)))
 | 
						|
	    fprintf(f,"\t %s _arg%d = &%s;\n", p->t->print_type(),i, p->defvalue);
 | 
						|
	  else	
 | 
						|
	    fprintf(f,"\t %s _arg%d = %s;\n", p->t->print_type(),i, p->defvalue);
 | 
						|
      } else {
 | 
						|
	fprintf(f,"\t %s _arg%d;\n", p->t->print_type(),i);
 | 
						|
	tm = typemap_lookup("arginit", typemap_lang, p->t, p->name,"",temp);
 | 
						|
	if (tm) {
 | 
						|
	  def << tm;
 | 
						|
	}
 | 
						|
      }
 | 
						|
 | 
						|
      // Check for ignore or default typemaps
 | 
						|
      
 | 
						|
      tm = typemap_lookup("default",typemap_lang,p->t,p->name,"",temp);
 | 
						|
      if (tm) 
 | 
						|
	def << tm;
 | 
						|
      tm = typemap_lookup("ignore",typemap_lang,p->t,p->name,"",temp);
 | 
						|
 | 
						|
      if (tm) {
 | 
						|
	def << tm;
 | 
						|
	p->ignore = 1;
 | 
						|
      }
 | 
						|
      tm = typemap_check("build",typemap_lang,p->t,p->name);
 | 
						|
      if (tm) {
 | 
						|
	p->ignore = 1;
 | 
						|
      }
 | 
						|
      i++;
 | 
						|
    }
 | 
						|
    p = l->get_next();
 | 
						|
  }
 | 
						|
 | 
						|
  fprintf(f,"%s",def.get());
 | 
						|
 | 
						|
  // i now contains number of parameters
 | 
						|
  
 | 
						|
  return(i);
 | 
						|
 | 
						|
 }
 | 
						|
 | 
						|
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
// int emit_args(char *d, DataType *rt, ParmList *l, WrapperFunction &f)
 | 
						|
//
 | 
						|
// Creates a list of variable declarations for both the return value
 | 
						|
// and function parameters.
 | 
						|
//
 | 
						|
// The return value is always called _result and arguments label as
 | 
						|
// _arg0, _arg1, _arg2, etc...
 | 
						|
//
 | 
						|
// Returns the number of parameters associated with a function.
 | 
						|
// 
 | 
						|
// Inputs :
 | 
						|
//          d     = Name of function
 | 
						|
//          rt    = Return type
 | 
						|
//          l     = Parameter list
 | 
						|
//          f     = Wrapper function object
 | 
						|
//
 | 
						|
// Output : Number of function arguments 
 | 
						|
//
 | 
						|
// Side Effects : None
 | 
						|
//
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
 | 
						|
int emit_args(DataType *rt, ParmList *l, WrapperFunction &f) {
 | 
						|
 | 
						|
  Parm *p;
 | 
						|
  int   i;
 | 
						|
  char *tm;
 | 
						|
 | 
						|
  // Declare the return variable
 | 
						|
 | 
						|
  if ((rt->type != T_VOID) || (rt->is_pointer)) {
 | 
						|
    if ((rt->type == T_USER) && (!rt->is_pointer)) {
 | 
						|
 | 
						|
      // Special case for return by "value"
 | 
						|
      rt->is_pointer++;
 | 
						|
      f.add_local(rt->print_type(), "_result");
 | 
						|
      rt->is_pointer--;
 | 
						|
    } else {
 | 
						|
 | 
						|
      // Normal return value
 | 
						|
 | 
						|
      f.add_local(rt->print_type(), "_result");
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Emit function arguments
 | 
						|
 | 
						|
  i = 0;
 | 
						|
  p = l->get_first();
 | 
						|
  while (p != 0) {
 | 
						|
    if ((p->t->type != T_VOID) || (p->t->is_pointer))  {
 | 
						|
      char *temp = emit_local(i);
 | 
						|
      // Figure out default values
 | 
						|
      if (((p->t->is_reference) && (p->defvalue)) || 
 | 
						|
	  ((p->t->type == T_USER) && (p->call_type == CALL_REFERENCE) && (p->defvalue))) {
 | 
						|
	String deftmp;
 | 
						|
	deftmp << "(" << p->t->print_type() << ") &" << p->defvalue;
 | 
						|
	f.add_local(p->t->print_type(),temp,deftmp.get());
 | 
						|
      } else {
 | 
						|
	String deftmp;
 | 
						|
	char *dv = 0;
 | 
						|
	if (p->defvalue) {
 | 
						|
	  deftmp << "(" << p->t->print_type() << ") " << p->defvalue;
 | 
						|
	  dv = deftmp.get();
 | 
						|
	}
 | 
						|
	f.add_local(p->t->print_type(), temp, dv);
 | 
						|
	tm = typemap_lookup("arginit", typemap_lang, p->t,p->name,"",temp,&f);
 | 
						|
	if (tm) {
 | 
						|
	  f.code << tm << "\n";
 | 
						|
	}
 | 
						|
      }
 | 
						|
      // Check for ignore or default typemaps
 | 
						|
      tm = typemap_lookup("default",typemap_lang,p->t,p->name,"",temp,&f);
 | 
						|
      if (tm) 
 | 
						|
	f.code << tm << "\n";
 | 
						|
      tm = typemap_lookup("ignore",typemap_lang,p->t,p->name,"",temp,&f);
 | 
						|
      if (tm) {
 | 
						|
	f.code << tm << "\n";
 | 
						|
	p->ignore = 1;
 | 
						|
      }
 | 
						|
      tm = typemap_check("build",typemap_lang,p->t,p->name);
 | 
						|
      if (tm) {
 | 
						|
	p->ignore = 1;
 | 
						|
      }
 | 
						|
      i++;
 | 
						|
    }
 | 
						|
    p = l->get_next();
 | 
						|
  }
 | 
						|
 | 
						|
  // i now contains number of parameters
 | 
						|
  return(i);
 | 
						|
}
 | 
						|
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
// int emit_func_call(char *decl, DataType *t, ParmList *l, FILE *f)
 | 
						|
//
 | 
						|
// Emits code for a function call.
 | 
						|
// 
 | 
						|
// Inputs :
 | 
						|
//           decl   = name of function
 | 
						|
//           t      = Return datatype
 | 
						|
//           l      = Parameter list
 | 
						|
//           f      = FILE Handle
 | 
						|
//
 | 
						|
// Output : None
 | 
						|
//
 | 
						|
// Side Effects : None
 | 
						|
//
 | 
						|
// Note : This function is obsolete
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
 | 
						|
void emit_func_call(char *decl, DataType *t, ParmList *l, FILE *f) {
 | 
						|
 | 
						|
  int  i;
 | 
						|
  Parm  *p;
 | 
						|
 | 
						|
//  fprintf(f,"#line %d \"%s\"\n", line_number, input_file);
 | 
						|
  fprintf(f,"\t ");
 | 
						|
 | 
						|
  // First check if there is a return value
 | 
						|
 | 
						|
  if ((t->type != T_VOID) || (t->is_pointer)) {
 | 
						|
    if ((t->type == T_USER) && (!t->is_pointer)) {
 | 
						|
 | 
						|
      // Special case for return by "value"
 | 
						|
      // Caution : This *will* cause a memory leak if not
 | 
						|
      // used properly.
 | 
						|
 | 
						|
      if (CPlusPlus) {
 | 
						|
	fprintf(f,"_result = new %s(", t->print_type());
 | 
						|
      } else {
 | 
						|
	t->is_pointer++;
 | 
						|
	fprintf(f,"_result = %s malloc(sizeof(", t->print_cast());
 | 
						|
	t->is_pointer--;
 | 
						|
	fprintf(f,"%s));\n", t->print_type());
 | 
						|
	fprintf(f,"\t*(_result) = ");
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      // Check if this is a C++ reference
 | 
						|
      if (t->is_reference) {
 | 
						|
	t->is_pointer--;
 | 
						|
	fprintf(f,"%s& _result_ref = ", t->print_full());
 | 
						|
	t->is_pointer++;
 | 
						|
      } else {
 | 
						|
	
 | 
						|
      // Normal return values
 | 
						|
	fprintf(f,"_result = %s", t->print_cast());
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Now print out function call
 | 
						|
 | 
						|
  fprintf(f,"%s(",decl);
 | 
						|
 | 
						|
  i = 0;
 | 
						|
  p = l->get_first();
 | 
						|
  while(p != 0) {
 | 
						|
    if ((p->t->type != T_VOID) || (p->t->is_pointer)){
 | 
						|
      fprintf(f,"%s",p->t->print_arraycast());
 | 
						|
      if ((!p->t->is_reference) && (p->call_type & CALL_VALUE)) fprintf(f,"&");
 | 
						|
      if ((!(p->call_type & CALL_VALUE)) &&
 | 
						|
	  ((p->t->is_reference) || (p->call_type & CALL_REFERENCE)))
 | 
						|
	fprintf(f,"*");
 | 
						|
      fprintf(f,"_arg%d",i);
 | 
						|
      i++;
 | 
						|
    }
 | 
						|
    p = l->get_next();
 | 
						|
    if (p != 0)
 | 
						|
      fprintf(f,",");
 | 
						|
  }
 | 
						|
 | 
						|
  fprintf(f,")");
 | 
						|
  if ((t->type == T_USER) && (!t->is_pointer)) {
 | 
						|
    if (CPlusPlus) {
 | 
						|
      fprintf(f,")");
 | 
						|
    }
 | 
						|
  }
 | 
						|
  fprintf(f,";\n");
 | 
						|
  if (t->is_reference) {
 | 
						|
    fprintf(f,"\t _result = %s &_result_ref;\n", t->print_cast());
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
// int emit_func_call(char *decl, DataType *t, ParmList *l, WrapperFunction &f)
 | 
						|
//
 | 
						|
// Emits code for a function call (new version).
 | 
						|
// 
 | 
						|
// Exception handling support :
 | 
						|
//
 | 
						|
//     -  This function checks to see if any sort of exception mechanism
 | 
						|
//        has been defined.  If so, we emit the function call in an exception
 | 
						|
//        handling block.
 | 
						|
//
 | 
						|
// Inputs :
 | 
						|
//           decl   = name of function
 | 
						|
//           t      = Return datatype
 | 
						|
//           l      = Parameter list
 | 
						|
//           f      = WrapperFunction object
 | 
						|
//
 | 
						|
// Output : None
 | 
						|
//
 | 
						|
// Side Effects : None
 | 
						|
//
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
 | 
						|
void emit_func_call(char *decl, DataType *t, ParmList *l, WrapperFunction &f) {
 | 
						|
 | 
						|
  int  i;
 | 
						|
  Parm  *p;
 | 
						|
  String fcall;
 | 
						|
  String exc;
 | 
						|
  char *tm;
 | 
						|
 | 
						|
//  f.code << "#line " << line_number << " \"" << input_file << "\"\n";
 | 
						|
  fcall << tab4;
 | 
						|
 | 
						|
  // First check if there is a return value
 | 
						|
 | 
						|
  if ((t->type != T_VOID) || (t->is_pointer)) {
 | 
						|
    if ((t->type == T_USER) && (!t->is_pointer)) {
 | 
						|
 | 
						|
      // Special case for return by "value"
 | 
						|
      // Caution : This *will* cause a memory leak if not
 | 
						|
      // used properly.
 | 
						|
 | 
						|
      if (CPlusPlus) {
 | 
						|
	fcall << "_result = new " << t->print_type() << "(";
 | 
						|
      } else {
 | 
						|
	t->is_pointer++;
 | 
						|
	fcall << "_result = " << t->print_cast() << " malloc(sizeof(";
 | 
						|
	t->is_pointer--;
 | 
						|
	fcall << t->print_type() << "));\n";
 | 
						|
	fcall << tab4 << "*(_result) = ";
 | 
						|
      }
 | 
						|
    } else {
 | 
						|
      // Check if this is a C++ reference
 | 
						|
      if (t->is_reference) {
 | 
						|
	t->is_pointer--;
 | 
						|
	fcall << t->print_full() << "& _result_ref = ";
 | 
						|
	t->is_pointer++;
 | 
						|
      } else {
 | 
						|
 | 
						|
	// Normal return value
 | 
						|
	fcall << "_result = " << t->print_cast();
 | 
						|
      }
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  // Now print out function call
 | 
						|
 | 
						|
  fcall << decl << "(";
 | 
						|
 | 
						|
  i = 0;
 | 
						|
  p = l->get_first();
 | 
						|
  while(p != 0) {
 | 
						|
    if ((p->t->type != T_VOID) || (p->t->is_pointer)){
 | 
						|
      fcall << p->t->print_arraycast();
 | 
						|
      if ((!p->t->is_reference) && (p->call_type & CALL_VALUE))
 | 
						|
	fcall << "&";
 | 
						|
      if ((!(p->call_type & CALL_VALUE)) &&
 | 
						|
	  ((p->t->is_reference) || (p->call_type & CALL_REFERENCE)))
 | 
						|
	fcall << "*";
 | 
						|
      fcall << emit_local(i);
 | 
						|
      i++;
 | 
						|
    }
 | 
						|
    p = l->get_next();
 | 
						|
    if (p != 0)
 | 
						|
      fcall << ",";
 | 
						|
  }
 | 
						|
  fcall << ")";
 | 
						|
 | 
						|
  if ((t->type == T_USER) && (!t->is_pointer)) {
 | 
						|
    if (CPlusPlus) {
 | 
						|
      fcall << ")";
 | 
						|
    }
 | 
						|
  }
 | 
						|
  fcall << ";\n";
 | 
						|
 | 
						|
  if (t->is_reference) {
 | 
						|
    fcall << tab4 << "_result = "<< t->print_cast() << " &_result_ref;\n";
 | 
						|
  }
 | 
						|
  // Check for exception handling
 | 
						|
 | 
						|
  if ((tm = typemap_lookup("except",typemap_lang,t,decl,"_result",""))) {
 | 
						|
    // Found a type-specific mapping
 | 
						|
    exc << tm;
 | 
						|
    exc.replace("$function",fcall);
 | 
						|
    exc.replace("$name",decl);
 | 
						|
    f.code << exc;
 | 
						|
  } else if ((tm = fragment_lookup("except",typemap_lang, t->id))) {
 | 
						|
    exc << tm;
 | 
						|
    exc.replace("$function",fcall);
 | 
						|
    exc.replace("$name",decl);
 | 
						|
    f.code << exc;
 | 
						|
  } else {
 | 
						|
    f.code << fcall;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
// void emit_hex(FILE *f)
 | 
						|
// 
 | 
						|
// Emits the default C-code to handle pointers.   This is normally contained
 | 
						|
// in the SWIG library file 'swigptr.swg'
 | 
						|
//
 | 
						|
// Inputs : f   = FILE handle
 | 
						|
//
 | 
						|
// Output : None
 | 
						|
//
 | 
						|
// Side Effects : None
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
 | 
						|
void emit_hex(FILE *f) {
 | 
						|
  
 | 
						|
  int stat;
 | 
						|
 | 
						|
   // Look for a pointer configuration file
 | 
						|
 | 
						|
   stat = insert_file("swigptr.swg", f);
 | 
						|
 | 
						|
   if (stat == -1) {
 | 
						|
     fprintf(stderr,"** Fatal error.  Unable to locate 'swigptr.swg'\n");
 | 
						|
     SWIG_exit(1);
 | 
						|
   }
 | 
						|
}
 | 
						|
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
// void emit_set_get(char *name, char *iname, DataType *type)
 | 
						|
//
 | 
						|
// Emits a pair of functions to set/get the value of a variable.
 | 
						|
// This should be used as backup in case the target language can't
 | 
						|
// provide variable linking.
 | 
						|
// 
 | 
						|
// double foo;
 | 
						|
//
 | 
						|
// Gets translated into the following :
 | 
						|
//
 | 
						|
// double foo_set(double x) {
 | 
						|
//      return foo = x;
 | 
						|
// }
 | 
						|
//
 | 
						|
// double foo_get() {
 | 
						|
//      return foo;
 | 
						|
// }
 | 
						|
//
 | 
						|
// 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.
 | 
						|
// 
 | 
						|
// 
 | 
						|
// Inputs :
 | 
						|
//          name    = Name of variable
 | 
						|
//          iname   = Renamed version of variable
 | 
						|
//          type    = Datatype of the variable
 | 
						|
//
 | 
						|
// Output : None
 | 
						|
//
 | 
						|
// Side Effects : None
 | 
						|
// -----------------------------------------------------------------------------
 | 
						|
 | 
						|
void emit_set_get(char *name, char *iname, DataType *t) {
 | 
						|
 | 
						|
    Parm *p;
 | 
						|
    ParmList *l;
 | 
						|
    String new_name;
 | 
						|
    String new_iname;
 | 
						|
    String wname;
 | 
						|
 | 
						|
    // First write a function to set the variable of the variable
 | 
						|
 | 
						|
    if (!(Status & STAT_READONLY)) {
 | 
						|
      if ((t->type == T_USER) && (!t->is_pointer)) {
 | 
						|
	t->is_pointer++;
 | 
						|
	fprintf(f_header,"static %s %s(%s val) {\n",
 | 
						|
		t->print_type(), name_set(name), t->print_type());
 | 
						|
	t->is_pointer--;
 | 
						|
      } else {
 | 
						|
	fprintf(f_header,"static %s %s(%s val) {\n",
 | 
						|
		t->print_type(), name_set(name), t->print_type());
 | 
						|
      }
 | 
						|
      
 | 
						|
      if ((t->type != T_VOID) || (t->is_pointer)) {
 | 
						|
	if (!t->is_pointer) {
 | 
						|
	  
 | 
						|
	  // Have a real value here 
 | 
						|
	  // If it's a user defined type, we'll do something special.
 | 
						|
	  // Otherwise, just assign it.
 | 
						|
	  
 | 
						|
	  if (t->type != T_USER) {
 | 
						|
	    fprintf(f_header,"\t return (%s) (%s = val);\n", t->print_type(), name);
 | 
						|
	  } else {
 | 
						|
	    fprintf(f_header,"\t %s = *(val);\n", name);
 | 
						|
	    t->is_pointer++;
 | 
						|
	    fprintf(f_header,"\t return (%s) &%s;\n", t->print_type(),name);
 | 
						|
	    t->is_pointer--;
 | 
						|
	  }
 | 
						|
	} else {
 | 
						|
	  
 | 
						|
	  // Is a pointer type here.  If string, we do something
 | 
						|
	  // special.  Otherwise. No problem.
 | 
						|
	  
 | 
						|
	  if ((t->type == T_CHAR) && (t->is_pointer == 1)) {
 | 
						|
	    if (CPlusPlus) {
 | 
						|
	      fprintf(f_header,"\t if (%s) delete %s;\n", name,name);
 | 
						|
	      fprintf(f_header,"\t %s = new char[strlen(val)+1];\n",name);
 | 
						|
	      fprintf(f_header,"\t strcpy(%s,val);\n", name);
 | 
						|
	      fprintf(f_header,"\t return %s;\n", name);
 | 
						|
	    } else {
 | 
						|
	      fprintf(f_header,"\t if (%s) free(%s);\n", name,name);
 | 
						|
	      fprintf(f_header,"\t %s = (char *) malloc(strlen(val)+1);\n",name);
 | 
						|
	      fprintf(f_header,"\t strcpy(%s,val);\n", name);
 | 
						|
	      fprintf(f_header,"\t return %s;\n", name);
 | 
						|
	    }
 | 
						|
	  } else {
 | 
						|
	    fprintf(f_header,"\t return (%s) (%s = val);\n", t->print_type(), name);
 | 
						|
	  }
 | 
						|
	}
 | 
						|
      }
 | 
						|
 | 
						|
      fprintf(f_header,"}\n");
 | 
						|
 | 
						|
      // Now wrap it.
 | 
						|
 | 
						|
      l = new ParmList;
 | 
						|
      p = new Parm(t,0);
 | 
						|
      if ((t->type == T_USER) && (!t->is_pointer)) p->t->is_pointer++;
 | 
						|
      p->name = new char[1];
 | 
						|
      p->name[0] = 0;
 | 
						|
      l->append(p);
 | 
						|
      
 | 
						|
      new_name = name_set(name);
 | 
						|
      new_iname = name_set(iname);
 | 
						|
      
 | 
						|
      if ((t->type == T_USER) && (!t->is_pointer)) {
 | 
						|
	t->is_pointer++;
 | 
						|
	lang->create_function(new_name, new_iname, t, l);
 | 
						|
	t->is_pointer--;
 | 
						|
      } else {
 | 
						|
	lang->create_function(new_name, new_iname, t, l);
 | 
						|
      }
 | 
						|
      delete l;
 | 
						|
      delete p;
 | 
						|
      if (doc_entry) doc_entry->usage << "\n";
 | 
						|
    }
 | 
						|
 | 
						|
    // Now write a function to get the value of the variable
 | 
						|
 | 
						|
    if ((t->type == T_USER) && (!t->is_pointer)) {
 | 
						|
      t->is_pointer++;
 | 
						|
      fprintf(f_header,"static %s %s() { \n",
 | 
						|
	      t->print_type(), name_get(name));
 | 
						|
      fprintf(f_header,"\t return (%s) &%s;\n", t->print_type(), name);
 | 
						|
      t->is_pointer--;
 | 
						|
    } else {
 | 
						|
      fprintf(f_header,"static %s %s() { \n",
 | 
						|
	      t->print_type(), name_get(name));
 | 
						|
      fprintf(f_header,"\t return (%s) %s;\n", t->print_type(), name);
 | 
						|
    }
 | 
						|
 | 
						|
    fprintf(f_header,"}\n");
 | 
						|
    
 | 
						|
    // Wrap this function
 | 
						|
 | 
						|
    l = new ParmList;
 | 
						|
 | 
						|
    new_name = name_get(name);
 | 
						|
    new_iname = name_get(iname);
 | 
						|
 | 
						|
    if ((t->type == T_USER) && (!t->is_pointer)) {
 | 
						|
      t->is_pointer++;
 | 
						|
      lang->create_function(new_name, new_iname, t, l);
 | 
						|
      t->is_pointer--;
 | 
						|
    } else {
 | 
						|
      lang->create_function(new_name, new_iname, t, l);
 | 
						|
    }
 | 
						|
    delete l;
 | 
						|
}
 | 
						|
  
 | 
						|
 | 
						|
 | 
						|
 |