git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@163 626c5289-ae23-0410-ae9c-e8d60b6d4f22
915 lines
26 KiB
C
915 lines
26 KiB
C
/* -------------------------------------------------------------------------
|
|
* type.c
|
|
*
|
|
* Definition of a DOH type to represent a C type. The interface
|
|
* to this DOH type is fairly simple, but its implementation is
|
|
* complex, as it uses a tree structure internally to cache
|
|
* already-represented types and avoid the need to allocate an
|
|
* entire DOH object every time a type object is created.
|
|
*
|
|
* While this library is designed to handle C types, it should be
|
|
* sufficiently general to handle most system-level langages.
|
|
*
|
|
* Author(s) : Dustin Mitchell (djmitche@cs.uchicago.edu)
|
|
*
|
|
* Copyright (C) 1999-2000. The University of Chicago
|
|
* See the file LICENSE for information on usage and redistribution.
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
#include "doh.h"
|
|
#include "swig.h"
|
|
|
|
static char cvstag[] = "$Header$";
|
|
|
|
/* =========================================================================
|
|
* implementation overview
|
|
* ========================================================================= */
|
|
|
|
/* Public appearance
|
|
|
|
To the public, types appear as a chain of constructors, e.g.
|
|
|
|
t = Pointer(Pointer(Array(Pointer(Char()))))
|
|
|
|
where each of the constructors can have some attributes (const /
|
|
volatile, array size, etc.)
|
|
|
|
The 'parent' of a type is the argument to the outermost constructor
|
|
used in the creation of that type. Thus the parent of t is
|
|
|
|
tp = Pointer(Array(Pointer(Char())))
|
|
|
|
|
|
Internal representation
|
|
|
|
In order to save space, we store all of our types in a large tree.
|
|
Because types are constructed from the innermost constructor out
|
|
(e.g. 'Char()' would be the first call in the example above), we
|
|
put the base types (e.g. Char, Int, UInt) at the base of this tree,
|
|
and build from there. Thus we would find 't', above, by beginning
|
|
at the root of the tree and following the path Char, Pointer,
|
|
Array, Pointer, Pointer. If we were to construct a type
|
|
|
|
t2 = Array(Pointer(Char()))
|
|
|
|
we would first walk from our root via the path Char, Pointer,
|
|
Array, and then return a pointer to that node. To construct
|
|
|
|
t3 = Pointer(Pointer(Char()))
|
|
|
|
we would walk from our root via the path Char, Pointer, Pointer,
|
|
where we create the final node.
|
|
|
|
Fortunately, when we refer to the 'parent' of a type, it is also
|
|
that type's parent in our tree. Similarly, the 'children' of a
|
|
given type are not visible to the user, but are all the types
|
|
defined by application of further constructors to the given
|
|
type. */
|
|
|
|
|
|
/* =========================================================================
|
|
* constants for internal use
|
|
* ========================================================================= */
|
|
|
|
/* Base types
|
|
|
|
Base types have no parent (with one exception; see *), and can be
|
|
const or volatile (that is, 'is_const' and 'is_volatile' are
|
|
relevant). 'width' specifies the length in bits of an integral or
|
|
character (e.g. wchar) type, and the length in bits of the mantissa
|
|
of a Float. 'exp_width' specifies the width of the exponent in a
|
|
float type. Only ints can be signed or unsigned (i.e. their
|
|
'is_signed' and 'is_unsigned' are relevant) (N.B.: the axiom of the
|
|
excluded middle does not apply here: an integer, an unsigned
|
|
integer, and a signed integer are distinct types). 'name' specifies
|
|
the name of a Name type, as well as the optional tag for an Enum or
|
|
Struct. 'attributes' specifies the indirect attributes of a type.
|
|
For Enums, this is the optional list of defined names and their
|
|
values. For Structs, this is an optional list of the types and
|
|
names of the members. Structs also have a 'subtype' to
|
|
differentiate structs from unions.
|
|
|
|
Note: it is up to the parser to distinguish character types
|
|
(i.e. those containing ASCII data) from 8-bit integer types, most
|
|
likely using some simple heuristics.
|
|
|
|
(*) If a Name's underlying type is known, then its child field
|
|
points to that type. */
|
|
|
|
#define Swig_Type_Int 0
|
|
#define Swig_Type_Float 1
|
|
#define Swig_Type_Void 2
|
|
#define Swig_Type_Char 3
|
|
#define Swig_Type_Name 4
|
|
#define Swig_Type_Enum 5
|
|
#define Swig_Type_Struct 6
|
|
|
|
/* Constructors
|
|
|
|
Constructors have a parent. Further, Arrays may have their size
|
|
expression in 'attributes', and Functions have the types and names
|
|
of their arguments in 'attributes'. A Pointer may be const or
|
|
volatile (which characteristic more accurately applies to its
|
|
child, although this is a matter of interpretation). */
|
|
|
|
#define Swig_Type_Array 7
|
|
#define Swig_Type_Function 8
|
|
#define Swig_Type_Pointer 9
|
|
|
|
/* Subtypes
|
|
|
|
A Struct may either be a Struct or a Union -- since SWIG handles
|
|
them similarly, this is considered a subtype. */
|
|
|
|
#define Swig_Type_Subtype_Struct 1
|
|
#define Swig_Type_Subtype_Union 2
|
|
|
|
/* (for results of comparisons) */
|
|
|
|
#define TAGS_EQ 0
|
|
#define TAGS_NEQ 1
|
|
|
|
/* =========================================================================
|
|
* structure definitions
|
|
* ========================================================================= */
|
|
/* These are both DOH types so that we can hash them. The first
|
|
(Swig_Type_tag) is a completely internal DOH type, while the second
|
|
is the publicly exported DOH type. */
|
|
|
|
typedef struct Swig_Type_tag
|
|
{
|
|
DOHCOMMON;
|
|
|
|
short type;
|
|
short subtype;
|
|
DOH *name;
|
|
DOH **attributes;
|
|
short width;
|
|
short exp_width;
|
|
int is_const;
|
|
int is_volatile;
|
|
int is_signed;
|
|
int is_unsigned;
|
|
|
|
int hashkey;
|
|
} Swig_Type_tag;
|
|
|
|
typedef DOH *Swig_Type_children; /* a DOH Hash */
|
|
|
|
typedef struct Swig_Type_node
|
|
{
|
|
DOHCOMMON;
|
|
|
|
Swig_Type_tag *tag;
|
|
struct Swig_Type_node *parent;
|
|
Swig_Type_children children;
|
|
|
|
int hashkey;
|
|
} Swig_Type_node;
|
|
|
|
/* =========================================================================
|
|
* static variables
|
|
* ========================================================================= */
|
|
|
|
/* shorthand */
|
|
#define ROOT Swig_Type_root
|
|
static Swig_Type_children Swig_Type_root = NULL;
|
|
|
|
/* =========================================================================
|
|
* utility function declarations
|
|
* ========================================================================= */
|
|
|
|
/* Take one step down into the children, creating a new node if
|
|
necessary. If parent is NULL, add to the root. */
|
|
static Swig_Type_node *
|
|
Swig_Type_step(Swig_Type_node *parent, Swig_Type_tag *tag);
|
|
|
|
/* Make sure that this is a real DOH string, not a (char *). */
|
|
static DOH *
|
|
Swig_Type_make_string(DOH *in);
|
|
|
|
/* the smallest n such that i < 2**n */
|
|
static int Swig_Type_bit_count(unsigned int i);
|
|
|
|
/* return a string of tag's flags, possibly including signs */
|
|
static DOH *
|
|
Swig_Type_tag_flags(Swig_Type_tag *tag, int do_signs);
|
|
|
|
/* =========================================================================
|
|
* Swig_Type_tag DOH type declaration
|
|
* ========================================================================= */
|
|
|
|
static DOH *
|
|
Swig_Type_tag_new(short type, short subtype,
|
|
DOH *name, DOH *attributes,
|
|
int width, int exp_width,
|
|
int is_const, int is_volatile,
|
|
int is_signed, int is_unsigned);
|
|
|
|
static DOH *Swig_Type_tag_str(DOH *o); /* e.g. 'pointer to' */
|
|
static int Swig_Type_tag_hash(DOH *o);
|
|
static int Swig_Type_tag_cmp(DOH *o1, DOH *o2);
|
|
#define TagData(x) ((Swig_Type_tag *)(x))
|
|
|
|
static DohObjInfo Swig_Type_tag_Type =
|
|
{
|
|
"TypeTag", /* objname */
|
|
sizeof(Swig_Type_tag), /* objsize */
|
|
0, /* doh_del -- will never happen */
|
|
0, /* doh_copy */
|
|
0, /* doh_clear */
|
|
0, /* doh_scope */
|
|
Swig_Type_tag_str, /* doh_str */
|
|
0, /* doh_data */
|
|
0, /* doh_dump */
|
|
0, /* doh_load */
|
|
0, /* doh_len */
|
|
Swig_Type_tag_hash, /* doh_hash */
|
|
Swig_Type_tag_cmp, /* doh_cmp */
|
|
0, /* doh_mapping */
|
|
0, /* doh_sequence */
|
|
0, /* doh_file */
|
|
0, /* doh_string */
|
|
0, /* doh_callable */
|
|
0, /* doh_position */
|
|
};
|
|
|
|
/* =========================================================================
|
|
* Swig_Type_node DOH type declaration
|
|
* ========================================================================= */
|
|
|
|
static DOH *Swig_Type_node_new(DOH *tag, DOH *parent);
|
|
|
|
static DOH *Swig_Type_node_str(DOH *o); /* e.g. 'pointer to array (10)
|
|
of pointer to char'' */
|
|
static int Swig_Type_node_hash(DOH *o);
|
|
static int Swig_Type_node_cmp(DOH *o, DOH *o2);
|
|
#define NodeData(x) ((Swig_Type_node *)(x))
|
|
|
|
static DohObjInfo Swig_Type_node_Type =
|
|
{
|
|
"Type", /* objname */
|
|
sizeof(Swig_Type_node), /* objsize */
|
|
0, /* doh_del -- will never happen */
|
|
0, /* doh_copy */
|
|
0, /* doh_clear */
|
|
0, /* doh_scope */
|
|
Swig_Type_node_str, /* doh_str */
|
|
0, /* doh_data */
|
|
0, /* doh_dump */
|
|
0, /* doh_load */
|
|
0, /* doh_len */
|
|
Swig_Type_node_hash, /* doh_hash */
|
|
Swig_Type_node_cmp, /* doh_cmp */
|
|
0, /* doh_mapping */
|
|
0, /* doh_sequence */
|
|
0, /* doh_file */
|
|
0, /* doh_string */
|
|
0, /* doh_callable */
|
|
0, /* doh_position */
|
|
};
|
|
|
|
/* =========================================================================
|
|
* utility functions
|
|
* ========================================================================= */
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static Swig_Type_node *
|
|
* Swig_Type_step(Swig_Type_node *parent, Swig_Type_children children,
|
|
* Swig_Type_tag *tag);
|
|
* -------------------------------------------------------------------------
|
|
* Take a step down the tree, creating a new node if necessary, and
|
|
* return a pointer to the node we arrive at.
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
static Swig_Type_node *
|
|
Swig_Type_step(Swig_Type_node *parent, Swig_Type_tag *tag)
|
|
{
|
|
Swig_Type_children children;
|
|
DOH *subnode;
|
|
|
|
if (parent) children = parent->children;
|
|
else if (ROOT) children = ROOT;
|
|
else children = ROOT = NewHash();
|
|
|
|
subnode = Getattr(children, tag);
|
|
|
|
if (!subnode) {
|
|
subnode = Swig_Type_node_new(tag, parent);
|
|
Setattr(children, tag, subnode);
|
|
}
|
|
|
|
return NodeData(subnode);
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static DOH *
|
|
* Swig_Type_make_string(DOH *in);
|
|
* -------------------------------------------------------------------------
|
|
* Make sure that this is a real DOH string, not a (char *).
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
static DOH *
|
|
Swig_Type_make_string(DOH *in)
|
|
{
|
|
if (String_check(in) || SuperString_check(in))
|
|
return in;
|
|
|
|
/* assume (char *) */
|
|
if (in)
|
|
return NewString(in);
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static int Swig_Type_bit_count(unsigned int i);
|
|
* -------------------------------------------------------------------------
|
|
/* The smallest n such that i < 2**n
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
static int Swig_Type_bit_count(unsigned int i)
|
|
{
|
|
int n = 0;
|
|
while (i)
|
|
n++, i >>= 1;
|
|
return n;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static DOH *
|
|
* Swig_Type_tag_flags(Swig_Type_tag *tag, int do_signs);
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
static DOH *
|
|
Swig_Type_tag_flags(Swig_Type_tag *tag, int do_signs)
|
|
{
|
|
char * fmt = "%s";
|
|
DOH *s = NewString("[");
|
|
Seek(s, 0, SEEK_END);
|
|
|
|
if (tag->is_const) Printf(s, fmt, "const"), fmt = " %s";
|
|
if (tag->is_volatile) Printf(s, fmt, "volatile"), fmt = " %s";
|
|
if (do_signs && tag->is_signed) Printf(s, fmt, "signed"), fmt = " %s";
|
|
if (do_signs && tag->is_unsigned) Printf(s, fmt, "unsigned"), fmt = " %s";
|
|
|
|
Printf(s, "]");
|
|
|
|
return s;
|
|
}
|
|
|
|
/* =========================================================================
|
|
* Swig_Type_tag DOH type implementation
|
|
* ========================================================================= */
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static DOH *
|
|
* Swig_Type_tag_new( ... );
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
static DOH *
|
|
Swig_Type_tag_new(short type, short subtype,
|
|
DOH *name, DOH *attributes,
|
|
int width, int exp_width,
|
|
int is_const, int is_volatile,
|
|
int is_signed, int is_unsigned)
|
|
{
|
|
Swig_Type_tag *t;
|
|
|
|
t = (Swig_Type_tag *)DohObjMalloc(sizeof(Swig_Type_tag));
|
|
t->objinfo = &Swig_Type_tag_Type;
|
|
t->hashkey = -1;
|
|
t->type = type;
|
|
t->subtype = subtype;
|
|
t->name = Swig_Type_make_string(name); if (t->name) Incref(t->name);
|
|
t->attributes = attributes; if (t->attributes) Incref(t->attributes);
|
|
t->width = width;
|
|
t->exp_width = exp_width;
|
|
t->is_const = is_const;
|
|
t->is_volatile = is_volatile;
|
|
t->is_signed = is_signed;
|
|
t->is_unsigned = is_unsigned;
|
|
|
|
return t;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static DOH *
|
|
* Swig_Type_tag_str(DOH *o);
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
static DOH *Swig_Type_tag_str(DOH *o)
|
|
{
|
|
Swig_Type_tag *tag = TagData(o);
|
|
DOH *s = NewString("");
|
|
Seek(s, 0, SEEK_END);
|
|
|
|
switch (tag->type)
|
|
{
|
|
case Swig_Type_Int:
|
|
Printf(s, "Int(%d, %s)", tag->width,
|
|
Swig_Type_tag_flags(tag, 1));
|
|
break;
|
|
case Swig_Type_Float:
|
|
Printf(s, "Float(%d ** %d, %s)",
|
|
tag->width, tag->exp_width,
|
|
Swig_Type_tag_flags(tag, 0));
|
|
break;
|
|
case Swig_Type_Void:
|
|
Printf(s, "Void");
|
|
break;
|
|
case Swig_Type_Char:
|
|
Printf(s, "Char(%d, %s)", tag->width,
|
|
Swig_Type_tag_flags(tag, 0));
|
|
break;
|
|
case Swig_Type_Name:
|
|
Printf(s, "Name('%s', %s)", tag->name,
|
|
Swig_Type_tag_flags(tag, 0));
|
|
break;
|
|
case Swig_Type_Enum:
|
|
Printf(s, "Enum(");
|
|
if (tag->name)
|
|
Printf(s, "'%s', ", tag->name);
|
|
if (tag->attributes)
|
|
Printf(s, "%s, ", tag->attributes);
|
|
Printf(s, "%s)", Swig_Type_tag_flags(tag, 0));
|
|
break;
|
|
case Swig_Type_Struct:
|
|
if (tag->subtype == Swig_Type_Subtype_Struct)
|
|
Printf(s, "Struct(");
|
|
else
|
|
Printf(s, "Union(");
|
|
if (tag->name)
|
|
Printf(s, "'%s', ", tag->name);
|
|
if (tag->attributes)
|
|
Printf(s, "%s, ", tag->attributes);
|
|
Printf(s, "%s)", Swig_Type_tag_flags(tag, 0));
|
|
break;
|
|
case Swig_Type_Array:
|
|
if (tag->attributes)
|
|
Printf(s, "Array (%s)", tag->attributes);
|
|
Printf(s, "Array of ");
|
|
break;
|
|
case Swig_Type_Function:
|
|
Printf(s, "Function (%s) returning ", tag->attributes);
|
|
break;
|
|
case Swig_Type_Pointer:
|
|
Printf(s, "Pointer %s to ", Swig_Type_tag_flags(tag, 0));
|
|
break;
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static int
|
|
* Swig_Type_tag_hash(DOH *o);
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
static int Swig_Type_tag_hash(DOH *o)
|
|
{
|
|
Swig_Type_tag *tag = TagData(o);
|
|
if (tag->hashkey != -1) return tag->hashkey;
|
|
|
|
/* barring the use of any sub-object's Hashval, we assign a
|
|
different integer to each of our types. */
|
|
switch (tag->type)
|
|
{
|
|
/* base types are assigned certain numbers */
|
|
case Swig_Type_Int:
|
|
tag->hashkey =
|
|
Swig_Type_bit_count(tag->width) +
|
|
(tag->is_const << 4) +
|
|
(tag->is_volatile << 5) +
|
|
(tag->is_signed << 6) +
|
|
(tag->is_unsigned << 7);
|
|
break;
|
|
case Swig_Type_Float:
|
|
tag->hashkey =
|
|
Swig_Type_bit_count(tag->width) +
|
|
(Swig_Type_bit_count(tag->exp_width) << 4) +
|
|
(tag->is_const << 8) +
|
|
(tag->is_volatile << 9) +
|
|
1 << 10;
|
|
break;
|
|
case Swig_Type_Void:
|
|
tag->hashkey =
|
|
Swig_Type_bit_count(tag->width) +
|
|
(tag->is_const << 4) +
|
|
(tag->is_volatile << 5) +
|
|
(tag->is_signed << 6) +
|
|
(tag->is_unsigned << 7) +
|
|
2 << 10;
|
|
break;
|
|
case Swig_Type_Char:
|
|
tag->hashkey =
|
|
Swig_Type_bit_count(tag->width) +
|
|
(tag->is_const << 4) +
|
|
(tag->is_volatile << 5) +
|
|
(tag->is_signed << 6) +
|
|
(tag->is_unsigned << 7) +
|
|
3 << 10;
|
|
break;
|
|
case Swig_Type_Name:
|
|
tag->hashkey =
|
|
Hashval(tag->name);
|
|
break;
|
|
case Swig_Type_Enum:
|
|
tag->hashkey =
|
|
(tag->name) ? Hashval(tag->name) : 0 +
|
|
(tag->attributes) ? Hashval(tag->attributes) : 0 +
|
|
5 << 10;
|
|
break;
|
|
case Swig_Type_Struct:
|
|
tag->hashkey =
|
|
(tag->name) ? Hashval(tag->name) : 0 +
|
|
(tag->attributes) ? Hashval(tag->attributes) : 0 +
|
|
6 << 10 +
|
|
tag->subtype << 20;
|
|
break;
|
|
case Swig_Type_Array:
|
|
tag->hashkey =
|
|
(tag->attributes) ? Hashval(tag->attributes) : 0 +
|
|
7 << 10;
|
|
break;
|
|
case Swig_Type_Function:
|
|
tag->hashkey =
|
|
(tag->attributes) ? Hashval(tag->attributes) : 0 +
|
|
8 << 10;
|
|
break;
|
|
case Swig_Type_Pointer:
|
|
tag->hashkey =
|
|
(tag->is_const << 8) +
|
|
(tag->is_volatile << 9) +
|
|
9 << 10;
|
|
break;
|
|
|
|
default:
|
|
tag->hashkey =
|
|
tag->type;
|
|
break;
|
|
}
|
|
|
|
if (tag->hashkey == -1) tag->hashkey = 1;
|
|
return tag->hashkey;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static int
|
|
* Swig_Type_tag_cmp(DOH *o1, DOH *o2);
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
static int Swig_Type_tag_cmp(DOH *o1, DOH *o2)
|
|
{
|
|
Swig_Type_tag *t1, *t2;
|
|
t1 = TagData(o1);
|
|
t2 = TagData(o2);
|
|
|
|
/* we define only equal or not equal, as that's all we need to hash
|
|
types. */
|
|
|
|
if (t1 == t2)
|
|
return TAGS_EQ;
|
|
|
|
if (t1->type != t2->type)
|
|
return TAGS_NEQ;
|
|
|
|
switch (t1->type)
|
|
{
|
|
case Swig_Type_Int:
|
|
if (t1->width != t2->width ||
|
|
t1->is_const != t2->is_const ||
|
|
t1->is_volatile != t2->is_volatile ||
|
|
t1->is_unsigned != t2->is_unsigned ||
|
|
t1->is_signed != t2->is_signed)
|
|
return TAGS_NEQ;
|
|
break;
|
|
case Swig_Type_Float:
|
|
if (t1->width != t2->width ||
|
|
t1->exp_width != t2->exp_width ||
|
|
t1->is_const != t2->is_const ||
|
|
t1->is_volatile != t2->is_volatile)
|
|
return TAGS_NEQ;
|
|
break;
|
|
case Swig_Type_Void:
|
|
break; /* nothing to it.. */
|
|
case Swig_Type_Char:
|
|
if (t1->width != t2->width ||
|
|
t1->is_const != t2->is_const ||
|
|
t1->is_volatile != t2->is_volatile)
|
|
return TAGS_NEQ;
|
|
break;
|
|
case Swig_Type_Name:
|
|
return Cmp(t1->name, t2->name);
|
|
case Swig_Type_Struct:
|
|
if (t1->subtype != t2->subtype)
|
|
return TAGS_NEQ;
|
|
/* fall through */
|
|
case Swig_Type_Enum:
|
|
/* do the names differ? */
|
|
if (t1->name && t2->name)
|
|
{
|
|
if (Cmp(t1->name, t2->name))
|
|
return TAGS_NEQ;
|
|
else if (t1->attributes && t2->attributes)
|
|
return Cmp(t1->attributes, t2->attributes);
|
|
else if (t1->attributes || t2->attributes)
|
|
/* both named, only one has attributes... */
|
|
return TAGS_NEQ;
|
|
else
|
|
/* both named, neither has attributes */
|
|
return TAGS_EQ;
|
|
}
|
|
else if (t1->name || t2->name)
|
|
/* one named, one not */
|
|
return TAGS_NEQ;
|
|
else
|
|
{
|
|
/* neither named -- structural equivalence */
|
|
if (t1->attributes && t2->attributes)
|
|
return Cmp(t1->attributes, t2->attributes);
|
|
else
|
|
/* this should never happen .. */
|
|
return TAGS_NEQ;
|
|
}
|
|
case Swig_Type_Array:
|
|
if (t1->attributes && t2->attributes)
|
|
return Cmp(t1->attributes, t2->attributes);
|
|
else if (t1->attributes || t2->attributes)
|
|
return TAGS_NEQ;
|
|
else
|
|
return TAGS_EQ;
|
|
case Swig_Type_Function:
|
|
return Cmp(t1->attributes, t2->attributes);
|
|
case Swig_Type_Pointer:
|
|
if (t1->is_volatile != t2->is_volatile ||
|
|
t1->is_const != t2->is_const)
|
|
return TAGS_NEQ;
|
|
break;
|
|
default:
|
|
return TAGS_NEQ;
|
|
}
|
|
|
|
/* fall through -> equal */
|
|
return TAGS_EQ;
|
|
}
|
|
|
|
/* =========================================================================
|
|
* Swig_Type_node DOH type implementation
|
|
* ========================================================================= */
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static DOH *
|
|
* Swig_Type_NewXXX( <varies> );
|
|
* -------------------------------------------------------------------------
|
|
* Public constructors for various sorts of types (types of sorts?)
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
DOH *Swig_Type_NewInt(int width, int is_const, int is_volatile,
|
|
int is_signed, int is_unsigned)
|
|
{
|
|
return Swig_Type_step(NULL,
|
|
Swig_Type_tag_new(Swig_Type_Int, 0,
|
|
NULL, NULL,
|
|
width, 0,
|
|
is_const, is_volatile,
|
|
is_signed, is_unsigned));
|
|
}
|
|
|
|
DOH *Swig_Type_NewFloat(int width, int exp_width, int is_const,
|
|
int is_volatile)
|
|
{
|
|
return Swig_Type_step(NULL,
|
|
Swig_Type_tag_new(Swig_Type_Float, 0,
|
|
NULL, NULL,
|
|
width, exp_width,
|
|
is_const, is_volatile,
|
|
0, 0));
|
|
}
|
|
|
|
DOH *Swig_Type_NewVoid()
|
|
{
|
|
return Swig_Type_step(NULL,
|
|
Swig_Type_tag_new(Swig_Type_Void, 0,
|
|
NULL, NULL,
|
|
0, 0,
|
|
0, 0,
|
|
0, 0));
|
|
}
|
|
|
|
DOH *Swig_Type_NewChar(int width, int is_const, int is_volatile)
|
|
{
|
|
return Swig_Type_step(NULL,
|
|
Swig_Type_tag_new(Swig_Type_Char, 0,
|
|
NULL, NULL,
|
|
width, 0,
|
|
is_const, is_volatile,
|
|
0, 0));
|
|
}
|
|
|
|
DOH *Swig_Type_NewName(DOH *name, int is_const, int is_volatile)
|
|
{
|
|
return Swig_Type_step(NULL,
|
|
Swig_Type_tag_new(Swig_Type_Name, 0,
|
|
name, NULL,
|
|
0, 0,
|
|
is_const, is_volatile,
|
|
0, 0));
|
|
}
|
|
|
|
DOH *Swig_Type_NewEnum(DOH *name, DOH *body,
|
|
int is_const, int is_volatile)
|
|
{
|
|
return Swig_Type_step(NULL,
|
|
Swig_Type_tag_new(Swig_Type_Name, 0,
|
|
name, body,
|
|
0, 0,
|
|
is_const, is_volatile,
|
|
0, 0));
|
|
}
|
|
|
|
DOH *Swig_Type_NewStruct(DOH *name, DOH *body,
|
|
int is_const, int is_volatile)
|
|
{
|
|
return Swig_Type_step(NULL,
|
|
Swig_Type_tag_new(Swig_Type_Struct,
|
|
Swig_Type_Subtype_Struct,
|
|
name, body,
|
|
0, 0,
|
|
is_const, is_volatile,
|
|
0, 0));
|
|
}
|
|
|
|
DOH *Swig_Type_NewUnion(DOH *name, DOH *body,
|
|
int is_const, int is_volatile)
|
|
{
|
|
return Swig_Type_step(NULL,
|
|
Swig_Type_tag_new(Swig_Type_Struct,
|
|
Swig_Type_Subtype_Union,
|
|
name, body,
|
|
0, 0,
|
|
is_const, is_volatile,
|
|
0, 0));
|
|
}
|
|
|
|
DOH *Swig_Type_NewArray(DOH *size, DOH *parent)
|
|
{
|
|
return Swig_Type_step(parent,
|
|
Swig_Type_tag_new(Swig_Type_Array,
|
|
0,
|
|
0, size,
|
|
0, 0,
|
|
0, 0,
|
|
0, 0));
|
|
}
|
|
|
|
DOH *Swig_Type_NewFunction(DOH *parameters, DOH *parent)
|
|
{
|
|
return Swig_Type_step(parent,
|
|
Swig_Type_tag_new(Swig_Type_Function,
|
|
0,
|
|
0, parameters,
|
|
0, 0,
|
|
0, 0,
|
|
0, 0));
|
|
}
|
|
|
|
DOH *Swig_Type_NewPointer(int is_const, int is_volatile, DOH *parent)
|
|
{
|
|
return Swig_Type_step(parent,
|
|
Swig_Type_tag_new(Swig_Type_Pointer,
|
|
0,
|
|
0, 0,
|
|
0, 0,
|
|
is_const, is_volatile,
|
|
0, 0));
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static DOH *
|
|
* Swig_Type_node_new(DOH *tag, DOH *parent);
|
|
* -------------------------------------------------------------------------
|
|
* private, 'real' constructor
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
static DOH *
|
|
Swig_Type_node_new(DOH *tag, DOH *parent)
|
|
{
|
|
Swig_Type_node *n;
|
|
|
|
n = (Swig_Type_node *)DohObjMalloc(sizeof(Swig_Type_node));
|
|
n->objinfo = &Swig_Type_node_Type;
|
|
|
|
n->parent = parent;
|
|
n->tag = tag; Incref(tag);
|
|
n->children = NewHash();
|
|
n->hashkey = -1;
|
|
|
|
return n;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static DOH *
|
|
* Swig_Type_node_str(DOH *o);
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
static DOH *
|
|
Swig_Type_node_str(DOH *o)
|
|
{
|
|
Swig_Type_node *n = (Swig_Type_node *)o;
|
|
DOH *s = NewString("");
|
|
if (n->parent)
|
|
Printf(s, "%s%s", n->tag, n->parent);
|
|
else
|
|
Printf(s, "%s", Str(n->tag));
|
|
|
|
return s;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static int
|
|
* Swig_Type_node_hash(DOH *o);
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
static int
|
|
Swig_Type_node_hash(DOH *o)
|
|
{
|
|
Swig_Type_node *n = (Swig_Type_node *)o;
|
|
if (n->hashkey != -1) return n->hashkey;
|
|
|
|
n->hashkey = Hashval(n->tag);
|
|
if (n->parent)
|
|
{
|
|
int hvp = Hashval(n->parent);
|
|
|
|
n->hashkey += (hvp << 12) + (hvp >> 12);
|
|
}
|
|
|
|
if (n->hashkey == -1) n->hashkey = 1;
|
|
|
|
return n->hashkey;
|
|
}
|
|
|
|
/* -------------------------------------------------------------------------
|
|
* static int
|
|
* Swig_Type_node_cmp(DOH *o1, DOH *o2);
|
|
* ------------------------------------------------------------------------- */
|
|
|
|
static int
|
|
Swig_Type_node_cmp(DOH *o1, DOH *o2)
|
|
{
|
|
Swig_Type_node *n1 = (Swig_Type_node *)o1;
|
|
Swig_Type_node *n2 = (Swig_Type_node *)o1;
|
|
|
|
/* we call the comparison functions directly just to shave a hair
|
|
off the execution time */
|
|
|
|
if (Swig_Type_tag_cmp(n1->tag, n2->tag))
|
|
return TAGS_NEQ;
|
|
|
|
else if (n1->parent && n2->parent)
|
|
return Swig_Type_node_cmp(n1->parent, n2->parent);
|
|
|
|
else if (n1->parent || n2->parent)
|
|
return TAGS_NEQ;
|
|
else
|
|
return TAGS_EQ;
|
|
}
|
|
|
|
#ifdef TYPE_TEST
|
|
#include <stdio.h>
|
|
int main(int argc, char **argv)
|
|
{
|
|
int i;
|
|
DOH *node[10];
|
|
DOH *key;
|
|
|
|
node[0] = Swig_Type_NewInt(8, 0, 0, 1, 0);
|
|
node[1] = Swig_Type_NewPointer(0, 1, node[0]);
|
|
node[2] = Swig_Type_NewPointer(1, 0, node[1]);
|
|
node[3] = Swig_Type_NewArray(NULL, node[2]);
|
|
|
|
node[4] = Swig_Type_NewInt(8, 0, 0, 1, 0);
|
|
node[5] = Swig_Type_NewPointer(0, 1, node[4]);
|
|
node[6] = Swig_Type_NewPointer(1, 1, node[5]);
|
|
node[7] = Swig_Type_NewArray(NULL, node[6]);
|
|
|
|
node[8] = Swig_Type_NewVoid();
|
|
node[9] = Swig_Type_NewVoid();
|
|
node[9] = Swig_Type_NewPointer(0, 1, node[9]);
|
|
node[9] = Swig_Type_NewPointer(1, 1, node[9]);
|
|
node[9] = Swig_Type_NewPointer(1, 0, node[9]);
|
|
node[9] = Swig_Type_NewPointer(0, 0, node[9]);
|
|
|
|
Printf(stdout, "Address\t\tHashvalue\tType\n");
|
|
for (i = 0; i < 10; i++)
|
|
Printf(stdout, "0x%08x\t0x%08x\t%s\n", node[i],
|
|
Hashval(node[i]), node[i]);
|
|
|
|
Printf(stdout, "\nROOT (0x%08x):\n", ROOT);
|
|
for (key = Firstkey(ROOT); key; key = Nextkey(ROOT))
|
|
Printf(stdout, "%s : %s\n", key, Getattr(ROOT, key));
|
|
|
|
return 0;
|
|
}
|
|
#endif
|