swig/Source/Swig/typesys.c
Maciej Drwal e058e1f42f Merged revisions 10498-10499,10503-10504,10506,10508,10511,10515-10516,10518-10519,10527,10530-10531,10536-10537,10539-10552,10558-10568,10574-10580,10582,10584,10588-10589,10594 via svnmerge from
https://swig.svn.sourceforge.net/svnroot/swig/trunk

........
  r10498 | talby | 2008-05-26 22:09:56 +0200 (Pn, 26 maj 2008) | 2 lines
  
  run test cases in the Perl set by the --with-perl5 configure option.
........
  r10499 | talby | 2008-05-26 23:04:06 +0200 (Pn, 26 maj 2008) | 3 lines
  
  The perl5 minherit runtime test will work better if the classes are 
  actually built under SWIGPERL.
........
  r10503 | wsfulton | 2008-05-28 11:44:37 +0200 (Śr, 28 maj 2008) | 1 line
  
  Fix variable wrappers when using -proxy. Patch from Jan Jezabek
........
  r10504 | bhy | 2008-05-28 19:27:48 +0200 (Śr, 28 maj 2008) | 2 lines
  
  Fixed SF #1971977:  typo in pycontainer.swg (related to -extranative option)
........
  r10506 | wsfulton | 2008-05-29 02:45:28 +0200 (Cz, 29 maj 2008) | 1 line
  
  Fix variable wrappers when using -noproxy
........
  r10508 | bhy | 2008-05-30 15:53:33 +0200 (Pt, 30 maj 2008) | 1 line
  
  Fixed SF #1976978, apply the macros for primitive types to std::wstring
