/**********************************************************************
* Simplified Wrapper and Interface Generator (SWIG)
*
* Dave Beazley
*
* Theoretical Division (T-11) Department of Computer Science
* Los Alamos National Laboratory University of Utah
* Los Alamos, New Mexico 87545 Salt Lake City, Utah 84112
* beazley@lanl.gov beazley@cs.utah.edu
*
* Copyright (c) 1995-1998
* The Regents of the University of California and the University of Utah
* 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.
*
**************************************************************************/
#include "internal.h"
#include <limits.h>
// ------------------------------------------------------------------------
// $Header: /home/beazley/SWIG/SWIG1.2/SWIG/RCS/typemap.cxx,v 1.20 1997/08/22 05:51:48 beazley Exp $
//
// typemap.cxx
//
// This file provides universal support for typemaps. Typemaps are created
// using the following SWIG command in an interface file:
//
// %typemap(lang,operation) type { code } Make a new typemap
// %typemap(lang,operation) type; Clears any previous typemap
//
// lang is an identifier indicating the target language. The typemap will
// simply be ignored if its for a different language. The code is the
// corresponding C code for the mapping. An example typemap might look
// like this :
//
// %typemap(tcl,get) double {
// $target = atof($source);
// }
// %typemap(tcl,set) double {
// sprintf($target,"%0.17f",$source);
// }
//
// The variables $target and $source should be used in any type-mappings.
// Additional local variables can be created, but this should be done
// by enclosing the entire code fragment in an extra set of braces.
//
// The C++ API to the type-mapper is as follows :
//
// void typemap_register(char *op, char *lang, DataType *type, char *pname, String &getcode, ParmList *args)
// char *typemap_lookup(char *op, char *lang, DataType *type, char *pname, char *source, char *target);
// void typemap_clear(char *op, char *lang, DataType *type, char *pname);
//
// The lookup functions return a character string corresponding to the type-mapping
// code or NULL if none exists. The string return will have the source and target
// strings substituted for the strings "$source" and "$target" in the type-mapping code.
//
// (2/19/97) This module has been extended somewhat to provide generic mappings
// of other parts of the code--most notably exceptions.
//
// void fragment_register(char *op, char *lang, String &code)
// char fragment_lookup(char *op, char *lang, int age);
// char fragment_clear(char *op, char *lang);
//
// ------------------------------------------------------------------------
// Structure for holding a typemap
struct TypeMap {
char *lang;
DataType *type;
String code;
int first;
int last;
TypeMap *next;
TypeMap *previous; // Previously defined typemap (if any)
ParmList *args; // Local variables (if any)
TypeMap(char *l, DataType *t, String &c, ParmList *p = 0) {
lang = copy_string(l);
type = new DataType(t);
code << c;
first = type_id;
last = INT_MAX;
next = 0;
previous = 0;
if (p) {
args = new ParmList(p);
} else {
args = 0;
}
}
TypeMap(char *l, DataType *t, char *c, ParmList *p = 0) {
lang = copy_string(l);
type = new DataType(t);
code << c;
first = type_id;
last = INT_MAX;
next = 0;
previous = 0;
if (p) {
args = new ParmList(p);
} else {
args = 0;
}
}
TypeMap(char *l, char *c) {
lang = copy_string(l);
type = 0;
code << c;
first = type_id;
last = INT_MAX;
next = 0;
previous = 0;
args = 0;
}
TypeMap(TypeMap *t) {
lang = copy_string(t->lang);
type = new DataType(t->type);
code << t->code;
first = type_id;
last = INT_MAX;
next = 0;
previous = t->previous;
if (args) {
args = new ParmList(args);
} else {
args = 0;
}
}
};
// Hash tables for storing type-mappings
static Hash typemap_hash;
// Structure for holding "applications of a typemap"
struct TmMethod {
char *name; // Typemap name;
DataType *type; // Typemap type
TmMethod *next; // Next method
TmMethod(char *n, DataType *t, TmMethod *m = 0) {
if (n) name = copy_string(n);
else name = 0;
if (t) {
type = new DataType(t);
} else {
type = 0;
}
next = m;
}
};
// Hash table for storing applications of a datatype
static Hash application_hash;
// ------------------------------------------------------------------------
// void typemap_apply(DataType *tm_type, char *tm_name, DataType *type, char *pname)
//
// Attempts to apply a typemap given by (tm_type,tm_name) to (type,pname)
// Called by the %apply directive.
// ------------------------------------------------------------------------
void typemap_apply(DataType *tm_type, char *tm_name, DataType *type, char *pname) {
TmMethod *m,*m1;
char temp[512];
// Form the application name
if (!pname) pname = "";
sprintf(temp,"%s$%s",type->print_type(),pname);
// See if there is a method already defined
m = (TmMethod *) application_hash.lookup(temp);
if (!m) {
m = new TmMethod(temp,type,0);
application_hash.add(temp,m);
}
// Check to see if an array typemap has been applied to a non-array type
if ((tm_type->arraystr) && (!type->arraystr)) {
fprintf(stderr,"%s:%d: Warning. Array typemap has been applied to a non-array type.\n",
input_file,line_number);
}
// If both are arrays, make sure they have the same dimension
if ((tm_type->arraystr) && (type->arraystr)) {
char s[128],*t;
if (tm_type->array_dimensions() != type->array_dimensions()) {
fprintf(stderr,"%s:%d: Warning. Array types have different number of dimensions.\n",
input_file,line_number);
} else {
for (int i = 0; i < tm_type->array_dimensions(); i++) {
strcpy(s,tm_type->get_dimension(i));
t = type->get_dimension(i);
if (strcmp(s,"ANY") != 0) {
if (strcmp(s,t))
fprintf(stderr,"%s:%d: Warning. Array typemap applied to an array of different size.\n",
input_file, line_number);
}
}
}
}
// Add a new mapping corresponding to the typemap
m1 = new TmMethod(tm_name,tm_type,m->next);
m->next = m1;
}
// ------------------------------------------------------------------------
// void typemap_clear_apply(DataType *type, char *pname)
//
// Clears the application of a typemap.
// Called by the %clear directive.
// ------------------------------------------------------------------------
void typemap_clear_apply(DataType *type, char *pname) {
char temp[512];
if (!pname) pname = "";
sprintf(temp,"%s$%s", type->print_type(), pname);
application_hash.remove(temp);
}
// ------------------------------------------------------------------------
// char *typemap_string(char *lang, DataType *type, char *pname, char *ary, char *suffix)
//
// Produces a character string corresponding to a lang, datatype, and
// method. This string is used as the key for our typemap hash table.
// ------------------------------------------------------------------------
static char *typemap_string(char *lang, DataType *type, char *pname, char *ary, char *suffix) {
static String str;
int old_status;
old_status = type->status;
type->status = 0;
str = "";
if (ary)
str << lang << type->print_type() << pname << ary << suffix;
else
str << lang << type->print_type() << pname << suffix;
type->status = old_status;
return str;
}
// ------------------------------------------------------------------------
// void typemap_register(char *op, char *lang, DataType *type, char *pname,
// char *getcode, ParmList *args)
//
// Register a new mapping with the type-mapper.
// ------------------------------------------------------------------------
void typemap_register(char *op, char *lang, DataType *type, char *pname,
char *getcode, ParmList *args) {
char *key;
TypeMap *tm,*tm_old;
char temp[256];
int is_default = 0;
// printf("Registering : %s %s %s %s\n%s\n", op, lang, type->print_type(), pname, getcode);
tm = new TypeMap(lang,type,getcode,args);
// If this is a default typemap, downgrade the type!
if (strcmp(pname,"SWIG_DEFAULT_TYPE") == 0) {
tm->type->primitive();
is_default = 1;
}
key = typemap_string(lang,tm->type,pname,tm->type->arraystr, op);
// Get any previous setting of the typemap
tm_old = (TypeMap *) typemap_hash.lookup(key);
if (tm_old) {
// Perform a chaining operation, but only if the last typemap is
// active.
if (type_id < tm_old->last) {
sprintf(temp,"$%s",op);
tm->code.replace(temp,tm_old->code);
}
// If found, we need to attach the old version to the new one
tm->previous = tm_old;
tm->next = tm_old;
tm_old->last = type_id;
// Remove the old one from the hash
typemap_hash.remove(key);
}
// Add new typemap to the hash table
typemap_hash.add(key,(void *) tm);
// Now try to perform default chaining operation (if available)
// if (!is_default) {
// sprintf(temp,"$%s",op);
// if (strstr(tm->code,temp)) {
// tm->code.replace(temp,typemap_resolve_default(op,lang,type));
// }
// }
// Just a sanity check to make sure args look okay.
if (args) {
Parm *p;
p = tm->args->get_first();
while (p) {
if (p->name) {
// printf(" %s %s\n", p->t->print_type(),p->name);
} else {
fprintf(stderr,"%s:%d: Typemap error. Local variables must have a name\n",
input_file, line_number);
}
// If a call by reference thingy, fix that
if (p->call_type & CALL_REFERENCE) {
p->t->is_pointer--;
p->call_type = 0;
}
p = tm->args->get_next();
}
}
}
// ------------------------------------------------------------------------
// void typemap_register(char *op, char *lang, char *type, char *pname,
// char *getcode, ParmList *args)
//
// Register a new mapping with the type-mapper. Special version that uses a
// string instead of a datatype.
// ------------------------------------------------------------------------
void typemap_register(char *op, char *lang, char *type, char *pname,
char *getcode, ParmList *args) {
DataType temp;
strcpy(temp.name,type);
temp.is_pointer = 0;
temp.type = T_USER;
typemap_register(op,lang,&temp,pname,getcode,args);
}
// ------------------------------------------------------------------------
// void typemap_register_default(char *op, char *lang, int type, int ptr, char *arraystr,
// char *code, ParmList *args)
//
// Registers a default typemap with the system using numerical type codes.
// type is the numerical code, ptr is the level of indirection.
// ------------------------------------------------------------------------
void typemap_register_default(char *op, char *lang, int type, int ptr, char *arraystr,
char *code, ParmList *args) {
DataType *t = new DataType(type);
// Create a raw datatype from the arguments
t->is_pointer = ptr;
t->arraystr = copy_string(arraystr);
// Now, go register this as a default type
typemap_register(op,lang,t,"SWIG_DEFAULT_TYPE",code,args);
delete t;
}
// ------------------------------------------------------------------------
// static TypeMap *typemap_search(char *key, int id)
//
// An internal function for searching for a particular typemap given
// a key value and datatype id.
//
// Basically this checks the hash table and then checks the id against
// first and last values, looking for a match. This is to properly
// handle scoping problems.
// ------------------------------------------------------------------------
TypeMap *typemap_search(char *key, int id) {
TypeMap *tm;
tm = (TypeMap *) typemap_hash.lookup(key);
while (tm) {
if ((id >= tm->first) && (id < tm->last)) return tm;
else tm = tm->next;
}
return tm;
}
// ------------------------------------------------------------------------
// TypeMap *typemap_search_array(char *op, char *lang, DataType *type, char *pname, String &str)
//
// Performs a typemap lookup on an array type. This is abit complicated
// because we need to look for ANY tags specifying that any array dimension
// is valid. The resulting code will be placed in str with dimension variables
// substituted.
// ------------------------------------------------------------------------
TypeMap *typemap_search_array(char *op, char *lang, DataType *type, char *pname, String &str) {
char *origarr = type->arraystr;
char *key;
int ndim,i,j,k,n;
TypeMap *tm;
char temp[10];
if (!type->arraystr) return 0;
// First check to see if exactly this array has been mapped
key = typemap_string(lang,type,pname,type->arraystr,op);
tm = typemap_search(key,type->id);
// Check for unnamed array of specific dimensions
if (!tm) {
key = typemap_string(lang,type,"",type->arraystr,op);
tm = typemap_search(key,type->id);
}
if (!tm) {
// We're going to go search for matches with the ANY tag
String tempastr;
ndim = type->array_dimensions(); // Get number of dimensions
j = (1 << ndim) - 1; // Status bits
for (i = 0; i < (1 << ndim); i++) {
// Form an array string
tempastr = "";
k = j;
for (n = 0; n < ndim; n++) {
if (k & 1) {
tempastr << "[" << type->get_dimension(n) << "]";
} else {
tempastr << "[ANY]";
}
k = k >> 1;
}
// printf("checking (%s) : %s\n",origarr,tempastr.get());
type->arraystr = tempastr.get();
key = typemap_string(lang,type,pname,type->arraystr,op);
tm = typemap_search(key,type->id);
if (!tm) {
key = typemap_string(lang,type,"",type->arraystr,op);
tm = typemap_search(key,type->id);
}
type->arraystr = origarr;
if (tm) break;
j--;
}
}
if (tm) {
str << tm->code;
ndim = type->array_dimensions();
for (i = 0; i < ndim; i++) {
sprintf(temp,"$dim%d",i);
str.replace(temp,type->get_dimension(i));
}
}
return tm;
}
// ------------------------------------------------------------------------
// static typemap_locals(Datatype *t, char *pname, String &s, ParmList *l, WrapperFunction &f)
//
// Takes a string, a parameter list and a wrapper function argument and
// starts creating local variables.
//
// Substitutes locals in the string with actual values used.
// ------------------------------------------------------------------------
static void typemap_locals(DataType *t, char *pname, String &s, ParmList *l, WrapperFunction &f) {
Parm *p;
char *new_name;
p = l->get_first();
while (p) {
if (p->name) {
if (strlen(p->name) > 0) {
String str;
DataType *tt;
// If the user gave us $type as the name of the local variable, we'll use
// the passed datatype instead
if (strcmp(p->t->name,"$type")==0 || strcmp(p->t->name,"$basetype")==0) {
tt = t;
} else {
tt = p->t;
}
// Have a real parameter here
if (tt->arraystr) {
tt->is_pointer--;
str << p->name << tt->arraystr;
}
else {
str << p->name;
}
// Substitute parameter names
str.replace("$arg",pname);
if (strcmp(p->t->name,"$basetype")==0) {
// use $basetype
char temp_ip = tt->is_pointer;
char temp_ip1 = tt->implicit_ptr;
tt->is_pointer = 0;
tt->implicit_ptr = 0;
new_name = f.new_local(tt->print_type(),str);
tt->is_pointer = temp_ip;
tt->implicit_ptr = temp_ip1;
}
else
new_name = f.new_local(tt->print_full(),str);
if (tt->arraystr) tt->is_pointer++;
// Substitute
s.replaceid(p->name,new_name);
}
}
p = l->get_next();
}
// If the original datatype was an array. We're going to go through and substitute
// it's array dimensions
if (t->arraystr) {
char temp[10];
for (int i = 0; i < t->array_dimensions(); i++) {
sprintf(temp,"$dim%d",i);
f.locals.replace(temp,t->get_dimension(i));
}
}
}
// ------------------------------------------------------------------------
// char *typemap_lookup(char *op, char *lang, DataType *type, char *pname, char *source,
// char *target, WrapperFunction *f)
//
// Looks up a "get" function in the type-map and returns a character string
// containing the appropriate translation code.
//
// op is string code for type of mapping
// lang is the target language string
// type is the datatype
// pname is an optional parameter name
// source is a string with the source variable
// target is a string containing the target value
// f is a wrapper function object (optional)
//
// Returns NULL if no mapping is found.
//
// Typemaps follow a few rules regarding naming and C pointers by checking
// declarations in this order.
//
// 1. type name [] - A named array (most specific)
// 2. type name - Named argument
// 3. type [] - Type with array
// 4. type - Ordinary type
//
// Array checking is only made if the datatype actally has an array specifier
//
// Array checking uses a special token "ANY" that indicates that any
// dimension will match. Since we are passed a real datatype here, we
// need to hack this a special case.
//
// Array dimensions are substituted into the variables $dim1, $dim2,...,$dim9
// ------------------------------------------------------------------------
static DataType *realtype; // This is a gross hack
static char *realname = 0; // Real parameter name
char *typemap_lookup_internal(char *op, char *lang, DataType *type, char *pname, char *source,
char *target, WrapperFunction *f) {
static String str;
char *key = 0;
TypeMap *tm = 0;
if (!lang) {
return 0;
}
// First check for named array
str = "";
tm = typemap_search_array(op,lang,type,pname,str);
// Check for named argument
if (!tm) {
key = typemap_string(lang,type,pname,0,op);
tm = typemap_search(key,type->id);
if (tm)
str << tm->code;
}
// Check for unnamed type
if (!tm) {
key = typemap_string(lang,type,"",0,op);
tm = typemap_search(key,type->id);
if (tm)
str << tm->code;
}
if (!tm) return 0;
// Now perform character replacements
str.replace("$source",source);
str.replace("$target",target);
str.replace("$type", realtype->print_type());
if (realname) {
str.replace("$parmname", realname);
} else {
str.replace("$parmname","");
}
// Print base type (without any pointers)
{
char temp_ip = realtype->is_pointer;
char temp_ip1 = realtype->implicit_ptr;
realtype->is_pointer = 0;
realtype->implicit_ptr = 0;
str.replace("$basetype",realtype->print_type());
str.replace("$basemangle",realtype->print_mangle());
realtype->is_pointer = temp_ip;
realtype->implicit_ptr = temp_ip1;
}
str.replace("$mangle",realtype->print_mangle());
// If there were locals and a wrapper function, replace
if ((tm->args) && f) {
typemap_locals(realtype, pname, str,tm->args,*f);
}
// If there were locals and no wrapper function, print a warning
if ((tm->args) && !f) {
if (!pname) pname = "";
fprintf(stderr,"%s:%d: Warning. '%%typemap(%s,%s) %s %s' being applied with ignored locals.\n",
input_file, line_number, lang,op, type->print_type(), pname);
}
// Return character string
return str;
}
// ----------------------------------------------------------
// Real function call that takes care of application mappings
// ----------------------------------------------------------
char *typemap_lookup(char *op, char *lang, DataType *type, char *pname, char *source,
char *target, WrapperFunction *f) {
TmMethod *m;
char temp[512];
char *result;
char *ppname;
char *tstr;
realtype = type; // The other half of the gross hack
realname = pname;
// Try to apply typemap right away
result = typemap_lookup_internal(op,lang,type,pname,source,target,f);
// If not found, try to pick up anything that might have been
// specified with %apply
if ((!result) && (pname)) {
int drop_pointer = 0;
ppname = pname;
if (!ppname) ppname = "";
// The idea : We're going to cycle through applications and
// drop pointers off until we get a match.
while (drop_pointer <= (type->is_pointer - type->implicit_ptr)) {
type->is_pointer -= drop_pointer;
tstr = type->print_type();
sprintf(temp,"%s$%s",tstr,ppname);
// No mapping was found. See if the name has been mapped with %apply
m = (TmMethod *) application_hash.lookup(temp);
if (!m) {
sprintf(temp,"%s$",tstr);
m = (TmMethod *) application_hash.lookup(temp);
}
if (m) {
m = m->next;
while (m) {
char *oldary = 0;
static String newarray;
if (*(m->name)) ppname = m->name;
else ppname = pname;
m->type->is_pointer += drop_pointer;
// Copy old array string (just in case)
oldary = m->type->arraystr;
// If the mapping type is an array and has the 'ANY' keyword, we
// have to play some magic
if ((m->type->arraystr) && (type->arraystr)) {
// Build up the new array string
newarray = "";
for (int n = 0; n < m->type->array_dimensions(); n++) {
char *d = m->type->get_dimension(n);
if (strcmp(d,"ANY") == 0) {
newarray << "[" << type->get_dimension(n) << "]";
} else {
newarray << "[" << d << "]";
}
}
m->type->arraystr = newarray.get();
} else if (type->arraystr) {
// If an array string is available for the current datatype,
// make it available.
m->type->arraystr = type->arraystr;
}
result = typemap_lookup_internal(op,lang,m->type,ppname,source,target,f);
m->type->arraystr = oldary;
m->type->is_pointer -= drop_pointer;
if (result) {
type->is_pointer += drop_pointer;
return result;
}
m = m->next;
}
}
type->is_pointer += drop_pointer;
drop_pointer++;
}
}
// Still no idea, try to find a default typemap
if (!result) {
DataType *t = new DataType(type);
t->primitive(); // Knock it down to its basic type
result = typemap_lookup_internal(op,lang,t,"SWIG_DEFAULT_TYPE",source,target,f);
if (result) {
delete t;
return result;
}
if ((t->type == T_USER) || (t->is_pointer)) {
if ((t->type == T_CHAR) && (t->is_pointer == 1)) return 0;
// Still no result, go even more primitive
t->type = T_USER;
t->is_pointer = 1;
if (t->arraystr) delete [] t->arraystr;
t->arraystr = 0;
t->primitive();
result = typemap_lookup_internal(op,lang,t,"SWIG_DEFAULT_TYPE",source,target,f);
}
delete t;
}
return result;
}
// ----------------------------------------------------------------------------
// char *typemap_check(char *op, char *lang, DataType *type, char *pname)
//
// Checks to see if there is a typemap. Returns typemap string if found, NULL
// if not.
// ----------------------------------------------------------------------------
char *typemap_check_internal(char *op, char *lang, DataType *type, char *pname) {
static String str;
char *key = 0;
TypeMap *tm = 0;
if (!lang) {
return 0;
}
// First check for named array
if (type->arraystr) {
key = typemap_string(lang,type,pname,type->arraystr,op);
tm = typemap_search(key,type->id);
}
// Check for named argument
if (!tm) {
key = typemap_string(lang,type,pname,0,op);
tm = typemap_search(key,type->id);
}
// Check for unnamed array
if ((!tm) && (type->arraystr)) {
key = typemap_string(lang,type,"",type->arraystr,op);
tm = typemap_search(key,type->id);
}
// Check for unname type
if (!tm) {
key = typemap_string(lang,type,"",0,op);
tm = typemap_search(key,type->id);
}
if (!tm) return 0;
str = "";
str << tm->code;
// Return character string
return str;
}
// Function for checking with applications
char *typemap_check(char *op, char *lang, DataType *type, char *pname) {
TmMethod *m;
char temp[512];
char *result;
char *ppname;
char *tstr;
// Try to apply typemap right away
result = typemap_check_internal(op,lang,type,pname);
if (!result) {
int drop_pointer = 0;
ppname = pname;
if (!ppname) ppname = "";
// The idea : We're going to cycle through applications and
// drop pointers off until we get a match.
while (drop_pointer <= (type->is_pointer - type->implicit_ptr)) {
type->is_pointer -= drop_pointer;
tstr = type->print_type();
sprintf(temp,"%s$%s",tstr,ppname);
// No mapping was found. See if the name has been mapped with %apply
m = (TmMethod *) application_hash.lookup(temp);
if (!m) {
sprintf(temp,"%s$",tstr);
m = (TmMethod *) application_hash.lookup(temp);
}
if (m) {
m = m->next;
while (m) {
char *oldary = 0;
static String newarray;
if (*(m->name)) ppname = m->name;
else ppname = pname;
m->type->is_pointer += drop_pointer;
oldary = m->type->arraystr;
// If the mapping type is an array and has the 'ANY' keyword, we
// have to play some magic
if ((m->type->arraystr) && (type->arraystr)) {
// Build up the new array string
newarray = "";
for (int n = 0; n < m->type->array_dimensions(); n++) {
char *d = m->type->get_dimension(n);
if (strcmp(d,"ANY") == 0) {
newarray << "[" << type->get_dimension(n) << "]";
} else {
newarray << "[" << d << "]";
}
}
oldary = m->type->arraystr;
m->type->arraystr = newarray.get();
} else if (type->arraystr) {
m->type->arraystr = type->arraystr;
}
result = typemap_check_internal(op,lang,m->type,ppname);
m->type->arraystr = oldary;
m->type->is_pointer -= drop_pointer;
if (result) {
type->is_pointer += drop_pointer;
return result;
}
m = m->next;
}
}
type->is_pointer += drop_pointer;
drop_pointer++;
}
}
#ifdef OLD_METHOD
if (!result) {
ppname = pname;
if (!ppname) ppname = "";
tstr = type->print_type();
sprintf(temp,"%s$%s",tstr,ppname);
// No mapping was found. See if the name has been mapped with %apply
m = (TmMethod *) application_hash.lookup(temp);
if (!m) {
sprintf(temp,"%s$",tstr);
m = (TmMethod *) application_hash.lookup(temp);
}
if (m) {
m = m->next;
while (m) {
if (*(m->name)) ppname = m->name;
else ppname = pname;
result = typemap_check_internal(op,lang,m->type,ppname);
if (result)
return result;
m = m->next;
}
}
}
#endif
// If still no result, might have a default typemap
if (!result) {
DataType *t = new DataType(type);
t->primitive(); // Knock it down to its basic type
result = typemap_check_internal(op,lang,t,"SWIG_DEFAULT_TYPE");
if (result) {
delete t;
return result;
}
if ((t->type == T_USER) || (t->is_pointer)) {
if ((t->type == T_CHAR) && (t->is_pointer == 1)) return 0;
// Still no result, go even more primitive
t->type = T_USER;
t->is_pointer = 1;
if (t->arraystr) delete [] t->arraystr;
t->arraystr = 0;
t->primitive();
result = typemap_check_internal(op,lang,t,"SWIG_DEFAULT_TYPE");
}
delete t;
}
return result;
}
// ------------------------------------------------------------------------
// void typemap_clear(char *op, char *lang, DataType *type, char *pname)
//
// Clears any previous typemap. This works like a stack. Clearing a
// typemap returns to any previous typemap in force. If there is no
// previous map, then don't worry about it.
// ------------------------------------------------------------------------
void typemap_clear(char *op, char *lang, DataType *type, char *pname) {
char *key;
TypeMap *tm;
key = typemap_string(lang,type,pname,type->arraystr,op);
// Look for any previous version, simply set the last id if
// applicable.
tm = (TypeMap *) typemap_hash.lookup(key);
if (tm) {
if (tm->last > type_id) tm->last = type_id;
}
}
// ------------------------------------------------------------------------
// void typemap_copy(char *op, char *lang, DataType *stype, char *sname,
// DataType *ttype, char *tname)
//
// Copies the code associate with a typemap
// ------------------------------------------------------------------------
void typemap_copy(char *op, char *lang, DataType *stype, char *sname,
DataType *ttype, char *tname) {
char *key;
TypeMap *tm, *tk, *tn;
// Try to locate a previous typemap
key = typemap_string(lang,stype,sname,stype->arraystr,op);
tm = typemap_search(key,stype->id);
if (!tm) return;
if (strcmp(ttype->name,"PREVIOUS") == 0) {
// Pop back up to the previous typemap (if any)
tk = tm->next;
if (tk) {
tn = new TypeMap(tk); // Make a copy of the previous typemap
tn->next = tm; // Set up symlinks
typemap_hash.remove(key); // Remove old hash entry
typemap_hash.add(key,(void *) tn);
}
} else {
typemap_register(op,lang,ttype,tname,tm->code,tm->args);
}
}
// ------------------------------------------------------------------------
// char *fragment_string(char *op, char *lang)
//
// Produces a character string corresponding to a language and method
// This string is used as the key for our typemap hash table.
// ------------------------------------------------------------------------
static char *fragment_string(char *op, char *lang) {
static String str;
str = "";
str << "fragment:" << lang << op;
return str;
}
// ------------------------------------------------------------------------
// void fragment_register(char *op, char *lang, char *code)
//
// Register a code fragment with the type-mapper.
// ------------------------------------------------------------------------
void fragment_register(char *op, char *lang, char *code) {
char *key;
TypeMap *tm,*tm_old;
char temp[256];
tm = new TypeMap(lang,code);
key = fragment_string(op,lang);
// Get any previous setting of the typemap
tm_old = (TypeMap *) typemap_hash.lookup(key);
if (tm_old) {
// If found, we need to attach the old version to the new one
// Perform a chaining operation
sprintf(temp,"$%s",op);
if (type_id < tm_old->last)
tm->code.replace(temp,tm_old->code);
tm->next = tm_old;
tm_old->last = type_id;
// Remove the old one from the hash
typemap_hash.remove(key);
}
// Perform a default chaining operation if needed (defaults to nothing)
sprintf(temp,"$%s",op);
tm->code.replace(temp,"");
// Add new typemap to the hash table
typemap_hash.add(key,(void *) tm);
}
// ------------------------------------------------------------------------
// char *fragment_lookup(char *op, char *lang, int age)
//
// op is string code for type of mapping
// lang is the target language string
// age is age of fragment.
//
// Returns NULL if no mapping is found.
//
// ------------------------------------------------------------------------
char *fragment_lookup(char *op, char *lang, int age) {
static String str;
char *key = 0;
TypeMap *tm = 0;
if (!lang) {
return 0;
}
str = "";
key = fragment_string(op,lang);
tm = typemap_search(key,age);
if (!tm) return 0;
str << tm->code;
return str;
}
// ------------------------------------------------------------------------
// void fragment_clear(char *op, char *lang)
//
// Clears any previous fragment definition. Is a stack operation--will
// restore any previously declared typemap.
// ------------------------------------------------------------------------
void fragment_clear(char *op, char *lang) {
char *key;
TypeMap *tm;
key = fragment_string(op,lang);
// Look for any previous version, simply set the last id if
// applicable.
tm = (TypeMap *) typemap_hash.lookup(key);
if (tm) {
if (tm->last > type_id) tm->last = type_id;
}
}
// --------------------------------------------------------------------------------
// Revision History
// ----------------
// $Log: typemap.cxx,v $
// Revision 1.20 1997/08/22 05:51:48 beazley
// Changed format of error messages
//
// Revision 1.19 1997/08/20 04:34:50 beazley
// Modified the local variable emitter to allow the $arg variable to
// appear in variable names.
//
// Revision 1.18 1997/08/11 06:14:37 beazley
// Added substitution of $type variable.
//
// Revision 1.17 1997/07/27 20:30:13 beazley
// Many bug fixes to the %apply mechanism.
//
// Revision 1.16 1997/07/14 03:57:13 beazley
// Fixed some problems with array locals.
//
// Revision 1.15 1997/06/20 06:19:53 beazley
// Fixed memory leak
//
// Revision 1.14 1997/05/28 17:00:44 beazley
// Moved revision history to end.
//
// Revision 1.13 1997/05/24 04:14:23 beazley
// Added default typemap support
//
// Revision 1.12 1997/05/13 04:11:39 beazley
// Fixed bug in local variable declarations with structures.
//
// Revision 1.11 1997/05/10 17:47:02 beazley
// Fixed bugs when declaring local variables of arrays.
//
// Revision 1.10 1997/05/08 05:19:30 beazley
// Fixed a few minor quirks with typemap renaming and lookup.
//
// Revision 1.9 1997/05/05 15:54:33 beazley
// Modified to support parameterized typemaps. A typemap can now
// add local variables to a wrapper function (if supplied).
//
// Support for %apply and %clear added. These can be used to apply
// a whole group of typemaps to a new datatype/name.
//
// Revision 1.8 1997/04/18 04:07:45 beazley
// Added PREVIOUS symbol. Also made typemaps more stack-like.
//
// Revision 1.7 1997/03/18 22:40:48 beazley
// Added better support for chaining typemaps together. This isn't
// really documented very well however.
//
// Revision 1.6 1997/03/12 05:01:14 beazley
// Removed compiler warning.
//
// Revision 1.5 1997/03/08 19:18:09 beazley
// Added better support for typemaps involving arrays.
//
// Revision 1.4 1997/02/19 23:00:47 beazley
// Added support for generic code fragments. These are used to
// support exceptions.
//
// Revision 1.3 1997/02/16 20:15:29 beazley
// Fixed major bug in typemap scoping
//
// Revision 1.2 1997/01/08 01:24:51 beazley
// Pre 1.1b3 checkin
//
// Revision 1.1 1997/01/06 17:08:17 beazley
// Initial revision
// --------------------------------------------------------------------------------
syntax highlighted by Code2HTML, v. 0.9.1