swig/Source/LParse/type.c
Dave Beazley 607f0882ae Fixed copy_string.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@130 626c5289-ae23-0410-ae9c-e8d60b6d4f22
2000-01-20 05:53:50 +00:00

396 lines
12 KiB
C

/* -----------------------------------------------------------------------------
* type.c
*
* Lame SWIG1.1 type implementation.
*
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
*
* Copyright (C) 1999-2000. The University of Chicago
* See the file LICENSE for information on usage and redistribution.
* ----------------------------------------------------------------------------- */
static char cvsroot[] = "$Header$";
#include "lparse.h"
extern DOH *LParseTypeStr(DOH *to);
static DohObjInfo LParseTypeType = {
"LParseType", /* objname */
sizeof(LParseType), /* objsize */
DelLParseType, /* doh_del */
CopyLParseType, /* doh_copy */
0, /* doh_clear */
0, /* doh_scope */
LParseTypeStr, /* doh_str */
0, /* doh_data */
0, /* doh_dump */
0, /* doh_load */
0, /* doh_len */
0, /* doh_hash */
0, /* doh_cmp */
0, /* doh_mapping */
0, /* doh_sequence */
0, /* doh_file */
0, /* doh_string */
0, /* doh_callable */
0, /* doh_position */
};
/* -----------------------------------------------------------------------------
* NewLParseType() - Create a new datatype
* ----------------------------------------------------------------------------- */
LParseType *
NewLParseType(int ty) {
LParseType *t = (LParseType *) DohObjMalloc(sizeof(LParseType));
t->objinfo = &LParseTypeType;
t->type = ty;
t->name = (char *) malloc(LPARSE_MAX_NAME);
t->name[0] = 0;
t->is_pointer = 0;
t->implicit_ptr = 0;
t->is_reference = 0;
t->status = 0;
t->qualifier = 0;
t->arraystr = 0;
switch(ty) {
case LPARSE_T_INT:
strcpy(t->name,"int");
break;
case LPARSE_T_UINT:
strcpy(t->name,"unsigned");
break;
case LPARSE_T_SHORT:
strcpy(t->name,"short");
break;
case LPARSE_T_USHORT:
strcpy(t->name,"unsigned short");
break;
case LPARSE_T_LONG:
strcpy(t->name,"long");
break;
case LPARSE_T_ULONG:
strcpy(t->name,"unsigned long");
break;
case LPARSE_T_FLOAT:
strcpy(t->name,"float");
break;
case LPARSE_T_DOUBLE:
strcpy(t->name,"double");
break;
case LPARSE_T_CHAR:
strcpy(t->name,"char");
break;
case LPARSE_T_SCHAR:
strcpy(t->name,"signed char");
break;
case LPARSE_T_UCHAR:
strcpy(t->name,"unsigned char");
break;
case LPARSE_T_VOID:
strcpy(t->name,"void");
break;
case LPARSE_T_BOOL:
strcpy(t->name,"bool");
break;
default:
break;
}
return t;
}
/* -----------------------------------------------------------------------------
* DelLParseType() - Destroy a datatype
* ----------------------------------------------------------------------------- */
void DelLParseType(DOH *t) {
LParseType *ty = (LParseType *) t;
assert(ty->refcount <= 0);
free(ty->name);
if (ty->qualifier) free(ty->qualifier);
if (ty->arraystr) free(ty->arraystr);
}
/* -----------------------------------------------------------------------------
* CopyLParseType() - Copy a type
* ----------------------------------------------------------------------------- */
DOH *
CopyLParseType(DOH *co) {
LParseType *c;
LParseType *t = (LParseType *) DohObjMalloc(sizeof(LParseType));
c = (LParseType *) co;
t->objinfo = &LParseTypeType;
t->type = c->type;
t->name = (char *) malloc(LPARSE_MAX_NAME);
strcpy(t->name,c->name);
t->is_pointer = c->is_pointer;
t->implicit_ptr = c->implicit_ptr;
t->is_reference = c->is_reference;
t->status = c->status;
t->qualifier = Swig_copy_string(c->qualifier);
t->arraystr = Swig_copy_string(c->arraystr);
return t;
}
/* -----------------------------------------------------------------------------
* LParseTypeStr() - Make a string of a datatype.
* ----------------------------------------------------------------------------- */
DOH *
LParseTypeStr(DOH *to) {
DOH *s;
int i;
LParseType *t = (LParseType *) to;
s = NewString("");
if (t->qualifier)
Printf(s,"%s ",t->qualifier);
Printf(s,"%s ",t->name);
if (t->is_reference || t->arraystr) t->is_pointer--;
for (i = 0; i < t->is_pointer; i++)
Putc('*',s);
if (t->is_reference || t->arraystr) t->is_pointer++;
if (t->is_reference)
Putc('&',s);
if (t->arraystr)
Printf(s,"%s", t->arraystr);
return s;
}
/* -----------------------------------------------------------------------------
* --- typedef support ---
* ----------------------------------------------------------------------------- */
#define MAXSCOPE 256
static DOH *typedef_hash[MAXSCOPE];
static int scope = 0;
static int typedef_init = 0;
static void init_typedef() {
int i;
for (i = 0; i < MAXSCOPE; i++)
typedef_hash[i] = 0;
scope = 0;
typedef_hash[scope] = NewHash();
typedef_init = 1;
}
/* -----------------------------------------------------------------------------
* void LParse_typedef_add(LParseType *t, DOH *tname)
*
* Create a new typedef.
* ----------------------------------------------------------------------------- */
void LParse_typedef_add(LParseType *t, DOH *tname) {
LParseType *nt;
if (!typedef_init) init_typedef();
/* Check to see if the type already exists */
if ((nt = (LParseType *) Getattr(typedef_hash[scope],tname))) {
Printf(stderr,"Warning. Datatype %s already defined (2nd definition ignored).\n", tname);
return;
}
nt = (LParseType *) CopyLParseType(t);
nt->implicit_ptr = (t->is_pointer-t->implicit_ptr); /* Record if mapped type is a pointer */
nt->is_pointer = (t->is_pointer-t->implicit_ptr); /* Adjust pointer value to be correct */
LParse_typedef_resolve(nt,0); /* Resolve any other mappings of this type */
/* Add this type to our hash table */
Setattr(typedef_hash[scope],tname, nt);
}
/* -----------------------------------------------------------------------------
* void LParse_typedef_resolve(LParseType *t, int level = 0)
*
* Checks to see if this datatype is in the typedef hash and
* resolves it if necessary. This will check all of the typedef
* hash tables we know about.
*
* level is an optional parameter that determines which scope to use.
* Usually this is only used with a bare :: operator in a datatype.
*
* The const headache :
*
* Normally SWIG will fail if a const variable is used in a typedef
* like this :
*
* typedef const char *String;
*
* This is because future occurrences of "String" will be treated like
* a char *, but without regard to the "constness". To work around
* this problem. The resolve() method checks to see if these original
* data type is const. If so, we'll substitute the name of the original
* datatype instead. Got it?
* ----------------------------------------------------------------------------- */
void LParse_typedef_resolve(LParseType *t, int level) {
LParseType *td;
int s = scope - level;
if (!typedef_init) init_typedef();
while (s >= 0) {
if ((td = (LParseType *) Getattr(typedef_hash[s],t->name))) {
t->type = td->type;
t->is_pointer += td->is_pointer;
t->implicit_ptr += td->implicit_ptr;
t->status = t->status | td->status;
/* Check for constness, and replace type name if necessary */
if (td->qualifier) {
if (strcmp(td->qualifier,"const") == 0) {
strcpy(t->name,td->name);
t->qualifier = Swig_copy_string(td->qualifier);
t->implicit_ptr -= td->implicit_ptr;
}
}
return;
}
s--;
}
/* Not found, do nothing */
return;
}
/* -----------------------------------------------------------------------------
* void LParse_typedef_replace()
*
* Checks to see if this datatype is in the typedef hash and
* replaces it with the hash entry. Only applies to current scope.
* ----------------------------------------------------------------------------- */
void LParse_typedef_replace(LParseType *t) {
LParseType *td;
DOH *temp;
if (!typedef_init) init_typedef();
temp = NewString("");
if ((td = (LParseType *) Getattr(typedef_hash[scope],t->name))) {
t->type = td->type;
t->is_pointer = td->is_pointer;
t->implicit_ptr -= td->implicit_ptr;
strcpy(t->name, td->name);
if (td->arraystr) {
if (t->arraystr) {
Printf(temp,"%s", t->arraystr);
free(t->arraystr);
}
Printf(temp,"%s", td->arraystr);
t->arraystr = Swig_copy_string(Char(temp));
}
}
Delete(temp);
/* Not found, do nothing */
return;
}
/* -----------------------------------------------------------------------------
* int LParse_typedef_check(DOH *tname)
*
* Checks to see whether tname is the name of a datatype we know
* about. Returns 1 if there's a match, 0 otherwise
* ----------------------------------------------------------------------------- */
int LParse_typedef_check(DOH *tname) {
int s = scope;
if (!typedef_init) init_typedef();
while (s >= 0) {
if (Getattr(typedef_hash[s],tname)) return 1;
s--;
}
return 0;
}
/* -----------------------------------------------------------------------------
* void LParse_typedef_updatestatus(LParseType *t, int newstatus)
*
* Checks to see if this datatype is in the hash table. If
* so, we'll update its status. This is sometimes used with
* typemap handling. Only applies to current scope.
* ----------------------------------------------------------------------------- */
void LParse_typedef_updatestatus(LParseType *t, int newstatus) {
LParseType *td;
if (!typedef_init) init_typedef();
if ((td = (LParseType *) Getattr(typedef_hash[scope], t->name))) {
td->status = newstatus;
}
}
/* -----------------------------------------------------------------------------
* void LParse_merge_scope(DOH *h)
*
* Copies all of the entries in scope h into the current scope. This is
* primarily done with C++ inheritance.
* ----------------------------------------------------------------------------- */
void LParse_merge_scope(DOH *h) {
DOH *key;
DOH *nt;
if (!typedef_init) init_typedef();
if (h) {
/* Copy all of the entries in the given hash table to this new one */
key = Firstkey(h);
while (key) {
nt = Copy(Getattr(h,key));
Setattr(typedef_hash[scope],key,nt);
key = Nextkey(h);
}
}
}
/* -----------------------------------------------------------------------------
* void LParse_new_scope(DOH *h)
*
* Creates a new scope for handling typedefs. This is used in C++ handling
* to create typedef local to a class definition.
* ----------------------------------------------------------------------------- */
void LParse_new_scope(DOH *h) {
if (!typedef_init) init_typedef();
scope++;
typedef_hash[scope] = NewHash();
if (h) {
LParse_merge_scope(h);
}
}
/* -----------------------------------------------------------------------------
* DOH *LParse_collapse_scope(DOH *prefix)
*
* Collapses the current scope into the previous one, but applies a prefix to
* all of the datatypes. This is done in order to properly handle C++ stuff.
* For example :
*
* class Foo {
* ...
* typedef double Real;
* }
*
* will have a type mapping of "double --> Real" within the class itself.
* When we collapse the scope, this mapping will become "double --> Foo::Real"
* ----------------------------------------------------------------------------- */
DOH *LParse_collapse_scope(DOH *prefix) {
LParseType *nt;
DOH *key;
DOH *temp;
DOH *h;
if (!typedef_init) init_typedef();
if (scope > 0) {
if (prefix) {
key = Firstkey(typedef_hash[scope]);
while (key) {
nt = (LParseType *) Copy(Getattr(typedef_hash[scope],key));
temp = NewString("");
Printf(temp,"%s::%s", prefix,key);
Setattr(typedef_hash[scope-1],temp,nt);
key = Nextkey(typedef_hash[scope]);
}
}
h = typedef_hash[scope];
typedef_hash[scope] = 0;
scope--;
return h;
}
return 0;
}