........
  r10511 | olly | 2008-05-30 18:11:27 +0200 (Pt, 30 maj 2008) | 4 lines
  
  Fix typo in handling of /*@SWIG[...]*/ comments in the scanner.  This just
  meant we were only actually looking for /*@SWI at the start of the comment, so
  was pretty harmless in practice.
........
  r10515 | wsfulton | 2008-06-02 22:10:40 +0200 (Pn, 02 cze 2008) | 1 line
  
  Fix samename testcase for c# and java
........
  r10516 | wsfulton | 2008-06-02 22:15:39 +0200 (Pn, 02 cze 2008) | 1 line
  
  Fix enums when using -noproxy
........
  r10518 | bhy | 2008-06-07 13:20:07 +0200 (So, 07 cze 2008) | 4 lines
  
  Added a test case for keyword renaming.
  Now it works for Python in SWIG's -c++ mode,
  but in C mode it doesn't work! (you can try with make keyword_rename.ctest)
........
  r10519 | bhy | 2008-06-07 15:40:51 +0200 (So, 07 cze 2008) | 1 line
  
  fixed keyword_rename.ctest tese case, caused by a mistake in Swig/naming.c
........
  r10527 | mgossage | 2008-06-17 04:57:15 +0200 (Wt, 17 cze 2008) | 1 line
  
  [lua] bugfix 1938142 (bool& and bool* support)
........
  r10530 | wsfulton | 2008-06-19 22:02:13 +0200 (Cz, 19 cze 2008) | 1 line
  
  Add R keyword support. Rename keywords for successful compilation of Java and C# code. More consistent keyword warnings across the different languages.
........
  r10531 | wsfulton | 2008-06-19 23:15:48 +0200 (Cz, 19 cze 2008) | 1 line
  
  add complete list of R reserved words
........
  r10536 | wsfulton | 2008-06-21 13:35:33 +0200 (So, 21 cze 2008) | 1 line
  
  better terminology for static types
........
  r10537 | wsfulton | 2008-06-21 13:42:48 +0200 (So, 21 cze 2008) | 1 line
  
  remove raise as keyword test- it conflicts with _raise in LIBCMT on windows
........
  r10539 | wsfulton | 2008-06-21 17:21:29 +0200 (So, 21 cze 2008) | 1 line
  
  Lua example warning removal fixes for vc++
........
  r10540 | wsfulton | 2008-06-21 17:23:02 +0200 (So, 21 cze 2008) | 1 line
  
  Remove some vc++ /W4 warnings
........
  r10541 | wsfulton | 2008-06-21 18:04:55 +0200 (So, 21 cze 2008) | 1 line
  
  minor vc++ /W4 warning fixes
........
  r10542 | wsfulton | 2008-06-21 21:07:51 +0200 (So, 21 cze 2008) | 1 line
  
  'byte' is already used in Ruby on windows, so use another keyword
........
  r10543 | wsfulton | 2008-06-21 22:45:32 +0200 (So, 21 cze 2008) | 1 line
  
  Fix crashing in the Ruby reject method in the STL wrappers
........
  r10544 | wsfulton | 2008-06-21 22:48:28 +0200 (So, 21 cze 2008) | 1 line
  
  Fix crashing in the Ruby reject method in the STL wrappers
........
  r10545 | wsfulton | 2008-06-21 22:49:10 +0200 (So, 21 cze 2008) | 1 line
  
  remove unnecessary variable int the char **STRING_ARRAY out typemap
........
  r10546 | wsfulton | 2008-06-21 23:07:49 +0200 (So, 21 cze 2008) | 1 line
  
  Fix Ruby C++ example dependencies in dsp files
........
  r10547 | wsfulton | 2008-06-22 00:25:36 +0200 (N, 22 cze 2008) | 1 line
  
  Fix unused parameter warnings in python when using gcc's -W -Wall options
........
  r10548 | wsfulton | 2008-06-22 00:26:35 +0200 (N, 22 cze 2008) | 1 line
  
  Fix virtual destructor
........
  r10549 | wsfulton | 2008-06-22 01:25:20 +0200 (N, 22 cze 2008) | 1 line
  
  various warning fixes
........
  r10550 | wsfulton | 2008-06-22 02:09:11 +0200 (N, 22 cze 2008) | 1 line
  
  Another fix for the JVM hanging on exit problem when using directors
........
  r10551 | wsfulton | 2008-06-22 02:09:51 +0200 (N, 22 cze 2008) | 1 line
  
  documentation sections update
........
  r10552 | wsfulton | 2008-06-22 02:18:10 +0200 (N, 22 cze 2008) | 1 line
  
  more docs on defining macros for the thread hanging problem
........
  r10558 | wsfulton | 2008-06-22 23:30:20 +0200 (N, 22 cze 2008) | 1 line
  
  fix unused parms in last commit for C code
........
  r10559 | wsfulton | 2008-06-23 00:12:43 +0200 (Pn, 23 cze 2008) | 1 line
  
  Suppress unused methods warning for VC++
........
  r10560 | wsfulton | 2008-06-23 22:26:07 +0200 (Pn, 23 cze 2008) | 1 line
  
  fix partialcheck-test-suite and parallel make for r, chicken, tcl and php
........
  r10561 | wsfulton | 2008-06-23 22:39:41 +0200 (Pn, 23 cze 2008) | 1 line
  
  correct message display when running the partialcheck-test-suite make target
........
  r10562 | wsfulton | 2008-06-23 23:14:53 +0200 (Pn, 23 cze 2008) | 1 line
  
  fix typo
........
  r10563 | olly | 2008-06-23 23:23:54 +0200 (Pn, 23 cze 2008) | 3 lines
  
  Fix bad use of Python API (untested, since I can't even compile this code on
  x86-64!)
........
  r10564 | olly | 2008-06-24 00:58:03 +0200 (Wt, 24 cze 2008) | 3 lines
  
  [PHP] Fix segfault when wrapping a non-class function marked with
  %newobject (testcase char_strings).
........
  r10565 | olly | 2008-06-24 02:27:34 +0200 (Wt, 24 cze 2008) | 3 lines
  
  [PHP] Fix assertion failure when handling %typemap(in,numinputs=0)
  (testcase ignore_parameter).
........
  r10566 | olly | 2008-06-24 02:33:08 +0200 (Wt, 24 cze 2008) | 2 lines
  
  [PHP] Fix typemap_namespace.i to not try to copy a non-existent typemap.
........
  r10567 | olly | 2008-06-24 02:41:07 +0200 (Wt, 24 cze 2008) | 3 lines
  
  Clean up dead and unused code in SwigToPhpType(), and rename to
  GetShadowReturnType().
........
  r10568 | olly | 2008-06-24 02:42:29 +0200 (Wt, 24 cze 2008) | 2 lines
  
  Fix cosmetic typo in string constant.
........
  r10574 | wsfulton | 2008-06-24 22:10:28 +0200 (Wt, 24 cze 2008) | 1 line
  
  zap last entry
........
  r10575 | wsfulton | 2008-06-24 22:11:46 +0200 (Wt, 24 cze 2008) | 1 line
  
  variable name changes to remove php keywords
........
  r10576 | wsfulton | 2008-06-24 22:12:08 +0200 (Wt, 24 cze 2008) | 1 line
  
  variable name hiding fix
........
  r10577 | wsfulton | 2008-06-24 22:12:43 +0200 (Wt, 24 cze 2008) | 1 line
  
  More info about numobjects added
........
  r10578 | wsfulton | 2008-06-24 22:13:41 +0200 (Wt, 24 cze 2008) | 1 line
  
  update for 1.3.36 release
........
  r10579 | wsfulton | 2008-06-24 23:48:46 +0200 (Wt, 24 cze 2008) | 1 line
  
  remove deprecated -c commandline option (runtime library generation)
........
  r10580 | wsfulton | 2008-06-24 23:53:12 +0200 (Wt, 24 cze 2008) | 1 line
  
  correct comment about deprecated option
........
  r10582 | wsfulton | 2008-06-25 01:00:27 +0200 (Śr, 25 cze 2008) | 1 line
  
  use rsync and ssh to upload releases to SourceForge as ftp no longer works
........
  r10584 | wsfulton | 2008-06-25 01:24:48 +0200 (Śr, 25 cze 2008) | 1 line
  
  correction for 1.3.36
........
  r10588 | wsfulton | 2008-06-25 02:16:04 +0200 (Śr, 25 cze 2008) | 1 line
  
  section update
........
  r10589 | wsfulton | 2008-06-25 02:16:40 +0200 (Śr, 25 cze 2008) | 1 line
  
  bump version to 1.3.37
........
  r10594 | wsfulton | 2008-06-26 20:33:06 +0200 (Cz, 26 cze 2008) | 1 line
  
  correct typo in first entry about %fragment
........


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2008-maciekd@10606 626c5289-ae23-0410-ae9c-e8d60b6d4f22
2008-06-28 23:26:18 +00:00

2073 lines
56 KiB
C

/* -----------------------------------------------------------------------------
* See the LICENSE file for information on copyright, usage and redistribution
* of SWIG, and the README file for authors - http://www.swig.org/release.html.
*
* typesys.c
*
* SWIG type system management. These functions are used to manage
* the C++ type system including typenames, typedef, type scopes,
* inheritance, and namespaces. Generation of support code for the
* run-time type checker is also handled here.
* ----------------------------------------------------------------------------- */
char cvsroot_typesys_c[] = "$Id$";
#include "swig.h"
#include "cparse.h"
/* -----------------------------------------------------------------------------
* Synopsis
*
* The purpose of this module is to manage type names and scoping issues related
* to the C++ type system. The primary use is tracking typenames through typedef
* and inheritance.
*
* New typenames are introduced by typedef, class, and enum declarations.
* Each type is declared in a scope. This is either the global scope, a
* class, or a namespace. For example:
*
* typedef int A; // Typename A, in global scope
* namespace Foo {
* typedef int A; // Typename A, in scope Foo::
* }
* class Bar { // Typename Bar, in global scope
* typedef int A; // Typename A, in scope Bar::
* }
*
* To manage scopes, the type system is constructed as a tree of hash tables. Each
* hash table contains the following attributes:
*
* "name" - Scope name
* "qname" - Fully qualified typename
* "typetab" - Type table containing typenames and typedef information
* "symtab" - Hash table of symbols defined in a scope
* "inherit" - List of inherited scopes
* "parent" - Parent scope
*
* Typedef information is stored in the "typetab" hash table. For example,
* if you have these declarations:
*
* typedef int A;
* typedef A B;
* typedef B *C;
*
* typetab is built as follows:
*
* "A" : "int"
* "B" : "A"
* "C" : "p.B"
*
* To resolve a type back to its root type, one repeatedly expands on the type base.
* For example:
*
* C *[40] ---> a(40).p.C (string type representation, see stype.c)
* ---> a(40).p.p.B (C --> p.B)
* ---> a(40).p.p.A (B --> A)
* ---> a(40).p.p.int (A --> int)
*
* For inheritance, SWIG tries to resolve types back to the base class. For instance, if
* you have this:
*
* class Foo {
* public:
* typedef int Integer;
* };
*
* class Bar : public Foo {
* void blah(Integer x);
* }
*
* The argument type of Bar::blah will be set to Foo::Integer.
*
* The scope-inheritance mechanism is used to manage C++ namespace aliases.
* For example, if you have this:
*
* namespace Foo {
* typedef int Integer;
* }
*
* namespace F = Foo;
*
* In this case, "F::" is defined as a scope that "inherits" from Foo. Internally,
* "F::" will merely be an empty scope that refers to Foo. SWIG will never
* place new type information into a namespace alias---attempts to do so
* will generate a warning message (in the parser) and will place information into
* Foo instead.
*
*----------------------------------------------------------------------------- */
static Typetab *current_scope = 0; /* Current type scope */
static Hash *current_typetab = 0; /* Current type table */
static Hash *current_symtab = 0; /* Current symbol table */
static Typetab *global_scope = 0; /* The global scope */
static Hash *scopes = 0; /* Hash table containing fully qualified scopes */
/* Performance optimization */
#define SWIG_TYPEDEF_RESOLVE_CACHE
static Hash *typedef_resolve_cache = 0;
static Hash *typedef_all_cache = 0;
static Hash *typedef_qualified_cache = 0;
static Typetab *SwigType_find_scope(Typetab *s, String *nameprefix);
/* common attribute keys, to avoid calling find_key all the times */
/*
Enable this one if your language fully support SwigValueWrapper<T>.
Leaving at '0' keeps the old swig behavior, which is not
always safe, but is well known.
Setting at '1' activates the new scheme, which is always safe but
it requires all the typemaps to be ready for that.
*/
static int value_wrapper_mode = 0;
int Swig_value_wrapper_mode(int mode) {
value_wrapper_mode = mode;
return mode;
}
static void flush_cache() {
typedef_resolve_cache = 0;
typedef_all_cache = 0;
typedef_qualified_cache = 0;
}
/* Initialize the scoping system */
void SwigType_typesystem_init() {
if (global_scope)
Delete(global_scope);
if (scopes)
Delete(scopes);
current_scope = NewHash();
global_scope = current_scope;
Setattr(current_scope, "name", ""); /* No name for global scope */
current_typetab = NewHash();
Setattr(current_scope, "typetab", current_typetab);
current_symtab = 0;
scopes = NewHash();
Setattr(scopes, "", current_scope);
}
/* -----------------------------------------------------------------------------
* SwigType_typedef()
*
* Defines a new typedef in the current scope. Returns -1 if the type name is
* already defined.
* ----------------------------------------------------------------------------- */
int SwigType_typedef(SwigType *type, String_or_char *name) {
if (Getattr(current_typetab, name))
return -1; /* Already defined */
if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */
return 0;
}
/* Check if 'type' is already a scope. If so, we create an alias in the type
system for it. This is needed to make strange nested scoping problems work
correctly. */
{
Typetab *t = SwigType_find_scope(current_scope, type);
if (t) {
SwigType_new_scope(name);
SwigType_inherit_scope(t);
SwigType_pop_scope();
}
}
Setattr(current_typetab, name, type);
flush_cache();
return 0;
}
/* -----------------------------------------------------------------------------
* SwigType_typedef_class()
*
* Defines a class in the current scope.
* ----------------------------------------------------------------------------- */
int SwigType_typedef_class(String_or_char *name) {
String *cname;
/* Printf(stdout,"class : '%s'\n", name); */
if (Getattr(current_typetab, name))
return -1; /* Already defined */
cname = NewString(name);
Setmeta(cname, "class", "1");
Setattr(current_typetab, cname, cname);
Delete(cname);
flush_cache();
return 0;
}
/* -----------------------------------------------------------------------------
* SwigType_scope_name()
*
* Returns the qualified scope name of a type table
* ----------------------------------------------------------------------------- */
String *SwigType_scope_name(Typetab *ttab) {
String *qname = NewString(Getattr(ttab, "name"));
ttab = Getattr(ttab, "parent");
while (ttab) {
String *pname = Getattr(ttab, "name");
if (Len(pname)) {
Insert(qname, 0, "::");
Insert(qname, 0, pname);
}
ttab = Getattr(ttab, "parent");
}
return qname;
}
/* -----------------------------------------------------------------------------
* SwigType_new_scope()
*
* Creates a new scope
* ----------------------------------------------------------------------------- */
void SwigType_new_scope(const String_or_char *name) {
Typetab *s;
Hash *ttab;
String *qname;
if (!name) {
name = "<unnamed>";
}
s = NewHash();
Setattr(s, "name", name);
Setattr(s, "parent", current_scope);
ttab = NewHash();
Setattr(s, "typetab", ttab);
/* Build fully qualified name and */
qname = SwigType_scope_name(s);
Setattr(scopes, qname, s);
Setattr(s, "qname", qname);
Delete(qname);
current_scope = s;
current_typetab = ttab;
current_symtab = 0;
flush_cache();
}
/* -----------------------------------------------------------------------------
* SwigType_inherit_scope()
*
* Makes the current scope inherit from another scope. This is used for both
* C++ class inheritance, namespaces, and namespace aliases.
* ----------------------------------------------------------------------------- */
void SwigType_inherit_scope(Typetab *scope) {
List *inherits;
int i, len;
inherits = Getattr(current_scope, "inherit");
if (!inherits) {
inherits = NewList();
Setattr(current_scope, "inherit", inherits);
Delete(inherits);
}
assert(scope != current_scope);
len = Len(inherits);
for (i = 0; i < len; i++) {
Node *n = Getitem(inherits, i);
if (n == scope)
return;
}
Append(inherits, scope);
}
/* -----------------------------------------------------------------------------
* SwigType_scope_alias()
*
* Creates a scope-alias.
* ----------------------------------------------------------------------------- */
void SwigType_scope_alias(String *aliasname, Typetab *ttab) {
String *q;
/* Printf(stdout,"alias: '%s' '%x'\n", aliasname, ttab); */
q = SwigType_scope_name(current_scope);
if (Len(q)) {
Append(q, "::");
}
Append(q, aliasname);
Setattr(scopes, q, ttab);
flush_cache();
}
/* -----------------------------------------------------------------------------
* SwigType_using_scope()
*
* Import another scope into this scope.
* ----------------------------------------------------------------------------- */
void SwigType_using_scope(Typetab *scope) {
SwigType_inherit_scope(scope);
{
List *ulist;
int i, len;
ulist = Getattr(current_scope, "using");
if (!ulist) {
ulist = NewList();
Setattr(current_scope, "using", ulist);
Delete(ulist);
}
assert(scope != current_scope);
len = Len(ulist);
for (i = 0; i < len; i++) {
Typetab *n = Getitem(ulist, i);
if (n == scope)
return;
}
Append(ulist, scope);
}
flush_cache();
}
/* -----------------------------------------------------------------------------
* SwigType_pop_scope()
*
* Pop off the last scope and perform a merge operation. Returns the hash
* table for the scope that was popped off.
* ----------------------------------------------------------------------------- */
Typetab *SwigType_pop_scope() {
Typetab *t, *old = current_scope;
t = Getattr(current_scope, "parent");
if (!t)
t = global_scope;
current_scope = t;
current_typetab = Getattr(t, "typetab");
current_symtab = Getattr(t, "symtab");
flush_cache();
return old;
}
/* -----------------------------------------------------------------------------
* SwigType_set_scope()
*
* Set the scope. Returns the old scope.
* ----------------------------------------------------------------------------- */
Typetab *SwigType_set_scope(Typetab *t) {
Typetab *old = current_scope;
if (!t)
t = global_scope;
current_scope = t;
current_typetab = Getattr(t, "typetab");
current_symtab = Getattr(t, "symtab");
flush_cache();
return old;
}
/* -----------------------------------------------------------------------------
* SwigType_attach_symtab()
*
* Attaches a symbol table to a type scope
* ----------------------------------------------------------------------------- */
void SwigType_attach_symtab(Symtab *sym) {
Setattr(current_scope, "symtab", sym);
current_symtab = sym;
}
/* -----------------------------------------------------------------------------
* SwigType_print_scope()
*
* Debugging function for printing out current scope
* ----------------------------------------------------------------------------- */
void SwigType_print_scope(Typetab *t) {
Hash *ttab;
Iterator i, j;
for (i = First(scopes); i.key; i = Next(i)) {
t = i.item;
ttab = Getattr(i.item, "typetab");
Printf(stdout, "Type scope '%s' (%x)\n", i.key, i.item);
{
List *inherit = Getattr(i.item, "inherit");
if (inherit) {
Iterator j;
for (j = First(inherit); j.item; j = Next(j)) {
Printf(stdout, " Inherits from '%s' (%x)\n", Getattr(j.item, "qname"), j.item);
}
}
}
Printf(stdout, "-------------------------------------------------------------\n");
for (j = First(ttab); j.key; j = Next(j)) {
Printf(stdout, "%40s -> %s\n", j.key, j.item);
}
}
}
static Typetab *SwigType_find_scope(Typetab *s, String *nameprefix) {
Typetab *ss;
String *nnameprefix = 0;
static int check_parent = 1;
/* Printf(stdout,"find_scope: %x(%s) '%s'\n", s, Getattr(s,"name"), nameprefix); */
if (SwigType_istemplate(nameprefix)) {
nnameprefix = SwigType_typedef_resolve_all(nameprefix);
nameprefix = nnameprefix;
}
ss = s;
while (ss) {
String *full;
String *qname = Getattr(ss, "qname");
if (qname) {
full = NewStringf("%s::%s", qname, nameprefix);
} else {
full = NewString(nameprefix);
}
if (Getattr(scopes, full)) {
s = Getattr(scopes, full);
} else {
s = 0;
}
Delete(full);
if (s) {
if (nnameprefix)
Delete(nnameprefix);
return s;
}
if (!s) {
/* Check inheritance */
List *inherit;
inherit = Getattr(ss, "using");
if (inherit) {
Typetab *ttab;
int i, len;
len = Len(inherit);
for (i = 0; i < len; i++) {
int oldcp = check_parent;
ttab = Getitem(inherit, i);
check_parent = 0;
s = SwigType_find_scope(ttab, nameprefix);
check_parent = oldcp;
if (s) {
if (nnameprefix)
Delete(nnameprefix);
return s;
}
}
}
}
if (!check_parent)
break;
ss = Getattr(ss, "parent");
}
if (nnameprefix)
Delete(nnameprefix);
return 0;
}
/* -----------------------------------------------------------------------------
* typedef_resolve()
*
* Resolves a typedef and returns a new type string. Returns 0 if there is no
* typedef mapping. base is a name without qualification.
* Internal function.
* ----------------------------------------------------------------------------- */
static Typetab *resolved_scope = 0;
/* Internal function */
static SwigType *_typedef_resolve(Typetab *s, String *base, int look_parent) {
Hash *ttab;
SwigType *type = 0;
List *inherit;
Typetab *parent;
/* if (!s) return 0; *//* now is checked bellow */
/* Printf(stdout,"Typetab %s : %s\n", Getattr(s,"name"), base); */
if (!Getmark(s)) {
Setmark(s, 1);
ttab = Getattr(s, "typetab");
type = Getattr(ttab, base);
if (type) {
resolved_scope = s;
Setmark(s, 0);
} else {
/* Hmmm. Not found in my scope. It could be in an inherited scope */
inherit = Getattr(s, "inherit");
if (inherit) {
int i, len;
len = Len(inherit);
for (i = 0; i < len; i++) {
type = _typedef_resolve(Getitem(inherit, i), base, 0);
if (type) {
Setmark(s, 0);
break;
}
}
}
if (!type) {
/* Hmmm. Not found in my scope. check parent */
if (look_parent) {
parent = Getattr(s, "parent");
type = parent ? _typedef_resolve(parent, base, 1) : 0;
}
}
Setmark(s, 0);
}
}
return type;
}
static SwigType *typedef_resolve(Typetab *s, String *base) {
return _typedef_resolve(s, base, 1);
}
/* -----------------------------------------------------------------------------
* SwigType_typedef_resolve()
* ----------------------------------------------------------------------------- */
/* #define SWIG_DEBUG */
SwigType *SwigType_typedef_resolve(SwigType *t) {
String *base;
String *type = 0;
String *r = 0;
Typetab *s;
Hash *ttab;
String *namebase = 0;
String *nameprefix = 0;
int newtype = 0;
/*
if (!noscope) {
noscope = NewStringEmpty();
}
*/
resolved_scope = 0;
#ifdef SWIG_TYPEDEF_RESOLVE_CACHE
if (!typedef_resolve_cache) {
typedef_resolve_cache = NewHash();
}
r = Getattr(typedef_resolve_cache, t);
if (r) {
resolved_scope = Getmeta(r, "scope");
return Copy(r);
}
#endif
base = SwigType_base(t);
#ifdef SWIG_DEBUG
Printf(stdout, "base = '%s' t='%s'\n", base, t);
#endif
if (SwigType_issimple(base)) {
s = current_scope;
ttab = current_typetab;
if (strncmp(Char(base), "::", 2) == 0) {
s = global_scope;
ttab = Getattr(s, "typetab");
Delitem(base, 0);
Delitem(base, 0);
}
/* Do a quick check in the local scope */
type = Getattr(ttab, base);
if (type) {
resolved_scope = s;
}
if (!type) {
/* Didn't find in this scope. We need to do a little more searching */
if (Swig_scopename_check(base)) {
/* A qualified name. */
Swig_scopename_split(base, &nameprefix, &namebase);
#ifdef SWIG_DEBUG
Printf(stdout, "nameprefix = '%s'\n", nameprefix);
#endif
if (nameprefix) {
/* Name had a prefix on it. See if we can locate the proper scope for it */
s = SwigType_find_scope(s, nameprefix);
/* Couldn't locate a scope for the type. */
if (!s) {
Delete(base);
Delete(namebase);
Delete(nameprefix);
r = 0;
goto return_result;
}
/* Try to locate the name starting in the scope */
#ifdef SWIG_DEBUG
Printf(stdout, "namebase = '%s'\n", namebase);
#endif
type = typedef_resolve(s, namebase);
if (type) {
/* we need to look for the resolved type, this will also
fix the resolved_scope if 'type' and 'namebase' are
declared in different scopes */
String *rtype = 0;
rtype = typedef_resolve(resolved_scope, type);
if (rtype)
type = rtype;
}
#ifdef SWIG_DEBUG
Printf(stdout, "%s type = '%s'\n", Getattr(s, "name"), type);
#endif
if ((type) && (!Swig_scopename_check(type)) && resolved_scope) {
Typetab *rtab = resolved_scope;
String *qname = Getattr(resolved_scope, "qname");
/* If qualified *and* the typename is defined from the resolved scope, we qualify */
if ((qname) && typedef_resolve(resolved_scope, type)) {
type = Copy(type);
Insert(type, 0, "::");
Insert(type, 0, qname);
#ifdef SWIG_DEBUG
Printf(stdout, "qual %s \n", type);
#endif
newtype = 1;
}
resolved_scope = rtab;
}
} else {
/* Name is unqualified. */
type = typedef_resolve(s, base);
}
} else {
/* Name is unqualified. */
type = typedef_resolve(s, base);
}
}
if (type && (Equal(base, type))) {
if (newtype)
Delete(type);
Delete(base);
Delete(namebase);
Delete(nameprefix);
r = 0;
goto return_result;
}
/* If the type is a template, and no typedef was found, we need to check the
template arguments one by one to see if they can be resolved. */
if (!type && SwigType_istemplate(base)) {
List *tparms;
String *suffix;
int i, sz;
int rep = 0;
type = SwigType_templateprefix(base);
newtype = 1;
suffix = SwigType_templatesuffix(base);
Append(type, "<(");
tparms = SwigType_parmlist(base);
sz = Len(tparms);
for (i = 0; i < sz; i++) {
SwigType *tpr;
SwigType *tp = Getitem(tparms, i);
if (!rep) {
tpr = SwigType_typedef_resolve(tp);
} else {
tpr = 0;
}
if (tpr) {
Append(type, tpr);
Delete(tpr);
rep = 1;
} else {
Append(type, tp);
}
if ((i + 1) < sz)
Append(type, ",");
}
Append(type, ")>");
Append(type, suffix);
Delete(suffix);
Delete(tparms);
if (!rep) {
Delete(type);
type = 0;
}
}
if (namebase)
Delete(namebase);
if (nameprefix)
Delete(nameprefix);
} else {
if (SwigType_isfunction(base)) {
List *parms;
int i, sz;
int rep = 0;
type = NewString("f(");
newtype = 1;
parms = SwigType_parmlist(base);
sz = Len(parms);
for (i = 0; i < sz; i++) {
SwigType *tpr;
SwigType *tp = Getitem(parms, i);
if (!rep) {
tpr = SwigType_typedef_resolve(tp);
} else {
tpr = 0;
}
if (tpr) {
Append(type, tpr);
Delete(tpr);
rep = 1;
} else {
Append(type, tp);
}
if ((i + 1) < sz)
Append(type, ",");
}
Append(type, ").");
Delete(parms);
if (!rep) {
Delete(type);
type = 0;
}
} else if (SwigType_ismemberpointer(base)) {
String *rt;
String *mtype = SwigType_parm(base);
rt = SwigType_typedef_resolve(mtype);
if (rt) {
type = NewStringf("m(%s).", rt);
newtype = 1;
Delete(rt);
}
Delete(mtype);
} else {
type = 0;
}
}
r = SwigType_prefix(t);
if (!type) {
if (r && Len(r)) {
char *cr = Char(r);
if ((strstr(cr, "f(") || (strstr(cr, "m(")))) {
SwigType *rt = SwigType_typedef_resolve(r);
if (rt) {
Delete(r);
Append(rt, base);
Delete(base);
r = rt;
goto return_result;
}
}
}
Delete(r);
Delete(base);
r = 0;
goto return_result;
}
Delete(base);
Append(r, type);
if (newtype) {
Delete(type);
}
return_result:
#ifdef SWIG_TYPEDEF_RESOLVE_CACHE
{
String *key = NewString(t);
if (r) {
SwigType *r1;
Setattr(typedef_resolve_cache, key, r);
Setmeta(r, "scope", resolved_scope);
r1 = Copy(r);
Delete(r);
r = r1;
}
Delete(key);
}
#endif
return r;
}
/* -----------------------------------------------------------------------------
* SwigType_typedef_resolve_all()
*
* Fully resolve a type down to its most basic datatype
* ----------------------------------------------------------------------------- */
SwigType *SwigType_typedef_resolve_all(SwigType *t) {
SwigType *n;
SwigType *r;
/* Check to see if the typedef resolve has been done before by checking the cache */
if (!typedef_all_cache) {
typedef_all_cache = NewHash();
}
r = Getattr(typedef_all_cache, t);
if (r) {
return Copy(r);
}
/* Recursively resolve the typedef */
r = NewString(t);
while ((n = SwigType_typedef_resolve(r))) {
Delete(r);
r = n;
}
/* Add the typedef to the cache for next time it is looked up */
{
String *key;
SwigType *rr = Copy(r);
key = NewString(t);
Setattr(typedef_all_cache, key, rr);
Delete(key);
Delete(rr);
}
return r;
}
/* -----------------------------------------------------------------------------
* SwigType_typedef_qualified()
*
* Given a type declaration, this function tries to fully qualify it according to
* typedef scope rules.
* ----------------------------------------------------------------------------- */
SwigType *SwigType_typedef_qualified(SwigType *t) {
List *elements;
String *result;
int i, len;
if (t && strncmp(Char(t), "::", 2) == 0) {
return Copy(t);
}
if (!typedef_qualified_cache)
typedef_qualified_cache = NewHash();
result = Getattr(typedef_qualified_cache, t);
if (result) {
String *rc = Copy(result);
return rc;
}
result = NewStringEmpty();
elements = SwigType_split(t);
len = Len(elements);
for (i = 0; i < len; i++) {
String *ty = 0;
String *e = Getitem(elements, i);
if (SwigType_issimple(e)) {
if (!SwigType_istemplate(e)) {
String *isenum = 0;
if (SwigType_isenum(e)) {
isenum = NewString("enum ");
ty = NewString(Char(e) + 5);
e = ty;
}
resolved_scope = 0;
if (typedef_resolve(current_scope, e)) {
/* resolved_scope contains the scope that actually resolved the symbol */
String *qname = Getattr(resolved_scope, "qname");
if (qname) {
Insert(e, 0, "::");
Insert(e, 0, qname);
}
} else {
if (Swig_scopename_check(e)) {
String *qlast;
String *qname;
Swig_scopename_split(e, &qname, &qlast);
if (qname) {
String *tqname = SwigType_typedef_qualified(qname);
Clear(e);
Printf(e, "%s::%s", tqname, qlast);
Delete(qname);
Delete(tqname);
}
Delete(qlast);
/* Automatic template instantiation might go here??? */
} else {
/* It's a bare name. It's entirely possible, that the
name is part of a namespace. We'll check this by unrolling
out of the current scope */
Typetab *cs = current_scope;
while (cs) {
String *qs = SwigType_scope_name(cs);
if (Len(qs)) {
Append(qs, "::");
}
Append(qs, e);
if (Getattr(scopes, qs)) {
Clear(e);
Append(e, qs);
Delete(qs);
break;
}
Delete(qs);
cs = Getattr(cs, "parent");
}
}
}
if (isenum) {
Insert(e, 0, isenum);
Delete(isenum);
}
} else {
/* Template. We need to qualify template parameters as well as the template itself */
String *tprefix, *qprefix;
String *tsuffix;
Iterator pi;
Parm *p;
List *parms;
ty = Swig_symbol_template_deftype(e, current_symtab);
e = ty;
parms = SwigType_parmlist(e);
tprefix = SwigType_templateprefix(e);
tsuffix = SwigType_templatesuffix(e);
qprefix = SwigType_typedef_qualified(tprefix);
Append(qprefix, "<(");
pi = First(parms);
while ((p = pi.item)) {
String *qt = SwigType_typedef_qualified(p);
if (Equal(qt, p)) { /* && (!Swig_scopename_check(qt))) */
/* No change in value. It is entirely possible that the parameter is an integer value.
If there is a symbol table associated with this scope, we're going to check for this */
if (current_symtab) {
Node *lastnode = 0;
String *value = Copy(p);
while (1) {
Node *n = Swig_symbol_clookup(value, current_symtab);
if (n == lastnode)
break;
lastnode = n;
if (n) {
char *ntype = Char(nodeType(n));
if (strcmp(ntype, "enumitem") == 0) {
/* An enum item. Generate a fully qualified name */
String *qn = Swig_symbol_qualified(n);
if (Len(qn)) {
Append(qn, "::");
Append(qn, Getattr(n, "name"));
Delete(value);
value = qn;
continue;
} else {
Delete(qn);
break;
}
} else if ((strcmp(ntype, "cdecl") == 0) && (Getattr(n, "value"))) {
Delete(value);
value = Copy(Getattr(n, "value"));
continue;
}
}
break;
}
Append(qprefix, value);
Delete(value);
} else {
Append(qprefix, p);
}
} else {
Append(qprefix, qt);
}
Delete(qt);
pi = Next(pi);
if (pi.item) {
Append(qprefix, ",");
}
}
Append(qprefix, ")>");
Append(qprefix, tsuffix);
Delete(tsuffix);
Clear(e);
Append(e, qprefix);
Delete(tprefix);
Delete(qprefix);
Delete(parms);
}
if (strncmp(Char(e), "::", 2) == 0) {
Delitem(e, 0);
Delitem(e, 0);
}
Append(result, e);
Delete(ty);
} else if (SwigType_isfunction(e)) {
List *parms = SwigType_parmlist(e);
String *s = NewString("f(");
Iterator pi;
pi = First(parms);
while (pi.item) {
String *pq = SwigType_typedef_qualified(pi.item);
Append(s, pq);
Delete(pq);
pi = Next(pi);
if (pi.item) {
Append(s, ",");
}
}
Append(s, ").");
Append(result, s);
Delete(s);
Delete(parms);
} else if (SwigType_isarray(e)) {
String *ndim;
String *dim = SwigType_parm(e);
ndim = Swig_symbol_string_qualify(dim, 0);
Printf(result, "a(%s).", ndim);
Delete(dim);
Delete(ndim);
} else {
Append(result, e);
}
}
Delete(elements);
{
String *key, *cresult;
key = NewString(t);
cresult = NewString(result);
Setattr(typedef_qualified_cache, key, cresult);
Delete(key);
Delete(cresult);
}
return result;
}
/* -----------------------------------------------------------------------------
* SwigType_istypedef()
*
* Checks a typename to see if it is a typedef.
* ----------------------------------------------------------------------------- */
int SwigType_istypedef(SwigType *t) {
String *type;
type = SwigType_typedef_resolve(t);
if (type) {
Delete(type);
return 1;
} else {
return 0;
}
}
/* -----------------------------------------------------------------------------
* SwigType_typedef_using()
*
* Processes a 'using' declaration to import types from one scope into another.
* Name is a qualified name like A::B.
* ----------------------------------------------------------------------------- */
int SwigType_typedef_using(String_or_char *name) {
String *base;
String *td;
String *prefix;
Typetab *s;
Typetab *tt = 0;
String *defined_name = 0;
/* Printf(stdout,"using %s\n", name); */
if (!Swig_scopename_check(name))
return -1; /* Not properly qualified */
base = Swig_scopename_last(name);
/* See if the base is already defined in this scope */
if (Getattr(current_typetab, base)) {
Delete(base);
return -1;
}
/* See if the using name is a scope */
/* tt = SwigType_find_scope(current_scope,name);
Printf(stdout,"tt = %x, name = '%s'\n", tt, name); */
/* We set up a typedef B --> A::B */
Setattr(current_typetab, base, name);
/* Find the scope name where the symbol is defined */
td = SwigType_typedef_resolve(name);
/* Printf(stdout,"td = '%s' %x\n", td, resolved_scope); */
if (resolved_scope) {
defined_name = Getattr(resolved_scope, "qname");
if (defined_name) {
defined_name = Copy(defined_name);
Append(defined_name, "::");
Append(defined_name, base);
/* Printf(stdout,"defined_name = '%s'\n", defined_name); */
tt = SwigType_find_scope(current_scope, defined_name);
}
}
if (td)
Delete(td);
/* Figure out the scope the using directive refers to */
{
prefix = Swig_scopename_prefix(name);
s = SwigType_find_scope(current_scope, prefix);
if (s) {
Hash *ttab = Getattr(s, "typetab");
if (!Getattr(ttab, base) && defined_name) {
Setattr(ttab, base, defined_name);
}
}
}
if (tt) {
/* Using directive had its own scope. We need to create a new scope for it */
SwigType_new_scope(base);
SwigType_inherit_scope(tt);
SwigType_pop_scope();
}
if (defined_name)
Delete(defined_name);
Delete(prefix);
Delete(base);
return 0;
}
/* -----------------------------------------------------------------------------
* SwigType_isclass()
*
* Determines if a type defines a class or not. A class is defined by
* its type-table entry maps to itself. Note: a pointer to a class is not
* a class.
* ----------------------------------------------------------------------------- */
int SwigType_isclass(SwigType *t) {
SwigType *qty, *qtys;
int isclass = 0;
qty = SwigType_typedef_resolve_all(t);
qtys = SwigType_strip_qualifiers(qty);
if (SwigType_issimple(qtys)) {
String *td = SwigType_typedef_resolve(qtys);
if (td) {
Delete(td);
}
if (resolved_scope) {
isclass = 1;
}
/* Hmmm. Not a class. If a template, it might be uninstantiated */
if (!isclass && SwigType_istemplate(qtys)) {
String *tp = SwigType_templateprefix(qtys);
if (Strcmp(tp, t) != 0) {
isclass = SwigType_isclass(tp);
}
Delete(tp);
}
}
Delete(qty);
Delete(qtys);
return isclass;
}
/* -----------------------------------------------------------------------------
* SwigType_type()
*
* Returns an integer code describing the datatype. This is only used for
* compatibility with SWIG1.1 language modules and is likely to go away once
* everything is based on typemaps.
* ----------------------------------------------------------------------------- */
int SwigType_type(SwigType *t) {
char *c;
/* Check for the obvious stuff */
c = Char(t);
if (strncmp(c, "p.", 2) == 0) {
if (SwigType_type(c + 2) == T_CHAR)
return T_STRING;
else
return T_POINTER;
}
if (strncmp(c, "a(", 2) == 0)
return T_ARRAY;
if (strncmp(c, "r.", 2) == 0)
return T_REFERENCE;
if (strncmp(c, "m(", 2) == 0)
return T_MPOINTER;
if (strncmp(c, "q(", 2) == 0) {
while (*c && (*c != '.'))
c++;
if (*c)
return SwigType_type(c + 1);
return T_ERROR;
}
if (strncmp(c, "f(", 2) == 0)
return T_FUNCTION;
/* Look for basic types */
if (strcmp(c, "int") == 0)
return T_INT;
if (strcmp(c, "long") == 0)
return T_LONG;
if (strcmp(c, "short") == 0)
return T_SHORT;
if (strcmp(c, "unsigned") == 0)
return T_UINT;
if (strcmp(c, "unsigned short") == 0)
return T_USHORT;
if (strcmp(c, "unsigned long") == 0)
return T_ULONG;
if (strcmp(c, "unsigned int") == 0)
return T_UINT;
if (strcmp(c, "char") == 0)
return T_CHAR;
if (strcmp(c, "signed char") == 0)
return T_SCHAR;
if (strcmp(c, "unsigned char") == 0)
return T_UCHAR;
if (strcmp(c, "float") == 0)
return T_FLOAT;
if (strcmp(c, "double") == 0)
return T_DOUBLE;
if (strcmp(c, "long double") == 0)
return T_LONGDOUBLE;
if (!cparse_cplusplus && (strcmp(c, "float complex") == 0))
return T_FLTCPLX;
if (!cparse_cplusplus && (strcmp(c, "double complex") == 0))
return T_DBLCPLX;
if (!cparse_cplusplus && (strcmp(c, "complex") == 0))
return T_COMPLEX;
if (strcmp(c, "void") == 0)
return T_VOID;
if (strcmp(c, "bool") == 0)
return T_BOOL;
if (strcmp(c, "long long") == 0)
return T_LONGLONG;
if (strcmp(c, "unsigned long long") == 0)
return T_ULONGLONG;
if (strncmp(c, "enum ", 5) == 0)
return T_INT;
if (strcmp(c, "v(...)") == 0)
return T_VARARGS;
/* Hmmm. Unknown type */
if (SwigType_istypedef(t)) {
int r;
SwigType *nt = SwigType_typedef_resolve(t);
r = SwigType_type(nt);
Delete(nt);
return r;
}
return T_USER;
}
/* -----------------------------------------------------------------------------
* SwigType_alttype()
*
* Returns the alternative value type needed in C++ for class value
* types. When swig is not sure about using a plain $ltype value,
* since the class doesn't have a default constructor, or it can't be
* assigned, you will get back 'SwigValueWrapper<type >'.
*
* This is the default behavior unless:
*
* 1.- swig detects a default_constructor and 'setallocate:default_constructor'
* attribute.
*
* 2.- swig doesn't mark 'type' as non-assignable.
*
* 3.- the user specify that the value wrapper is not needed by using
* the %feature("novaluewrapper"), in that case the user need to type
*
* %feature("novaluewrapper") MyOpaqueClass;
* class MyOpaqueClass;
*
* Users can also force the use of the value wrapper by using the
* %feature("valuewrapper").
* ----------------------------------------------------------------------------- */
SwigType *SwigType_alttype(SwigType *t, int local_tmap) {
Node *n;
SwigType *w = 0;
int use_wrapper = 0;
SwigType *td = 0;
if (!cparse_cplusplus)
return 0;
if (value_wrapper_mode == 0) {
/* old partial use of SwigValueTypes, it can fail for opaque types */
if (local_tmap)
return 0;
if (SwigType_isclass(t)) {
SwigType *ftd = SwigType_typedef_resolve_all(t);
td = SwigType_strip_qualifiers(ftd);
Delete(ftd);
n = Swig_symbol_clookup(td, 0);
if (n) {
if (GetFlag(n, "feature:valuewrapper")) {
use_wrapper = 1;
} else {
if (Checkattr(n, "nodeType", "class")
&& (!Getattr(n, "allocate:default_constructor")
|| (Getattr(n, "allocate:noassign")))) {
use_wrapper = !GetFlag(n, "feature:novaluewrapper") || GetFlag(n, "feature:nodefault");
}
}
} else {
if (SwigType_issimple(td) && SwigType_istemplate(td)) {
use_wrapper = !n || !GetFlag(n, "feature:novaluewrapper");
}
}
}
} else {
/* safe use of SwigValueTypes, it can fail with some typemaps */
SwigType *ftd = SwigType_typedef_resolve_all(t);
td = SwigType_strip_qualifiers(ftd);
Delete(ftd);
if (SwigType_type(td) == T_USER) {
use_wrapper = 1;
n = Swig_symbol_clookup(td, 0);
if (n) {
if ((Checkattr(n, "nodeType", "class")
&& !Getattr(n, "allocate:noassign")
&& (Getattr(n, "allocate:default_constructor")))
|| (GetFlag(n, "feature:novaluewrapper"))) {
use_wrapper = GetFlag(n, "feature:valuewrapper");
}
}
}
}
if (use_wrapper) {
/* Need a space before the type in case it starts "::" (since the <:
* token is a digraph for [ in C++. Also need a space after the
* type in case it ends with ">" since then we form the token ">>".
*/
w = NewStringf("SwigValueWrapper< %s >", td);
}
Delete(td);
return w;
}
/* ----------------------------------------------------------------------------
* * * * WARNING * * * ***
* ***
* Don't even think about modifying anything below this line unless you ***
* are completely on top of *EVERY* subtle aspect of the C++ type system ***
* and you are prepared to suffer endless hours of agony trying to ***
* debug the SWIG run-time type checker after you break it. ***
* ------------------------------------------------------------------------- */
/* -----------------------------------------------------------------------------
* SwigType_remember()
*
* This function "remembers" a datatype that was used during wrapper code generation
* so that a type-checking table can be generated later on. It is up to the language
* modules to actually call this function--it is not done automatically.
*
* Type tracking is managed through two separate hash tables. The hash 'r_mangled'
* is mapping between mangled type names (used in the target language) and
* fully-resolved C datatypes used in the source input. The second hash 'r_resolved'
* is the inverse mapping that maps fully-resolved C datatypes to all of the mangled
* names in the scripting languages. For example, consider the following set of
* typedef declarations:
*
* typedef double Real;
* typedef double Float;
* typedef double Point[3];
*
* Now, suppose that the types 'double *', 'Real *', 'Float *', 'double[3]', and
* 'Point' were used in an interface file and "remembered" using this function.
* The hash tables would look like this:
*
* r_mangled {
* _p_double : [ p.double, a(3).double ]
* _p_Real : [ p.double ]
* _p_Float : [ p.double ]
* _Point : [ a(3).double ]
*
* r_resolved {
* p.double : [ _p_double, _p_Real, _p_Float ]
* a(3).double : [ _p_double, _Point ]
* }
*
* Together these two hash tables can be used to determine type-equivalency between
* mangled typenames. To do this, we view the two hash tables as a large graph and
* compute the transitive closure.
* ----------------------------------------------------------------------------- */
static Hash *r_mangled = 0; /* Hash mapping mangled types to fully resolved types */
static Hash *r_resolved = 0; /* Hash mapping resolved types to mangled types */
static Hash *r_ltype = 0; /* Hash mapping mangled names to their local c type */
static Hash *r_clientdata = 0; /* Hash mapping resolved types to client data */
static Hash *r_mangleddata = 0; /* Hash mapping mangled types to client data */
static Hash *r_remembered = 0; /* Hash of types we remembered already */
static void (*r_tracefunc) (SwigType *t, String *mangled, String *clientdata) = 0;
void SwigType_remember_mangleddata(String *mangled, const String_or_char *clientdata) {
if (!r_mangleddata) {
r_mangleddata = NewHash();
}
Setattr(r_mangleddata, mangled, clientdata);
}
void SwigType_remember_clientdata(SwigType *t, const String_or_char *clientdata) {
String *mt;
SwigType *lt;
Hash *h;
SwigType *fr;
SwigType *qr;
String *tkey;
String *cd;
Hash *lthash;
if (!r_mangled) {
r_mangled = NewHash();
r_resolved = NewHash();
r_ltype = NewHash();
r_clientdata = NewHash();
r_remembered = NewHash();
}
{
String *last;
last = Getattr(r_remembered, t);
if (last && (Cmp(last, clientdata) == 0))
return;
}
tkey = Copy(t);
cd = clientdata ? NewString(clientdata) : NewStringEmpty();
Setattr(r_remembered, tkey, cd);
Delete(tkey);
Delete(cd);
mt = SwigType_manglestr(t); /* Create mangled string */
if (r_tracefunc) {
(*r_tracefunc) (t, mt, (String *) clientdata);
}
if (SwigType_istypedef(t)) {
lt = Copy(t);
} else {
lt = SwigType_ltype(t);
}
lthash = Getattr(r_ltype, mt);
if (!lthash) {
lthash = NewHash();
Setattr(r_ltype, mt, lthash);
}
Setattr(lthash, lt, "1");
Delete(lt);
fr = SwigType_typedef_resolve_all(t); /* Create fully resolved type */
qr = SwigType_typedef_qualified(fr);
Delete(fr);
/* Added to deal with possible table bug */
fr = SwigType_strip_qualifiers(qr);
Delete(qr);
/*Printf(stdout,"t = '%s'\n", t);
Printf(stdout,"fr= '%s'\n\n", fr); */
if (t) {
char *ct = Char(t);
if (strchr(ct, '<') && !(strstr(ct, "<("))) {
Printf(stdout, "Bad template type passed to SwigType_remember: %s\n", t);
assert(0);
}
}
h = Getattr(r_mangled, mt);
if (!h) {
h = NewHash();
Setattr(r_mangled, mt, h);
Delete(h);
}
Setattr(h, fr, mt);
h = Getattr(r_resolved, fr);
if (!h) {
h = NewHash();
Setattr(r_resolved, fr, h);
Delete(h);
}
Setattr(h, mt, fr);
if (clientdata) {
String *cd = Getattr(r_clientdata, fr);
if (cd) {
if (Strcmp(clientdata, cd) != 0) {
Printf(stderr, "*** Internal error. Inconsistent clientdata for type '%s'\n", SwigType_str(fr, 0));
Printf(stderr, "*** '%s' != '%s'\n", clientdata, cd);
assert(0);
}
} else {
String *cstr = NewString(clientdata);
Setattr(r_clientdata, fr, cstr);
Delete(cstr);
}
}
/* If the remembered type is a reference, we also remember the pointer version.
This is to prevent odd problems with mixing pointers and references--especially
when different functions are using different typenames (via typedef). */
if (SwigType_isreference(t)) {
SwigType *tt = Copy(t);
SwigType_del_reference(tt);
SwigType_add_pointer(tt);
SwigType_remember_clientdata(tt, clientdata);
}
}
void SwigType_remember(SwigType *ty) {
SwigType_remember_clientdata(ty, 0);
}
void (*SwigType_remember_trace(void (*tf) (SwigType *, String *, String *))) (SwigType *, String *, String *) {
void (*o) (SwigType *, String *, String *) = r_tracefunc;
r_tracefunc = tf;
return o;
}
/* -----------------------------------------------------------------------------
* SwigType_equivalent_mangle()
*
* Return a list of all of the mangled typenames that are equivalent to another
* mangled name. This works as follows: For each fully qualified C datatype
* in the r_mangled hash entry, we collect all of the mangled names from the
* r_resolved hash and combine them together in a list (removing duplicate entries).
* ----------------------------------------------------------------------------- */
List *SwigType_equivalent_mangle(String *ms, Hash *checked, Hash *found) {
List *l;
Hash *h;
Hash *ch;
Hash *mh;
if (found) {
h = found;
} else {
h = NewHash();
}
if (checked) {
ch = checked;
} else {
ch = NewHash();
}
if (Getattr(ch, ms))
goto check_exit; /* Already checked this type */
Setattr(h, ms, "1");
Setattr(ch, ms, "1");
mh = Getattr(r_mangled, ms);
if (mh) {
Iterator ki;
ki = First(mh);
while (ki.key) {
Hash *rh;
if (Getattr(ch, ki.key)) {
ki = Next(ki);
continue;
}
Setattr(ch, ki.key, "1");
rh = Getattr(r_resolved, ki.key);
if (rh) {
Iterator rk;
rk = First(rh);
while (rk.key) {
Setattr(h, rk.key, "1");
SwigType_equivalent_mangle(rk.key, ch, h);
rk = Next(rk);
}
}
ki = Next(ki);
}
}
check_exit:
if (!found) {
l = Keys(h);
Delete(h);
Delete(ch);
return l;
} else {
return 0;
}
}
/* -----------------------------------------------------------------------------
* SwigType_clientdata_collect()
*
* Returns the clientdata field for a mangled type-string.
* ----------------------------------------------------------------------------- */
static
String *SwigType_clientdata_collect(String *ms) {
Hash *mh;
String *clientdata = 0;
if (r_mangleddata) {
clientdata = Getattr(r_mangleddata, ms);
if (clientdata)
return clientdata;
}
mh = Getattr(r_mangled, ms);
if (mh) {
Iterator ki;
ki = First(mh);
while (ki.key) {
clientdata = Getattr(r_clientdata, ki.key);
if (clientdata)
break;
ki = Next(ki);
}
}
return clientdata;
}
/* -----------------------------------------------------------------------------
* SwigType_inherit()
*
* Record information about inheritance. We keep a hash table that keeps
* a mapping between base classes and all of the classes that are derived
* from them.
*
* subclass is a hash that maps base-classes to all of the classes derived from them.
*
* derived - name of derived class
* base - name of base class
* cast - additional casting code when casting from derived to base
* conversioncode - if set, overrides the default code in the function when casting
* from derived to base
* ----------------------------------------------------------------------------- */
static Hash *subclass = 0;
static Hash *conversions = 0;
void SwigType_inherit(String *derived, String *base, String *cast, String *conversioncode) {
Hash *h;
String *dd = 0;
String *bb = 0;
if (!subclass)
subclass = NewHash();
/* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */
if (SwigType_istemplate(derived)) {
String *ty = SwigType_typedef_resolve_all(derived);
dd = SwigType_typedef_qualified(ty);
derived = dd;
Delete(ty);
}
if (SwigType_istemplate(base)) {
String *ty = SwigType_typedef_resolve_all(base);
bb = SwigType_typedef_qualified(ty);
base = bb;
Delete(ty);
}
/* Printf(stdout,"'%s' --> '%s' '%s'\n", derived, base, cast); */
h = Getattr(subclass, base);
if (!h) {
h = NewHash();
Setattr(subclass, base, h);
Delete(h);
}
if (!Getattr(h, derived)) {
Hash *c = NewHash();
if (cast)
Setattr(c, "cast", cast);
if (conversioncode)
Setattr(c, "convcode", conversioncode);
Setattr(h, derived, c);
Delete(c);
}
Delete(dd);
Delete(bb);
}
/* -----------------------------------------------------------------------------
* SwigType_issubtype()
*
* Determines if a t1 is a subtype of t2, ie, is t1 derived from t2
* ----------------------------------------------------------------------------- */
int SwigType_issubtype(SwigType *t1, SwigType *t2) {
SwigType *ft1, *ft2;
String *b1, *b2;
Hash *h;
int r = 0;
if (!subclass)
return 0;
ft1 = SwigType_typedef_resolve_all(t1);
ft2 = SwigType_typedef_resolve_all(t2);
b1 = SwigType_base(ft1);
b2 = SwigType_base(ft2);
h = Getattr(subclass, b2);
if (h) {
if (Getattr(h, b1)) {
r = 1;
}
}
Delete(ft1);
Delete(ft2);
Delete(b1);
Delete(b2);
/* Printf(stdout, "issubtype(%s,%s) --> %d\n", t1, t2, r); */
return r;
}
/* -----------------------------------------------------------------------------
* SwigType_inherit_equiv()
*
* Modify the type table to handle C++ inheritance
* ----------------------------------------------------------------------------- */
void SwigType_inherit_equiv(File *out) {
String *ckey;
String *prefix, *base;
String *mprefix, *mkey;
Hash *sub;
Hash *rh;
List *rlist;
Iterator rk, bk, ck;
if (!conversions)
conversions = NewHash();
if (!subclass)
subclass = NewHash();
rk = First(r_resolved);
while (rk.key) {
/* rkey is a fully qualified type. We strip all of the type constructors off of it just to get the base */
base = SwigType_base(rk.key);
/* Check to see whether the base is recorded in the subclass table */
sub = Getattr(subclass, base);
Delete(base);
if (!sub) {
rk = Next(rk);
continue;
}
/* This type has subclasses. We now need to walk through these subtypes and generate pointer converion functions */
rh = Getattr(r_resolved, rk.key);
rlist = NewList();
for (ck = First(rh); ck.key; ck = Next(ck)) {
Append(rlist, ck.key);
}
/* Printf(stdout,"rk.key = '%s'\n", rk.key);
Printf(stdout,"rh = %x '%s'\n", rh,rh); */
bk = First(sub);
while (bk.key) {
prefix = SwigType_prefix(rk.key);
Append(prefix, bk.key);
/* Printf(stdout,"set %x = '%s' : '%s'\n", rh, SwigType_manglestr(prefix),prefix); */
mprefix = SwigType_manglestr(prefix);
Setattr(rh, mprefix, prefix);
mkey = SwigType_manglestr(rk.key);
ckey = NewStringf("%s+%s", mprefix, mkey);
if (!Getattr(conversions, ckey)) {
String *convname = NewStringf("%sTo%s", mprefix, mkey);
String *lkey = SwigType_lstr(rk.key, 0);
String *lprefix = SwigType_lstr(prefix, 0);
Hash *subhash = Getattr(sub, bk.key);
String *convcode = Getattr(subhash, "convcode");
if (convcode) {
char *newmemoryused = Strstr(convcode, "newmemory"); /* see if newmemory parameter is used in order to avoid unused parameter warnings */
String *fn = Copy(convcode);
Replaceall(fn, "$from", "x");
Printf(out, "static void *%s(void *x, int *%s) {", convname, newmemoryused ? "newmemory" : "SWIGUNUSEDPARM(newmemory)");
Printf(out, "%s", fn);
} else {
String *cast = Getattr(subhash, "cast");
Printf(out, "static void *%s(void *x, int *SWIGUNUSEDPARM(newmemory)) {", convname);
Printf(out, "\n return (void *)((%s) ", lkey);
if (cast)
Printf(out, "%s", cast);
Printf(out, " ((%s) x));\n", lprefix);
}
Printf(out, "}\n");
Setattr(conversions, ckey, convname);
Delete(ckey);
Delete(lkey);
Delete(lprefix);
/* This inserts conversions for typedefs */
{
Hash *r = Getattr(r_resolved, prefix);
if (r) {
Iterator rrk;
rrk = First(r);
while (rrk.key) {
Iterator rlk;
String *rkeymangle;
/* Make sure this name equivalence is not due to inheritance */
if (Cmp(prefix, Getattr(r, rrk.key)) == 0) {
rkeymangle = Copy(mkey);
ckey = NewStringf("%s+%s", rrk.key, rkeymangle);
if (!Getattr(conversions, ckey)) {
Setattr(conversions, ckey, convname);
}
Delete(ckey);
for (rlk = First(rlist); rlk.item; rlk = Next(rlk)) {
ckey = NewStringf("%s+%s", rrk.key, rlk.item);
Setattr(conversions, ckey, convname);
Delete(ckey);
}
Delete(rkeymangle);
/* This is needed to pick up other alternative names for the same type.
Needed to make templates work */
Setattr(rh, rrk.key, rrk.item);
}
rrk = Next(rrk);
}
}
}
Delete(convname);
}
Delete(prefix);
Delete(mprefix);
Delete(mkey);
bk = Next(bk);
}
rk = Next(rk);
Delete(rlist);
}
}
/* Helper function to sort the mangled list */
static int SwigType_compare_mangled(const DOH *a, const DOH *b) {
return strcmp((char *) Data(a), (char *) Data(b));
}
/* -----------------------------------------------------------------------------
* SwigType_get_sorted_mangled_list()
*
* Returns the sorted list of mangled type names that should be exported into the
* wrapper file.
* ----------------------------------------------------------------------------- */
List *SwigType_get_sorted_mangled_list() {
List *l = Keys(r_mangled);
SortList(l, SwigType_compare_mangled);
return l;
}
/* -----------------------------------------------------------------------------
* SwigType_type_table()
*
* Generate the type-table for the type-checker.
* ----------------------------------------------------------------------------- */
void SwigType_emit_type_table(File *f_forward, File *f_table) {
Iterator ki;
String *types, *table, *cast, *cast_init, *cast_temp;
Hash *imported_types;
List *mangled_list;
List *table_list = NewList();
int i = 0;
if (!r_mangled) {
r_mangled = NewHash();
r_resolved = NewHash();
}
Printf(f_table, "\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */\n\n");
SwigType_inherit_equiv(f_table);
/*#define DEBUG 1*/
#ifdef DEBUG
Printf(stdout, "---r_mangled---\n");
Printf(stdout, "%s\n", r_mangled);
Printf(stdout, "---r_resolved---\n");
Printf(stdout, "%s\n", r_resolved);
Printf(stdout, "---r_ltype---\n");
Printf(stdout, "%s\n", r_ltype);
Printf(stdout, "---subclass---\n");
Printf(stdout, "%s\n", subclass);
Printf(stdout, "---conversions---\n");
Printf(stdout, "%s\n", conversions);
Printf(stdout, "---r_clientdata---\n");
Printf(stdout, "%s\n", r_clientdata);
#endif
table = NewStringEmpty();
types = NewStringEmpty();
cast = NewStringEmpty();
cast_init = NewStringEmpty();
imported_types = NewHash();
Printf(table, "static swig_type_info *swig_type_initial[] = {\n");
Printf(cast_init, "static swig_cast_info *swig_cast_initial[] = {\n");
Printf(f_forward, "\n/* -------- TYPES TABLE (BEGIN) -------- */\n\n");
mangled_list = SwigType_get_sorted_mangled_list();
for (ki = First(mangled_list); ki.item; ki = Next(ki)) {
List *el;
Iterator ei;
SwigType *lt;
SwigType *rt = 0;
String *nt;
String *ln;
String *rn;
const String *cd;
Hash *lthash;
Iterator ltiter;
Hash *nthash;
cast_temp = NewStringEmpty();
Printv(types, "static swig_type_info _swigt_", ki.item, " = {", NIL);
Append(table_list, ki.item);
Printf(cast_temp, "static swig_cast_info _swigc_%s[] = {", ki.item);
i++;
cd = SwigType_clientdata_collect(ki.item);
if (!cd)
cd = "0";
lthash = Getattr(r_ltype, ki.item);
nt = 0;
nthash = NewHash();
ltiter = First(lthash);
while (ltiter.key) {
lt = ltiter.key;
rt = SwigType_typedef_resolve_all(lt);
/* we save the original type and the fully resolved version */
ln = SwigType_lstr(lt, 0);
rn = SwigType_lstr(rt, 0);
if (Equal(ln, rn)) {
Setattr(nthash, ln, "1");
} else {
Setattr(nthash, rn, "1");
Setattr(nthash, ln, "1");
}
if (SwigType_istemplate(rt)) {
String *dt = Swig_symbol_template_deftype(rt, 0);
String *dn = SwigType_lstr(dt, 0);
if (!Equal(dn, rn) && !Equal(dn, ln)) {
Setattr(nthash, dn, "1");
}
Delete(dt);
Delete(dn);
}
ltiter = Next(ltiter);
}
/* now build nt */
ltiter = First(nthash);
nt = 0;
while (ltiter.key) {
if (nt) {
Printf(nt, "|%s", ltiter.key);
} else {
nt = NewString(ltiter.key);
}
ltiter = Next(ltiter);
}
Delete(nthash);
Printf(types, "\"%s\", \"%s\", 0, 0, (void*)%s, 0};\n", ki.item, nt, cd);
el = SwigType_equivalent_mangle(ki.item, 0, 0);
for (ei = First(el); ei.item; ei = Next(ei)) {
String *ckey;
String *conv;
ckey = NewStringf("%s+%s", ei.item, ki.item);
conv = Getattr(conversions, ckey);
if (conv) {
Printf(cast_temp, " {&_swigt_%s, %s, 0, 0},", ei.item, conv);
} else {
Printf(cast_temp, " {&_swigt_%s, 0, 0, 0},", ei.item);
}
Delete(ckey);
if (!Getattr(r_mangled, ei.item) && !Getattr(imported_types, ei.item)) {
Printf(types, "static swig_type_info _swigt_%s = {\"%s\", 0, 0, 0, 0, 0};\n", ei.item, ei.item);
Append(table_list, ei.item);
Printf(cast, "static swig_cast_info _swigc_%s[] = {{&_swigt_%s, 0, 0, 0},{0, 0, 0, 0}};\n", ei.item, ei.item);
i++;
Setattr(imported_types, ei.item, "1");
}
}
Delete(el);
Printf(cast, "%s{0, 0, 0, 0}};\n", cast_temp);
Delete(cast_temp);
Delete(nt);
Delete(rt);
}
/* print the tables in the proper order */
SortList(table_list, SwigType_compare_mangled);
i = 0;
for (ki = First(table_list); ki.item; ki = Next(ki)) {
Printf(f_forward, "#define SWIGTYPE%s swig_types[%d]\n", ki.item, i++);
Printf(table, " &_swigt_%s,\n", ki.item);
Printf(cast_init, " _swigc_%s,\n", ki.item);
}
if (i == 0) {
/* empty arrays are not allowed by ISO C */
Printf(table, " NULL\n");
Printf(cast_init, " NULL\n");
}
Delete(table_list);
Delete(mangled_list);
Printf(table, "};\n");
Printf(cast_init, "};\n");
Printf(f_table, "%s\n", types);
Printf(f_table, "%s\n", table);
Printf(f_table, "%s\n", cast);
Printf(f_table, "%s\n", cast_init);
Printf(f_table, "\n/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */\n\n");
Printf(f_forward, "static swig_type_info *swig_types[%d];\n", i + 1);
Printf(f_forward, "static swig_module_info swig_module = {swig_types, %d, 0, 0, 0, 0};\n", i);
Printf(f_forward, "#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)\n");
Printf(f_forward, "#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)\n");
Printf(f_forward, "\n/* -------- TYPES TABLE (END) -------- */\n\n");
Delete(types);
Delete(table);
Delete(cast);
Delete(cast_init);
Delete(imported_types);
}