/********************************************************************** * 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 // ------------------------------------------------------------------------ // $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 // --------------------------------------------------------------------------------