summaryrefslogtreecommitdiff
path: root/Source
diff options
context:
space:
mode:
Diffstat (limited to 'Source')
-rw-r--r--Source/CParse/cscanner.c105
-rw-r--r--Source/CParse/parser.y45
-rw-r--r--Source/DOH/base.c2
-rw-r--r--Source/DOH/doh.h12
-rw-r--r--Source/DOH/dohint.h4
-rw-r--r--Source/DOH/file.c2
-rw-r--r--Source/DOH/hash.c55
-rw-r--r--Source/DOH/list.c2
-rw-r--r--Source/DOH/string.c70
-rw-r--r--Source/Include/swigwarn.h32
-rw-r--r--Source/Makefile.am1
-rw-r--r--Source/Modules/allocate.cxx8
-rw-r--r--Source/Modules/clisp.cxx16
-rw-r--r--Source/Modules/csharp.cxx82
-rw-r--r--Source/Modules/d.cxx4351
-rw-r--r--Source/Modules/go.cxx59
-rw-r--r--Source/Modules/java.cxx32
-rw-r--r--Source/Modules/lang.cxx36
-rw-r--r--Source/Modules/lua.cxx2
-rw-r--r--Source/Modules/main.cxx16
-rw-r--r--Source/Modules/modula3.cxx11
-rw-r--r--Source/Modules/mzscheme.cxx2
-rw-r--r--Source/Modules/ocaml.cxx45
-rw-r--r--Source/Modules/php.cxx21
-rw-r--r--Source/Modules/python.cxx6
-rw-r--r--Source/Modules/r.cxx17
-rw-r--r--Source/Modules/ruby.cxx13
-rw-r--r--Source/Modules/swigmain.cxx2
-rw-r--r--Source/Modules/swigmod.h11
-rw-r--r--Source/Modules/tcl8.cxx5
-rw-r--r--Source/Modules/typepass.cxx23
-rw-r--r--Source/Modules/utils.cxx113
-rw-r--r--Source/Preprocessor/cpp.c321
-rw-r--r--Source/Swig/cwrap.c42
-rw-r--r--Source/Swig/error.c35
-rw-r--r--Source/Swig/include.c2
-rw-r--r--Source/Swig/misc.c219
-rw-r--r--Source/Swig/naming.c111
-rw-r--r--Source/Swig/scanner.c159
-rw-r--r--Source/Swig/stype.c209
-rw-r--r--Source/Swig/swig.h93
-rw-r--r--Source/Swig/swigscan.h2
-rw-r--r--Source/Swig/symbol.c2
-rw-r--r--Source/Swig/tree.c8
-rw-r--r--Source/Swig/typemap.c20
-rw-r--r--Source/Swig/typeobj.c30
-rw-r--r--Source/Swig/typesys.c37
47 files changed, 5721 insertions, 770 deletions
diff --git a/Source/CParse/cscanner.c b/Source/CParse/cscanner.c
index f88841c09..bf684c4cc 100644
--- a/Source/CParse/cscanner.c
+++ b/Source/CParse/cscanner.c
@@ -45,8 +45,6 @@ static int num_brace = 0;
static int last_brace = 0;
static int last_id = 0;
static int rename_active = 0;
-static int expanding_macro = 0;
-static int follow_locators = 0;
/* -----------------------------------------------------------------------------
* Swig_cparse_cplusplus()
@@ -56,101 +54,6 @@ void Swig_cparse_cplusplus(int v) {
cparse_cplusplus = v;
}
-/* ----------------------------------------------------------------------
- * locator()
- *
- * Support for locator strings. These are strings of the form
- * @SWIG:filename,line,id@ emitted by the SWIG preprocessor. They
- * are primarily used for macro line number reporting
- * ---------------------------------------------------------------------- */
-
-typedef struct Locator {
- String *filename;
- int line_number;
- struct Locator *next;
-} Locator;
-
-static Locator *locs = 0;
-
-/* we just use the locator to mark when active/deactive the linecounting */
-
-static void scanner_locator(String *loc) {
- if (!follow_locators) {
- if (Equal(loc, "/*@SWIG@*/")) {
- /* End locator. */
- if (expanding_macro)
- --expanding_macro;
- } else {
- /* Begin locator. */
- ++expanding_macro;
- }
- /* Freeze line number processing in Scanner */
- Scanner_freeze_line(scan,expanding_macro);
- } else {
- int c;
- Locator *l;
- Seek(loc, 7, SEEK_SET);
- c = Getc(loc);
- if (c == '@') {
- /* Empty locator. We pop the last location off */
- if (locs) {
- Scanner_set_location(scan,locs->filename,locs->line_number);
- cparse_file = locs->filename;
- cparse_line = locs->line_number;
- l = locs->next;
- free(locs);
- locs = l;
- }
- return;
- }
-
- /* We're going to push a new location */
- l = (Locator *) malloc(sizeof(Locator));
- l->filename = cparse_file;
- l->line_number = cparse_line;
- l->next = locs;
- locs = l;
-
- /* Now, parse the new location out of the locator string */
- {
- String *fn = NewStringEmpty();
- /* Putc(c, fn); */
-
- while ((c = Getc(loc)) != EOF) {
- if ((c == '@') || (c == ','))
- break;
- Putc(c, fn);
- }
- cparse_file = Swig_copy_string(Char(fn));
- Clear(fn);
- cparse_line = 1;
- /* Get the line number */
- while ((c = Getc(loc)) != EOF) {
- if ((c == '@') || (c == ','))
- break;
- Putc(c, fn);
- }
- cparse_line = atoi(Char(fn));
- Clear(fn);
-
- /* Get the rest of it */
- while ((c = Getc(loc)) != EOF) {
- if (c == '@')
- break;
- Putc(c, fn);
- }
- /* Swig_diagnostic(cparse_file, cparse_line, "Scanner_set_location\n"); */
- Scanner_set_location(scan,cparse_file,cparse_line);
- Delete(fn);
- }
- }
-}
-
-void Swig_cparse_follow_locators(int v) {
- follow_locators = v;
-}
-
-
/* ----------------------------------------------------------------------------
* scanner_init()
*
@@ -432,7 +335,7 @@ static int yylook(void) {
String *cmt = Scanner_text(scan);
char *loc = Char(cmt);
if ((strncmp(loc,"/*@SWIG",7) == 0) && (loc[Len(cmt)-3] == '@')) {
- scanner_locator(cmt);
+ Scanner_locator(scan, cmt);
}
}
break;
@@ -791,7 +694,7 @@ int yylex(void) {
if (strcmp(yytext, "typename") == 0)
return (TYPENAME);
if (strcmp(yytext, "template") == 0) {
- yylval.ivalue = cparse_line;
+ yylval.intvalue = cparse_line;
return (TEMPLATE);
}
if (strcmp(yytext, "delete") == 0) {
@@ -833,7 +736,7 @@ int yylex(void) {
return (SIZEOF);
if (strcmp(yytext, "typedef") == 0) {
- yylval.ivalue = 0;
+ yylval.intvalue = 0;
return (TYPEDEF);
}
@@ -875,7 +778,7 @@ int yylex(void) {
if (strcmp(yytext, "%constant") == 0)
return (CONSTANT);
if (strcmp(yytext, "%typedef") == 0) {
- yylval.ivalue = 1;
+ yylval.intvalue = 1;
return (TYPEDEF);
}
if (strcmp(yytext, "%native") == 0)
diff --git a/Source/CParse/parser.y b/Source/CParse/parser.y
index 6e41fa565..d792021c6 100644
--- a/Source/CParse/parser.y
+++ b/Source/CParse/parser.y
@@ -1628,7 +1628,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) {
String *str;
Parm *p;
ParmList *pl;
- int ivalue;
+ int intvalue;
Node *node;
};
@@ -1639,7 +1639,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) {
%token <loc> INCLUDE IMPORT INSERT
%token <str> CHARCONST
%token <dtype> NUM_INT NUM_FLOAT NUM_UNSIGNED NUM_LONG NUM_ULONG NUM_LONGLONG NUM_ULONGLONG NUM_BOOL
-%token <ivalue> TYPEDEF
+%token <intvalue> TYPEDEF
%token <type> TYPE_INT TYPE_UNSIGNED TYPE_SHORT TYPE_LONG TYPE_FLOAT TYPE_DOUBLE TYPE_CHAR TYPE_WCHAR TYPE_VOID TYPE_SIGNED TYPE_BOOL TYPE_COMPLEX TYPE_TYPEDEF TYPE_RAW TYPE_NON_ISO_INT8 TYPE_NON_ISO_INT16 TYPE_NON_ISO_INT32 TYPE_NON_ISO_INT64
%token LPAREN RPAREN COMMA SEMI EXTERN INIT LBRACE RBRACE PERIOD
%token CONST_QUAL VOLATILE REGISTER STRUCT UNION EQUAL SIZEOF MODULE LBRACKET RBRACKET
@@ -1657,7 +1657,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) {
%token QUESTIONMARK
%token TYPES PARMS
%token NONID DSTAR DCNOT
-%token <ivalue> TEMPLATE
+%token <intvalue> TEMPLATE
%token <str> OPERATOR
%token <str> COPERATOR
%token PARSETYPE PARSEPARM PARSEPARMS
@@ -1728,7 +1728,7 @@ static void tag_nodes(Node *n, const_String_or_char_ptr attrname, DOH *value) {
%type <id> string stringnum ;
%type <tparms> template_parms;
%type <dtype> cpp_end cpp_vend;
-%type <ivalue> rename_namewarn;
+%type <intvalue> rename_namewarn;
%type <ptype> type_specifier primitive_type_list ;
%type <node> fname stringtype;
%type <node> featattr;
@@ -2121,7 +2121,7 @@ include_directive: includetype options string LBRACKET {
} interface RBRACKET {
String *mname = 0;
$$ = $6;
- scanner_set_location($1.filename,$1.line);
+ scanner_set_location($1.filename,$1.line+1);
if (strcmp($1.type,"include") == 0) set_nodeType($$,"include");
if (strcmp($1.type,"import") == 0) {
mname = $2 ? Getattr($2,"module") : 0;
@@ -2176,15 +2176,14 @@ inline_directive : INLINE HBLOCK {
String *cpps;
if (Namespaceprefix) {
Swig_error(cparse_file, cparse_start_line, "%%inline directive inside a namespace is disallowed.\n");
-
$$ = 0;
} else {
$$ = new_node("insert");
Setattr($$,"code",$2);
/* Need to run through the preprocessor */
+ Seek($2,0,SEEK_SET);
Setline($2,cparse_start_line);
Setfile($2,cparse_file);
- Seek($2,0,SEEK_SET);
cpps = Preprocessor_parse($2);
start_inline(Char(cpps), cparse_start_line);
Delete($2);
@@ -4541,7 +4540,8 @@ cpp_protection_decl : PUBLIC COLON {
------------------------------------------------------------ */
cpp_nested : storage_class cpptype idcolon inherit LBRACE {
- cparse_start_line = cparse_line; skip_balanced('{','}');
+ cparse_start_line = cparse_line;
+ skip_balanced('{','}');
$<str>$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */
} cpp_opt_declarators {
$$ = 0;
@@ -4566,7 +4566,8 @@ cpp_nested : storage_class cpptype idcolon inherit LBRACE {
------------------------------------------------------------ */
| storage_class cpptype inherit LBRACE {
- cparse_start_line = cparse_line; skip_balanced('{','}');
+ cparse_start_line = cparse_line;
+ skip_balanced('{','}');
$<str>$ = NewString(scanner_ccode); /* copied as initializers overwrite scanner_ccode */
} cpp_opt_declarators {
$$ = 0;
@@ -5884,28 +5885,34 @@ base_list : base_specifier {
}
;
-base_specifier : opt_virtual idcolon {
+base_specifier : opt_virtual {
+ $<intvalue>$ = cparse_line;
+ } idcolon {
$$ = NewHash();
Setfile($$,cparse_file);
- Setline($$,cparse_line);
- Setattr($$,"name",$2);
+ Setline($$,$<intvalue>2);
+ Setattr($$,"name",$3);
+ Setfile($3,cparse_file);
+ Setline($3,$<intvalue>2);
if (last_cpptype && (Strcmp(last_cpptype,"struct") != 0)) {
Setattr($$,"access","private");
- Swig_warning(WARN_PARSE_NO_ACCESS,cparse_file,cparse_line,
- "No access specifier given for base class %s (ignored).\n",$2);
+ Swig_warning(WARN_PARSE_NO_ACCESS, Getfile($$), Getline($$), "No access specifier given for base class '%s' (ignored).\n", SwigType_namestr($3));
} else {
Setattr($$,"access","public");
}
}
- | opt_virtual access_specifier opt_virtual idcolon {
+ | opt_virtual access_specifier {
+ $<intvalue>$ = cparse_line;
+ } opt_virtual idcolon {
$$ = NewHash();
Setfile($$,cparse_file);
- Setline($$,cparse_line);
- Setattr($$,"name",$4);
+ Setline($$,$<intvalue>3);
+ Setattr($$,"name",$5);
+ Setfile($5,cparse_file);
+ Setline($5,$<intvalue>3);
Setattr($$,"access",$2);
if (Strcmp($2,"public") != 0) {
- Swig_warning(WARN_PARSE_PRIVATE_INHERIT, cparse_file,
- cparse_line,"%s inheritance ignored.\n", $2);
+ Swig_warning(WARN_PARSE_PRIVATE_INHERIT, Getfile($$), Getline($$), "%s inheritance from base '%s' (ignored).\n", $2, SwigType_namestr($5));
}
}
;
diff --git a/Source/DOH/base.c b/Source/DOH/base.c
index 36ceb7ae3..cfbd2bdc4 100644
--- a/Source/DOH/base.c
+++ b/Source/DOH/base.c
@@ -645,7 +645,7 @@ int DohRead(DOH *obj, void *buffer, int length) {
* DohWrite()
* ----------------------------------------------------------------------------- */
-int DohWrite(DOH *obj, void *buffer, int length) {
+int DohWrite(DOH *obj, const void *buffer, int length) {
DohBase *b = (DohBase *) obj;
DohObjInfo *objinfo;
if (DohCheck(obj)) {
diff --git a/Source/DOH/doh.h b/Source/DOH/doh.h
index bd692596d..cfa6d79b2 100644
--- a/Source/DOH/doh.h
+++ b/Source/DOH/doh.h
@@ -222,7 +222,7 @@ extern int DohDelslice(DOH *obj, int sindex, int eindex);
/* File methods */
-extern int DohWrite(DOHFile * obj, void *buffer, int length);
+extern int DohWrite(DOHFile * obj, const void *buffer, int length);
extern int DohRead(DOHFile * obj, void *buffer, int length);
extern int DohSeek(DOHFile * obj, long offset, int whence);
extern long DohTell(DOHFile * obj);
@@ -268,6 +268,8 @@ extern int DohIsSequence(const DOH *obj);
extern int DohIsString(const DOH *obj);
extern int DohIsFile(const DOH *obj);
+extern void DohSetMaxHashExpand(int count);
+extern int DohGetMaxHashExpand(void);
extern void DohSetmark(DOH *obj, int x);
extern int DohGetmark(DOH *obj);
@@ -276,9 +278,9 @@ extern int DohGetmark(DOH *obj);
* ----------------------------------------------------------------------------- */
extern DOHString *DohNewStringEmpty(void);
-extern DOHString *DohNewString(const DOH *c);
-extern DOHString *DohNewStringWithSize(const DOH *c, int len);
-extern DOHString *DohNewStringf(const DOH *fmt, ...);
+extern DOHString *DohNewString(const DOHString_or_char *c);
+extern DOHString *DohNewStringWithSize(const DOHString_or_char *c, int len);
+extern DOHString *DohNewStringf(const DOHString_or_char *fmt, ...);
extern int DohStrcmp(const DOHString_or_char *s1, const DOHString_or_char *s2);
extern int DohStrncmp(const DOHString_or_char *s1, const DOHString_or_char *s2, int n);
@@ -427,6 +429,8 @@ extern void DohMemoryDebug(void);
#define SplitLines DohSplitLines
#define Setmark DohSetmark
#define Getmark DohGetmark
+#define SetMaxHashExpand DohSetMaxHashExpand
+#define GetMaxHashExpand DohGetMaxHashExpand
#define None DohNone
#define Call DohCall
#define First DohFirst
diff --git a/Source/DOH/dohint.h b/Source/DOH/dohint.h
index 661bed075..9f5c06272 100644
--- a/Source/DOH/dohint.h
+++ b/Source/DOH/dohint.h
@@ -43,7 +43,7 @@ typedef struct {
/* File methods */
typedef struct {
int (*doh_read) (DOH *obj, void *buffer, int nbytes); /* Read bytes */
- int (*doh_write) (DOH *obj, void *buffer, int nbytes); /* Write bytes */
+ int (*doh_write) (DOH *obj, const void *buffer, int nbytes); /* Write bytes */
int (*doh_putc) (DOH *obj, int ch); /* Put character */
int (*doh_getc) (DOH *obj); /* Get character */
int (*doh_ungetc) (DOH *obj, int ch); /* Unget character */
@@ -54,7 +54,7 @@ typedef struct {
/* String methods */
typedef struct {
- int (*doh_replace) (DOH *obj, DOH *old, DOH *rep, int flags);
+ int (*doh_replace) (DOH *obj, const DOHString_or_char *old, const DOHString_or_char *rep, int flags);
void (*doh_chop) (DOH *obj);
} DohStringMethods;
diff --git a/Source/DOH/file.c b/Source/DOH/file.c
index a9ee332bf..11482fa7f 100644
--- a/Source/DOH/file.c
+++ b/Source/DOH/file.c
@@ -67,7 +67,7 @@ static int File_read(DOH *fo, void *buffer, int len) {
* File_write()
* ----------------------------------------------------------------------------- */
-static int File_write(DOH *fo, void *buffer, int len) {
+static int File_write(DOH *fo, const void *buffer, int len) {
DohFile *f = (DohFile *) ObjData(fo);
if (f->filep) {
int ret = (int) fwrite(buffer, 1, len, f->filep);
diff --git a/Source/DOH/hash.c b/Source/DOH/hash.c
index 87f8e3c40..241383327 100644
--- a/Source/DOH/hash.c
+++ b/Source/DOH/hash.c
@@ -42,6 +42,7 @@ typedef struct KeyValue {
} KeyValue;
static KeyValue *root = 0;
+static int max_expand = 1;
/* Find or create a key in the interned key table */
static DOH *find_key(DOH *doh_c) {
@@ -362,7 +363,7 @@ static DohIterator Hash_nextiter(DohIterator iter) {
}
/* -----------------------------------------------------------------------------
- * Hash_keys(DOH *)
+ * Hash_keys()
*
* Return a list of keys
* ----------------------------------------------------------------------------- */
@@ -379,6 +380,26 @@ static DOH *Hash_keys(DOH *so) {
}
/* -----------------------------------------------------------------------------
+ * DohSetMaxHashExpand()
+ *
+ * Controls how many Hash objects are displayed in full in Hash_str
+ * ----------------------------------------------------------------------------- */
+
+void DohSetMaxHashExpand(int count) {
+ max_expand = count;
+}
+
+/* -----------------------------------------------------------------------------
+ * DohGetMaxHashExpand()
+ *
+ * Returns how many Hash objects are displayed in full in Hash_str
+ * ----------------------------------------------------------------------------- */
+
+int DohGetMaxHashExpand(void) {
+ return max_expand;
+}
+
+/* -----------------------------------------------------------------------------
* Hash_str()
*
* Create a string representation of a hash table (mainly for debugging).
@@ -388,7 +409,8 @@ static DOH *Hash_str(DOH *ho) {
int i, j;
HashNode *n;
DOH *s;
- static int indent = 4;
+ static int expanded = 0;
+ static const char *tab = " ";
Hash *h = (Hash *) ObjData(ho);
s = NewStringEmpty();
@@ -396,22 +418,35 @@ static DOH *Hash_str(DOH *ho) {
Printf(s, "Hash(0x%x)", ho);
return s;
}
+ if (expanded >= max_expand) {
+ /* replace each hash attribute with a '.' */
+ Printf(s, "Hash(0x%x) {", ho);
+ for (i = 0; i < h->hashsize; i++) {
+ n = h->hashtable[i];
+ while (n) {
+ Putc('.', s);
+ n = n->next;
+ }
+ }
+ Putc('}', s);
+ return s;
+ }
ObjSetMark(ho, 1);
- Printf(s, "Hash {\n");
+ Printf(s, "Hash(0x%x) {\n", ho);
for (i = 0; i < h->hashsize; i++) {
n = h->hashtable[i];
while (n) {
- for (j = 0; j < indent; j++)
- Putc(' ', s);
- indent += 4;
+ for (j = 0; j < expanded + 1; j++)
+ Printf(s, tab);
+ expanded += 1;
Printf(s, "'%s' : %s, \n", n->key, n->object);
- indent -= 4;
+ expanded -= 1;
n = n->next;
}
}
- for (j = 0; j < (indent - 4); j++)
- Putc(' ', s);
- Printf(s, "}\n");
+ for (j = 0; j < expanded; j++)
+ Printf(s, tab);
+ Printf(s, "}");
ObjSetMark(ho, 0);
return s;
}
diff --git a/Source/DOH/list.c b/Source/DOH/list.c
index a08cadb5a..d5b532409 100644
--- a/Source/DOH/list.c
+++ b/Source/DOH/list.c
@@ -252,7 +252,7 @@ static DOH *List_str(DOH *lo) {
if ((i + 1) < l->nitems)
Printf(s, ", ");
}
- Printf(s, " ]\n");
+ Printf(s, " ]");
ObjSetMark(lo, 0);
return s;
}
diff --git a/Source/DOH/string.c b/Source/DOH/string.c
index 276ae6b96..ac770cea2 100644
--- a/Source/DOH/string.c
+++ b/Source/DOH/string.c
@@ -29,7 +29,7 @@ typedef struct String {
} String;
/* -----------------------------------------------------------------------------
- * void *String_data() - Return as a 'void *'
+ * String_data() - Return as a 'void *'
* ----------------------------------------------------------------------------- */
static void *String_data(DOH *so) {
@@ -44,7 +44,7 @@ static void *String_data(DOH *so) {
*/
/* -----------------------------------------------------------------------------
- * int String_dump() - Serialize a string onto out
+ * String_dump() - Serialize a string onto out
* ----------------------------------------------------------------------------- */
static int String_dump(DOH *so, DOH *out) {
@@ -105,7 +105,7 @@ static int String_len(DOH *so) {
/* -----------------------------------------------------------------------------
- * int String_cmp() - Compare two strings
+ * String_cmp() - Compare two strings
* ----------------------------------------------------------------------------- */
static int String_cmp(DOH *so1, DOH *so2) {
@@ -137,7 +137,7 @@ static int String_cmp(DOH *so1, DOH *so2) {
}
/* -----------------------------------------------------------------------------
- * int String_equal() - Say if two string are equal
+ * String_equal() - Say if two string are equal
* ----------------------------------------------------------------------------- */
static int String_equal(DOH *so1, DOH *so2) {
@@ -174,7 +174,7 @@ static int String_equal(DOH *so1, DOH *so2) {
}
/* -----------------------------------------------------------------------------
- * int String_hash() - Compute string hash value
+ * String_hash() - Compute string hash value
* ----------------------------------------------------------------------------- */
static int String_hash(DOH *so) {
@@ -203,10 +203,10 @@ static int String_hash(DOH *so) {
}
/* -----------------------------------------------------------------------------
- * DohString_append(String *s, const char *newstr) - Append to s
+ * DohString_append() - Append to s
* ----------------------------------------------------------------------------- */
-void DohString_append(DOH *so, DOH *str) {
+static void DohString_append(DOH *so, const DOHString_or_char *str) {
int oldlen, newlen, newmaxsize, l, sp;
char *tc;
String *s = (String *) ObjData(so);
@@ -251,7 +251,7 @@ void DohString_append(DOH *so, DOH *str) {
/* -----------------------------------------------------------------------------
- * void String_clear() - Clear a string
+ * String_clear() - Clear a string
* ----------------------------------------------------------------------------- */
static void String_clear(DOH *so) {
@@ -264,7 +264,7 @@ static void String_clear(DOH *so) {
}
/* -----------------------------------------------------------------------------
- * void String_insert() - Insert a string
+ * String_insert() - Insert a string
* ----------------------------------------------------------------------------- */
static int String_insert(DOH *so, int pos, DOH *str) {
@@ -320,7 +320,7 @@ static int String_insert(DOH *so, int pos, DOH *str) {
}
/* -----------------------------------------------------------------------------
- * int String_delitem() - Delete a character
+ * String_delitem() - Delete a character
* ----------------------------------------------------------------------------- */
static int String_delitem(DOH *so, int pos) {
@@ -346,7 +346,7 @@ static int String_delitem(DOH *so, int pos) {
}
/* -----------------------------------------------------------------------------
- * int String_delslice() - Delete a range
+ * String_delslice() - Delete a range
* ----------------------------------------------------------------------------- */
static int String_delslice(DOH *so, int sindex, int eindex) {
@@ -384,7 +384,7 @@ static int String_delslice(DOH *so, int sindex, int eindex) {
}
/* -----------------------------------------------------------------------------
- * DOH *String_str() - Returns a string (used by printing commands)
+ * String_str() - Returns a string (used by printing commands)
* ----------------------------------------------------------------------------- */
static DOH *String_str(DOH *so) {
@@ -394,7 +394,7 @@ static DOH *String_str(DOH *so) {
}
/* -----------------------------------------------------------------------------
- * int String_read() - Read data from a string
+ * String_read() - Read data from a string
* ----------------------------------------------------------------------------- */
static int String_read(DOH *so, void *buffer, int len) {
@@ -417,9 +417,9 @@ static int String_read(DOH *so, void *buffer, int len) {
}
/* -----------------------------------------------------------------------------
- * int String_write() - Write data to a string
+ * String_write() - Write data to a string
* ----------------------------------------------------------------------------- */
-static int String_write(DOH *so, void *buffer, int len) {
+static int String_write(DOH *so, const void *buffer, int len) {
int newlen;
String *s = (String *) ObjData(so);
s->hashkey = -1;
@@ -441,7 +441,7 @@ static int String_write(DOH *so, void *buffer, int len) {
}
/* -----------------------------------------------------------------------------
- * int String_seek() - Seek to a new position
+ * String_seek() - Seek to a new position
* ----------------------------------------------------------------------------- */
static int String_seek(DOH *so, long offset, int whence) {
@@ -498,7 +498,7 @@ static int String_seek(DOH *so, long offset, int whence) {
}
/* -----------------------------------------------------------------------------
- * long String_tell() - Return current position
+ * String_tell() - Return current position
* ----------------------------------------------------------------------------- */
static long String_tell(DOH *so) {
@@ -507,7 +507,7 @@ static long String_tell(DOH *so) {
}
/* -----------------------------------------------------------------------------
- * int String_putc()
+ * String_putc()
* ----------------------------------------------------------------------------- */
static int String_putc(DOH *so, int ch) {
@@ -538,7 +538,7 @@ static int String_putc(DOH *so, int ch) {
}
/* -----------------------------------------------------------------------------
- * int String_getc()
+ * String_getc()
* ----------------------------------------------------------------------------- */
static int String_getc(DOH *so) {
@@ -554,7 +554,7 @@ static int String_getc(DOH *so) {
}
/* -----------------------------------------------------------------------------
- * int String_ungetc()
+ * String_ungetc()
* ----------------------------------------------------------------------------- */
static int String_ungetc(DOH *so, int ch) {
@@ -569,12 +569,6 @@ static int String_ungetc(DOH *so, int ch) {
return ch;
}
-/* -----------------------------------------------------------------------------
- * replace_simple(String *str, char *token, char *rep, int flags, int count)
- *
- * Replaces count non-overlapping occurrences of token with rep in a string.
- * ----------------------------------------------------------------------------- */
-
static char *end_quote(char *s) {
char *qs;
char qc;
@@ -659,6 +653,12 @@ static char *match_identifier_end(char *base, char *s, char *token, int tokenlen
return 0;
}
+/* -----------------------------------------------------------------------------
+ * replace_simple()
+ *
+ * Replaces count non-overlapping occurrences of token with rep in a string.
+ * ----------------------------------------------------------------------------- */
+
static int replace_simple(String *str, char *token, char *rep, int flags, int count, char *(*match) (char *, char *, char *, int)) {
int tokenlen; /* Length of the token */
int replen; /* Length of the replacement */
@@ -885,10 +885,10 @@ static int replace_simple(String *str, char *token, char *rep, int flags, int co
}
/* -----------------------------------------------------------------------------
- * int String_replace()
+ * String_replace()
* ----------------------------------------------------------------------------- */
-static int String_replace(DOH *stro, DOH *token, DOH *rep, int flags) {
+static int String_replace(DOH *stro, const DOHString_or_char *token, const DOHString_or_char *rep, int flags) {
int count = -1;
String *str = (String *) ObjData(stro);
@@ -907,7 +907,7 @@ static int String_replace(DOH *stro, DOH *token, DOH *rep, int flags) {
}
/* -----------------------------------------------------------------------------
- * void String_chop(DOH *str)
+ * String_chop()
* ----------------------------------------------------------------------------- */
static void String_chop(DOH *so) {
@@ -1012,10 +1012,10 @@ DohObjInfo DohStringType = {
#define INIT_MAXSIZE 16
/* -----------------------------------------------------------------------------
- * NewString(const char *c) - Create a new string
+ * NewString() - Create a new string
* ----------------------------------------------------------------------------- */
-DOHString *DohNewString(const DOH *so) {
+DOHString *DohNewString(const DOHString_or_char *so) {
int l = 0, max;
String *str;
char *s;
@@ -1073,10 +1073,10 @@ DOHString *DohNewStringEmpty(void) {
}
/* -----------------------------------------------------------------------------
- * NewStringWithSize(const char *c, int len) - Create a new string
+ * NewStringWithSize() - Create a new string
* ----------------------------------------------------------------------------- */
-DOHString *DohNewStringWithSize(const DOH *so, int len) {
+DOHString *DohNewStringWithSize(const DOHString_or_char *so, int len) {
int l = 0, max;
String *str;
char *s;
@@ -1111,12 +1111,12 @@ DOHString *DohNewStringWithSize(const DOH *so, int len) {
}
/* -----------------------------------------------------------------------------
- * NewStringf(DOH *fmt, ...)
+ * NewStringf()
*
* Create a new string from a list of objects.
* ----------------------------------------------------------------------------- */
-DOHString *DohNewStringf(const DOH *fmt, ...) {
+DOHString *DohNewStringf(const DOHString_or_char *fmt, ...) {
va_list ap;
DOH *r;
va_start(ap, fmt);
diff --git a/Source/Include/swigwarn.h b/Source/Include/swigwarn.h
index 46f5b79a5..9c5c3be74 100644
--- a/Source/Include/swigwarn.h
+++ b/Source/Include/swigwarn.h
@@ -1,5 +1,5 @@
-/* -----------------------------------------------------------------------------
- * This file is part of SWIG, which is licensed as a whole under version 3
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
* (or any later version) of the GNU General Public License. Some additional
* terms also apply to certain portions of SWIG. The full details of the SWIG
* license and copyrights can be found in the LICENSE and COPYRIGHT files
@@ -193,14 +193,37 @@
#define WARN_LANG_DIRECTOR_ABSTRACT 517
#define WARN_LANG_PORTABILITY_FILENAME 518
#define WARN_LANG_TEMPLATE_METHOD_IGNORE 519
+#define WARN_LANG_SMARTPTR_MISSING 520
/* -- Reserved (600-799) -- */
-/* -- Language module specific warnings (800 - 999) -- */
+/* -- Language module specific warnings (700 - 899) -- */
+
+/* Feel free to claim any number in this space that's not currently being used. Just make sure you
+ add an entry here */
+
+#define WARN_D_TYPEMAP_CTYPE_UNDEF 700
+#define WARN_D_TYPEMAP_IMTYPE_UNDEF 701
+#define WARN_D_TYPEMAP_DTYPE_UNDEF 702
+#define WARN_D_MULTIPLE_INHERITANCE 703
+#define WARN_D_TYPEMAP_CLASSMOD_UNDEF 704
+#define WARN_D_TYPEMAP_DBODY_UNDEF 705
+#define WARN_D_TYPEMAP_DOUT_UNDEF 706
+#define WARN_D_TYPEMAP_DIN_UNDEF 707
+#define WARN_D_TYPEMAP_DDIRECTORIN_UNDEF 708
+#define WARN_D_TYPEMAP_DCONSTRUCTOR_UNDEF 709
+#define WARN_D_EXCODE_MISSING 710
+#define WARN_D_CANTHROW_MISSING 711
+#define WARN_D_NO_DIRECTORCONNECT_ATTR 712
+#define WARN_D_NAME_COLLISION 713
+
+/* please leave 700-719 free for D */
#define WARN_RUBY_WRONG_NAME 801
#define WARN_RUBY_MULTIPLE_INHERITANCE 802
+/* please leave 800-809 free for Ruby */
+
#define WARN_JAVA_TYPEMAP_JNI_UNDEF 810
#define WARN_JAVA_TYPEMAP_JTYPE_UNDEF 811
#define WARN_JAVA_TYPEMAP_JSTYPE_UNDEF 812
@@ -262,7 +285,6 @@
/* please leave 890-899 free for Go */
-/* Feel free to claim any number in this space that's not currently being used. Just make sure you
- add an entry here */
+/* -- User defined warnings (900 - 999) -- */
#endif
diff --git a/Source/Makefile.am b/Source/Makefile.am
index b880a9543..0313dcade 100644
--- a/Source/Makefile.am
+++ b/Source/Makefile.am
@@ -42,6 +42,7 @@ eswig_SOURCES = CParse/cscanner.c \
Modules/clisp.cxx \
Modules/contract.cxx \
Modules/csharp.cxx \
+ Modules/d.cxx \
Modules/directors.cxx \
Modules/emit.cxx \
Modules/fortran.cxx \
diff --git a/Source/Modules/allocate.cxx b/Source/Modules/allocate.cxx
index 2e05fd190..110a92939 100644
--- a/Source/Modules/allocate.cxx
+++ b/Source/Modules/allocate.cxx
@@ -216,7 +216,7 @@ class Allocate:public Dispatcher {
if (!most_base_covariant_type) {
// Eliminate the derived virtual method.
- if (virtual_elimination_mode)
+ if (virtual_elimination_mode && !is_member_director(n))
if (both_have_public_access)
if (!is_non_public_base(inclass, b))
if (!Swig_symbol_isoverloaded(n)) {
@@ -824,9 +824,12 @@ Allocate():
int isconst = 0;
Delete(SwigType_pop(type));
if (SwigType_isconst(type)) {
- isconst = 1;
+ isconst = !Getattr(inclass, "allocate:smartpointermutable");
Setattr(inclass, "allocate:smartpointerconst", "1");
}
+ else {
+ Setattr(inclass, "allocate:smartpointermutable", "1");
+ }
List *methods = smart_pointer_methods(sc, 0, isconst);
Setattr(inclass, "allocate:smartpointer", methods);
Setattr(inclass, "allocate:smartpointerbase", base);
@@ -834,7 +837,6 @@ Allocate():
/* Hmmm. The return value is not a pointer. If the type is a value
or reference. We're going to chase it to see if another operator->()
can be found */
-
if ((SwigType_check_decl(type, "")) || (SwigType_check_decl(type, "r."))) {
Node *nn = Swig_symbol_clookup((char *) "operator ->", Getattr(sc, "symtab"));
if (nn) {
diff --git a/Source/Modules/clisp.cxx b/Source/Modules/clisp.cxx
index b1a6f5610..d26df36c2 100644
--- a/Source/Modules/clisp.cxx
+++ b/Source/Modules/clisp.cxx
@@ -293,16 +293,18 @@ int CLISP::classDeclaration(Node *n) {
}
String *temp = Copy(Getattr(c, "decl"));
- Append(temp, Getattr(c, "type")); //appending type to the end, otherwise wrong type
- String *lisp_type = get_ffi_type(n, temp);
- Delete(temp);
+ if (temp) {
+ Append(temp, Getattr(c, "type")); //appending type to the end, otherwise wrong type
+ String *lisp_type = get_ffi_type(n, temp);
+ Delete(temp);
- String *slot_name = Getattr(c, "sym:name");
- Printf(f_cl, "\n\t(%s %s)", slot_name, lisp_type);
+ String *slot_name = Getattr(c, "sym:name");
+ Printf(f_cl, "\n\t(%s %s)", slot_name, lisp_type);
- Append(entries, NewStringf("%s-%s", name, slot_name));
+ Append(entries, NewStringf("%s-%s", name, slot_name));
- Delete(lisp_type);
+ Delete(lisp_type);
+ }
}
Printf(f_cl, ")\n");
diff --git a/Source/Modules/csharp.cxx b/Source/Modules/csharp.cxx
index 8ffd9768a..1444dbd87 100644
--- a/Source/Modules/csharp.cxx
+++ b/Source/Modules/csharp.cxx
@@ -1640,10 +1640,10 @@ public:
base = Next(base);
continue;
}
- String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
- String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
- Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number,
- "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#.\n", proxyclassname, baseclassname);
+ String *proxyclassname = Getattr(n, "classtypeobj");
+ String *baseclassname = Getattr(base.item, "name");
+ Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
base = Next(base);
}
}
@@ -1661,9 +1661,9 @@ public:
Delete(baseclass);
baseclass = NULL;
if (purebase_notderived)
- Swig_error(input_file, line_number, "The csbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
+ Swig_error(Getfile(n), Getline(n), "The csbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
} else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
- Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, input_file, line_number,
+ Swig_warning(WARN_CSHARP_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in C#. "
"Perhaps you need one of the 'replace' or 'notderived' attributes in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
}
@@ -1704,10 +1704,10 @@ public:
}
if (tm && *Char(tm)) {
if (!destruct_methodname) {
- Swig_error(input_file, line_number, "No methodname attribute defined in csdestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
+ Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in csdestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
}
if (!destruct_methodmodifiers) {
- Swig_error(input_file, line_number,
+ Swig_error(Getfile(n), Getline(n),
"No methodmodifiers attribute defined in csdestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
}
}
@@ -2292,17 +2292,24 @@ public:
String *ex_imcall = Copy(imcall);
Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
Replaceall(imcall, "$imfuncname", intermediary_function_name);
-
String *excode = NewString("");
- if (!Cmp(return_type, "void"))
- Printf(excode, "if (this.GetType() == typeof(%s)) %s; else %s", proxy_class_name, imcall, ex_imcall);
- else
- Printf(excode, "((this.GetType() == typeof(%s)) ? %s : %s)", proxy_class_name, imcall, ex_imcall);
+ Node *directorNode = Getattr(n, "directorNode");
+ if (directorNode) {
+ UpcallData *udata = Getattr(directorNode, "upcalldata");
+ String *methid = Getattr(udata, "class_methodidx");
- Clear(imcall);
- Printv(imcall, excode, NIL);
- Delete(ex_overloaded_name);
+ if (!Cmp(return_type, "void"))
+ Printf(excode, "if (SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s)) %s; else %s", proxy_function_name, methid, ex_imcall, imcall);
+ else
+ Printf(excode, "(SwigDerivedClassHasMethod(\"%s\", swigMethodTypes%s) ? %s : %s)", proxy_function_name, methid, ex_imcall, imcall);
+
+ Clear(imcall);
+ Printv(imcall, excode, NIL);
+ } else {
+ // probably an ignored method or nodirector
+ }
Delete(excode);
+ Delete(ex_overloaded_name);
} else {
Replaceall(imcall, "$imfuncname", intermediary_function_name);
}
@@ -2343,6 +2350,7 @@ public:
SwigType *pt = Getattr(p, "type");
if ((tm = Getattr(p, "tmap:csvarin"))) {
substituteClassname(pt, tm);
+ Replaceall(tm, "$csinput", "value");
Replaceall(tm, "$imcall", imcall);
excodeSubstitute(n, tm, "csvarin", p);
Printf(proxy_class_code, "%s", tm);
@@ -3472,7 +3480,6 @@ public:
String *callback_def = NewString("");
String *callback_code = NewString("");
String *imcall_args = NewString("");
- int gencomma = 0;
bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
// Kludge Alert: functionWrapper sets sym:overload properly, but it
@@ -3616,14 +3623,14 @@ public:
Printf(w->code, "} else {\n");
/* Go through argument list, convert from native to Java */
- for (p = l; p; /* empty */ ) {
+ for (i = 0, p = l; p; ++i) {
/* Is this superfluous? */
while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
p = Getattr(p, "tmap:directorin:next");
}
SwigType *pt = Getattr(p, "type");
- String *ln = Copy(Getattr(p, "name"));
+ String *ln = makeParameterName(n, p, i, false);
String *c_param_type = NULL;
String *c_decl = NewString("");
String *arg = NewString("");
@@ -3631,7 +3638,7 @@ public:
Printf(arg, "j%s", ln);
/* And add to the upcall args */
- if (gencomma > 0)
+ if (i > 0)
Printf(jupcall_args, ", ");
Printf(jupcall_args, "%s", arg);
@@ -3641,17 +3648,13 @@ public:
if (ctypeout)
c_param_type = ctypeout;
- Parm *tp = NewParm(c_param_type, empty_str, n);
- String *desc_tm = NULL;
-
/* Add to local variables */
Printf(c_decl, "%s %s", c_param_type, arg);
if (!ignored_method)
Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
/* Add input marshalling code */
- if ((desc_tm = Swig_typemap_lookup("directorin", tp, "", 0))
- && (tm = Getattr(p, "tmap:directorin"))) {
+ if ((tm = Getattr(p, "tmap:directorin"))) {
Replaceall(tm, "$input", arg);
Replaceall(tm, "$owner", "0");
@@ -3663,7 +3666,7 @@ public:
Delete(tm);
/* Add C type to callback typedef */
- if (gencomma > 0)
+ if (i > 0)
Printf(callback_typedef_parms, ", ");
Printf(callback_typedef_parms, "%s", c_param_type);
@@ -3684,7 +3687,7 @@ public:
substituteClassname(pt, din);
Replaceall(din, "$iminput", ln);
- if (gencomma > 0) {
+ if (i > 0) {
Printf(delegate_parms, ", ");
Printf(proxy_method_types, ", ");
Printf(imcall_args, ", ");
@@ -3716,24 +3719,13 @@ public:
p = Getattr(p, "tmap:directorin:next");
- Delete(desc_tm);
} else {
- if (!desc_tm) {
- Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number,
- "No or improper directorin typemap defined for %s for use in %s::%s (skipping director method)\n",
- SwigType_str(c_param_type, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
- p = nextSibling(p);
- } else if (!tm) {
- Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number,
- "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
- SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
- p = nextSibling(p);
- }
-
+ Swig_warning(WARN_CSHARP_TYPEMAP_CSDIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = nextSibling(p);
output_director = false;
}
-
- Delete(tp);
} else {
Swig_warning(WARN_CSHARP_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
@@ -3741,7 +3733,7 @@ public:
p = nextSibling(p);
}
- gencomma++;
+ Delete(ln);
Delete(arg);
Delete(c_decl);
Delete(c_param_type);
@@ -3884,6 +3876,10 @@ public:
/* Emit the actual upcall through */
UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, decl, overloaded_name);
String *methid = Getattr(udata, "class_methodidx");
+ Setattr(n, "upcalldata", udata);
+ /*
+ Printf(stdout, "setting upcalldata, nodeType: %s %s::%s %p\n", nodeType(n), classname, Getattr(n, "name"), n);
+ */
Printf(director_callback_typedefs, " typedef %s (SWIGSTDCALL* SWIG_Callback%s_t)(", c_ret_type, methid);
Printf(director_callback_typedefs, "%s);\n", callback_typedef_parms);
diff --git a/Source/Modules/d.cxx b/Source/Modules/d.cxx
new file mode 100644
index 000000000..cc1bd2365
--- /dev/null
+++ b/Source/Modules/d.cxx
@@ -0,0 +1,4351 @@
+/* -----------------------------------------------------------------------------
+ * This file is part of SWIG, which is licensed as a whole under version 3
+ * (or any later version) of the GNU General Public License. Some additional
+ * terms also apply to certain portions of SWIG. The full details of the SWIG
+ * license and copyrights can be found in the LICENSE and COPYRIGHT files
+ * included with the SWIG source code as distributed by the SWIG developers
+ * and at http://www.swig.org/legal.html.
+ *
+ * d.cxx
+ *
+ * D language module for SWIG.
+ * ----------------------------------------------------------------------------- */
+
+char cvsroot_d_cxx[] = "$Id$";
+
+#include "swigmod.h"
+#include "cparse.h"
+#include <ctype.h>
+
+// Hash type used for storing information about director callbacks for a class.
+typedef DOH UpcallData;
+
+class D : public Language {
+ static const char *usage;
+ const String *empty_string;
+ const String *public_string;
+ const String *protected_string;
+ const String *static_string;
+
+ /*
+ * Files and file sections containing C/C++ code.
+ */
+ File *f_begin;
+ File *f_runtime;
+ File *f_runtime_h;
+ File *f_header;
+ File *f_wrappers;
+ File *f_init;
+ File *f_directors;
+ File *f_directors_h;
+ List *filenames_list;
+
+ /*
+ * Command line-set modes of operation.
+ */
+ // Whether a single proxy D module is generated or classes and enums are
+ // written to their own files.
+ bool split_proxy_dmodule;
+
+ // The major D version targeted (currently 1 or 2).
+ unsigned short d_version;
+
+ /*
+ * State variables which indicate what is being wrapped at the moment.
+ * This is probably not the most elegant way of handling state, but it has
+ * proven to work in the C# and Java modules.
+ */
+ // Indicates if wrapping a native function.
+ bool native_function_flag;
+
+ // Indicates if wrapping a static functions or member variables
+ bool static_flag;
+
+ // Indicates if wrapping a nonstatic member variable
+ bool variable_wrapper_flag;
+
+ // Indicates if wrapping a member variable/enum/const.
+ bool wrapping_member_flag;
+
+ // Indicates if wrapping a global variable.
+ bool global_variable_flag;
+
+ // Name of a variable being wrapped.
+ String *variable_name;
+
+ /*
+ * Variables temporarily holding the generated C++ code.
+ */
+ // C++ code for the generated wrapper functions for casts up the C++
+ // for inheritance hierarchies.
+ String *upcasts_code;
+
+ // Function pointer typedefs for handling director callbacks on the C++ side.
+ String *director_callback_typedefs;
+
+ // Variables for storing the function pointers to the director callbacks on
+ // the C++ side.
+ String *director_callback_pointers;
+
+ /*
+ * Names of generated D entities.
+ */
+ // The name of the D module containing the interface to the C wrapper.
+ String *im_dmodule_name;
+
+ // The fully qualified name of the wrap D module (package name included).
+ String *im_dmodule_fq_name;
+
+ // The name of the proxy module which exposes the (SWIG) module contents as a
+ // D module.
+ String *proxy_dmodule_name;
+
+ // The fully qualified name of the proxy D module.
+ String *proxy_dmodule_fq_name;
+
+ // Optional: Package the D modules are placed in (set via the -package
+ // command line option).
+ String *package;
+
+ // The directory the generated D module files are written to. Is constructed
+ // from the package path if a target package is set, points to the general
+ // output directory otherwise.
+ String *dmodule_directory;
+
+ // The name of the library which contains the C wrapper (used when generating
+ // the dynamic library loader). Can be overridden via the -wrapperlibrary
+ // command line flag.
+ String *wrap_library_name;
+
+ /*
+ * Variables temporarily holding the generated D code.
+ */
+ // Import statements written to the intermediary D module header set via
+ // %pragma(d) imdmoduleimports.
+ String *im_dmodule_imports;
+
+ // The code for the intermediary D module body.
+ String *im_dmodule_code;
+
+ // Import statements for all proxy modules (the main proxy module and, if in
+ // split proxy module mode, the proxy class modules) from
+ // %pragma(d) globalproxyimports.
+ String *global_proxy_imports;
+
+ // Imports written to the proxy D module header from global_proxy_imports
+ // and, if in split proxy module mode, from D::requireDType().
+ String *proxy_dmodule_imports;
+
+ // The D code for proxy functions/classes which is written to the proxy D
+ // module. If not in split proxy mode, this contains the whole proxy code.
+ String *proxy_dmodule_code;
+
+ // The D code generated for the currently processed enum.
+ String *proxy_enum_code;
+
+ /*
+ * D data for the current proxy class.
+ */
+ // The name of the current proxy class.
+ String *proxy_class_name;
+
+ // The import directives for the current proxy class. They are written to the
+ // same D module the proxy class is written to.
+ String *proxy_class_imports;
+
+ // Code for enumerations nested in the current proxy class. Is emitted earlier
+ // than the rest of the body to work around forward referencing-issues.
+ String *proxy_class_enums_code;
+
+ // The generated D code making up the body of the current proxy class.
+ String *proxy_class_body_code;
+
+ // D code which is emitted right after the proxy class.
+ String *proxy_class_epilogue_code;
+
+ // The full code for the current proxy class, including the epilogue.
+ String* proxy_class_code;
+
+ // Contains a D call to the function wrapping C++ the destructor of the
+ // current class (if there is a public C++ destructor).
+ String *destructor_call;
+
+ // D code for the director callbacks generated for the current class.
+ String *director_dcallbacks_code;
+
+ /*
+ * Code for dynamically loading the wrapper library on the D side.
+ */
+ // D code which is inserted into the im D module if dynamic linking is used.
+ String *wrapper_loader_code;
+
+ // The D code to bind a function pointer to a library symbol.
+ String *wrapper_loader_bind_command;
+
+ // The cumulated binding commands binding all the functions declared in the
+ // intermediary D module to the C/C++ library symbols.
+ String *wrapper_loader_bind_code;
+
+ /*
+ * Director data.
+ */
+ List *dmethods_seq;
+ Hash *dmethods_table;
+ int n_dmethods;
+ int first_class_dmethod;
+ int curr_class_dmethod;
+
+ /*
+ * SWIG types data.
+ */
+ // Collects information about encountered types SWIG does not know about (e.g.
+ // incomplete types). This is used later to generate type wrapper proxy
+ // classes for the unknown types.
+ Hash *unknown_types;
+
+
+public:
+ /* ---------------------------------------------------------------------------
+ * D::D()
+ * --------------------------------------------------------------------------- */
+ D():empty_string(NewString("")),
+ public_string(NewString("public")),
+ protected_string(NewString("protected")),
+ f_begin(NULL),
+ f_runtime(NULL),
+ f_runtime_h(NULL),
+ f_header(NULL),
+ f_wrappers(NULL),
+ f_init(NULL),
+ f_directors(NULL),
+ f_directors_h(NULL),
+ filenames_list(NULL),
+ split_proxy_dmodule(false),
+ d_version(1),
+ native_function_flag(false),
+ static_flag(false),
+ variable_wrapper_flag(false),
+ wrapping_member_flag(false),
+ global_variable_flag(false),
+ variable_name(NULL),
+ upcasts_code(NULL),
+ director_callback_typedefs(NULL),
+ director_callback_pointers(NULL),
+ im_dmodule_name(NULL),
+ im_dmodule_fq_name(NULL),
+ proxy_dmodule_name(NULL),
+ proxy_dmodule_fq_name(NULL),
+ package(NULL),
+ dmodule_directory(NULL),
+ wrap_library_name(NULL),
+ im_dmodule_imports(NULL),
+ im_dmodule_code(NULL),
+ global_proxy_imports(NULL),
+ proxy_dmodule_imports(NULL),
+ proxy_dmodule_code(NULL),
+ proxy_enum_code(NULL),
+ proxy_class_name(NULL),
+ proxy_class_imports(NULL),
+ proxy_class_enums_code(NULL),
+ proxy_class_body_code(NULL),
+ proxy_class_epilogue_code(NULL),
+ proxy_class_code(NULL),
+ destructor_call(NULL),
+ director_dcallbacks_code(NULL),
+ wrapper_loader_code(NULL),
+ wrapper_loader_bind_command(NULL),
+ wrapper_loader_bind_code(NULL),
+ dmethods_seq(NULL),
+ dmethods_table(NULL),
+ n_dmethods(0),
+ unknown_types(NULL) {
+
+ // For now, multiple inheritance with directors is not possible. It should be
+ // easy to implement though.
+ director_multiple_inheritance = 0;
+ director_language = 1;
+
+ // Not used:
+ Delete(none_comparison);
+ none_comparison = NewString("");
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::main()
+ * --------------------------------------------------------------------------- */
+ virtual void main(int argc, char *argv[]) {
+ SWIG_library_directory("d");
+
+ // Look for certain command line options
+ for (int i = 1; i < argc; i++) {
+ if (argv[i]) {
+ if ((strcmp(argv[i], "-d2") == 0)) {
+ Swig_mark_arg(i);
+ d_version = 2;
+ } else if (strcmp(argv[i], "-wrapperlibrary") == 0) {
+ if (argv[i + 1]) {
+ wrap_library_name = NewString("");
+ Printf(wrap_library_name, argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if (strcmp(argv[i], "-package") == 0) {
+ if (argv[i + 1]) {
+ package = NewString("");
+ Printf(package, argv[i + 1]);
+ Swig_mark_arg(i);
+ Swig_mark_arg(i + 1);
+ i++;
+ } else {
+ Swig_arg_error();
+ }
+ } else if ((strcmp(argv[i], "-splitproxy") == 0)) {
+ Swig_mark_arg(i);
+ split_proxy_dmodule = true;
+ } else if (strcmp(argv[i], "-help") == 0) {
+ Printf(stdout, "%s\n", usage);
+ }
+ }
+ }
+
+ // Add a symbol to the parser for conditional compilation
+ Preprocessor_define("SWIGD 1", 0);
+
+ // Also make the target D version available as preprocessor symbol for
+ // use in our library files.
+ String *version_define = NewStringf("SWIG_D_VERSION %u", d_version);
+ Preprocessor_define(version_define, 0);
+ Delete(version_define);
+
+ // Add typemap definitions
+ SWIG_typemap_lang("d");
+ SWIG_config_file("d.swg");
+
+ allow_overloading();
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::top()
+ * --------------------------------------------------------------------------- */
+ virtual int top(Node *n) {
+ // Get any options set in the module directive
+ Node *optionsnode = Getattr(Getattr(n, "module"), "options");
+
+ if (optionsnode) {
+ if (Getattr(optionsnode, "imdmodulename")) {
+ im_dmodule_name = Copy(Getattr(optionsnode, "imdmodulename"));
+ }
+
+ if (Getattr(optionsnode, "directors")) {
+ // Check if directors are enabled for this module. Note: This is a
+ // "master switch", if it is not set, not director code will be emitted
+ // at all. %feature("director") statements are also required to enable
+ // directors for individual classes or methods.
+ //
+ // Use the »directors« attributte of the %module directive to enable
+ // director generation (e.g. »%module(directors="1") modulename«).
+ allow_directors();
+ }
+
+ if (Getattr(optionsnode, "dirprot")) {
+ allow_dirprot();
+ }
+
+ allow_allprotected(GetFlag(optionsnode, "allprotected"));
+ }
+
+ /* Initialize all of the output files */
+ String *outfile = Getattr(n, "outfile");
+ String *outfile_h = Getattr(n, "outfile_h");
+
+ if (!outfile) {
+ Printf(stderr, "Unable to determine outfile\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ f_begin = NewFile(outfile, "w", SWIG_output_files());
+ if (!f_begin) {
+ FileErrorDisplay(outfile);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (directorsEnabled()) {
+ if (!outfile_h) {
+ Printf(stderr, "Unable to determine outfile_h\n");
+ SWIG_exit(EXIT_FAILURE);
+ }
+ f_runtime_h = NewFile(outfile_h, "w", SWIG_output_files());
+ if (!f_runtime_h) {
+ FileErrorDisplay(outfile_h);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+
+ f_runtime = NewString("");
+ f_init = NewString("");
+ f_header = NewString("");
+ f_wrappers = NewString("");
+ f_directors_h = NewString("");
+ f_directors = NewString("");
+
+ /* Register file targets with the SWIG file handler */
+ Swig_register_filebyname("header", f_header);
+ Swig_register_filebyname("wrapper", f_wrappers);
+ Swig_register_filebyname("begin", f_begin);
+ Swig_register_filebyname("runtime", f_runtime);
+ Swig_register_filebyname("init", f_init);
+ Swig_register_filebyname("director", f_directors);
+ Swig_register_filebyname("director_h", f_directors_h);
+
+ unknown_types = NewHash();
+ filenames_list = NewList();
+
+ // Make the package name and the resulting module output path.
+ if (package) {
+ // Append a dot so we can prepend the package variable directly to the
+ // module names in the rest of the code.
+ Printv(package, ".", NIL);
+ } else {
+ // Write the generated D modules to the »root« package by default.
+ package = NewString("");
+ }
+
+ dmodule_directory = Copy(SWIG_output_directory());
+ if (Len(package) > 0) {
+ String *package_directory = Copy(package);
+ Replaceall(package_directory, ".", SWIG_FILE_DELIMITER);
+ Printv(dmodule_directory, package_directory, NIL);
+ Delete(package_directory);
+ }
+
+ // Make the wrap and proxy D module names.
+ // The wrap module name can be set in the module directive.
+ if (!im_dmodule_name) {
+ im_dmodule_name = NewStringf("%s_im", Getattr(n, "name"));
+ }
+ im_dmodule_fq_name = NewStringf("%s%s", package, im_dmodule_name);
+ proxy_dmodule_name = Copy(Getattr(n, "name"));
+ proxy_dmodule_fq_name = NewStringf("%s%s", package, proxy_dmodule_name);
+
+ im_dmodule_code = NewString("");
+ proxy_class_imports = NewString("");
+ proxy_class_enums_code = NewString("");
+ proxy_class_body_code = NewString("");
+ proxy_class_epilogue_code = NewString("");
+ proxy_class_code = NewString("");
+ destructor_call = NewString("");
+ proxy_dmodule_code = NewString("");
+ proxy_dmodule_imports = NewString("");
+ im_dmodule_imports = NewString("");
+ upcasts_code = NewString("");
+ global_proxy_imports = NewString("");
+ wrapper_loader_code = NewString("");
+ wrapper_loader_bind_command = NewString("");
+ wrapper_loader_bind_code = NewString("");
+ dmethods_seq = NewList();
+ dmethods_table = NewHash();
+ n_dmethods = 0;
+
+ // By default, expect the dynamically loaded wrapper library to be named
+ // [lib]<module>_wrap[.so/.dll].
+ if (!wrap_library_name)
+ wrap_library_name = NewStringf("%s_wrap", Getattr(n, "name"));
+
+ Swig_banner(f_begin);
+
+ Printf(f_runtime, "\n");
+ Printf(f_runtime, "#define SWIGD\n");
+
+ if (directorsEnabled()) {
+ Printf(f_runtime, "#define SWIG_DIRECTORS\n");
+
+ /* Emit initial director header and director code: */
+ Swig_banner(f_directors_h);
+ Printf(f_directors_h, "\n");
+ Printf(f_directors_h, "#ifndef SWIG_%s_WRAP_H_\n", proxy_dmodule_name);
+ Printf(f_directors_h, "#define SWIG_%s_WRAP_H_\n\n", proxy_dmodule_name);
+
+ Printf(f_directors, "\n\n");
+ Printf(f_directors, "/* ---------------------------------------------------\n");
+ Printf(f_directors, " * C++ director class methods\n");
+ Printf(f_directors, " * --------------------------------------------------- */\n\n");
+ if (outfile_h)
+ Printf(f_directors, "#include \"%s\"\n\n", Swig_file_filename(outfile_h));
+ }
+
+ Printf(f_runtime, "\n");
+
+ Swig_name_register("wrapper", "D_%f");
+
+ Printf(f_wrappers, "\n#ifdef __cplusplus\n");
+ Printf(f_wrappers, "extern \"C\" {\n");
+ Printf(f_wrappers, "#endif\n\n");
+
+ // Emit all the wrapper code.
+ Language::top(n);
+
+ if (directorsEnabled()) {
+ // Insert director runtime into the f_runtime file (before %header section).
+ Swig_insert_file("director.swg", f_runtime);
+ }
+
+ // Generate the wrap D module.
+ // TODO: Add support for »static« linking.
+ {
+ String *filen = NewStringf("%s%s.d", dmodule_directory, im_dmodule_name);
+ File *im_d_file = NewFile(filen, "w", SWIG_output_files());
+ if (!im_d_file) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ // Start writing out the intermediary class file.
+ emitBanner(im_d_file);
+
+ Printf(im_d_file, "module %s;\n", im_dmodule_fq_name);
+
+ Printv(im_d_file, im_dmodule_imports, "\n", NIL);
+
+ Replaceall(wrapper_loader_code, "$wraplibrary", wrap_library_name);
+ Replaceall(wrapper_loader_code, "$wrapperloaderbindcode", wrapper_loader_bind_code);
+ Replaceall(wrapper_loader_code, "$module", proxy_dmodule_name);
+ Printf(im_d_file, "%s\n", wrapper_loader_code);
+
+ // Add the wrapper function declarations.
+ replaceModuleVariables(im_dmodule_code);
+ Printv(im_d_file, im_dmodule_code, NIL);
+
+ Close(im_d_file);
+ }
+
+ // Generate the D proxy module for the wrapped module.
+ {
+ String *filen = NewStringf("%s%s.d", dmodule_directory, proxy_dmodule_name);
+ File *proxy_d_file = NewFile(filen, "w", SWIG_output_files());
+ if (!proxy_d_file) {
+ FileErrorDisplay(filen);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filen));
+ Delete(filen);
+ filen = NULL;
+
+ emitBanner(proxy_d_file);
+
+ Printf(proxy_d_file, "module %s;\n", proxy_dmodule_fq_name);
+ Printf(proxy_d_file, "\nstatic import %s;\n", im_dmodule_fq_name);
+ Printv(proxy_d_file, global_proxy_imports, NIL);
+ Printv(proxy_d_file, proxy_dmodule_imports, NIL);
+ Printv(proxy_d_file, "\n", NIL);
+
+ // Write a D type wrapper class for each SWIG type to the proxy module code.
+ for (Iterator swig_type = First(unknown_types); swig_type.key; swig_type = Next(swig_type)) {
+ writeTypeWrapperClass(swig_type.key, swig_type.item);
+ }
+
+ // Add the proxy functions (and classes, if they are not written to a
+ // seperate file).
+ replaceModuleVariables(proxy_dmodule_code);
+ Printv(proxy_d_file, proxy_dmodule_code, NIL);
+
+ Close(proxy_d_file);
+ }
+
+ if (upcasts_code)
+ Printv(f_wrappers, upcasts_code, NIL);
+
+ Printf(f_wrappers, "#ifdef __cplusplus\n");
+ Printf(f_wrappers, "}\n");
+ Printf(f_wrappers, "#endif\n");
+
+ // Check for overwriting file problems on filesystems that are case insensitive
+ Iterator it1;
+ Iterator it2;
+ for (it1 = First(filenames_list); it1.item; it1 = Next(it1)) {
+ String *item1_lower = Swig_string_lower(it1.item);
+ for (it2 = Next(it1); it2.item; it2 = Next(it2)) {
+ String *item2_lower = Swig_string_lower(it2.item);
+ if (it1.item && it2.item) {
+ if (Strcmp(item1_lower, item2_lower) == 0) {
+ Swig_warning(WARN_LANG_PORTABILITY_FILENAME, input_file, line_number,
+ "Portability warning: File %s will be overwritten by %s on case insensitive filesystems such as "
+ "Windows' FAT32 and NTFS unless the class/module name is renamed\n", it1.item, it2.item);
+ }
+ }
+ Delete(item2_lower);
+ }
+ Delete(item1_lower);
+ }
+
+ Delete(unknown_types);
+ unknown_types = NULL;
+ Delete(filenames_list);
+ filenames_list = NULL;
+ Delete(im_dmodule_name);
+ im_dmodule_name = NULL;
+ Delete(im_dmodule_fq_name);
+ im_dmodule_fq_name = NULL;
+ Delete(im_dmodule_code);
+ im_dmodule_code = NULL;
+ Delete(proxy_class_imports);
+ proxy_class_imports = NULL;
+ Delete(proxy_class_enums_code);
+ proxy_class_enums_code = NULL;
+ Delete(proxy_class_body_code);
+ proxy_class_body_code = NULL;
+ Delete(proxy_class_epilogue_code);
+ proxy_class_epilogue_code = NULL;
+ Delete(proxy_class_code);
+ proxy_class_code = NULL;
+ Delete(destructor_call);
+ destructor_call = NULL;
+ Delete(proxy_dmodule_name);
+ proxy_dmodule_name = NULL;
+ Delete(proxy_dmodule_fq_name);
+ proxy_dmodule_fq_name = NULL;
+ Delete(proxy_dmodule_code);
+ proxy_dmodule_code = NULL;
+ Delete(proxy_dmodule_imports);
+ proxy_dmodule_imports = NULL;
+ Delete(im_dmodule_imports);
+ im_dmodule_imports = NULL;
+ Delete(upcasts_code);
+ upcasts_code = NULL;
+ Delete(global_proxy_imports);
+ global_proxy_imports = NULL;
+ Delete(wrapper_loader_code);
+ wrapper_loader_code = NULL;
+ Delete(wrapper_loader_bind_code);
+ wrapper_loader_bind_code = NULL;
+ Delete(wrapper_loader_bind_command);
+ wrapper_loader_bind_command = NULL;
+ Delete(dmethods_seq);
+ dmethods_seq = NULL;
+ Delete(dmethods_table);
+ dmethods_table = NULL;
+ Delete(package);
+ package = NULL;
+ Delete(dmodule_directory);
+ dmodule_directory = NULL;
+ n_dmethods = 0;
+
+ // Merge all the generated C/C++ code and close the output files.
+ Dump(f_runtime, f_begin);
+ Dump(f_header, f_begin);
+
+ if (directorsEnabled()) {
+ Dump(f_directors, f_begin);
+ Dump(f_directors_h, f_runtime_h);
+
+ Printf(f_runtime_h, "\n");
+ Printf(f_runtime_h, "#endif\n");
+
+ Close(f_runtime_h);
+ Delete(f_runtime_h);
+ f_runtime_h = NULL;
+ Delete(f_directors);
+ f_directors = NULL;
+ Delete(f_directors_h);
+ f_directors_h = NULL;
+ }
+
+ Dump(f_wrappers, f_begin);
+ Wrapper_pretty_print(f_init, f_begin);
+ Delete(f_header);
+ Delete(f_wrappers);
+ Delete(f_init);
+ Close(f_begin);
+ Delete(f_runtime);
+ Delete(f_begin);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::insertDirective()
+ * --------------------------------------------------------------------------- */
+ virtual int insertDirective(Node *n) {
+ String *code = Getattr(n, "code");
+ replaceModuleVariables(code);
+ return Language::insertDirective(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::pragmaDirective()
+ *
+ * Valid Pragmas:
+ * imdmodulecode - text (D code) is copied verbatim to the wrap module
+ * imdmoduleimports - import statements for the im D module
+ *
+ * proxydmodulecode - text (D code) is copied verbatim to the proxy module
+ * (the main proxy module if in split proxy mode).
+ * globalproxyimports - import statements inserted into _all_ proxy modules.
+ *
+ * wrapperloadercode - D code for loading the wrapper library (is copied to
+ * the im D module).
+ * wrapperloaderbindcommand - D code for binding a symbol from the wrapper
+ * library to the declaration in the im D module.
+ * --------------------------------------------------------------------------- */
+ virtual int pragmaDirective(Node *n) {
+ if (!ImportMode) {
+ String *lang = Getattr(n, "lang");
+ String *code = Getattr(n, "name");
+ String *value = Getattr(n, "value");
+
+ if (Strcmp(lang, "d") == 0) {
+ String *strvalue = NewString(value);
+ Replaceall(strvalue, "\\\"", "\"");
+
+ if (Strcmp(code, "imdmodulecode") == 0) {
+ Printf(im_dmodule_code, "%s\n", strvalue);
+ } else if (Strcmp(code, "imdmoduleimports") == 0) {
+ replaceImportTypeMacros(strvalue);
+ Chop(strvalue);
+ Printf(im_dmodule_imports, "%s\n", strvalue);
+ } else if (Strcmp(code, "proxydmodulecode") == 0) {
+ Printf(proxy_dmodule_code, "%s\n", strvalue);
+ } else if (Strcmp(code, "globalproxyimports") == 0) {
+ replaceImportTypeMacros(strvalue);
+ Chop(strvalue);
+ Printf(global_proxy_imports, "%s\n", strvalue);
+ } else if (Strcmp(code, "wrapperloadercode") == 0) {
+ Delete(wrapper_loader_code);
+ wrapper_loader_code = Copy(strvalue);
+ } else if (Strcmp(code, "wrapperloaderbindcommand") == 0) {
+ Delete(wrapper_loader_bind_command);
+ wrapper_loader_bind_command = Copy(strvalue);
+ } else {
+ Swig_error(input_file, line_number, "Unrecognized pragma.\n");
+ }
+ Delete(strvalue);
+ }
+ }
+ return Language::pragmaDirective(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::enumDeclaration()
+ *
+ * Wraps C/C++ enums as D enums.
+ * --------------------------------------------------------------------------- */
+ virtual int enumDeclaration(Node *n) {
+ if (ImportMode)
+ return SWIG_OK;
+
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ proxy_enum_code = NewString("");
+ String *symname = Getattr(n, "sym:name");
+ String *typemap_lookup_type = Getattr(n, "name");
+
+ // Emit the enum declaration.
+ if (typemap_lookup_type) {
+ const String *enummodifiers = lookupCodeTypemap(n, "dclassmodifiers", typemap_lookup_type, WARN_D_TYPEMAP_CLASSMOD_UNDEF);
+ Printv(proxy_enum_code, "\n", enummodifiers, " ", symname, " {\n", NIL);
+ } else {
+ // Handle anonymous enums.
+ Printv(proxy_enum_code, "\nenum {\n", NIL);
+ }
+
+ // Emit each enum item.
+ Language::enumDeclaration(n);
+
+ if (!GetFlag(n, "nonempty")) {
+ // Do not wrap empty enums; the resulting D code would be illegal.
+ Delete(proxy_enum_code);
+ return SWIG_NOWRAP;
+ }
+
+ // Finish the enum.
+ if (typemap_lookup_type) {
+ Printv(proxy_enum_code,
+ lookupCodeTypemap(n, "dcode", typemap_lookup_type, WARN_NONE), // Extra D code
+ "\n}\n", NIL);
+ } else {
+ // Handle anonymous enums.
+ Printv(proxy_enum_code, "\n}\n", NIL);
+ }
+
+ Replaceall(proxy_enum_code, "$dclassname", symname);
+
+ const String* imports =
+ lookupCodeTypemap(n, "dimports", typemap_lookup_type, WARN_NONE);
+ String* imports_trimmed;
+ if (Len(imports) > 0) {
+ imports_trimmed = Copy(imports);
+ Chop(imports_trimmed);
+ replaceImportTypeMacros(imports_trimmed);
+ Printv(imports_trimmed, "\n", NIL);
+ } else {
+ imports_trimmed = NewString("");
+ }
+
+ if (is_wrapping_class()) {
+ // Enums defined within the C++ class are written into the proxy
+ // class.
+ Printv(proxy_class_imports, imports_trimmed, NIL);
+ Printv(proxy_class_enums_code, proxy_enum_code, NIL);
+ } else {
+ // Write non-anonymous enums to their own file if in split proxy module
+ // mode.
+ if (split_proxy_dmodule && typemap_lookup_type) {
+ assertClassNameValidity(proxy_class_name);
+
+ String *filename = NewStringf("%s%s.d", dmodule_directory, symname);
+ File *class_file = NewFile(filename, "w", SWIG_output_files());
+ if (!class_file) {
+ FileErrorDisplay(filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filename));
+ Delete(filename);
+
+ emitBanner(class_file);
+ Printf(class_file, "module %s%s;\n", package, symname);
+ Printv(class_file, imports_trimmed, NIL);
+
+ Printv(class_file, proxy_enum_code, NIL);
+
+ Close(class_file);
+ Delete(class_file);
+ } else {
+ Printv(proxy_dmodule_imports, imports, NIL);
+ Printv(proxy_dmodule_code, proxy_enum_code, NIL);
+ }
+ }
+
+ Delete(imports_trimmed);
+
+ Delete(proxy_enum_code);
+ proxy_enum_code = NULL;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::enumvalueDeclaration()
+ * --------------------------------------------------------------------------- */
+ virtual int enumvalueDeclaration(Node *n) {
+ if (getCurrentClass() && (cplus_mode != PUBLIC))
+ return SWIG_NOWRAP;
+
+ Swig_require("enumvalueDeclaration", n, "*name", "?value", NIL);
+ String *value = Getattr(n, "value");
+ String *name = Getattr(n, "name");
+ Node *parent = parentNode(n);
+ String *tmpValue;
+
+ // Strange hack from parent method.
+ // RESEARCH: What is this doing?
+ if (value)
+ tmpValue = NewString(value);
+ else
+ tmpValue = NewString(name);
+ // Note that this is used in enumValue() amongst other places
+ Setattr(n, "value", tmpValue);
+
+ String *proxy_name = Getattr(n, "sym:name");
+
+ // Emit the enum item.
+ {
+ if (!GetFlag(n, "firstenumitem"))
+ Printf(proxy_enum_code, ",\n");
+
+ Printf(proxy_enum_code, " %s", proxy_name);
+
+ // Check for the %dconstvalue feature
+ String *value = Getattr(n, "feature:d:constvalue");
+
+ // Note that in D, enum values must be compile-time constants. Thus,
+ // %dmanifestconst(0) (getting the enum values at runtime) is not supported.
+ value = value ? value : Getattr(n, "enumvalue");
+ if (value) {
+ Printf(proxy_enum_code, " = %s", value);
+ }
+
+ // Keep track that the currently processed enum has at least one value.
+ SetFlag(parent, "nonempty");
+ }
+
+ Delete(tmpValue);
+ Swig_restore(n);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::memberfunctionHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int memberfunctionHandler(Node *n) {
+ Language::memberfunctionHandler(n);
+
+ String *overloaded_name = getOverloadedName(n);
+ String *intermediary_function_name =
+ Swig_name_member(NSPACE_TODO,proxy_class_name, overloaded_name);
+ Setattr(n, "imfuncname", intermediary_function_name);
+
+ String *proxy_func_name = Getattr(n, "sym:name");
+ Setattr(n, "proxyfuncname", proxy_func_name);
+ if (split_proxy_dmodule &&
+ Len(Getattr(n, "parms")) == 0 &&
+ Strncmp(proxy_func_name, package, Len(proxy_func_name)) == 0) {
+ // If we are in split proxy mode and the function is named like the
+ // target package, the D compiler is unable to resolve the ambiguity
+ // between the package name and an argument-less function call.
+ Swig_warning(WARN_D_NAME_COLLISION, input_file, line_number,
+ "%s::%s might collide with the package name, consider using %%rename to resolve the ambiguity.\n",
+ proxy_class_name, proxy_func_name);
+ }
+
+ writeProxyClassFunction(n);
+
+ Delete(overloaded_name);
+
+ // For each function, look if we have to alias in the parent class function
+ // for the overload resolution process to work as expected from C++
+ // (http://www.digitalmars.com/d/2.0/function.html#function-inheritance).
+ // For multiple overloads, only emit the alias directive once (for the
+ // last method, »sym:nextSibling« is null then).
+ // Smart pointer classes do not mirror the inheritance hierarchy of the
+ // underlying types, so aliasing the base class methods in is not required
+ // for them.
+ // DMD BUG: We have to emit the alias after the last function becasue
+ // taking a delegate in the overload checking code fails otherwise
+ // (http://d.puremagic.com/issues/show_bug.cgi?id=4860).
+ if (!Getattr(n, "sym:nextSibling") && !is_smart_pointer() &&
+ !areAllOverloadsOverridden(n)) {
+ String *name = Getattr(n, "sym:name");
+ Printf(proxy_class_body_code, "\nalias $dbaseclass.%s %s;\n", name, name);
+ }
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::staticmemberfunctionHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int staticmemberfunctionHandler(Node *n) {
+ static_flag = true;
+
+ Language::staticmemberfunctionHandler(n);
+
+ String *overloaded_name = getOverloadedName(n);
+ String *intermediary_function_name =
+ Swig_name_member(NSPACE_TODO,proxy_class_name, overloaded_name);
+ Setattr(n, "proxyfuncname", Getattr(n, "sym:name"));
+ Setattr(n, "imfuncname", intermediary_function_name);
+ writeProxyClassFunction(n);
+ Delete(overloaded_name);
+
+ static_flag = false;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::globalvariableHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int globalvariableHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ global_variable_flag = true;
+ int ret = Language::globalvariableHandler(n);
+ global_variable_flag = false;
+
+ return ret;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::membervariableHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int membervariableHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ variable_wrapper_flag = true;
+ Language::membervariableHandler(n);
+ wrapping_member_flag = false;
+ variable_wrapper_flag = false;
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::staticmembervariableHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int staticmembervariableHandler(Node *n) {
+ if (GetFlag(n, "feature:d:manifestconst") != 1) {
+ Delattr(n, "value");
+ }
+
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ static_flag = true;
+ Language::staticmembervariableHandler(n);
+ wrapping_member_flag = false;
+ static_flag = false;
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::memberconstantHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int memberconstantHandler(Node *n) {
+ variable_name = Getattr(n, "sym:name");
+ wrapping_member_flag = true;
+ Language::memberconstantHandler(n);
+ wrapping_member_flag = false;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::constructorHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int constructorHandler(Node *n) {
+ Language::constructorHandler(n);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in D.
+ if (Getattr(n, "overload:ignore")) {
+ return SWIG_OK;
+ }
+
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ String *proxy_constructor_code = NewString("");
+ int i;
+
+ // Holds code for the constructor helper method generated only when the din
+ // typemap has code in the pre or post attributes.
+ String *helper_code = NewString("");
+ String *helper_args = NewString("");
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+ NewString("");
+
+ String *overloaded_name = getOverloadedName(n);
+ String *mangled_overname = Swig_name_construct(NSPACE_TODO,overloaded_name);
+ String *imcall = NewString("");
+
+ const String *methodmods = Getattr(n, "feature:d:methodmodifiers");
+ methodmods = methodmods ? methodmods : (is_public(n) ? public_string : protected_string);
+
+ // Typemaps were attached earlier to the node, get the return type of the
+ // call to the C++ constructor wrapper.
+ const String *wrapper_return_type = lookupDTypemap(n, "imtype", true);
+
+ String *imtypeout = Getattr(n, "tmap:imtype:out");
+ if (imtypeout) {
+ // The type in the imtype typemap's out attribute overrides the type in
+ // the typemap itself.
+ wrapper_return_type = imtypeout;
+ }
+
+ Printf(proxy_constructor_code, "\n%s this(", methodmods);
+ Printf(helper_code, "static private %s SwigConstruct%s(",
+ wrapper_return_type, proxy_class_name);
+
+ Printv(imcall, im_dmodule_fq_name, ".", mangled_overname, "(", NIL);
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("dtype", l, NULL);
+ Swig_typemap_attach_parms("din", l, NULL);
+
+ emit_mark_varargs(l);
+
+ int gencomma = 0;
+
+ /* Output each parameter */
+ Parm *p = l;
+ for (i = 0; p; i++) {
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ // Skip ignored varargs.
+ p = nextSibling(p);
+ continue;
+ }
+
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ // Skip ignored parameters.
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ // Get the D parameter type.
+ if ((tm = lookupDTypemap(p, "dtype", true))) {
+ const String *inattributes = Getattr(p, "tmap:dtype:inattributes");
+ Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ String *arg = makeParameterName(n, p, i, false);
+ String *parmtype = 0;
+
+ // Get the D code to convert the parameter value to the type used in the
+ // intermediary D module.
+ if ((tm = lookupDTypemap(p, "din"))) {
+ Replaceall(tm, "$dinput", arg);
+ String *pre = Getattr(p, "tmap:din:pre");
+ if (pre) {
+ replaceClassname(pre, pt);
+ Replaceall(pre, "$dinput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:din:post");
+ if (post) {
+ replaceClassname(post, pt);
+ Replaceall(post, "$dinput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:din:terminator");
+ if (terminator) {
+ replaceClassname(terminator, pt);
+ Replaceall(terminator, "$dinput", arg);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ parmtype = Getattr(p, "tmap:din:parmtype");
+ if (parmtype)
+ Replaceall(parmtype, "$dinput", arg);
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DIN_UNDEF, input_file, line_number,
+ "No din typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to proxy function */
+ if (gencomma) {
+ Printf(proxy_constructor_code, ", ");
+ Printf(helper_code, ", ");
+ Printf(helper_args, ", ");
+ }
+ Printf(proxy_constructor_code, "%s %s", param_type, arg);
+ Printf(helper_code, "%s %s", param_type, arg);
+ Printf(helper_args, "%s", parmtype ? parmtype : arg);
+ ++gencomma;
+
+ Delete(parmtype);
+ Delete(arg);
+ Delete(param_type);
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+
+ Printf(proxy_constructor_code, ")");
+ Printf(helper_code, ")");
+
+ // Insert the dconstructor typemap (replacing $directorconnect as needed).
+ Hash *attributes = NewHash();
+ String *construct_tm = Copy(lookupCodeTypemap(n, "dconstructor",
+ Getattr(n, "name"), WARN_D_TYPEMAP_DCONSTRUCTOR_UNDEF, attributes));
+ if (construct_tm) {
+ const bool use_director = (parentNode(n) && Swig_directorclass(n));
+ if (!use_director) {
+ Replaceall(construct_tm, "$directorconnect", "");
+ } else {
+ String *connect_attr = Getattr(attributes, "tmap:dconstructor:directorconnect");
+
+ if (connect_attr) {
+ Replaceall(construct_tm, "$directorconnect", connect_attr);
+ } else {
+ Swig_warning(WARN_D_NO_DIRECTORCONNECT_ATTR, input_file, line_number,
+ "\"directorconnect\" attribute missing in %s \"dconstructor\" typemap.\n",
+ Getattr(n, "name"));
+ Replaceall(construct_tm, "$directorconnect", "");
+ }
+ }
+
+ Printv(proxy_constructor_code, " ", construct_tm, NIL);
+ }
+
+ replaceExcode(n, proxy_constructor_code, "dconstructor", attributes);
+
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ Printf(helper_code, " {\n");
+ if (is_pre_code) {
+ Printv(helper_code, pre_code, "\n", NIL);
+ }
+ if (is_post_code) {
+ Printf(helper_code, " try {\n");
+ Printv(helper_code, " return ", imcall, ";\n", NIL);
+ Printv(helper_code, " } finally {\n", post_code, "\n }", NIL);
+ } else {
+ Printv(helper_code, " return ", imcall, ";", NIL);
+ }
+ if (is_terminator_code) {
+ Printv(helper_code, "\n", terminator_code, NIL);
+ }
+ Printf(helper_code, "\n}\n");
+ String *helper_name = NewStringf("%s.SwigConstruct%s(%s)",
+ proxy_class_name, proxy_class_name, helper_args);
+ Replaceall(proxy_constructor_code, "$imcall", helper_name);
+ Delete(helper_name);
+ } else {
+ Replaceall(proxy_constructor_code, "$imcall", imcall);
+ }
+
+ Printv(proxy_class_body_code, proxy_constructor_code, "\n", NIL);
+
+ Delete(helper_args);
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(construct_tm);
+ Delete(attributes);
+ Delete(overloaded_name);
+ Delete(imcall);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::destructorHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int destructorHandler(Node *n) {
+ Language::destructorHandler(n);
+ String *symname = Getattr(n, "sym:name");
+ Printv(destructor_call, im_dmodule_fq_name, ".", Swig_name_destroy(NSPACE_TODO,symname), "(cast(void*)swigCPtr)", NIL);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classHandler()
+ * --------------------------------------------------------------------------- */
+ virtual int classHandler(Node *n) {
+ File *class_file = NULL;
+
+ proxy_class_name = Copy(Getattr(n, "sym:name"));
+
+ if (!addSymbol(proxy_class_name, n)) {
+ return SWIG_ERROR;
+ }
+
+ assertClassNameValidity(proxy_class_name);
+
+ if (split_proxy_dmodule) {
+ String *filename = NewStringf("%s%s.d", dmodule_directory, proxy_class_name);
+ class_file = NewFile(filename, "w", SWIG_output_files());
+ if (!class_file) {
+ FileErrorDisplay(filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filename));
+ Delete(filename);
+
+ emitBanner(class_file);
+ Printf(class_file, "module %s%s;\n", package, proxy_class_name);
+ Printf(class_file, "\nstatic import %s;\n", im_dmodule_fq_name);
+ }
+
+ Clear(proxy_class_imports);
+ Clear(proxy_class_enums_code);
+ Clear(proxy_class_body_code);
+ Clear(proxy_class_epilogue_code);
+ Clear(proxy_class_code);
+ Clear(destructor_call);
+
+
+ Language::classHandler(n);
+
+
+ writeProxyClassAndUpcasts(n);
+ writeDirectorConnectWrapper(n);
+
+ Replaceall(proxy_class_code, "$dclassname", proxy_class_name);
+
+ if (split_proxy_dmodule) {
+ Printv(class_file, global_proxy_imports, NIL);
+ Printv(class_file, proxy_class_imports, NIL);
+
+ replaceModuleVariables(proxy_class_code);
+ Printv(class_file, proxy_class_code, NIL);
+
+ Close(class_file);
+ Delete(class_file);
+ } else {
+ Printv(proxy_dmodule_imports, proxy_class_imports, NIL);
+ Printv(proxy_dmodule_code, proxy_class_code, NIL);
+ }
+
+ Delete(proxy_class_name);
+ proxy_class_name = NULL;
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::constantWrapper()
+ *
+ * Used for wrapping constants declared by #define or %constant and also for
+ * (primitive) static member constants initialised inline.
+ *
+ * If the %dmanifestconst feature is used, the C/C++ constant value is used to
+ * initialize a D »const«. If not, a »getter« method is generated which
+ * retrieves the value via a call to the C wrapper. However, if there is a
+ * %dconstvalue specified, it overrides all other settings.
+ * --------------------------------------------------------------------------- */
+ virtual int constantWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ if (!addSymbol(symname, n))
+ return SWIG_ERROR;
+
+ // The %dmanifestconst feature determines if a D manifest constant
+ // (const/enum) or a getter function is created.
+ if (GetFlag(n, "feature:d:manifestconst") != 1) {
+ // Default constant handling will work with any type of C constant. It
+ // generates a getter function (which is the same as a read only property
+ // in D) which retrieves the value via by calling the C wrapper.
+ // Note that this is only called for global constants, static member
+ // constants are already handeled in staticmemberfunctionHandler().
+
+ Swig_save("constantWrapper", n, "value", NIL);
+
+ // Add the stripped quotes back in.
+ String *old_value = Getattr(n, "value");
+ SwigType *t = Getattr(n, "type");
+ if (SwigType_type(t) == T_STRING) {
+ Setattr(n, "value", NewStringf("\"%s\"", old_value));
+ Delete(old_value);
+ } else if (SwigType_type(t) == T_CHAR) {
+ Setattr(n, "value", NewStringf("\'%s\'", old_value));
+ Delete(old_value);
+ }
+
+ int result = globalvariableHandler(n);
+
+ Swig_restore(n);
+ return result;
+ }
+
+ String *constants_code = NewString("");
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+
+ // Attach the non-standard typemaps to the parameter list.
+ Swig_typemap_attach_parms("dtype", l, NULL);
+
+ // Get D return type.
+ String *return_type = NewString("");
+ String *tm;
+ if ((tm = lookupDTypemap(n, "dtype"))) {
+ String *dtypeout = Getattr(n, "tmap:dtype:out");
+ if (dtypeout) {
+ // The type in the out attribute of the typemap overrides the type
+ // in the dtype typemap.
+ tm = dtypeout;
+ replaceClassname(tm, t);
+ }
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ const String *itemname = wrapping_member_flag ? variable_name : symname;
+
+ String *attributes = Getattr(n, "feature:d:methodmodifiers");
+ if (attributes) {
+ attributes = Copy(attributes);
+ } else {
+ attributes = Copy(is_public(n) ? public_string : protected_string);
+ }
+
+ if (d_version == 1) {
+ if (static_flag) {
+ Printv(attributes, " static", NIL);
+ }
+ Printf(constants_code, "\n%s const %s %s = ", attributes, return_type, itemname);
+ } else {
+ Printf(constants_code, "\n%s enum %s %s = ", attributes, return_type, itemname);
+ }
+ Delete(attributes);
+
+ // Retrive the override value set via %dconstvalue, if any.
+ String *override_value = Getattr(n, "feature:d:constvalue");
+ if (override_value) {
+ Printf(constants_code, "%s;\n", override_value);
+ } else {
+ // Just take the value from the C definition and hope it compiles in D.
+ String* value = Getattr(n, "wrappedasconstant") ?
+ Getattr(n, "staticmembervariableHandler:value") : Getattr(n, "value");
+
+ // Add the stripped quotes back in.
+ if (SwigType_type(t) == T_STRING) {
+ Printf(constants_code, "\"%s\";\n", value);
+ } else if (SwigType_type(t) == T_CHAR) {
+ Printf(constants_code, "\'%s\';\n", value);
+ } else {
+ Printf(constants_code, "%s;\n", value);
+ }
+ }
+
+ // Emit the generated code to appropriate place.
+ if (wrapping_member_flag) {
+ Printv(proxy_class_body_code, constants_code, NIL);
+ } else {
+ Printv(proxy_dmodule_code, constants_code, NIL);
+ }
+
+ // Cleanup.
+ Delete(return_type);
+ Delete(constants_code);
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::functionWrapper()
+ *
+ * Generates the C wrapper code for a function and the corresponding
+ * declaration in the wrap D module.
+ * --------------------------------------------------------------------------- */
+ virtual int functionWrapper(Node *n) {
+ String *symname = Getattr(n, "sym:name");
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *c_return_type = NewString("");
+ String *im_return_type = NewString("");
+ String *cleanup = NewString("");
+ String *outarg = NewString("");
+ String *body = NewString("");
+ int num_arguments = 0;
+ int num_required = 0;
+ bool is_void_return;
+ String *overloaded_name = getOverloadedName(n);
+
+ if (!Getattr(n, "sym:overloaded")) {
+ if (!addSymbol(Getattr(n, "sym:name"), n))
+ return SWIG_ERROR;
+ }
+
+ // A new wrapper function object
+ Wrapper *f = NewWrapper();
+
+ // Make a wrapper name for this function
+ String *wname = Swig_name_wrapper(overloaded_name);
+
+ /* Attach the non-standard typemaps to the parameter list. */
+ Swig_typemap_attach_parms("ctype", l, f);
+ Swig_typemap_attach_parms("imtype", l, f);
+
+ /* Get return types */
+ if ((tm = lookupDTypemap(n, "ctype"))) {
+ String *ctypeout = Getattr(n, "tmap:ctype:out");
+ if (ctypeout) {
+ // The type in the ctype typemap's out attribute overrides the type in
+ // the typemap itself.
+ tm = ctypeout;
+ }
+ Printf(c_return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
+ "No ctype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if ((tm = lookupDTypemap(n, "imtype"))) {
+ String *imtypeout = Getattr(n, "tmap:imtype:out");
+ if (imtypeout) {
+ // The type in the imtype typemap's out attribute overrides the type in
+ // the typemap itself.
+ tm = imtypeout;
+ }
+ Printf(im_return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ is_void_return = (Cmp(c_return_type, "void") == 0);
+ if (!is_void_return)
+ Wrapper_add_localv(f, "jresult", c_return_type, "jresult", NIL);
+
+ Printv(f->def, " SWIGEXPORT ", c_return_type, " ", wname, "(", NIL);
+
+ // Emit all of the local variables for holding arguments.
+ emit_parameter_variables(l, f);
+
+ /* Attach the standard typemaps */
+ emit_attach_parmmaps(l, f);
+
+ // Parameter overloading
+ Setattr(n, "wrap:parms", l);
+ Setattr(n, "wrap:name", wname);
+
+ // Wrappers not wanted for some methods where the parameters cannot be overloaded in D
+ if (Getattr(n, "sym:overloaded")) {
+ // Emit warnings for the few cases that can't be overloaded in D and give up on generating wrapper
+ Swig_overload_check(n);
+ if (Getattr(n, "overload:ignore"))
+ return SWIG_OK;
+ }
+
+ // Collect the parameter list for the intermediary D module declaration of
+ // the generated wrapper function.
+ String *im_dmodule_parameters = NewString("(");
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+ num_required = emit_num_required(l);
+ int gencomma = 0;
+
+ // Now walk the function parameter list and generate code to get arguments
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = Getattr(p, "lname");
+ String *im_param_type = NewString("");
+ String *c_param_type = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ /* Get the ctype types of the parameter */
+ if ((tm = lookupDTypemap(p, "ctype", true))) {
+ Printv(c_param_type, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number, "No ctype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Get the intermediary class parameter types of the parameter */
+ if ((tm = lookupDTypemap(p, "imtype", true))) {
+ const String *inattributes = Getattr(p, "tmap:imtype:inattributes");
+ Printf(im_param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number, "No imtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to intermediary class method */
+ if (gencomma)
+ Printf(im_dmodule_parameters, ", ");
+ Printf(im_dmodule_parameters, "%s %s", im_param_type, arg);
+
+ // Add parameter to C function
+ Printv(f->def, gencomma ? ", " : "", c_param_type, " ", arg, NIL);
+
+ gencomma = 1;
+
+ // Get typemap for this argument
+ if ((tm = Getattr(p, "tmap:in"))) {
+ canThrow(n, "in", p);
+ Replaceall(tm, "$input", arg);
+ Setattr(p, "emit:input", arg);
+ Printf(f->code, "%s\n", tm);
+ p = Getattr(p, "tmap:in:next");
+ } else {
+ Swig_warning(WARN_TYPEMAP_IN_UNDEF, input_file, line_number, "Unable to use type %s as a function argument.\n", SwigType_str(pt, 0));
+ p = nextSibling(p);
+ }
+ Delete(im_param_type);
+ Delete(c_param_type);
+ Delete(arg);
+ }
+
+ /* Insert constraint checking code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:check"))) {
+ canThrow(n, "check", p);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(f->code, tm, "\n", NIL);
+ p = Getattr(p, "tmap:check:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert cleanup code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:freearg"))) {
+ canThrow(n, "freearg", p);
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(cleanup, tm, "\n", NIL);
+ p = Getattr(p, "tmap:freearg:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ /* Insert argument output code */
+ for (p = l; p;) {
+ if ((tm = Getattr(p, "tmap:argout"))) {
+ canThrow(n, "argout", p);
+ Replaceall(tm, "$result", "jresult");
+ Replaceall(tm, "$input", Getattr(p, "emit:input"));
+ Printv(outarg, tm, "\n", NIL);
+ p = Getattr(p, "tmap:argout:next");
+ } else {
+ p = nextSibling(p);
+ }
+ }
+
+ // Look for usage of throws typemap and the canthrow flag
+ ParmList *throw_parm_list = NULL;
+ if ((throw_parm_list = Getattr(n, "catchlist"))) {
+ Swig_typemap_attach_parms("throws", throw_parm_list, f);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if ((tm = Getattr(p, "tmap:throws"))) {
+ canThrow(n, "throws", p);
+ }
+ }
+ }
+
+ String *null_attribute = 0;
+ // Now write code to make the function call
+ if (!native_function_flag) {
+ if (Cmp(nodeType(n), "constant") == 0) {
+ // Wrapping a constant hack
+ Swig_save("functionWrapper", n, "wrap:action", NIL);
+
+ // below based on Swig_VargetToFunction()
+ SwigType *ty = Swig_wrapped_var_type(Getattr(n, "type"), use_naturalvar_mode(n));
+ Setattr(n, "wrap:action", NewStringf("result = (%s) %s;", SwigType_lstr(ty, 0), Getattr(n, "value")));
+ }
+
+ Swig_director_emit_dynamic_cast(n, f);
+ String *actioncode = emit_action(n);
+
+ if (Cmp(nodeType(n), "constant") == 0)
+ Swig_restore(n);
+
+ /* Return value if necessary */
+ if ((tm = Swig_typemap_lookup_out("out", n, "result", f, actioncode))) {
+ canThrow(n, "out", n);
+ Replaceall(tm, "$result", "jresult");
+
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "1");
+ else
+ Replaceall(tm, "$owner", "0");
+
+ Printf(f->code, "%s", tm);
+ null_attribute = Getattr(n, "tmap:out:null");
+ if (Len(tm))
+ Printf(f->code, "\n");
+ } else {
+ Swig_warning(WARN_TYPEMAP_OUT_UNDEF, input_file, line_number, "Unable to use return type %s in function %s.\n", SwigType_str(t, 0), Getattr(n, "name"));
+ }
+ emit_return_variable(n, t, f);
+ }
+
+ /* Output argument output code */
+ Printv(f->code, outarg, NIL);
+
+ /* Output cleanup code */
+ Printv(f->code, cleanup, NIL);
+
+ /* Look to see if there is any newfree cleanup code */
+ if (GetFlag(n, "feature:new")) {
+ if ((tm = Swig_typemap_lookup("newfree", n, "result", 0))) {
+ canThrow(n, "newfree", n);
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ /* See if there is any return cleanup code */
+ if (!native_function_flag) {
+ if ((tm = Swig_typemap_lookup("ret", n, "result", 0))) {
+ canThrow(n, "ret", n);
+ Printf(f->code, "%s\n", tm);
+ }
+ }
+
+ // Complete D im parameter list and emit the declaration/binding code.
+ Printv(im_dmodule_parameters, ")", NIL);
+ writeImDModuleFunction(overloaded_name, im_return_type,
+ im_dmodule_parameters, wname);
+ Delete(im_dmodule_parameters);
+
+ // Finish C function header.
+ Printf(f->def, ") {");
+
+ if (!is_void_return)
+ Printv(f->code, " return jresult;\n", NIL);
+ Printf(f->code, "}\n");
+
+ /* Substitute the cleanup code */
+ Replaceall(f->code, "$cleanup", cleanup);
+
+ /* Substitute the function name */
+ Replaceall(f->code, "$symname", symname);
+
+ /* Contract macro modification */
+ if (Replaceall(f->code, "SWIG_contract_assert(", "SWIG_contract_assert($null, ") > 0) {
+ Setattr(n, "d:canthrow", "1");
+ }
+
+ if (!null_attribute)
+ Replaceall(f->code, "$null", "0");
+ else
+ Replaceall(f->code, "$null", null_attribute);
+
+ /* Dump the function out */
+ if (!native_function_flag) {
+ Wrapper_print(f, f_wrappers);
+
+ // Handle %exception which sets the canthrow attribute.
+ if (Getattr(n, "feature:except:canthrow")) {
+ Setattr(n, "d:canthrow", "1");
+ }
+
+ // A very simple check (it is not foolproof) to assist typemap writers
+ // with setting the correct features when the want to throw D exceptions
+ // from C++ code. It checks for the common methods which set
+ // a pending D exception and issues a warning if one of them has been found
+ // in the typemap, but the »canthrow« attribute/feature is not set.
+ if (!Getattr(n, "d:canthrow")) {
+ if (Strstr(f->code, "SWIG_exception")) {
+ Swig_warning(WARN_D_CANTHROW_MISSING, input_file, line_number,
+ "C code contains a call to SWIG_exception and D code does not handle pending exceptions via the canthrow attribute.\n");
+ } else if (Strstr(f->code, "SWIG_DSetPendingException")) {
+ Swig_warning(WARN_D_CANTHROW_MISSING, input_file, line_number,
+ "C code contains a call to a SWIG_DSetPendingException method and D code does not handle pending exceptions via the canthrow attribute.\n");
+ }
+ }
+ }
+
+ // If we are not processing an enum or constant, and we were not generating
+ // a wrapper function which will be accessed via a proxy class, write a
+ // function to the proxy D module.
+ if (!is_wrapping_class()) {
+ writeProxyDModuleFunction(n);
+ }
+
+ // If we are processing a public member variable, write the property-style
+ // member function to the proxy class.
+ if (wrapping_member_flag) {
+ Setattr(n, "proxyfuncname", variable_name);
+ Setattr(n, "imfuncname", symname);
+
+ writeProxyClassFunction(n);
+ }
+
+ Delete(c_return_type);
+ Delete(im_return_type);
+ Delete(cleanup);
+ Delete(outarg);
+ Delete(body);
+ Delete(overloaded_name);
+ DelWrapper(f);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::nativeWrapper()
+ * --------------------------------------------------------------------------- */
+ virtual int nativeWrapper(Node *n) {
+ String *wrapname = Getattr(n, "wrap:name");
+
+ if (!addSymbol(wrapname, n))
+ return SWIG_ERROR;
+
+ if (Getattr(n, "type")) {
+ Swig_save("nativeWrapper", n, "name", NIL);
+ Setattr(n, "name", wrapname);
+ native_function_flag = true;
+ functionWrapper(n);
+ Swig_restore(n);
+ native_function_flag = false;
+ } else {
+ Swig_error(input_file, line_number, "No return type for %%native method %s.\n", Getattr(n, "wrap:name"));
+ }
+
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirector()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirector(Node *n) {
+ proxy_class_name = NewString(Getattr(n, "sym:name"));
+
+ int success = Language::classDirector(n);
+
+ Delete(proxy_class_name);
+ proxy_class_name = NULL;
+
+ return success;
+ }
+
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorInit()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorInit(Node *n) {
+ Delete(director_ctor_code);
+ director_ctor_code = NewString("$director_new");
+
+ // Write C++ director class declaration, for example:
+ // class SwigDirector_myclass : public myclass, public Swig::Director {
+ String *classname = Swig_class_name(n);
+ String *directorname = NewStringf("SwigDirector_%s", classname);
+ String *declaration = Swig_class_declaration(n, directorname);
+ const String *base = Getattr(n, "classtype");
+
+ Printf(f_directors_h,
+ "%s : public %s, public Swig::Director {\n", declaration, base);
+ Printf(f_directors_h, "\npublic:\n");
+
+ Delete(declaration);
+ Delete(directorname);
+ Delete(classname);
+
+ // Stash for later.
+ Setattr(n, "director:ctor", NewString("Swig::Director()"));
+
+ // Keep track of the director methods for this class.
+ first_class_dmethod = curr_class_dmethod = n_dmethods;
+
+ director_callback_typedefs = NewString("");
+ director_callback_pointers = NewString("");
+ director_dcallbacks_code = NewString("");
+
+ return Language::classDirectorInit(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorMethod()
+ *
+ * Emit a virtual director method to pass a method call on to the
+ * underlying D object.
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorMethod(Node *n, Node *parent, String *super) {
+ String *empty_str = NewString("");
+ String *classname = Getattr(parent, "sym:name");
+ String *c_classname = Getattr(parent, "name");
+ String *name = Getattr(n, "name");
+ String *symname = Getattr(n, "sym:name");
+ SwigType *type = Getattr(n, "type");
+ SwigType *returntype = Getattr(n, "returntype");
+ String *overloaded_name = getOverloadedName(n);
+ String *storage = Getattr(n, "storage");
+ String *value = Getattr(n, "value");
+ String *decl = Getattr(n, "decl");
+ String *declaration = NewString("");
+ String *tm;
+ Parm *p;
+ int i;
+ Wrapper *w = NewWrapper();
+ ParmList *l = Getattr(n, "parms");
+ bool is_void = !(Cmp(returntype, "void"));
+ String *qualified_return = NewString("");
+ bool pure_virtual = (!(Cmp(storage, "virtual")) && !(Cmp(value, "0")));
+ int status = SWIG_OK;
+ bool output_director = true;
+ String *dirclassname = getDirectorClassName(parent);
+ String *qualified_name = NewStringf("%s::%s", dirclassname, name);
+ SwigType *c_ret_type = NULL;
+ String *dcallback_call_args = NewString("");
+ String *imclass_dmethod;
+ String *callback_typedef_parms = NewString("");
+ String *delegate_parms = NewString("");
+ String *proxy_method_param_list = NewString("");
+ String *proxy_callback_return_type = NewString("");
+ String *callback_def = NewString("");
+ String *callback_code = NewString("");
+ String *imcall_args = NewString("");
+ bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
+
+ // Kludge Alert: functionWrapper sets sym:overload properly, but it
+ // isn't at this point, so we have to manufacture it ourselves. At least
+ // we're consistent with the sym:overload name in functionWrapper. (?? when
+ // does the overloaded method name get set?)
+
+ imclass_dmethod = NewStringf("SwigDirector_%s", Swig_name_member(NSPACE_TODO,classname, overloaded_name));
+
+ if (returntype) {
+ qualified_return = SwigType_rcaststr(returntype, "c_result");
+
+ if (!is_void && !ignored_method) {
+ if (!SwigType_isclass(returntype)) {
+ if (!(SwigType_ispointer(returntype) || SwigType_isreference(returntype))) {
+ String *construct_result = NewStringf("= SwigValueInit< %s >()", SwigType_lstr(returntype, 0));
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), construct_result, NIL);
+ Delete(construct_result);
+ } else {
+ String *base_typename = SwigType_base(returntype);
+ String *resolved_typename = SwigType_typedef_resolve_all(base_typename);
+ Symtab *symtab = Getattr(n, "sym:symtab");
+ Node *typenode = Swig_symbol_clookup(resolved_typename, symtab);
+
+ if (SwigType_ispointer(returntype) || (typenode && Getattr(typenode, "abstract"))) {
+ /* initialize pointers to something sane. Same for abstract
+ classes when a reference is returned. */
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= 0", NIL);
+ } else {
+ /* If returning a reference, initialize the pointer to a sane
+ default - if a D exception occurs, then the pointer returns
+ something other than a NULL-initialized reference. */
+ String *non_ref_type = Copy(returntype);
+
+ /* Remove reference and const qualifiers */
+ Replaceall(non_ref_type, "r.", "");
+ Replaceall(non_ref_type, "q(const).", "");
+ Wrapper_add_localv(w, "result_default", "static", SwigType_str(non_ref_type, "result_default"), "=", SwigType_str(non_ref_type, "()"), NIL);
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), "= &result_default", NIL);
+
+ Delete(non_ref_type);
+ }
+
+ Delete(base_typename);
+ Delete(resolved_typename);
+ }
+ } else {
+ SwigType *vt;
+
+ vt = cplus_value_type(returntype);
+ if (!vt) {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(returntype, "c_result"), NIL);
+ } else {
+ Wrapper_add_localv(w, "c_result", SwigType_lstr(vt, "c_result"), NIL);
+ Delete(vt);
+ }
+ }
+ }
+
+ /* Create the intermediate class wrapper */
+ Parm *tp = NewParm(returntype, empty_str, n);
+
+ tm = lookupDTypemap(tp, "imtype");
+ if (tm) {
+ String *imtypeout = Getattr(tp, "tmap:imtype:out");
+ if (imtypeout) {
+ // The type in the imtype typemap's out attribute overrides the type
+ // in the typemap.
+ tm = imtypeout;
+ }
+ Printf(callback_def, "\nprivate extern(C) %s swigDirectorCallback_%s_%s(void* dObject", tm, classname, overloaded_name);
+ Printv(proxy_callback_return_type, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number,
+ "No imtype typemap defined for %s\n", SwigType_str(returntype, 0));
+ }
+
+ Parm *retpm = NewParm(returntype, empty_str, n);
+
+ if ((c_ret_type = Swig_typemap_lookup("ctype", retpm, "", 0))) {
+ if (!is_void && !ignored_method) {
+ String *jretval_decl = NewStringf("%s jresult", c_ret_type);
+ Wrapper_add_localv(w, "jresult", jretval_decl, "= 0", NIL);
+ Delete(jretval_decl);
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
+ "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(retpm);
+ }
+
+ /* Go through argument list, attach lnames for arguments */
+ for (i = 0, p = l; p; p = nextSibling(p), ++i) {
+ String *arg = Getattr(p, "name");
+ String *lname = NewString("");
+
+ if (!arg && Cmp(Getattr(p, "type"), "void")) {
+ lname = NewStringf("arg%d", i);
+ Setattr(p, "name", lname);
+ } else
+ lname = arg;
+
+ Setattr(p, "lname", lname);
+ }
+
+ // Attach the standard typemaps.
+ Swig_typemap_attach_parms("out", l, 0);
+ Swig_typemap_attach_parms("ctype", l, 0);
+ Swig_typemap_attach_parms("imtype", l, 0);
+ Swig_typemap_attach_parms("dtype", l, 0);
+ Swig_typemap_attach_parms("directorin", l, 0);
+ Swig_typemap_attach_parms("ddirectorin", l, 0);
+
+ // Preamble code.
+ if (!ignored_method)
+ Printf(w->code, "if (!swig_callback_%s) {\n", overloaded_name);
+
+ if (!pure_virtual) {
+ String *super_call = Swig_method_call(super, l);
+ if (is_void) {
+ Printf(w->code, "%s;\n", super_call);
+ if (!ignored_method)
+ Printf(w->code, "return;\n");
+ } else {
+ Printf(w->code, "return %s;\n", super_call);
+ }
+ Delete(super_call);
+ } else {
+ Printf(w->code, " throw Swig::DirectorPureVirtualException(\"%s::%s\");\n", SwigType_namestr(c_classname), SwigType_namestr(name));
+ }
+
+ if (!ignored_method)
+ Printf(w->code, "} else {\n");
+
+ // Go through argument list.
+ for (i = 0, p = l; p; ++i) {
+ /* Is this superfluous? */
+ while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
+ p = Getattr(p, "tmap:directorin:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *ln = makeParameterName(n, p, i, false);
+ String *c_param_type = NULL;
+ String *c_decl = NewString("");
+ String *arg = NewString("");
+
+ Printf(arg, "j%s", ln);
+
+ // Add each parameter to the D callback invocation arguments.
+ Printf(dcallback_call_args, ", %s", arg);
+
+ /* Get parameter's intermediary C type */
+ if ((c_param_type = lookupDTypemap(p, "ctype", true))) {
+ String *ctypeout = Getattr(p, "tmap:ctype:out");
+ if (ctypeout) {
+ // The type in the ctype typemap's out attribute overrides the type
+ // in the typemap itself.
+ c_param_type = ctypeout;
+ }
+
+ /* Add to local variables */
+ Printf(c_decl, "%s %s", c_param_type, arg);
+ if (!ignored_method)
+ Wrapper_add_localv(w, arg, c_decl, (!(SwigType_ispointer(pt) || SwigType_isreference(pt)) ? "" : "= 0"), NIL);
+
+ /* Add input marshalling code */
+ if ((tm = Getattr(p, "tmap:directorin"))) {
+
+ Replaceall(tm, "$input", arg);
+ Replaceall(tm, "$owner", "0");
+
+ if (Len(tm))
+ if (!ignored_method)
+ Printf(w->code, "%s\n", tm);
+
+ Delete(tm);
+
+ // Add parameter type to the C typedef for the D callback function.
+ Printf(callback_typedef_parms, ", %s", c_param_type);
+
+ /* Add parameter to the intermediate class code if generating the
+ * intermediate's upcall code */
+ if ((tm = lookupDTypemap(p, "imtype", true))) {
+ String *imtypeout = Getattr(p, "tmap:imtype:out");
+ if (imtypeout) {
+ // The type in the imtype typemap's out attribute overrides the
+ // type in the typemap itself.
+ tm = imtypeout;
+ }
+ const String *im_directorinattributes = Getattr(p, "tmap:imtype:directorinattributes");
+
+ // TODO: Is this copy really needed?
+ String *din = Copy(lookupDTypemap(p, "ddirectorin", true));
+
+ if (din) {
+ Replaceall(din, "$winput", ln);
+
+ Printf(delegate_parms, ", ");
+ if (i > 0) {
+ Printf(proxy_method_param_list, ", ");
+ Printf(imcall_args, ", ");
+ }
+ Printf(delegate_parms, "%s%s %s", im_directorinattributes ? im_directorinattributes : empty_string, tm, ln);
+
+ if (Cmp(din, ln)) {
+ Printv(imcall_args, din, NIL);
+ } else {
+ Printv(imcall_args, ln, NIL);
+ }
+
+ Delete(din);
+
+ // Get the parameter type in the proxy D class (used later when
+ // generating the overload checking code for the directorConnect
+ // function).
+ if ((tm = lookupDTypemap(p, "dtype", true))) {
+ Printf(proxy_method_param_list, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DDIRECTORIN_UNDEF, input_file, line_number,
+ "No ddirectorin typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_IMTYPE_UNDEF, input_file, line_number,
+ "No imtype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ p = Getattr(p, "tmap:directorin:next");
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DDIRECTORIN_UNDEF, input_file, line_number,
+ "No or improper directorin typemap defined for argument %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ p = nextSibling(p);
+ output_director = false;
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_CTYPE_UNDEF, input_file, line_number,
+ "No ctype typemap defined for %s for use in %s::%s (skipping director method)\n",
+ SwigType_str(pt, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ p = nextSibling(p);
+ }
+
+ Delete(arg);
+ Delete(c_decl);
+ Delete(c_param_type);
+ Delete(ln);
+ }
+
+ /* header declaration, start wrapper definition */
+ String *target;
+ SwigType *rtype = Getattr(n, "conversion_operator") ? 0 : type;
+ target = Swig_method_decl(rtype, decl, qualified_name, l, 0, 0);
+ Printf(w->def, "%s", target);
+ Delete(qualified_name);
+ Delete(target);
+ target = Swig_method_decl(rtype, decl, name, l, 0, 1);
+ Printf(declaration, " virtual %s", target);
+ Delete(target);
+
+ // Add any exception specifications to the methods in the director class
+ ParmList *throw_parm_list = NULL;
+ if ((throw_parm_list = Getattr(n, "throws")) || Getattr(n, "throw")) {
+ int gencomma = 0;
+
+ Append(w->def, " throw(");
+ Append(declaration, " throw(");
+
+ if (throw_parm_list)
+ Swig_typemap_attach_parms("throws", throw_parm_list, 0);
+ for (p = throw_parm_list; p; p = nextSibling(p)) {
+ if ((tm = Getattr(p, "tmap:throws"))) {
+ if (gencomma++) {
+ Append(w->def, ", ");
+ Append(declaration, ", ");
+ }
+ Printf(w->def, "%s", SwigType_str(Getattr(p, "type"), 0));
+ Printf(declaration, "%s", SwigType_str(Getattr(p, "type"), 0));
+ }
+ }
+
+ Append(w->def, ")");
+ Append(declaration, ")");
+ }
+
+ Append(w->def, " {");
+ Append(declaration, ";\n");
+
+ // Finish the callback function declaraction.
+ Printf(callback_def, "%s)", delegate_parms);
+ Printf(callback_def, " {\n");
+
+ /* Emit the intermediate class's upcall to the actual class */
+
+ String *upcall = NewStringf("(cast(%s)dObject).%s(%s)", classname, symname, imcall_args);
+
+ if (!is_void) {
+ Parm *tp = NewParm(returntype, empty_str, n);
+
+ // RESEARCH: What happens if there is no ddirectorout typemap?
+ if ((tm = lookupDTypemap(tp, "ddirectorout"))) {
+ Replaceall(tm, "$dcall", upcall);
+
+ Printf(callback_code, " return %s;\n", tm);
+ }
+
+ Delete(tm);
+ Delete(tp);
+ } else {
+ Printf(callback_code, " %s;\n", upcall);
+ }
+
+ Printf(callback_code, "}\n");
+ Delete(upcall);
+
+ if (!ignored_method) {
+ if (!is_void)
+ Printf(w->code, "jresult = (%s) ", c_ret_type);
+
+ Printf(w->code, "swig_callback_%s(d_object%s);\n", overloaded_name, dcallback_call_args);
+
+ if (!is_void) {
+ String *jresult_str = NewString("jresult");
+ String *result_str = NewString("c_result");
+ Parm *tp = NewParm(returntype, result_str, n);
+
+ /* Copy jresult into c_result... */
+ // FIXME: lookupDTypemap?
+ if ((tm = Swig_typemap_lookup("directorout", tp, result_str, w))) {
+ Replaceall(tm, "$input", jresult_str);
+ Replaceall(tm, "$result", result_str);
+ Printf(w->code, "%s\n", tm);
+ } else {
+ Swig_warning(WARN_TYPEMAP_DIRECTOROUT_UNDEF, input_file, line_number,
+ "Unable to use return type %s used in %s::%s (skipping director method)\n",
+ SwigType_str(returntype, 0), SwigType_namestr(c_classname), SwigType_namestr(name));
+ output_director = false;
+ }
+
+ Delete(tp);
+ Delete(jresult_str);
+ Delete(result_str);
+ }
+
+ /* Terminate wrapper code */
+ Printf(w->code, "}\n");
+ if (!is_void)
+ Printf(w->code, "return %s;", qualified_return);
+ }
+
+ Printf(w->code, "}");
+
+ // We expose virtual protected methods via an extra public inline method which makes a straight call to the wrapped class' method
+ String *inline_extra_method = NewString("");
+ if (dirprot_mode() && !is_public(n) && !pure_virtual) {
+ Printv(inline_extra_method, declaration, NIL);
+ String *extra_method_name = NewStringf("%sSwigPublic", name);
+ Replaceall(inline_extra_method, name, extra_method_name);
+ Replaceall(inline_extra_method, ";\n", " {\n ");
+ if (!is_void)
+ Printf(inline_extra_method, "return ");
+ String *methodcall = Swig_method_call(super, l);
+ Printv(inline_extra_method, methodcall, ";\n }\n", NIL);
+ Delete(methodcall);
+ Delete(extra_method_name);
+ }
+
+ /* emit code */
+ if (status == SWIG_OK && output_director) {
+ if (!is_void) {
+ Replaceall(w->code, "$null", qualified_return);
+ } else {
+ Replaceall(w->code, "$null", "");
+ }
+ if (!ignored_method)
+ Printv(director_dcallbacks_code, callback_def, callback_code, NIL);
+ if (!Getattr(n, "defaultargs")) {
+ Wrapper_print(w, f_directors);
+ Printv(f_directors_h, declaration, NIL);
+ Printv(f_directors_h, inline_extra_method, NIL);
+ }
+ }
+
+ if (!ignored_method) {
+ // Register the upcall method so that the callback registering code can
+ // be written later.
+
+ // We cannot directly use n here because its »type« attribute does not
+ // the full return type any longer after Language::functionHandler has
+ // returned.
+ Parm *tp = NewParm(returntype, empty_str, n);
+ String *dp_return_type = lookupDTypemap(tp, "dtype");
+ if (dp_return_type) {
+ String *dtypeout = Getattr(n, "tmap:dtype:out");
+ if (dtypeout) {
+ // The type in the dtype typemap's out attribute overrides the type
+ // in the typemap itself.
+ dp_return_type = dtypeout;
+ replaceClassname(dp_return_type, returntype);
+ }
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(type, 0));
+ dp_return_type = NewString("");
+ }
+
+ UpcallData *udata = addUpcallMethod(imclass_dmethod, symname, decl, overloaded_name, dp_return_type, proxy_method_param_list);
+ Delete(dp_return_type);
+
+ // Write the global callback function pointer on the C code.
+ String *methid = Getattr(udata, "class_methodidx");
+
+ Printf(director_callback_typedefs, " typedef %s (* SWIG_Callback%s_t)", c_ret_type, methid);
+ Printf(director_callback_typedefs, "(void *dobj%s);\n", callback_typedef_parms);
+ Printf(director_callback_pointers, " SWIG_Callback%s_t swig_callback_%s;\n", methid, overloaded_name);
+
+ // Write the type alias for the callback to the intermediary D module.
+ String* proxy_callback_type = NewString("");
+ Printf(proxy_callback_type, "SwigDirector_%s_Callback%s", classname, methid);
+ Printf(im_dmodule_code, "alias extern(C) %s function(void*%s) %s;\n", proxy_callback_return_type, delegate_parms, proxy_callback_type);
+ Delete(proxy_callback_type);
+ }
+
+ Delete(qualified_return);
+ Delete(c_ret_type);
+ Delete(declaration);
+ Delete(callback_typedef_parms);
+ Delete(delegate_parms);
+ Delete(proxy_method_param_list);
+ Delete(callback_def);
+ Delete(callback_code);
+ DelWrapper(w);
+
+ return status;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorConstructor()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorConstructor(Node *n) {
+ Node *parent = parentNode(n);
+ String *decl = Getattr(n, "decl");;
+ String *supername = Swig_class_name(parent);
+ String *classname = getDirectorClassName(parent);
+ String *sub = NewString("");
+ Parm *p;
+ ParmList *superparms = Getattr(n, "parms");
+ ParmList *parms;
+ int argidx = 0;
+
+ /* Assign arguments to superclass's parameters, if not already done */
+ for (p = superparms; p; p = nextSibling(p)) {
+ String *pname = Getattr(p, "name");
+
+ if (!pname) {
+ pname = NewStringf("arg%d", argidx++);
+ Setattr(p, "name", pname);
+ }
+ }
+
+ // TODO: Is this copy needed?
+ parms = CopyParmList(superparms);
+
+ if (!Getattr(n, "defaultargs")) {
+ /* constructor */
+ {
+ String *basetype = Getattr(parent, "classtype");
+ String *target = Swig_method_decl(0, decl, classname, parms, 0, 0);
+ String *call = Swig_csuperclass_call(0, basetype, superparms);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+
+ Printf(f_directors, "%s::%s : %s, %s {\n", classname, target, call, Getattr(parent, "director:ctor"));
+ Printf(f_directors, " swig_init_callbacks();\n");
+ Printf(f_directors, "}\n\n");
+
+ Delete(classtype);
+ Delete(target);
+ Delete(call);
+ }
+
+ /* constructor header */
+ {
+ String *target = Swig_method_decl(0, decl, classname, parms, 0, 1);
+ Printf(f_directors_h, " %s;\n", target);
+ Delete(target);
+ }
+ }
+
+ Delete(sub);
+ Delete(supername);
+ Delete(parms);
+ return Language::classDirectorConstructor(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorDefaultConstructor()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorDefaultConstructor(Node *n) {
+ String *classname = Swig_class_name(n);
+ String *classtype = SwigType_namestr(Getattr(n, "name"));
+ Wrapper *w = NewWrapper();
+
+ Printf(w->def, "SwigDirector_%s::SwigDirector_%s() : %s {", classname, classname, Getattr(n, "director:ctor"));
+ Printf(w->code, "}\n");
+ Wrapper_print(w, f_directors);
+
+ Printf(f_directors_h, " SwigDirector_%s();\n", classname);
+ DelWrapper(w);
+ Delete(classtype);
+ Delete(classname);
+ return Language::classDirectorDefaultConstructor(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorDestructor()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorDestructor(Node *n) {
+ Node *current_class = getCurrentClass();
+ String *classname = Swig_class_name(current_class);
+ Wrapper *w = NewWrapper();
+
+ if (Getattr(n, "throw")) {
+ Printf(f_directors_h, " virtual ~SwigDirector_%s() throw ();\n", classname);
+ Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() throw () {\n", classname, classname);
+ } else {
+ Printf(f_directors_h, " virtual ~SwigDirector_%s();\n", classname);
+ Printf(w->def, "SwigDirector_%s::~SwigDirector_%s() {\n", classname, classname);
+ }
+
+ Printv(w->code, "}\n", NIL);
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+ Delete(classname);
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorEnd()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorEnd(Node *n) {
+ int i;
+ String *director_classname = getDirectorClassName(n);
+
+ Wrapper *w = NewWrapper();
+
+ if (Len(director_callback_typedefs) > 0) {
+ Printf(f_directors_h, "\n%s", director_callback_typedefs);
+ }
+
+ Printf(f_directors_h, " void swig_connect_director(void* dobj");
+
+ Printf(w->def, "void %s::swig_connect_director(void* dobj", director_classname);
+ Printf(w->code, "d_object = dobj;");
+
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+ String *overname = Getattr(udata, "overname");
+
+ Printf(f_directors_h, ", SWIG_Callback%s_t callback%s", methid, overname);
+ Printf(w->def, ", SWIG_Callback%s_t callback_%s", methid, overname);
+ Printf(w->code, "swig_callback_%s = callback_%s;\n", overname, overname);
+ }
+
+ Printf(f_directors_h, ");\n");
+ Printf(w->def, ") {");
+
+ Printf(f_directors_h, "\nprivate:\n");
+ Printf(f_directors_h, " void swig_init_callbacks();\n");
+ Printf(f_directors_h, " void *d_object;\n");
+ if (Len(director_callback_typedefs) > 0) {
+ Printf(f_directors_h, "%s", director_callback_pointers);
+ }
+ Printf(f_directors_h, "};\n\n");
+ Printf(w->code, "}\n\n");
+
+ Printf(w->code, "void %s::swig_init_callbacks() {\n", director_classname);
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *overname = Getattr(udata, "overname");
+ Printf(w->code, "swig_callback_%s = 0;\n", overname);
+ }
+ Printf(w->code, "}");
+
+ Wrapper_print(w, f_directors);
+
+ DelWrapper(w);
+
+ return Language::classDirectorEnd(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::classDirectorDisown()
+ * --------------------------------------------------------------------------- */
+ virtual int classDirectorDisown(Node *n) {
+ (void) n;
+ return SWIG_OK;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceSpecialVariables()
+ * --------------------------------------------------------------------------- */
+ virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
+ (void)method;
+ SwigType *type = Getattr(parm, "type");
+
+ // Just assume that this goes to the proxy class, we cannot know.
+ replaceClassname(tm, type);
+ }
+
+protected:
+ /* ---------------------------------------------------------------------------
+ * D::extraDirectorProtectedCPPMethodsRequired()
+ * --------------------------------------------------------------------------- */
+ virtual bool extraDirectorProtectedCPPMethodsRequired() const {
+ return false;
+ }
+
+private:
+ /* ---------------------------------------------------------------------------
+ * D::writeImDModuleFunction()
+ *
+ * Writes a function declaration for the given (C) wrapper function to the
+ * intermediary D module.
+ *
+ * d_name - The name the function in the intermediary D module will get.
+ * wrapper_function_name - The name of the exported function in the C wrapper
+ * (usually d_name prefixed by »D_«).
+ * --------------------------------------------------------------------------- */
+ void writeImDModuleFunction(const_String_or_char_ptr d_name,
+ const_String_or_char_ptr return_type, const_String_or_char_ptr parameters,
+ const_String_or_char_ptr wrapper_function_name) {
+
+ // TODO: Add support for static linking here.
+ Printf(im_dmodule_code, "extern(C) %s function%s %s;\n", return_type,
+ parameters, d_name);
+ Printv(wrapper_loader_bind_code, wrapper_loader_bind_command, NIL);
+ Replaceall(wrapper_loader_bind_code, "$function", d_name);
+ Replaceall(wrapper_loader_bind_code, "$symbol", wrapper_function_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeProxyClassFunction()
+ *
+ * Creates a D proxy function for a C++ function in the wrapped class. Used
+ * for both static and non-static C++ class functions.
+ *
+ * The Node must contain two extra attributes.
+ * - "proxyfuncname": The name of the D proxy function.
+ * - "imfuncname": The corresponding function in the intermediary D module.
+ * --------------------------------------------------------------------------- */
+ void writeProxyClassFunction(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *intermediary_function_name = Getattr(n, "imfuncname");
+ String *proxy_function_name = Getattr(n, "proxyfuncname");
+ String *tm;
+ Parm *p;
+ int i;
+ String *imcall = NewString("");
+ String *return_type = NewString("");
+ String *function_code = NewString("");
+ bool setter_flag = false;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+
+ // Wrappers not wanted for some methods where the parameters cannot be
+ // overloaded in D.
+ if (Getattr(n, "overload:ignore"))
+ return;
+
+ // Don't generate proxy method for additional explicitcall method used in
+ // directors.
+ if (GetFlag(n, "explicitcall"))
+ return;
+
+ // RESEARCH: What is this good for?
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("in", l, NULL);
+ Swig_typemap_attach_parms("dtype", l, NULL);
+ Swig_typemap_attach_parms("din", l, NULL);
+
+ // Get return types.
+ if ((tm = lookupDTypemap(n, "dtype"))) {
+ String *dtypeout = Getattr(n, "tmap:dtype:out");
+ if (dtypeout) {
+ // The type in the dtype typemap's out attribute overrides the type in
+ // the typemap.
+ tm = dtypeout;
+ replaceClassname(tm, t);
+ }
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ if (wrapping_member_flag) {
+ // Check if this is a setter method for a public member.
+ setter_flag = (Cmp(Getattr(n, "sym:name"),
+ Swig_name_set(NSPACE_TODO,Swig_name_member(NSPACE_TODO,proxy_class_name, variable_name))) == 0);
+ }
+
+ // Write function modifiers.
+ {
+ String *modifiers;
+
+ const String *mods_override = Getattr(n, "feature:d:methodmodifiers");
+ if (mods_override) {
+ modifiers = Copy(mods_override);
+ } else {
+ modifiers = Copy(is_public(n) ? public_string : protected_string);
+
+ if (Getattr(n, "override")) {
+ Printf(modifiers, " override");
+ }
+ }
+
+ if (is_smart_pointer()) {
+ // Smart pointer classes do not mirror the inheritance hierarchy of the
+ // underlying pointer type, so no override required.
+ Replaceall(modifiers, "override", "");
+ }
+
+ Chop(modifiers);
+
+ if (static_flag) {
+ Printf(modifiers, " static");
+ }
+
+ Printf(function_code, "%s ", modifiers);
+ Delete(modifiers);
+ }
+
+ // Complete the function declaration up to the parameter list.
+ Printf(function_code, "%s %s(", return_type, proxy_function_name);
+
+ // Write the wrapper function call up to the parameter list.
+ Printv(imcall, im_dmodule_fq_name, ".$imfuncname(", NIL);
+ if (!static_flag) {
+ Printf(imcall, "cast(void*)swigCPtr");
+ }
+
+ String *proxy_param_types = NewString("");
+
+ // Write the parameter list for the proxy function declaration and the
+ // wrapper function call.
+ emit_mark_varargs(l);
+ int gencomma = !static_flag;
+ for (i = 0, p = l; p; i++) {
+ // Ignored varargs.
+ if (checkAttribute(p, "varargs:ignore", "1")) {
+ p = nextSibling(p);
+ continue;
+ }
+
+ // Ignored parameters.
+ if (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ continue;
+ }
+
+ // Ignore the 'this' argument for variable wrappers.
+ if (!(variable_wrapper_flag && i == 0)) {
+ String *param_name = makeParameterName(n, p, i, setter_flag);
+ SwigType *pt = Getattr(p, "type");
+
+ // Write the wrapper function call argument.
+ {
+ if (gencomma) {
+ Printf(imcall, ", ");
+ }
+
+ if ((tm = lookupDTypemap(p, "din", true))) {
+ Replaceall(tm, "$dinput", param_name);
+ String *pre = Getattr(p, "tmap:din:pre");
+ if (pre) {
+ replaceClassname(pre, pt);
+ Replaceall(pre, "$dinput", param_name);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:din:post");
+ if (post) {
+ replaceClassname(post, pt);
+ Replaceall(post, "$dinput", param_name);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:din:terminator");
+ if (terminator) {
+ replaceClassname(terminator, pt);
+ Replaceall(terminator, "$dinput", param_name);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DIN_UNDEF, input_file, line_number,
+ "No din typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+ }
+
+ // Write the D proxy function parameter.
+ {
+ String *proxy_type = NewString("");
+
+ if ((tm = lookupDTypemap(p, "dtype"))) {
+ const String *inattributes = Getattr(p, "tmap:dtype:inattributes");
+ Printf(proxy_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma >= 2) {
+ Printf(function_code, ", ");
+ Printf(proxy_param_types, ", ");
+ }
+ gencomma = 2;
+ Printf(function_code, "%s %s", proxy_type, param_name);
+ Append(proxy_param_types, proxy_type);
+
+ Delete(proxy_type);
+ }
+
+ Delete(param_name);
+ }
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ") ");
+
+ if (d_version > 1 && wrapping_member_flag) {
+ Printf(function_code, "@property ");
+ }
+
+ if (wrapMemberFunctionAsDConst(n)) {
+ Printf(function_code, "const ");
+ }
+
+ // Lookup the code used to convert the wrapper return value to the proxy
+ // function return type.
+ if ((tm = lookupDTypemap(n, "dout"))) {
+ replaceExcode(n, tm, "dout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ if (is_terminator_code) {
+ Printv(tm, "\n", terminator_code, NIL);
+ }
+ Insert(tm, 0, "{");
+ Printv(tm, "}", NIL);
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ replaceClassname(tm, t);
+
+ // For director methods: generate code to selectively make a normal
+ // polymorphic call or an explicit method call. Needed to prevent infinite
+ // recursion when calling director methods.
+ Node *explicit_n = Getattr(n, "explicitcallnode");
+ if (explicit_n) {
+ String *ex_overloaded_name = getOverloadedName(explicit_n);
+ String *ex_intermediary_function_name = Swig_name_member(NSPACE_TODO,proxy_class_name, ex_overloaded_name);
+
+ String *ex_imcall = Copy(imcall);
+ Replaceall(ex_imcall, "$imfuncname", ex_intermediary_function_name);
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+
+ String *excode = NewString("");
+ if (!Cmp(return_type, "void"))
+ Printf(excode, "if (swigIsMethodOverridden!(%s delegate(%s), %s function(%s), %s)()) %s; else %s",
+ return_type, proxy_param_types, return_type, proxy_param_types, proxy_function_name, ex_imcall, imcall);
+ else
+ Printf(excode, "((swigIsMethodOverridden!(%s delegate(%s), %s function(%s), %s)()) ? %s : %s)",
+ return_type, proxy_param_types, return_type, proxy_param_types, proxy_function_name, ex_imcall, imcall);
+
+ Clear(imcall);
+ Printv(imcall, excode, NIL);
+ Delete(ex_overloaded_name);
+ Delete(excode);
+ } else {
+ Replaceall(imcall, "$imfuncname", intermediary_function_name);
+ }
+ Replaceall(tm, "$imcall", imcall);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DOUT_UNDEF, input_file, line_number,
+ "No dout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ Delete(proxy_param_types);
+
+ // The whole function body is now in stored tm (if there was a matching type
+ // map, of course), so simply append it to the code buffer. The braces are
+ // included in the typemap.
+ Printv(function_code, tm, NIL);
+
+ // Write function code buffer to the class code.
+ Printv(proxy_class_body_code, "\n", function_code, "\n", NIL);
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeProxyDModuleFunction()
+ * --------------------------------------------------------------------------- */
+ void writeProxyDModuleFunction(Node *n) {
+ SwigType *t = Getattr(n, "type");
+ ParmList *l = Getattr(n, "parms");
+ String *tm;
+ Parm *p;
+ int i;
+ String *imcall = NewString("");
+ String *return_type = NewString("");
+ String *function_code = NewString("");
+ int num_arguments = 0;
+ int num_required = 0;
+ String *overloaded_name = getOverloadedName(n);
+ String *func_name = NULL;
+ String *pre_code = NewString("");
+ String *post_code = NewString("");
+ String *terminator_code = NewString("");
+
+ // RESEARCH: What is this good for?
+ if (l) {
+ if (SwigType_type(Getattr(l, "type")) == T_VOID) {
+ l = nextSibling(l);
+ }
+ }
+
+ /* Attach the non-standard typemaps to the parameter list */
+ Swig_typemap_attach_parms("dtype", l, NULL);
+ Swig_typemap_attach_parms("din", l, NULL);
+
+ /* Get return types */
+ if ((tm = lookupDTypemap(n, "dtype"))) {
+ String *dtypeout = Getattr(n, "tmap:dtype:out");
+ if (dtypeout) {
+ // The type in the dtype typemap's out attribute overrides the type in
+ // the typemap.
+ tm = dtypeout;
+ replaceClassname(tm, t);
+ }
+ Printf(return_type, "%s", tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ /* Change function name for global variables */
+ if (global_variable_flag) {
+ // RESEARCH: Is the Copy() needed here?
+ func_name = Copy(variable_name);
+ } else {
+ func_name = Copy(Getattr(n, "sym:name"));
+ }
+
+ /* Start generating the function */
+ const String *outattributes = Getattr(n, "tmap:dtype:outattributes");
+ if (outattributes)
+ Printf(function_code, " %s\n", outattributes);
+
+ const String *methodmods = Getattr(n, "feature:d:methodmodifiers");
+ // TODO: Check if is_public(n) could possibly make any sense here
+ // (private global functions would be useless anyway?).
+ methodmods = methodmods ? methodmods : empty_string;
+
+ Printf(function_code, "\n%s%s %s(", methodmods, return_type, func_name);
+ Printv(imcall, im_dmodule_fq_name, ".", overloaded_name, "(", NIL);
+
+ /* Get number of required and total arguments */
+ num_arguments = emit_num_arguments(l);
+ num_required = emit_num_required(l);
+
+ int gencomma = 0;
+
+ /* Output each parameter */
+ for (i = 0, p = l; i < num_arguments; i++) {
+
+ /* Ignored parameters */
+ while (checkAttribute(p, "tmap:in:numinputs", "0")) {
+ p = Getattr(p, "tmap:in:next");
+ }
+
+ SwigType *pt = Getattr(p, "type");
+ String *param_type = NewString("");
+
+ // Get the D parameter type.
+ if ((tm = lookupDTypemap(p, "dtype", true))) {
+ const String *inattributes = Getattr(p, "tmap:dtype:inattributes");
+ Printf(param_type, "%s%s", inattributes ? inattributes : empty_string, tm);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DTYPE_UNDEF, input_file, line_number,
+ "No dtype typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ if (gencomma)
+ Printf(imcall, ", ");
+
+ const bool generating_setter = global_variable_flag || wrapping_member_flag;
+ String *arg = makeParameterName(n, p, i, generating_setter);
+
+ // Get the D code to convert the parameter value to the type used in the
+ // wrapper D module.
+ if ((tm = lookupDTypemap(p, "din", true))) {
+ Replaceall(tm, "$dinput", arg);
+ String *pre = Getattr(p, "tmap:din:pre");
+ if (pre) {
+ replaceClassname(pre, pt);
+ Replaceall(pre, "$dinput", arg);
+ if (Len(pre_code) > 0)
+ Printf(pre_code, "\n");
+ Printv(pre_code, pre, NIL);
+ }
+ String *post = Getattr(p, "tmap:din:post");
+ if (post) {
+ replaceClassname(post, pt);
+ Replaceall(post, "$dinput", arg);
+ if (Len(post_code) > 0)
+ Printf(post_code, "\n");
+ Printv(post_code, post, NIL);
+ }
+ String *terminator = Getattr(p, "tmap:din:terminator");
+ if (terminator) {
+ replaceClassname(terminator, pt);
+ Replaceall(terminator, "$dinput", arg);
+ if (Len(terminator_code) > 0)
+ Insert(terminator_code, 0, "\n");
+ Insert(terminator_code, 0, terminator);
+ }
+ Printv(imcall, tm, NIL);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DIN_UNDEF, input_file, line_number,
+ "No din typemap defined for %s\n", SwigType_str(pt, 0));
+ }
+
+ /* Add parameter to module class function */
+ if (gencomma >= 2)
+ Printf(function_code, ", ");
+ gencomma = 2;
+ Printf(function_code, "%s %s", param_type, arg);
+
+ p = Getattr(p, "tmap:in:next");
+ Delete(arg);
+ Delete(param_type);
+ }
+
+ Printf(imcall, ")");
+ Printf(function_code, ") ");
+
+ if (global_variable_flag && (d_version > 1)) {
+ Printf(function_code, "@property ");
+ }
+
+ // Lookup the code used to convert the wrapper return value to the proxy
+ // function return type.
+ if ((tm = lookupDTypemap(n, "dout"))) {
+ replaceExcode(n, tm, "dout", n);
+ bool is_pre_code = Len(pre_code) > 0;
+ bool is_post_code = Len(post_code) > 0;
+ bool is_terminator_code = Len(terminator_code) > 0;
+ if (is_pre_code || is_post_code || is_terminator_code) {
+ if (is_post_code) {
+ Insert(tm, 0, "\n try ");
+ Printv(tm, " finally {\n", post_code, "\n }", NIL);
+ } else {
+ Insert(tm, 0, "\n ");
+ }
+ if (is_pre_code) {
+ Insert(tm, 0, pre_code);
+ Insert(tm, 0, "\n");
+ }
+ if (is_terminator_code) {
+ Printv(tm, "\n", terminator_code, NIL);
+ }
+ Insert(tm, 0, " {");
+ Printf(tm, "\n}");
+ }
+ if (GetFlag(n, "feature:new"))
+ Replaceall(tm, "$owner", "true");
+ else
+ Replaceall(tm, "$owner", "false");
+ replaceClassname(tm, t);
+ Replaceall(tm, "$imcall", imcall);
+ } else {
+ Swig_warning(WARN_D_TYPEMAP_DOUT_UNDEF, input_file, line_number,
+ "No dout typemap defined for %s\n", SwigType_str(t, 0));
+ }
+
+ // The whole function code is now stored in tm (if there was a matching
+ // type map, of course), so simply append it to the code buffer.
+ Printf(function_code, "%s\n", tm ? (const String *) tm : empty_string);
+ Printv(proxy_dmodule_code, function_code, NIL);
+
+ Delete(pre_code);
+ Delete(post_code);
+ Delete(terminator_code);
+ Delete(function_code);
+ Delete(return_type);
+ Delete(imcall);
+ Delete(func_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeProxyClassAndUpcasts()
+ * --------------------------------------------------------------------------- */
+ void writeProxyClassAndUpcasts(Node *n) {
+ SwigType *typemap_lookup_type = Getattr(n, "classtypeobj");
+
+ /*
+ * Handle inheriting from D and C++ classes.
+ */
+
+ String *c_classname = SwigType_namestr(Getattr(n, "name"));
+ String *c_baseclass = NULL;
+ String *baseclass = NULL;
+ String *c_baseclassname = NULL;
+
+ // Inheritance from pure D classes.
+ Node *attributes = NewHash();
+ const String *pure_baseclass =
+ lookupCodeTypemap(n, "dbase", typemap_lookup_type, WARN_NONE, attributes);
+ bool purebase_replace = GetFlag(attributes, "tmap:dbase:replace") ? true : false;
+ bool purebase_notderived = GetFlag(attributes, "tmap:dbase:notderived") ? true : false;
+ Delete(attributes);
+
+ // C++ inheritance.
+ if (!purebase_replace) {
+ List *baselist = Getattr(n, "bases");
+ if (baselist) {
+ Iterator base = First(baselist);
+ while (base.item && GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ }
+ if (base.item) {
+ c_baseclassname = Getattr(base.item, "name");
+ baseclass = Copy(getProxyName(c_baseclassname));
+ if (baseclass)
+ c_baseclass = SwigType_namestr(Getattr(base.item, "name"));
+ base = Next(base);
+ /* Warn about multiple inheritance for additional base class(es) */
+ while (base.item) {
+ if (GetFlag(base.item, "feature:ignore")) {
+ base = Next(base);
+ continue;
+ }
+ String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
+ String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
+ Swig_warning(WARN_D_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Base %s of class %s ignored: multiple inheritance is not supported in D.\n", baseclassname, proxyclassname);
+ base = Next(base);
+ }
+ }
+ }
+ }
+
+ bool derived = baseclass && getProxyName(c_baseclassname);
+
+ if (derived && purebase_notderived) {
+ pure_baseclass = empty_string;
+ }
+ const String *wanted_base = baseclass ? baseclass : pure_baseclass;
+
+ if (purebase_replace) {
+ wanted_base = pure_baseclass;
+ derived = false;
+ Delete(baseclass);
+ baseclass = NULL;
+ if (purebase_notderived) {
+ Swig_error(Getfile(n), Getline(n),
+ "The dbase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n",
+ typemap_lookup_type);
+ }
+ } else if (baseclass && Len(pure_baseclass) > 0) {
+ Swig_warning(WARN_D_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s proxy: Base class %s ignored. Multiple inheritance is not supported in D. "
+ "Perhaps you need one of the 'replace' or 'notderived' attributes in the dbase typemap?\n", typemap_lookup_type, pure_baseclass);
+ }
+
+ // Add code to do C++ casting to base class (only for classes in an inheritance hierarchy)
+ if (derived) {
+ writeClassUpcast(n, proxy_class_name, c_classname, c_baseclass);
+ }
+
+ /*
+ * Write needed imports.
+ */
+ // If this class is derived from a C++ class, we need to have the D class
+ // generated for it in scope.
+ if (derived) {
+ requireDType(baseclass);
+
+ if (split_proxy_dmodule) {
+ // Fully qualify the baseclass name.
+ String *module = NewStringf("%s%s.", package, baseclass);
+ Insert(baseclass, 0, module);
+ Delete(module);
+ }
+ }
+
+ // Write any custom import statements to the proxy module header.
+ const String *imports = lookupCodeTypemap(n, "dimports", typemap_lookup_type, WARN_NONE);
+ if (Len(imports) > 0) {
+ String* imports_trimmed = Copy(imports);
+ Chop(imports_trimmed);
+ replaceImportTypeMacros(imports_trimmed);
+ Printv(proxy_class_imports, imports_trimmed, "\n", NIL);
+ Delete(imports_trimmed);
+ }
+
+ /*
+ * Write the proxy class header.
+ */
+ // Class modifiers.
+ const String *modifiers =
+ lookupCodeTypemap(n, "dclassmodifiers", typemap_lookup_type, WARN_D_TYPEMAP_CLASSMOD_UNDEF);
+
+ // User-defined interfaces.
+ const String *interfaces =
+ lookupCodeTypemap(n, derived ? "dinterfaces_derived" : "dinterfaces", typemap_lookup_type, WARN_NONE);
+
+ Printv(proxy_class_code,
+ "\n",
+ modifiers,
+ " $dclassname",
+ (*Char(wanted_base) || *Char(interfaces)) ? " : " : "", wanted_base,
+ (*Char(wanted_base) && *Char(interfaces)) ? ", " : "", interfaces, " {",
+ NIL);
+
+ /*
+ * Write the proxy class body.
+ */
+ String* body = NewString("");
+
+ // Default class body.
+ const String *dbody;
+ if (derived) {
+ dbody = lookupCodeTypemap(n, "dbody_derived", typemap_lookup_type, WARN_D_TYPEMAP_DBODY_UNDEF);
+ } else {
+ dbody = lookupCodeTypemap(n, "dbody", typemap_lookup_type, WARN_D_TYPEMAP_DBODY_UNDEF);
+ }
+
+ Printv(body, dbody, NIL);
+
+ // Destructor and dispose().
+ // If the C++ destructor is accessible (public), it is wrapped by the
+ // dispose() method which is also called by the emitted D constructor. If it
+ // is not accessible, no D destructor is written and the generated dispose()
+ // method throws an exception.
+ // This enables C++ classes with protected or private destructors to be used
+ // in D as it would be used in C++ (GC finalization is a no-op then because
+ // of the empty D destructor) while preventing usage in »scope« variables.
+ // The method name for the dispose() method is specified in a typemap
+ // attribute called »methodname«.
+ const String *tm = NULL;
+
+ String *dispose_methodname;
+ String *dispose_methodmodifiers;
+ attributes = NewHash();
+ if (derived) {
+ tm = lookupCodeTypemap(n, "ddispose_derived", typemap_lookup_type, WARN_NONE, attributes);
+ dispose_methodname = Getattr(attributes, "tmap:ddispose_derived:methodname");
+ dispose_methodmodifiers = Getattr(attributes, "tmap:ddispose_derived:methodmodifiers");
+ } else {
+ tm = lookupCodeTypemap(n, "ddispose", typemap_lookup_type, WARN_NONE, attributes);
+ dispose_methodname = Getattr(attributes, "tmap:ddispose:methodname");
+ dispose_methodmodifiers = Getattr(attributes, "tmap:ddispose:methodmodifiers");
+ }
+
+ if (tm && *Char(tm)) {
+ if (!dispose_methodname) {
+ Swig_error(Getfile(n), Getline(n),
+ "No methodname attribute defined in the ddispose%s typemap for %s\n",
+ (derived ? "_derived" : ""), proxy_class_name);
+ }
+ if (!dispose_methodmodifiers) {
+ Swig_error(Getfile(n), Getline(n),
+ "No methodmodifiers attribute defined in ddispose%s typemap for %s.\n",
+ (derived ? "_derived" : ""), proxy_class_name);
+ }
+ }
+
+ if (tm) {
+ // Write the destructor if the C++ one is accessible.
+ if (*Char(destructor_call)) {
+ Printv(body,
+ lookupCodeTypemap(n, "ddestructor", typemap_lookup_type, WARN_NONE), NIL);
+ }
+
+ // Write the dispose() method.
+ String *dispose_code = NewString("");
+ Printv(dispose_code, tm, NIL);
+
+ if (*Char(destructor_call)) {
+ Replaceall(dispose_code, "$imcall", destructor_call);
+ } else {
+ Replaceall(dispose_code, "$imcall", "throw new object.Exception(\"C++ destructor does not have public access\")");
+ }
+
+ if (*Char(dispose_code)) {
+ Printv(body, "\n", dispose_methodmodifiers,
+ (derived ? " override" : ""), " void ", dispose_methodname, "() ",
+ dispose_code, "\n", NIL);
+ }
+ }
+
+ if (Swig_directorclass(n)) {
+ // If directors are enabled for the current class, generate the
+ // director connect helper function which is called from the constructor
+ // and write it to the class body.
+ writeDirectorConnectProxy();
+ }
+
+ // Write all constants and enumerations first to prevent forward reference
+ // errors.
+ Printv(body, proxy_class_enums_code, NIL);
+
+ // Write the code generated in other methods to the class body.
+ Printv(body, proxy_class_body_code, NIL);
+
+ // Append extra user D code to the class body.
+ Printv(body,
+ lookupCodeTypemap(n, "dcode", typemap_lookup_type, WARN_NONE), "\n", NIL);
+
+ // Write the class body and the curly bracket closing the class definition
+ // to the proxy module.
+ indentCode(body);
+ Replaceall(body, "$dbaseclass", baseclass);
+ Delete(baseclass);
+
+ Printv(proxy_class_code, body, "\n}\n", NIL);
+ Delete(body);
+
+ // Write the epilogue code if there is any.
+ Printv(proxy_class_code, proxy_class_epilogue_code, NIL);
+ }
+
+
+ /* ---------------------------------------------------------------------------
+ * D::writeClassUpcast()
+ * --------------------------------------------------------------------------- */
+ void writeClassUpcast(Node *n, const String* d_class_name,
+ String* c_class_name, String* c_base_name) {
+
+ String *smartptr = Getattr(n, "feature:smartptr");
+ String *upcast_name = NewString("");
+ Printv(upcast_name, d_class_name,
+ (smartptr != 0 ? "SmartPtrUpcast" : "Upcast"), NIL);
+
+ String *upcast_wrapper_name = Swig_name_wrapper(upcast_name);
+
+ writeImDModuleFunction(upcast_name, "void*", "(void* objectRef)",
+ upcast_wrapper_name);
+
+ if (smartptr) {
+ SwigType *spt = Swig_cparse_type(smartptr);
+ if (spt) {
+ SwigType *smart = SwigType_typedef_resolve_all(spt);
+ Delete(spt);
+ SwigType *bsmart = Copy(smart);
+ SwigType *rclassname = SwigType_typedef_resolve_all(c_class_name);
+ SwigType *rbaseclass = SwigType_typedef_resolve_all(c_base_name);
+ Replaceall(bsmart, rclassname, rbaseclass);
+ Delete(rclassname);
+ Delete(rbaseclass);
+ String *smartnamestr = SwigType_namestr(smart);
+ String *bsmartnamestr = SwigType_namestr(bsmart);
+ Printv(upcasts_code,
+ "SWIGEXPORT ", bsmartnamestr, " * ", upcast_wrapper_name,
+ "(", smartnamestr, " *objectRef) {\n",
+ " return objectRef ? new ", bsmartnamestr, "(*objectRef) : 0;\n"
+ "}\n",
+ "\n", NIL);
+ Delete(bsmartnamestr);
+ Delete(smartnamestr);
+ Delete(bsmart);
+ } else {
+ Swig_error(Getfile(n), Getline(n),
+ "Invalid type (%s) in 'smartptr' feature for class %s.\n",
+ smartptr, c_class_name);
+ }
+ } else {
+ Printv(upcasts_code,
+ "SWIGEXPORT ", c_base_name, " * ", upcast_wrapper_name,
+ "(", c_base_name, " *objectRef) {\n",
+ " return (", c_base_name, " *)objectRef;\n"
+ "}\n",
+ "\n", NIL);
+ }
+
+ Replaceall(upcasts_code, "$cclass", c_class_name);
+ Replaceall(upcasts_code, "$cbaseclass", c_base_name);
+
+ Delete(upcast_name);
+ Delete(upcast_wrapper_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeTypeWrapperClass()
+ * --------------------------------------------------------------------------- */
+ void writeTypeWrapperClass(String *classname, SwigType *type) {
+ Node *n = NewHash();
+ Setfile(n, input_file);
+ Setline(n, line_number);
+
+ assertClassNameValidity(classname);
+
+ String* imports_target;
+ String* code_target;
+ File *class_file = NULL;
+ if (split_proxy_dmodule) {
+ String *filename = NewStringf("%s%s.d", dmodule_directory, classname);
+ class_file = NewFile(filename, "w", SWIG_output_files());
+ if (!class_file) {
+ FileErrorDisplay(filename);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ Append(filenames_list, Copy(filename));
+ Delete(filename);
+
+ emitBanner(class_file);
+ Printf(class_file, "module %s%s;\n", package, classname);
+ Printf(class_file, "\nstatic import %s;\n", im_dmodule_fq_name);
+
+ imports_target = NewString("");
+ code_target = NewString("");
+ } else {
+ imports_target = proxy_dmodule_imports;
+ code_target = proxy_dmodule_code;
+ }
+
+ // Import statements.
+ const String *imports = lookupCodeTypemap(n, "dimports", type, WARN_NONE);
+ if (Len(imports) > 0) {
+ String *imports_trimmed = Copy(imports);
+ Chop(imports_trimmed);
+ replaceImportTypeMacros(imports_trimmed);
+ Printv(imports_target, imports_trimmed, "\n", NIL);
+ Delete(imports_trimmed);
+ }
+
+ // Pure D baseclass and interfaces (no C++ inheritance possible.
+ const String *pure_baseclass = lookupCodeTypemap(n, "dbase", type, WARN_NONE);
+ const String *pure_interfaces = lookupCodeTypemap(n, "dinterfaces", type, WARN_NONE);
+
+ // Emit the class.
+ Printv(code_target,
+ "\n",
+ lookupCodeTypemap(n, "dclassmodifiers", type, WARN_D_TYPEMAP_CLASSMOD_UNDEF),
+ " $dclassname",
+ (*Char(pure_baseclass) || *Char(pure_interfaces)) ? " : " : "", pure_baseclass,
+ ((*Char(pure_baseclass)) && *Char(pure_interfaces)) ? ", " : "", pure_interfaces,
+ " {", NIL);
+
+ String* body = NewString("");
+ Printv(body, lookupCodeTypemap(n, "dbody", type, WARN_D_TYPEMAP_DBODY_UNDEF),
+ lookupCodeTypemap(n, "dcode", type, WARN_NONE), NIL);
+ indentCode(body);
+ Printv(code_target, body, "\n}\n", NIL);
+ Delete(body);
+
+ Replaceall(code_target, "$dclassname", classname);
+
+ if (split_proxy_dmodule) {
+ Printv(class_file, imports_target, NIL);
+ Delete(imports_target);
+
+ replaceModuleVariables(code_target);
+ Printv(class_file, code_target, NIL);
+ Delete(code_target);
+
+ Close(class_file);
+ Delete(class_file);
+ }
+
+ Delete(n);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeDirectorConnectProxy()
+ *
+ * Writes the helper method which registers the director callbacks by calling
+ * the director connect function from the D side to the proxy class.
+ * --------------------------------------------------------------------------- */
+ void writeDirectorConnectProxy() {
+ Printf(proxy_class_body_code, "\nprivate void swigDirectorConnect() {\n");
+
+ int i;
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *method = Getattr(udata, "method");
+ String *overloaded_name = Getattr(udata, "overname");
+ String *return_type = Getattr(udata, "return_type");
+ String *param_list = Getattr(udata, "param_list");
+ String *methid = Getattr(udata, "class_methodidx");
+ Printf(proxy_class_body_code, " %s.SwigDirector_%s_Callback%s callback%s;\n", im_dmodule_fq_name, proxy_class_name, methid, methid);
+ Printf(proxy_class_body_code, " if (swigIsMethodOverridden!(%s delegate(%s), %s function(%s), %s)()) {\n", return_type, param_list, return_type, param_list, method);
+ Printf(proxy_class_body_code, " callback%s = &swigDirectorCallback_%s_%s;\n", methid, proxy_class_name, overloaded_name);
+ Printf(proxy_class_body_code, " }\n\n");
+ }
+ Printf(proxy_class_body_code, " %s.%s_director_connect(cast(void*)swigCPtr, cast(void*)this", im_dmodule_fq_name, proxy_class_name);
+ for (i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+ Printf(proxy_class_body_code, ", callback%s", methid);
+ }
+ Printf(proxy_class_body_code, ");\n");
+ Printf(proxy_class_body_code, "}\n");
+
+ // Helper function to determine if a method has been overridden in a
+ // subclass of the wrapped class. If not, we just pass null to the
+ // director_connect_function since the method from the C++ class should
+ // be called as usual (see above).
+ // Only emit it if the proxy class has at least one method.
+ if (first_class_dmethod < curr_class_dmethod) {
+ Printf(proxy_class_body_code, "\n");
+ Printf(proxy_class_body_code, "private bool swigIsMethodOverridden(DelegateType, FunctionType, alias fn)() %s{\n", (d_version > 1) ? "const " : "");
+ Printf(proxy_class_body_code, " DelegateType dg = &fn;\n");
+ Printf(proxy_class_body_code, " return dg.funcptr != SwigNonVirtualAddressOf!(FunctionType, fn);\n");
+ Printf(proxy_class_body_code, "}\n");
+ Printf(proxy_class_body_code, "\n");
+ Printf(proxy_class_body_code, "private static Function SwigNonVirtualAddressOf(Function, alias fn)() {\n");
+ Printf(proxy_class_body_code, " return cast(Function) &fn;\n");
+ Printf(proxy_class_body_code, "}\n");
+ }
+
+ if (Len(director_dcallbacks_code) > 0) {
+ Printv(proxy_class_epilogue_code, director_dcallbacks_code, NIL);
+ }
+
+ Delete(director_callback_typedefs);
+ director_callback_typedefs = NULL;
+ Delete(director_callback_pointers);
+ director_callback_pointers = NULL;
+ Delete(director_dcallbacks_code);
+ director_dcallbacks_code = NULL;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::writeDirectorConnectWrapper()
+ *
+ * Writes the director connect function and the corresponding declaration to
+ * the C++ wrapper respectively the D wrapper.
+ * --------------------------------------------------------------------------- */
+ void writeDirectorConnectWrapper(Node *n) {
+ if (!Swig_directorclass(n))
+ return;
+
+ // Output the director connect method.
+ String *norm_name = SwigType_namestr(Getattr(n, "name"));
+ String *connect_name = NewStringf("%s_director_connect", proxy_class_name);
+ String *sym_name = Getattr(n, "sym:name");
+ Wrapper *code_wrap;
+
+ Printv(wrapper_loader_bind_code, wrapper_loader_bind_command, NIL);
+ Replaceall(wrapper_loader_bind_code, "$function", connect_name);
+ Replaceall(wrapper_loader_bind_code, "$symbol", Swig_name_wrapper(connect_name));
+
+ Printf(im_dmodule_code, "extern(C) void function(void* cObject, void* dObject");
+
+ code_wrap = NewWrapper();
+ Printf(code_wrap->def, "SWIGEXPORT void D_%s(void *objarg, void *dobj", connect_name);
+
+ Printf(code_wrap->code, " %s *obj = (%s *)objarg;\n", norm_name, norm_name);
+ Printf(code_wrap->code, " SwigDirector_%s *director = dynamic_cast<SwigDirector_%s *>(obj);\n", sym_name, sym_name);
+
+ Printf(code_wrap->code, " if (director) {\n");
+ Printf(code_wrap->code, " director->swig_connect_director(dobj");
+
+ for (int i = first_class_dmethod; i < curr_class_dmethod; ++i) {
+ UpcallData *udata = Getitem(dmethods_seq, i);
+ String *methid = Getattr(udata, "class_methodidx");
+
+ Printf(code_wrap->def, ", SwigDirector_%s::SWIG_Callback%s_t callback%s", sym_name, methid, methid);
+ Printf(code_wrap->code, ", callback%s", methid);
+ Printf(im_dmodule_code, ", SwigDirector_%s_Callback%s callback%s", sym_name, methid, methid);
+ }
+
+ Printf(code_wrap->def, ") {\n");
+ Printf(code_wrap->code, ");\n");
+ Printf(im_dmodule_code, ") %s;\n", connect_name);
+ Printf(code_wrap->code, " }\n");
+ Printf(code_wrap->code, "}\n");
+
+ Wrapper_print(code_wrap, f_wrappers);
+ DelWrapper(code_wrap);
+
+ Delete(connect_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::requireDType()
+ *
+ * Adds an import statement for the given module to the header of current
+ * module. This is only used for dependencies created in generated code, user-
+ * (read: typemap-) specified import statements are handeled seperately.
+ * --------------------------------------------------------------------------- */
+ void requireDType(const String *dmodule_name) {
+ String *import = createImportStatement(dmodule_name);
+ Append(import, "\n");
+ if (is_wrapping_class()) {
+ addImportStatement(proxy_class_imports, import);
+ } else {
+ addImportStatement(proxy_dmodule_imports, import);
+ }
+ Delete(import);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::addImportStatement()
+ *
+ * Adds the given import statement to the given list of import statements if
+ * there is no statement importing that module present yet.
+ * --------------------------------------------------------------------------- */
+ void addImportStatement(String *target, const String *import) const {
+ char *position = Strstr(target, import);
+ if (position) {
+ // If the import statement has been found in the target string, we have to
+ // check if the previous import was static, which would lead to problems
+ // if this import is not.
+ // Thus, we check if the seven characters in front of the occurence are
+ // »static «. If the import string passed is also static, the checks fail
+ // even if the found statement is also static because the last seven
+ // characters would be part of the previous import statement then.
+
+ if (position - Char(target) < 7) {
+ return;
+ }
+ if (strncmp(position - 7, "static ", 7)) {
+ return;
+ }
+ }
+
+ Printv(target, import, NIL);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createImportStatement()
+ *
+ * Creates a string containing an import statement for the given module if it
+ * is needed in the currently generated proxy D module (i.e. if it is not the
+ * current module itself).
+ * --------------------------------------------------------------------------- */
+ String *createImportStatement(const String *dmodule_name,
+ bool static_import = true) const {
+
+ if (inProxyModule(dmodule_name)) {
+ return NewStringf("");
+ } else {
+ if (static_import) {
+ return NewStringf("static import %s%s;", package, dmodule_name);
+ } else {
+ return NewStringf("import %s%s;", package, dmodule_name);
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::inProxyModule()
+ *
+ * Determines if the specified proxy class is decleared in the currently
+ * processed proxy D module.
+ *
+ * This function is used to determine if fully qualified type names have to be
+ * used (package, module and type name). This is never the case if the split
+ * proxy mode is not used, all proxy types are written to the same module then.
+ * --------------------------------------------------------------------------- */
+ bool inProxyModule(const String *type_name) const {
+ if (!split_proxy_dmodule) {
+ // If we are not in split proxy module mode, proxy code is always written
+ // to the same module.
+ return true;
+ }
+
+ if (!Len(proxy_class_name)) {
+ return false;
+ }
+
+ return (Strcmp(proxy_class_name, type_name) == 0);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::addUpcallMethod()
+ *
+ * Adds new director upcall signature.
+ * --------------------------------------------------------------------------- */
+ UpcallData *addUpcallMethod(String *imclass_method, String *class_method,
+ String *decl, String *overloaded_name, String *return_type, String *param_list) {
+
+ UpcallData *udata;
+ String *imclass_methodidx;
+ String *class_methodidx;
+ Hash *new_udata;
+ String *key = NewStringf("%s|%s", imclass_method, decl);
+
+ ++curr_class_dmethod;
+
+ /* Do we know about this director class already? */
+ if ((udata = Getattr(dmethods_table, key))) {
+ Delete(key);
+ return Getattr(udata, "methodoff");
+ }
+
+ imclass_methodidx = NewStringf("%d", n_dmethods);
+ class_methodidx = NewStringf("%d", n_dmethods - first_class_dmethod);
+ n_dmethods++;
+
+ new_udata = NewHash();
+ Append(dmethods_seq, new_udata);
+ Setattr(dmethods_table, key, new_udata);
+
+ Setattr(new_udata, "method", Copy(class_method));
+ Setattr(new_udata, "class_methodidx", class_methodidx);
+ Setattr(new_udata, "decl", Copy(decl));
+ Setattr(new_udata, "overname", Copy(overloaded_name));
+ Setattr(new_udata, "return_type", Copy(return_type));
+ Setattr(new_udata, "param_list", Copy(param_list));
+
+ Delete(key);
+ return new_udata;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::assertClassNameValidity()
+ * --------------------------------------------------------------------------- */
+ void assertClassNameValidity(const String* class_name) const {
+ if (split_proxy_dmodule) {
+ if (Cmp(class_name, im_dmodule_name) == 0) {
+ Swig_error(input_file, line_number, "Class name cannot be equal to intermediary D module name: %s\n",
+ class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+
+ if (Cmp(class_name, proxy_dmodule_name) == 0) {
+ Swig_error(input_file, line_number, "Class name cannot be equal to proxy D module name: %s\n",
+ class_name);
+ SWIG_exit(EXIT_FAILURE);
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::getPrimitiveDptype()
+ *
+ * Returns the D proxy type for the passed type if it is a primitive type in
+ * both C and D.
+ * --------------------------------------------------------------------------- */
+ String *getPrimitiveDptype(Node *node, SwigType *type) {
+ SwigType *stripped_type = SwigType_typedef_resolve_all(type);
+
+ // A reference can only be the »outermost element« of a type.
+ bool mutable_ref = false;
+ if (SwigType_isreference(stripped_type)) {
+ SwigType_del_reference(stripped_type);
+
+ if (SwigType_isconst(stripped_type)) {
+ SwigType_del_qualifier(stripped_type);
+ } else {
+ mutable_ref = true;
+ }
+ }
+
+ // Strip all the pointers from the type.
+ int indirection_count = 0;
+ while (SwigType_ispointer(stripped_type)) {
+ ++indirection_count;
+ SwigType_del_pointer(stripped_type);
+ }
+
+ // Now that we got rid of the pointers, see if we are dealing with a
+ // primitive type.
+ String *dtype = 0;
+ if (SwigType_isfunction(stripped_type) && indirection_count > 0) {
+ // type was a function pointer, split it up.
+ SwigType_add_pointer(stripped_type);
+ --indirection_count;
+
+ SwigType *return_type = Copy(stripped_type);
+ SwigType *params_type = SwigType_functionpointer_decompose(return_type);
+ String *return_dtype = getPrimitiveDptype(node, return_type);
+ Delete(return_type);
+ if (!return_dtype) {
+ return 0;
+ }
+
+ List *parms = SwigType_parmlist(params_type);
+ List *param_dtypes = NewList();
+ for (Iterator it = First(parms); it.item; it = Next(it)) {
+ String *current_dtype = getPrimitiveDptype(node, it.item);
+ if (Cmp(current_dtype, "void") == 0) {
+ // void somefunc(void) is legal syntax in C, but not in D, so simply
+ // skip the void parameter.
+ Delete(current_dtype);
+ continue;
+ }
+ if (!current_dtype) {
+ Delete(return_dtype);
+ Delete(param_dtypes);
+ return 0;
+ }
+ Append(param_dtypes, current_dtype);
+ }
+
+ String *param_list = NewString("");
+ {
+ bool gen_comma = false;
+ for (Iterator it = First(param_dtypes); it.item; it = Next(it)) {
+ if (gen_comma) {
+ Append(param_list, ", ");
+ }
+ Append(param_list, it.item);
+ Delete(it.item);
+ gen_comma = true;
+ }
+ }
+
+ dtype = NewStringf("%s function(%s)", return_dtype, param_list);
+ Delete(param_list);
+ Delete(param_dtypes);
+ Delete(return_dtype);
+ } else {
+ Hash *attributes = NewHash();
+ const String *tm =
+ lookupCodeTypemap(node, "dtype", stripped_type, WARN_NONE, attributes);
+ if(!GetFlag(attributes, "tmap:dtype:cprimitive")) {
+ dtype = 0;
+ } else {
+ dtype = Copy(tm);
+
+ // We need to call replaceClassname here with the stripped type to avoid
+ // $dclassname in the enum typemaps being replaced later with the full
+ // type.
+ replaceClassname(dtype, stripped_type);
+ }
+ Delete(attributes);
+ }
+ Delete(stripped_type);
+
+ if (!dtype) {
+ // The type passed is no primitive type.
+ return 0;
+ }
+
+ // The type is ultimately a primitive type, now append the right number of
+ // indirection levels (pointers).
+ for (int i = 0; i < indirection_count; ++i) {
+ Append(dtype, "*");
+ }
+
+ // Add a level of indirection for a mutable reference since it is wrapped
+ // as a pointer.
+ if (mutable_ref) {
+ Append(dtype, "*");
+ }
+
+ return dtype;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::lookupCodeTypemap()
+ *
+ * Looks up a D code fragment for generating the wrapper class for the given
+ * type.
+ *
+ * n - for input only and must contain info for Getfile(n) and Getline(n) to work
+ * tmap_method - typemap method name
+ * type - typemap type to lookup
+ * warning - warning number to issue if no typemaps found
+ * typemap_attributes - the typemap attributes are attached to this node and will
+ * also be used for temporary storage if non null
+ * return is never NULL, unlike Swig_typemap_lookup()
+ * --------------------------------------------------------------------------- */
+ const String *lookupCodeTypemap(Node *n, const_String_or_char_ptr tmap_method,
+ SwigType *type, int warning, Node *typemap_attributes = 0) const {
+
+ Node *node = !typemap_attributes ? NewHash() : typemap_attributes;
+ Setattr(node, "type", type);
+ Setfile(node, Getfile(n));
+ Setline(node, Getline(n));
+ const String *tm = Swig_typemap_lookup(tmap_method, node, "", 0);
+ if (!tm) {
+ tm = empty_string;
+ if (warning != WARN_NONE) {
+ Swig_warning(warning, Getfile(n), Getline(n),
+ "No %s typemap defined for %s\n", tmap_method, SwigType_str(type, 0));
+ }
+ }
+ if (!typemap_attributes) {
+ Delete(node);
+ }
+
+ return tm;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::lookupDTypemap()
+ *
+ * Looks up a D typemap for the given node, replacing D-specific special
+ * variables as needed.
+ *
+ * The method parameter specifies the typemap method to use. If attached is
+ * true, the value is just fetched from the tmap:<method> node attribute,
+ * Swig_typemap_lookup is used otherwise.
+ * --------------------------------------------------------------------------- */
+ String *lookupDTypemap(Node *n, const_String_or_char_ptr method, bool attached = false) {
+ String *result = 0;
+
+ if (attached) {
+ String *attr_name = NewStringf("tmap:%s", method);
+ result = Getattr(n, attr_name);
+ Delete(attr_name);
+ } else {
+ // FIXME: As a workaround for a bug so far only surfacing in the
+ // smart_pointer_const_overload test case, remove the nativepointer
+ // typemap attribute since it seems to be already there from a dout
+ // typemap of a different type in that test.
+ String *np_key = NewStringf("tmap:%s:nativepointer", method);
+ Delattr(n, np_key);
+ Delete(np_key);
+
+ result = Swig_typemap_lookup(method, n, "", 0);
+ }
+
+ if (!result) {
+ return 0;
+ }
+
+ // Check if the passed node actually has type information attached. This
+ // is not the case e.g. in constructorWrapper.
+ SwigType *type = Getattr(n, "type");
+ if (type) {
+ String *np_key = NewStringf("tmap:%s:nativepointer", method);
+ String *np_value = Getattr(n, np_key);
+ Delete(np_key);
+ String *dtype;
+ if (np_value && (dtype = getPrimitiveDptype(n, type))) {
+ // If the typemap in question has a »nativepointer« attribute and we
+ // are dealing with a primitive type, use it instead.
+ result = Copy(np_value);
+ Replaceall(result, "$dtype", dtype);
+ }
+
+ replaceClassname(result, type);
+ }
+
+ return result;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceClassname()
+ *
+ * Replaces the special variable $dclassname with the proxy class name for
+ * classes/structs/unions SWIG knows about. Also substitutes the enumeration
+ * name for non-anonymous enums. Otherwise, $classname is replaced with a
+ * $descriptor(type)-like name.
+ *
+ * $*dclassname and $&classname work like with descriptors (see manual section
+ * 10.4.3), they remove a prointer from respectively add a pointer to the type.
+ *
+ * Inputs:
+ * tm - String to perform the substitution at (will usually come from a
+ * typemap.
+ * pt - The type to substitute for the variables.
+ * Outputs:
+ * tm - String with the variables substituted.
+ * Return:
+ * substitution_performed - flag indicating if a substitution was performed
+ * --------------------------------------------------------------------------- */
+ bool replaceClassname(String *tm, SwigType *pt) {
+ bool substitution_performed = false;
+ SwigType *type = Copy(SwigType_typedef_resolve_all(pt));
+ SwigType *strippedtype = SwigType_strip_qualifiers(type);
+
+ if (Strstr(tm, "$dclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ replaceClassnameVariable(tm, "$dclassname", classnametype);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$*dclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ Delete(SwigType_pop(classnametype));
+ replaceClassnameVariable(tm, "$*dclassname", classnametype);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+ if (Strstr(tm, "$&dclassname")) {
+ SwigType *classnametype = Copy(strippedtype);
+ SwigType_add_pointer(classnametype);
+ replaceClassnameVariable(tm, "$&dclassname", classnametype);
+ substitution_performed = true;
+ Delete(classnametype);
+ }
+
+ Delete(strippedtype);
+ Delete(type);
+
+ return substitution_performed;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceClassnameVariable()
+ *
+ * See D::replaceClassname().
+ * --------------------------------------------------------------------------- */
+ void replaceClassnameVariable(String *target, const char *variable, SwigType *type) {
+ // TODO: Fix const-correctness of methods called in here and make type const.
+
+ // We make use of the fact that this function is called at least once for
+ // every type encountered which is written to a seperate file, which allows
+ // us to handle imports here.
+ // When working in split proxy module mode, each generated proxy class/enum
+ // is written to a seperate module. This requires us to add a corresponding
+ // import when a type is used in another generated module. If we are not
+ // working in split proxy module mode, this is not relevant and the
+ // generated module name is discarded.
+ String *import_name;
+
+ String *qualified_type_name;
+ if (SwigType_isenum(type)) {
+ // RESEARCH: Make sure that we really cannot get here for anonymous enums.
+ Node *n = enumLookup(type);
+ const String *symname = Getattr(n, "sym:name");
+
+ // Add in class scope when referencing enum if not a global enum.
+ const String *parent_name = NULL;
+ String *scopename_prefix = Swig_scopename_prefix(Getattr(n, "name"));
+ if (scopename_prefix) {
+ parent_name = getProxyName(scopename_prefix);
+ Delete(scopename_prefix);
+ }
+
+ if (parent_name) {
+ qualified_type_name = createQualifiedName(parent_name);
+ Printv(qualified_type_name, ".", symname, NIL);
+
+ // An enum nested in a class is not written to a seperate module (this
+ // would not even be possible in D), so just import the parent.
+ import_name = Copy(parent_name);
+ } else {
+ qualified_type_name = createQualifiedName(symname);
+
+ // A non-nested enum is written to a seperate module, import it.
+ import_name = Copy(symname);
+ }
+ } else {
+ const String *class_name = getProxyName(type);
+ if (class_name) {
+ // This is something wrapped as a proxy class (getProxyName() works for
+ // pointers to classes too).
+ qualified_type_name = createQualifiedName(class_name);
+ import_name = Copy(class_name);
+ } else {
+ // SWIG does not know anything about the type (after resolving typedefs).
+ // Just mangle the type name string like $descriptor(type) would do.
+ String *descriptor = NewStringf("SWIGTYPE%s", SwigType_manglestr(type));
+ qualified_type_name = createQualifiedName(descriptor);
+ import_name = Copy(descriptor);
+
+ // Add to hash table so that a type wrapper class can be created later.
+ Setattr(unknown_types, descriptor, type);
+
+ Delete(descriptor);
+ }
+ }
+
+ Replaceall(target, variable, qualified_type_name);
+ Delete(qualified_type_name);
+
+ requireDType(import_name);
+ Delete(import_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::createQualifiedName()
+ * --------------------------------------------------------------------------- */
+ String *createQualifiedName(const String *class_name) const {
+ if (inProxyModule(class_name)) {
+ return Copy(class_name);
+ } else {
+ return NewStringf("%s%s.%s", package, class_name, class_name);
+ }
+}
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceModuleVariables()
+ *
+ * Replaces the $imdmodule and $module variables with their values in the
+ * target string.
+ * --------------------------------------------------------------------------- */
+ void replaceModuleVariables(String *target) const {
+ Replaceall(target, "$imdmodule", im_dmodule_fq_name);
+ Replaceall(target, "$module", proxy_dmodule_name);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceExcode()
+ *
+ * If a C++ method can throw a exception, additional code is added to the
+ * proxy method to check if an exception is pending so that it can be
+ * rethrown on the D side.
+ *
+ * This method replaces the $excode variable with the exception handling code
+ * in the excode typemap attribute if it »canthrow« an exception.
+ * --------------------------------------------------------------------------- */
+ void replaceExcode(Node *n, String *code, const String *typemap, Node *parameter) const {
+ String *excode_attribute = NewStringf("tmap:%s:excode", typemap);
+ String *excode = Getattr(parameter, excode_attribute);
+ if (Getattr(n, "d:canthrow")) {
+ int count = Replaceall(code, "$excode", excode);
+ if (count < 1 || !excode) {
+ Swig_warning(WARN_D_EXCODE_MISSING, input_file, line_number,
+ "D exception may not be thrown – no $excode or excode attribute in '%s' typemap.\n",
+ typemap);
+ }
+ } else {
+ Replaceall(code, "$excode", "");
+ }
+ Delete(excode_attribute);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::replaceImportTypeMacros()
+ *
+ * Replaces the $importtype(SomeDClass) macro with an import statement if it
+ * is required to get SomeDClass in scope for the currently generated proxy
+ * D module.
+ * --------------------------------------------------------------------------- */
+ void replaceImportTypeMacros(String *target) const {
+ // Code from replace_embedded_typemap.
+ char *start = 0;
+ while ((start = Strstr(target, "$importtype("))) {
+ char *end = 0;
+ char *param_start = 0;
+ char *param_end = 0;
+ int level = 0;
+ char *c = start;
+ while (*c) {
+ if (*c == '(') {
+ if (level == 0) {
+ param_start = c + 1;
+ }
+ level++;
+ }
+ if (*c == ')') {
+ level--;
+ if (level == 0) {
+ param_end = c;
+ end = c + 1;
+ break;
+ }
+ }
+ c++;
+ }
+
+ if (end) {
+ String *current_macro = NewStringWithSize(start, (end - start));
+ String *current_param = NewStringWithSize(param_start, (param_end - param_start));
+
+ String *import = createImportStatement(current_param, false);
+ Replace(target, current_macro, import, DOH_REPLACE_ANY);
+ Delete(import);
+
+ Delete(current_param);
+ Delete(current_macro);
+ } else {
+ String *current_macro = NewStringWithSize(start, (c - start));
+ Swig_error(Getfile(target), Getline(target), "Syntax error in: %s\n", current_macro);
+ Replace(target, current_macro, "<error in $importtype macro>", DOH_REPLACE_ANY);
+ Delete(current_macro);
+ }
+ }
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::getOverloadedName()
+ * --------------------------------------------------------------------------- */
+ String *getOverloadedName(Node *n) const {
+ // A void* parameter is used for all wrapped classes in the wrapper code.
+ // Thus, the wrapper function names for overloaded functions are postfixed
+ // with a counter string to make them unique.
+ String *overloaded_name = Copy(Getattr(n, "sym:name"));
+
+ if (Getattr(n, "sym:overloaded")) {
+ Append(overloaded_name, Getattr(n, "sym:overname"));
+ }
+
+ return overloaded_name;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::getProxyName()
+ *
+ * Returns the D class name if a type corresponds to something wrapped with a
+ * proxy class, NULL otherwise.
+ * --------------------------------------------------------------------------- */
+ const String *getProxyName(SwigType *t) {
+ Node *n = classLookup(t);
+ if (n) {
+ return Getattr(n, "sym:name");
+ } else {
+ return NULL;
+ }
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::directorClassName()
+ * --------------------------------------------------------------------------- */
+ String *getDirectorClassName(Node *n) const {
+ String *dirclassname;
+ const char *attrib = "director:classname";
+
+ if (!(dirclassname = Getattr(n, attrib))) {
+ String *classname = Getattr(n, "sym:name");
+
+ dirclassname = NewStringf("SwigDirector_%s", classname);
+ Setattr(n, attrib, dirclassname);
+ }
+
+ return dirclassname;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::makeParameterName()
+ *
+ * Inputs:
+ * n - Node
+ * p - parameter node
+ * arg_num - parameter argument number
+ * setter - set this flag when wrapping variables
+ * Return:
+ * arg - a unique parameter name
+ * --------------------------------------------------------------------------- */
+ String *makeParameterName(Node *n, Parm *p, int arg_num, bool setter) const {
+ String *arg = 0;
+ String *pn = Getattr(p, "name");
+
+ // Use C parameter name unless it is a duplicate or an empty parameter name
+ int count = 0;
+ ParmList *plist = Getattr(n, "parms");
+ while (plist) {
+ if ((Cmp(pn, Getattr(plist, "name")) == 0))
+ count++;
+ plist = nextSibling(plist);
+ }
+ String *wrn = pn ? Swig_name_warning(p, 0, pn, 0) : 0;
+ arg = (!pn || (count > 1) || wrn) ? NewStringf("arg%d", arg_num) : Copy(pn);
+
+ if (setter && Cmp(arg, "self") != 0) {
+ // In theory, we could use the normal parameter name for setter functions.
+ // Unfortunately, it is set to "Class::VariableName" for static public
+ // members by the parser, which is not legal D syntax. Thus, we just force
+ // it to "value".
+ Delete(arg);
+ arg = NewString("value");
+ }
+
+ if (split_proxy_dmodule && Strncmp(arg, package, Len(arg)) == 0) {
+ // If we are in split proxy mode and the argument is named like the target
+ // package, we append an underscore to its name to avoid clashes.
+ Append(arg, "_");
+ }
+
+ return arg;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::canThrow()
+ *
+ * Determines whether the code in the typemap can throw a D exception.
+ * If so, note it for later when excodeSubstitute() is called.
+ * --------------------------------------------------------------------------- */
+ void canThrow(Node *n, const String *typemap, Node *parameter) const {
+ String *canthrow_attribute = NewStringf("tmap:%s:canthrow", typemap);
+ String *canthrow = Getattr(parameter, canthrow_attribute);
+ if (canthrow)
+ Setattr(n, "d:canthrow", "1");
+ Delete(canthrow_attribute);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::wrapMemberFunctionAsDConst()
+ *
+ * Determines whether the member function represented by the passed node is
+ * wrapped as D »const« or not.
+ * --------------------------------------------------------------------------- */
+ bool wrapMemberFunctionAsDConst(Node *n) const {
+ if (d_version == 1) return false;
+ if (static_flag) return false; // Never emit »const« for static member functions.
+ return GetFlag(n, "memberget") || SwigType_isconst(Getattr(n, "decl"));
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::areAllOverloadsOverridden()
+ *
+ * Determines whether the class the passed function node belongs to overrides
+ * all the overlaods for the passed function node defined somewhere up the
+ * inheritance hierachy.
+ * --------------------------------------------------------------------------- */
+ bool areAllOverloadsOverridden(Node *n) const {
+ List *base_list = Getattr(parentNode(n), "bases");
+ if (!base_list) {
+ // If the class which contains n is not derived from any other class,
+ // there cannot be any not-overridden overloads.
+ return true;
+ }
+
+ // In case of multiple base classes, skip to the one which has not been
+ // ignored.
+ // RESEARCH: Also emit a warning in case of multiple inheritance here?
+ Iterator it = First(base_list);
+ while (it.item && GetFlag(it.item, "feature:ignore")) {
+ it = Next(it);
+ }
+ Node *base_class = it.item;
+
+ if (!base_class) {
+ // If all base classes have been ignored, there cannot be one either.
+ return true;
+ }
+
+ // We try to find at least a single overload which exists in the base class
+ // so we can progress up the inheritance hierachy even if there have been
+ // new overloads introduced after the topmost class.
+ Node *base_function = NULL;
+ for (Node *tmp = firstChild(base_class); tmp; tmp = nextSibling(tmp)) {
+ if (Strcmp(Getattr(tmp, "sym:name"), Getattr(n, "sym:name")) == 0) {
+ base_function = tmp;
+ break;
+ }
+ }
+
+ if (!base_function) {
+ // If there is no overload which also exists in the super class, there
+ // cannot be any base class overloads not overridden.
+ return true;
+ }
+
+ size_t base_overload_count = 0;
+ for (Node *tmp = firstSibling(base_function); tmp; tmp = Getattr(tmp, "sym:nextSibling")) {
+ if (is_protected(base_function) &&
+ !(Swig_director_mode() && Swig_director_protected_mode() && Swig_all_protected_mode())) {
+ // If the base class function is »protected« and were are not in
+ // director mode, it is not emitted to the base class and thus we do
+ // not count it. Otherwise, we would run into issues if the visiblity
+ // of some functions was changed from protected to public in a child
+ // class with the using directive.
+ continue;
+ }
+ ++base_overload_count;
+ }
+
+ return ((base_overload_count <= overridingOverloadCount(n)) &&
+ areAllOverloadsOverridden(base_function));
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::overridingOverloadCount()
+ *
+ * Given a member function node, this function counts how many of the
+ * overloads of the function (including itself) override a function in the
+ * base class.
+ * --------------------------------------------------------------------------- */
+ size_t overridingOverloadCount(Node *n) const {
+ size_t result = 0;
+
+ Node *tmp = firstSibling(n);
+ do {
+ // KLUDGE: We also have to count the function if the access attribute is
+ // not present, since this means that it has been promoted into another
+ // protection level in the base class with the C++ »using« directive, and
+ // is thus taken into account when counting the base class overloads, even
+ // if it is not marked as »override« by the SWIG parser.
+ if (Getattr(n, "override") || !Getattr(n, "access")) {
+ ++result;
+ }
+ } while((tmp = Getattr(tmp, "sym:nextSibling")));
+
+ return result;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::firstSibling()
+ *
+ * Returns the first sibling of the passed node.
+ * --------------------------------------------------------------------------- */
+ Node *firstSibling(Node *n) const {
+ Node *result = n;
+ while (Node *tmp = Getattr(result, "sym:previousSibling")) {
+ result = tmp;
+ }
+ return result;
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::indentCode()
+ *
+ * Helper function to indent a code (string) by one level.
+ * --------------------------------------------------------------------------- */
+ void indentCode(String* code) const {
+ Replaceall(code, "\n", "\n ");
+ Replaceall(code, " \n", "\n");
+ Chop(code);
+ }
+
+ /* ---------------------------------------------------------------------------
+ * D::emitBanner()
+ * --------------------------------------------------------------------------- */
+ void emitBanner(File *f) const {
+ Printf(f, "/* ----------------------------------------------------------------------------\n");
+ Swig_banner_target_lang(f, " *");
+ Printf(f, " * ----------------------------------------------------------------------------- */\n\n");
+ }
+};
+
+static Language *new_swig_d() {
+ return new D();
+}
+
+/* -----------------------------------------------------------------------------
+ * swig_d() - Instantiate module
+ * ----------------------------------------------------------------------------- */
+extern "C" Language *swig_d(void) {
+ return new_swig_d();
+}
+
+/* -----------------------------------------------------------------------------
+ * Usage information displayed at the command line.
+ * ----------------------------------------------------------------------------- */
+const char *D::usage = (char *) "\
+D Options (available with -d)\n\
+ -splitproxy - Write each D type to a dedicated file instead of\n\
+ generating a single proxy D module.\n\
+ -noproxy - Generate the low-level functional interface instead\n\
+ of proxy classes\n\
+ -package <pkg> - Write generated D modules into package <pkg>\n\
+ -wrapperlibrary <wl> - Sets the name of the wrapper library to <wl>\n\
+\n";
diff --git a/Source/Modules/go.cxx b/Source/Modules/go.cxx
index f62586b92..094b1dd5a 100644
--- a/Source/Modules/go.cxx
+++ b/Source/Modules/go.cxx
@@ -43,11 +43,9 @@ class GO:public Language {
File *f_go_runtime;
File *f_go_header;
File *f_go_wrappers;
- File *f_go_once;
File *f_gc_runtime;
File *f_gc_header;
File *f_gc_wrappers;
- File *f_gc_once;
// True if we imported a module.
bool saw_import;
@@ -100,11 +98,9 @@ public:
f_go_runtime(NULL),
f_go_header(NULL),
f_go_wrappers(NULL),
- f_go_once(NULL),
f_gc_runtime(NULL),
f_gc_header(NULL),
f_gc_wrappers(NULL),
- f_gc_once(NULL),
saw_import(false),
imported_package(NULL),
interfaces(NULL),
@@ -303,12 +299,10 @@ private:
f_go_runtime = NewString("");
f_go_header = NewString("");
f_go_wrappers = NewString("");
- f_go_once = NewString("");
if (!gccgo_flag) {
f_gc_runtime = NewString("");
f_gc_header = NewString("");
f_gc_wrappers = NewString("");
- f_gc_once = NewString("");
}
Swig_register_filebyname("begin", f_c_begin);
@@ -322,13 +316,11 @@ private:
Swig_register_filebyname("go_runtime", f_go_runtime);
Swig_register_filebyname("go_header", f_go_header);
Swig_register_filebyname("go_wrapper", f_go_wrappers);
- Swig_register_filebyname("go_once", f_go_once);
if (!gccgo_flag) {
Swig_register_filebyname("gc_begin", f_gc_begin);
Swig_register_filebyname("gc_runtime", f_gc_runtime);
Swig_register_filebyname("gc_header", f_gc_header);
Swig_register_filebyname("gc_wrapper", f_gc_wrappers);
- Swig_register_filebyname("gc_once", f_gc_once);
}
Swig_banner(f_c_begin);
@@ -349,6 +341,7 @@ private:
if (!gccgo_flag) {
Swig_banner(f_gc_begin);
Printf(f_gc_begin, "\n/* This file should be compiled with 6c/8c. */\n");
+ Printf(f_gc_begin, "#pragma dynimport _ _ \"%s\"\n", soname);
}
// Output module initialization code.
@@ -414,16 +407,10 @@ private:
Dump(f_c_wrappers, f_c_begin);
Dump(f_c_init, f_c_begin);
Dump(f_go_header, f_go_begin);
- if (!saw_import) {
- Dump(f_go_once, f_go_begin);
- }
Dump(f_go_runtime, f_go_begin);
Dump(f_go_wrappers, f_go_begin);
if (!gccgo_flag) {
Dump(f_gc_header, f_gc_begin);
- if (!saw_import) {
- Dump(f_gc_once, f_gc_begin);
- }
Dump(f_gc_runtime, f_gc_begin);
Dump(f_gc_wrappers, f_gc_begin);
}
@@ -1011,8 +998,9 @@ private:
int gcFunctionWrapper(Node *n, String *name, String *go_name, String *overname, String *wname, ParmList *parms, SwigType *result, bool is_static, bool needs_wrapper) {
Wrapper *f = NewWrapper();
- Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"", soname, "\"\n", NULL);
- Printv(f->def, "void (*", wname, ")(void*);\n", NULL);
+ Printv(f->def, "#pragma dynimport ", wname, " ", wname, " \"\"\n", NULL);
+ Printv(f->def, "extern void (*", wname, ")(void*);\n", NULL);
+ Printv(f->def, "static void (*x", wname, ")(void*) = ", wname, ";\n", NULL);
Printv(f->def, "\n", NULL);
Printv(f->def, "void\n", NULL);
@@ -1068,7 +1056,7 @@ private:
Delete(parm_size);
Printv(f->code, "{\n", NULL);
- Printv(f->code, "\tcgocall(", wname, ", &p);\n", NULL);
+ Printv(f->code, "\truntime\xc2\xb7" "cgocall(x", wname, ", &p);\n", NULL);
Printv(f->code, "}\n", NULL);
Printv(f->code, "\n", NULL);
@@ -1128,7 +1116,7 @@ private:
Parm *base_parm = NULL;
if (base && !isStatic(n)) {
- SwigType *base_type = Copy(Getattr(class_node, "classtype"));
+ SwigType *base_type = Copy(getClassType());
SwigType_add_pointer(base_type);
base_parm = NewParm(base_type, NewString("arg1"), n);
set_nextSibling(base_parm, parms);
@@ -1166,7 +1154,7 @@ private:
p = nextParm(p);
}
if (SwigType_type(result) != T_VOID) {
- Printv(f->code, "\t\tint : 0;\n", NULL);
+ Printv(f->code, "\t\tlong : 0;\n", NULL);
String *ln = NewString("result");
String *ct = gcCTypeForGoValue(n, result, ln);
Delete(ln);
@@ -1244,7 +1232,7 @@ private:
Parm *base_parm = NULL;
if (base && !isStatic(n)) {
- SwigType *base_type = Copy(Getattr(class_node, "classtype"));
+ SwigType *base_type = Copy(getClassType());
SwigType_add_pointer(base_type);
base_parm = NewParm(base_type, NewString("arg1"), n);
set_nextSibling(base_parm, parms);
@@ -1270,7 +1258,11 @@ private:
Parm *p = parms;
for (int i = 0; i < parm_count; ++i) {
p = getParm(p);
- SwigType *pt = Getattr(p, "type");
+ SwigType *pt = Copy(Getattr(p, "type"));
+ if (SwigType_isarray(pt)) {
+ SwigType_del_array(pt);
+ SwigType_add_pointer(pt);
+ }
String *pn = NewString("g");
Append(pn, Getattr(p, "lname"));
String *ct = gccgoCTypeForGoValue(p, pt, pn);
@@ -1280,6 +1272,7 @@ private:
Printv(fnname, ct, NULL);
Delete(ct);
Delete(pn);
+ Delete(pt);
p = nextParm(p);
}
@@ -1945,7 +1938,7 @@ private:
String *ty = NewString(Getattr(ni, "type"));
SwigType_push(ty, Getattr(ni, "decl"));
String *fullty = SwigType_typedef_resolve_all(ty);
- bool is_function = SwigType_isfunction(fullty);
+ bool is_function = SwigType_isfunction(fullty) ? true : false;
Delete(ty);
Delete(fullty);
@@ -2426,7 +2419,7 @@ private:
* ------------------------------------------------------------ */
int classDirectorConstructor(Node *n) {
- bool is_ignored = GetFlag(n, "feature:ignore");
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
String *name = Getattr(n, "sym:name");
if (!name) {
@@ -2667,7 +2660,7 @@ private:
return SWIG_OK;
}
- bool is_ignored = GetFlag(n, "feature:ignore");
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
if (!is_ignored) {
String *fnname = NewString("DeleteDirector");
@@ -2679,7 +2672,7 @@ private:
Setattr(n, "wrap:name", fnname);
- Swig_DestructorToFunction(n, getNSpace(), Getattr(parentNode(n), "classtype"), CPlusPlus, Extend);
+ Swig_DestructorToFunction(n, getNSpace(), getClassType(), CPlusPlus, Extend);
ParmList *parms = Getattr(n, "parms");
Setattr(n, "wrap:parms", parms);
@@ -2749,7 +2742,7 @@ private:
Printv(f_gc_wrappers, "void\n", NULL);
Printv(f_gc_wrappers, wname, "(void *a, int32 n)\n", NULL);
Printv(f_gc_wrappers, "{\n", NULL);
- Printv(f_gc_wrappers, "\tcgocallback(\xc2\xb7", go_name, ", a, n);\n", NULL);
+ Printv(f_gc_wrappers, "\truntime\xc2\xb7" "cgocallback(\xc2\xb7", go_name, ", a, n);\n", NULL);
Printv(f_gc_wrappers, "}\n\n", NULL);
} else {
Printv(f_c_directors, " ", wname, "(go_val);\n", NULL);
@@ -2781,7 +2774,7 @@ private:
int classDirectorMethod(Node *n, Node *parent, String *super) {
(void) super;
- bool is_ignored = GetFlag(n, "feature:ignore");
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
bool is_pure_virtual = (Cmp(Getattr(n, "storage"), "virtual") == 0 && Cmp(Getattr(n, "value"), "0") == 0);
// We don't need explicit calls.
@@ -2869,7 +2862,7 @@ private:
* ------------------------------------------------------------ */
int oneClassDirectorMethod(Node *n, Node *parent) {
- bool is_ignored = GetFlag(n, "feature:ignore");
+ bool is_ignored = GetFlag(n, "feature:ignore") ? true : false;
bool is_pure_virtual = (Cmp(Getattr(n, "storage"), "virtual") == 0 && Cmp(Getattr(n, "value"), "0") == 0);
String *name = Getattr(n, "sym:name");
@@ -3415,7 +3408,7 @@ private:
p = Getattr(p, "tmap:directorin:next");
}
if (SwigType_type(result) != T_VOID) {
- Printv(f->code, " int : 0;\n", NULL);
+ Printv(f->code, " long : 0;\n", NULL);
String *rname = NewString("result");
String *cg = gcCTypeForGoValue(n, result, rname);
Printv(f->code, " ", cg, ";\n", NULL);
@@ -3475,7 +3468,7 @@ private:
Printv(f_gc_wrappers, "void\n", NULL);
Printv(f_gc_wrappers, callback_wname, "(void *a, int32 n)\n", NULL);
Printv(f_gc_wrappers, "{\n", NULL);
- Printv(f_gc_wrappers, "\tcgocallback(\xc2\xb7", callback_name, ", a, n);\n", NULL);
+ Printv(f_gc_wrappers, "\truntime\xc2\xb7" "cgocallback(\xc2\xb7", callback_name, ", a, n);\n", NULL);
Printv(f_gc_wrappers, "}\n\n", NULL);
} else {
if (SwigType_type(result) != T_VOID) {
@@ -3545,7 +3538,7 @@ private:
}
} else {
assert(is_pure_virtual);
- Printv(f->code, " _swig_gopanic(\"call to pure virtual function ", Getattr(parent, "sym:name"), name, "\");\n");
+ Printv(f->code, " _swig_gopanic(\"call to pure virtual function ", Getattr(parent, "sym:name"), name, "\");\n", NULL);
if (SwigType_type(result) != T_VOID) {
String *retstr = SwigType_rcaststr(Getattr(n, "returntype"), "c_result");
Printv(f->code, " return ", retstr, ";\n", NULL);
@@ -3782,7 +3775,7 @@ private:
int num_required = emit_num_required(pi);
int num_arguments = emit_num_arguments(pi);
- bool varargs = emit_isvarargs(pi);
+ bool varargs = emit_isvarargs(pi) ? true : false;
if (varargs) {
Printf(f_go_wrappers, "\tif argc >= %d {\n", num_required);
@@ -4138,7 +4131,7 @@ private:
n1, name, n2);
return false;
}
- bool r = addSymbol(name, n, scope);
+ bool r = addSymbol(name, n, scope) ? true : false;
assert(r);
return true;
}
diff --git a/Source/Modules/java.cxx b/Source/Modules/java.cxx
index 4a6abd569..234a1e85b 100644
--- a/Source/Modules/java.cxx
+++ b/Source/Modules/java.cxx
@@ -1714,10 +1714,10 @@ public:
base = Next(base);
continue;
}
- String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
- String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
- Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, input_file, line_number,
- "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java.\n", proxyclassname, baseclassname);
+ String *proxyclassname = Getattr(n, "classtypeobj");
+ String *baseclassname = Getattr(base.item, "name");
+ Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
+ "Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java.\n", SwigType_namestr(proxyclassname), SwigType_namestr(baseclassname));
base = Next(base);
}
}
@@ -1735,9 +1735,9 @@ public:
Delete(baseclass);
baseclass = NULL;
if (purebase_notderived)
- Swig_error(input_file, line_number, "The javabase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
+ Swig_error(Getfile(n), Getline(n), "The javabase typemap for proxy %s must contain just one of the 'replace' or 'notderived' attributes.\n", typemap_lookup_type);
} else if (Len(pure_baseclass) > 0 && Len(baseclass) > 0) {
- Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, input_file, line_number,
+ Swig_warning(WARN_JAVA_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Java. "
"Perhaps you need one of the 'replace' or 'notderived' attributes in the csbase typemap?\n", typemap_lookup_type, pure_baseclass);
}
@@ -1772,12 +1772,10 @@ public:
}
if (tm && *Char(tm)) {
if (!destruct_methodname) {
- Swig_error(input_file, line_number,
- "No methodname attribute defined in javadestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
+ Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in javadestruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
}
if (!destruct_methodmodifiers) {
- Swig_error(input_file, line_number,
- "No methodmodifiers attribute defined in javadestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
+ Swig_error(Getfile(n), Getline(n), "No methodmodifiers attribute defined in javadestruct%s typemap for %s.\n", (derived ? "_derived" : ""), proxy_class_name);
}
}
// Emit the finalize and delete methods
@@ -3326,8 +3324,10 @@ public:
}
Printf(f_runtime, "namespace Swig {\n");
- Printf(f_runtime, " static jclass jclass_%s = NULL;\n", imclass_name);
- Printf(f_runtime, " static jmethodID director_methids[%d];\n", n_methods);
+ Printf(f_runtime, " namespace {\n");
+ Printf(f_runtime, " jclass jclass_%s = NULL;\n", imclass_name);
+ Printf(f_runtime, " jmethodID director_methids[%d];\n", n_methods);
+ Printf(f_runtime, " }\n");
Printf(f_runtime, "}\n");
Printf(w->def, "SWIGEXPORT void JNICALL Java_%s%s_%s(JNIEnv *jenv, jclass jcls) {", jnipackage, jni_imclass_name, swig_module_init_jni);
@@ -3548,7 +3548,6 @@ public:
String *callback_def = NewString("");
String *callback_code = NewString("");
String *imcall_args = NewString("");
- int gencomma = 0;
int classmeth_off = curr_class_dmethod - first_class_dmethod;
bool ignored_method = GetFlag(n, "feature:ignore") ? true : false;
@@ -3767,14 +3766,14 @@ public:
Delete(tp);
/* Go through argument list, convert from native to Java */
- for (p = l; p; /* empty */ ) {
+ for (i = 0, p = l; p; ++i) {
/* Is this superfluous? */
while (checkAttribute(p, "tmap:directorin:numinputs", "0")) {
p = Getattr(p, "tmap:directorin:next");
}
SwigType *pt = Getattr(p, "type");
- String *ln = Copy(Getattr(p, "name"));
+ String *ln = makeParameterName(n, p, i, false);
String *c_param_type = NULL;
String *c_decl = NewString("");
String *arg = NewString("");
@@ -3833,7 +3832,7 @@ public:
substituteClassname(pt, din);
Replaceall(din, "$jniinput", ln);
- if (++gencomma > 1)
+ if (i > 0)
Printf(imcall_args, ", ");
Printf(callback_def, ", %s %s", tm, ln);
@@ -3896,6 +3895,7 @@ public:
Delete(arg);
Delete(c_decl);
Delete(c_param_type);
+ Delete(ln);
}
/* header declaration, start wrapper definition */
diff --git a/Source/Modules/lang.cxx b/Source/Modules/lang.cxx
index e28fcbb89..82af250f7 100644
--- a/Source/Modules/lang.cxx
+++ b/Source/Modules/lang.cxx
@@ -52,7 +52,7 @@ extern "C" {
return all_protected_mode;
}
void Language_replace_special_variables(String *method, String *tm, Parm *parm) {
- Language::instance()->replaceSpecialVariables(method, tm, parm);
+ Language::instance()->replaceSpecialVariables(method, tm, parm);
}
}
@@ -1344,7 +1344,7 @@ int Language::variableHandler(Node *n) {
Swig_save("variableHandler", n, "feature:immutable", NIL);
if (SmartPointer) {
/* If a smart-pointer and it's a constant access, we have to set immutable */
- if (Getattr(CurrentClass, "allocate:smartpointerconst")) {
+ if (!Getattr(CurrentClass, "allocate:smartpointermutable")) {
SetFlag(n, "feature:immutable");
}
}
@@ -1391,7 +1391,7 @@ int Language::membervariableHandler(Node *n) {
int assignable = is_assignable(n);
if (SmartPointer) {
- if (Getattr(CurrentClass, "allocate:smartpointerconst")) {
+ if (!Getattr(CurrentClass, "allocate:smartpointermutable")) {
assignable = 0;
}
}
@@ -1806,17 +1806,25 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
classname = Getattr(n, "name");
for (ni = Getattr(n, "firstChild"); ni; ni = nextSibling(ni)) {
/* we only need to check the virtual members */
- if (!checkAttribute(ni, "storage", "virtual"))
- continue;
nodeType = Getattr(ni, "nodeType");
+ int is_using = (Cmp(nodeType, "using") == 0);
+ Node *nn = is_using ? firstChild(ni) : ni; /* assume there is only one child node for "using" nodes */
+ if (is_using) {
+ if (nn)
+ nodeType = Getattr(nn, "nodeType");
+ else
+ continue; // A private "using" node
+ }
+ if (!checkAttribute(nn, "storage", "virtual"))
+ continue;
/* we need to add methods(cdecl) and destructor (to check for throw decl) */
int is_destructor = (Cmp(nodeType, "destructor") == 0);
if ((Cmp(nodeType, "cdecl") == 0) || is_destructor) {
- decl = Getattr(ni, "decl");
+ decl = Getattr(nn, "decl");
/* extra check for function type and proper access */
- if (SwigType_isfunction(decl) && (((!protectedbase || dirprot_mode()) && is_public(ni)) || need_nonpublic_member(ni))) {
- String *name = Getattr(ni, "name");
- Node *method_id = is_destructor ? NewStringf("~destructor") : vtable_method_id(ni);
+ if (SwigType_isfunction(decl) && (((!protectedbase || dirprot_mode()) && is_public(nn)) || need_nonpublic_member(nn))) {
+ String *name = Getattr(nn, "name");
+ Node *method_id = is_destructor ? NewStringf("~destructor") : vtable_method_id(nn);
/* Make sure that the new method overwrites the existing: */
int len = Len(vm);
const int DO_NOT_REPLACE = -1;
@@ -1834,7 +1842,7 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
String *fqdname = NewStringf("%s::%s", classname, name);
Hash *item = NewHash();
Setattr(item, "fqdname", fqdname);
- Node *m = Copy(ni);
+ Node *m = Copy(nn);
/* Store the complete return type - needed for non-simple return types (pointers, references etc.) */
SwigType *ty = NewString(Getattr(m, "type"));
@@ -1854,6 +1862,7 @@ int Language::unrollVirtualMethods(Node *n, Node *parent, List *vm, int default_
Append(vm, item);
else
Setitem(vm, replace, item);
+ Setattr(nn, "directorNode", m);
Delete(mname);
}
@@ -2443,6 +2452,9 @@ int Language::classHandler(Node *n) {
List *methods = Getattr(n, "allocate:smartpointer");
cplus_mode = PUBLIC;
SmartPointer = CWRAP_SMART_POINTER;
+ if (Getattr(n, "allocate:smartpointerconst") && Getattr(n, "allocate:smartpointermutable")) {
+ SmartPointer |= CWRAP_SMART_POINTER_OVERLOAD;
+ }
Iterator c;
for (c = First(methods); c.item; c = Next(c)) {
emit_one(c.item);
@@ -2803,7 +2815,7 @@ int Language::validIdentifier(String *s) {
* ----------------------------------------------------------------------------- */
int Language::usingDeclaration(Node *n) {
- if ((cplus_mode == PUBLIC)) {
+ if ((cplus_mode == PUBLIC) || (!is_public(n) && dirprot_mode())) {
Node *np = Copy(n);
Node *c;
for (c = firstChild(np); c; c = nextSibling(c)) {
@@ -3008,7 +3020,7 @@ Node *Language::symbolLookup(String *s, const_String_or_char_ptr scope) {
* Tries to locate a class from a type definition
* ----------------------------------------------------------------------------- */
-Node *Language::classLookup(SwigType *s) {
+Node *Language::classLookup(const SwigType *s) {
Node *n = 0;
/* Look in hash of cached values */
diff --git a/Source/Modules/lua.cxx b/Source/Modules/lua.cxx
index d240d3d6f..d0cbc9195 100644
--- a/Source/Modules/lua.cxx
+++ b/Source/Modules/lua.cxx
@@ -919,7 +919,7 @@ public:
String *wrap_class = NewStringf("&_wrap_class_%s", mangled_classname);
SwigType_remember_clientdata(t, wrap_class);
- String *rt = Copy(Getattr(n, "classtype"));
+ String *rt = Copy(getClassType());
SwigType_add_pointer(rt);
// Register the class structure with the type checker
diff --git a/Source/Modules/main.cxx b/Source/Modules/main.cxx
index f0e941f22..95327018d 100644
--- a/Source/Modules/main.cxx
+++ b/Source/Modules/main.cxx
@@ -129,6 +129,7 @@ static const char *usage3 = (const char *) "\
-oh <headfile> - Set name of the output header file to <headfile>\n\
-outcurrentdir - Set default output dir to current dir instead of input file's path\n\
-outdir <dir> - Set language specific files output directory to <dir>\n\
+ -pcreversion - Display PCRE version information\n\
-small - Compile in virtual elimination & compact mode\n\
-swiglib - Report location of SWIG library and exit\n\
-templatereduce - Reduce all the typedefs in templates\n\
@@ -515,6 +516,12 @@ void SWIG_getoptions(int argc, char *argv[]) {
} else if (strcmp(argv[i], "-nodirprot") == 0) {
Wrapper_director_protected_mode_set(0);
Swig_mark_arg(i);
+ } else if (strcmp(argv[i], "-pcreversion") == 0) {
+ String *version = Swig_pcre_version();
+ Printf(stdout, "%s\n", version);
+ Delete(version);
+ Swig_mark_arg(i);
+ SWIG_exit(EXIT_SUCCESS);
} else if (strcmp(argv[i], "-small") == 0) {
Wrapper_compact_print_mode_set(1);
Wrapper_virtual_elimination_mode_set(1);
@@ -622,7 +629,14 @@ void SWIG_getoptions(int argc, char *argv[]) {
} else if (strcmp(argv[i], "-version") == 0) {
fprintf(stdout, "\nSWIG Version %s\n", Swig_package_version());
fprintf(stdout, "\nCompiled with %s [%s]\n", SWIG_CXX, SWIG_PLATFORM);
- fprintf(stdout, "Please see %s for reporting bugs and further information\n", PACKAGE_BUGREPORT);
+ fprintf(stdout, "\nConfigured options: %cpcre\n",
+#ifdef HAVE_PCRE
+ '+'
+#else
+ '-'
+#endif
+ );
+ fprintf(stdout, "\nPlease see %s for reporting bugs and further information\n", PACKAGE_BUGREPORT);
SWIG_exit(EXIT_SUCCESS);
} else if (strcmp(argv[i], "-copyright") == 0) {
fprintf(stdout, "\nSWIG Version %s\n", Swig_package_version());
diff --git a/Source/Modules/modula3.cxx b/Source/Modules/modula3.cxx
index edd6690ce..45ceba1a4 100644
--- a/Source/Modules/modula3.cxx
+++ b/Source/Modules/modula3.cxx
@@ -2222,8 +2222,7 @@ MODULA3():
}
base = Next(base);
if (base.item != NIL) {
- Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, input_file,
- line_number,
+ Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n",
classDeclarationName, Getattr(base.item, "name"));
}
@@ -2236,8 +2235,7 @@ MODULA3():
// Inheritance from pure Modula 3 classes
const String *pure_baseclass = typemapLookup(n, "m3base", classDeclarationName, WARN_NONE);
if (hasContent(pure_baseclass) && hasContent(baseclass)) {
- Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, input_file,
- line_number,
+ Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n", classDeclarationName, pure_baseclass);
}
// Pure Modula 3 interfaces
@@ -2273,7 +2271,7 @@ MODULA3():
destruct_methodname = Getattr(attributes, "tmap:m3destruct:methodname");
}
if (!destruct_methodname) {
- Swig_error(input_file, line_number, "No methodname attribute defined in m3destruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
+ Swig_error(Getfile(n), Getline(n), "No methodname attribute defined in m3destruct%s typemap for %s\n", (derived ? "_derived" : ""), proxy_class_name);
}
// Emit the Finalize and Dispose methods
if (tm) {
@@ -2466,8 +2464,7 @@ MODULA3():
Append(baseclassname, Getattr(base.item, "sym:name"));
base = Next(base);
if (base.item != NIL) {
- Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, input_file,
- line_number,
+ Swig_warning(WARN_MODULA3_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Modula 3.\n",
proxy_class_name, Getattr(base.item, "name"));
}
diff --git a/Source/Modules/mzscheme.cxx b/Source/Modules/mzscheme.cxx
index 0bc3c8a68..d071dc870 100644
--- a/Source/Modules/mzscheme.cxx
+++ b/Source/Modules/mzscheme.cxx
@@ -682,7 +682,7 @@ public:
String *mangled_classname = 0;
String *real_classname = 0;
String *scm_structname = NewString("");
- SwigType *ctype_ptr = NewStringf("p.%s", Getattr(n, "classtype"));
+ SwigType *ctype_ptr = NewStringf("p.%s", getClassType());
SwigType *t = NewStringf("p.%s", Getattr(n, "name"));
swigtype_ptr = SwigType_manglestr(t);
diff --git a/Source/Modules/ocaml.cxx b/Source/Modules/ocaml.cxx
index 82e3f846a..6021cf276 100644
--- a/Source/Modules/ocaml.cxx
+++ b/Source/Modules/ocaml.cxx
@@ -35,7 +35,7 @@ static String *classname = 0;
static String *module = 0;
static String *init_func_def = 0;
static String *f_classtemplate = 0;
-static String *name_qualifier = 0;
+static SwigType *name_qualifier_type = 0;
static Hash *seen_enums = 0;
static Hash *seen_enumvalues = 0;
@@ -898,12 +898,12 @@ public:
String *name = Getattr(n, "feature:symname");
SwigType *type = Getattr(n, "type");
String *value = Getattr(n, "value");
- String *qvalue = Getattr(n, "qualified:value");
+ SwigType *qname = Getattr(n, "qualified:name");
String *rvalue = NewString("");
String *temp = 0;
- if (qvalue)
- value = qvalue;
+ if (qname)
+ value = qname;
if (!name) {
name = mangleNameForCaml(Getattr(n, "name"));
@@ -1228,20 +1228,18 @@ public:
return out;
}
- String *fully_qualify_enum_name(Node *n, String *name) {
+ SwigType *fully_qualified_enum_type(Node *n) {
Node *parent = 0;
- String *qualification = NewString("");
String *fully_qualified_name = NewString("");
String *parent_type = 0;
- String *normalized_name;
parent = parentNode(n);
while (parent) {
parent_type = nodeType(parent);
if (Getattr(parent, "name")) {
String *parent_copy = NewStringf("%s::", Getattr(parent, "name"));
- if (!Cmp(parent_type, "class") || !Cmp(parent_type, "namespace"))
- Insert(qualification, 0, parent_copy);
+ if (Cmp(parent_type, "class") == 0 || Cmp(parent_type, "namespace") == 0)
+ Insert(fully_qualified_name, 0, parent_copy);
Delete(parent_copy);
}
if (!Cmp(parent_type, "class"))
@@ -1249,25 +1247,18 @@ public:
parent = parentNode(parent);
}
- Printf(fully_qualified_name, "%s%s", qualification, name);
-
- normalized_name = normalizeTemplatedClassName(fully_qualified_name);
- if (!strncmp(Char(normalized_name), "enum ", 5)) {
- Insert(normalized_name, 5, qualification);
- }
-
- return normalized_name;
+ return fully_qualified_name;
}
/* Benedikt Grundmann inspired --> Enum wrap styles */
int enumvalueDeclaration(Node *n) {
String *name = Getattr(n, "name");
- String *qvalue = 0;
+ SwigType *qtype = 0;
- if (name_qualifier) {
- qvalue = Copy(name_qualifier);
- Printv(qvalue, name, NIL);
+ if (name_qualifier_type) {
+ qtype = Copy(name_qualifier_type);
+ Printv(qtype, name, NIL);
}
if (const_enum && name && !Getattr(seen_enumvalues, name)) {
@@ -1275,10 +1266,10 @@ public:
SetFlag(n, "feature:immutable");
Setattr(n, "feature:enumvalue", "1"); // this does not appear to be used
- if (qvalue)
- Setattr(n, "qualified:value", qvalue);
+ if (qtype)
+ Setattr(n, "qualified:name", SwigType_namestr(qtype));
- String *evname = SwigType_manglestr(qvalue);
+ String *evname = SwigType_manglestr(qtype);
Insert(evname, 0, "SWIG_ENUM_");
Setattr(n, "feature:enumvname", name);
@@ -1309,10 +1300,10 @@ public:
/* name is now fully qualified */
String *fully_qualified_name = NewString(name);
bool seen_enum = false;
- if (name_qualifier)
- Delete(name_qualifier);
+ if (name_qualifier_type)
+ Delete(name_qualifier_type);
char *strip_position;
- name_qualifier = fully_qualify_enum_name(n, NewString(""));
+ name_qualifier_type = fully_qualified_enum_type(n);
strip_position = strstr(Char(oname), "::");
diff --git a/Source/Modules/php.cxx b/Source/Modules/php.cxx
index 365fcd370..554e40bb8 100644
--- a/Source/Modules/php.cxx
+++ b/Source/Modules/php.cxx
@@ -126,7 +126,7 @@ static enum {
} wrapperType = standard;
extern "C" {
- static void (*r_prevtracefunc) (SwigType *t, String *mangled, String *clientdata) = 0;
+ static void (*r_prevtracefunc) (const SwigType *t, String *mangled, String *clientdata) = 0;
}
static void SwigPHP_emit_resource_registrations() {
@@ -666,7 +666,7 @@ public:
/* We have an extra 'this' parameter. */
SetFlag(n, "wrap:this");
}
- String *dispatch = Swig_overload_dispatch(n, "return %s(INTERNAL_FUNCTION_PARAM_PASSTHRU);", &maxargs);
+ String *dispatch = Swig_overload_dispatch(n, "%s(INTERNAL_FUNCTION_PARAM_PASSTHRU); return;", &maxargs);
/* Generate a dispatch wrapper for all overloaded functions */
@@ -915,8 +915,10 @@ public:
}
/* Insert argument output code */
+ bool hasargout = false;
for (i = 0, p = l; p; i++) {
if ((tm = Getattr(p, "tmap:argout"))) {
+ hasargout = true;
Replaceall(tm, "$source", Getattr(p, "lname"));
// Replaceall(tm,"$input",Getattr(p,"lname"));
Replaceall(tm, "$target", "return_value");
@@ -974,7 +976,7 @@ public:
/* Error handling code */
Printf(f->code, "fail:\n");
Printv(f->code, cleanup, NIL);
- Printv(f->code, "zend_error_noreturn(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());", NIL);
+ Printv(f->code, "zend_error(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());", NIL);
Printf(f->code, "}\n");
@@ -1599,10 +1601,9 @@ public:
Delete(args);
args = NewString("$res=null");
}
- SwigType *t = Getattr(current_class, "classtype");
- String *mangled_type = SwigType_manglestr(SwigType_ltype(t));
+ String *mangled_type = SwigType_manglestr(Getattr(n, "type"));
Printf(output, "\t%sfunction %s(%s) {\n", acc, methodname, args);
- Printf(output, "\t\tif (is_resource($%s) && get_resource_type($%s) === '_p%s') {\n", arg0, arg0, mangled_type);
+ Printf(output, "\t\tif (is_resource($%s) && get_resource_type($%s) === '%s') {\n", arg0, arg0, mangled_type);
Printf(output, "\t\t\t$this->%s=$%s;\n", SWIG_PTR, arg0);
Printf(output, "\t\t\treturn;\n");
Printf(output, "\t\t}\n");
@@ -1663,7 +1664,7 @@ public:
}
}
Printf(output, "%s", prepare);
- } else if (Cmp(d, "void") == 0) {
+ } else if (Cmp(d, "void") == 0 && !hasargout) {
if (Cmp(invoke, "$r") != 0)
Printf(output, "\t\t%s;\n", invoke);
} else if (is_class(d)) {
@@ -2289,7 +2290,7 @@ done:
Append(f->code, "return;\n");
Append(f->code, "fail:\n");
- Append(f->code, "zend_error_noreturn(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\n");
+ Append(f->code, "zend_error(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\n");
Printf(f->code, "}\n");
Wrapper_print(f, s_wrappers);
@@ -2664,7 +2665,7 @@ done:
}
Append(w->code, "fail:\n");
- Append(w->code, "zend_error_noreturn(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\n");
+ Append(w->code, "zend_error(SWIG_ErrorCode(),\"%s\",SWIG_ErrorMsg());\n");
Append(w->code, "}\n");
// We expose protected methods via an extra public inline method which makes a straight call to the wrapped class' method
@@ -2709,7 +2710,7 @@ static PHP *maininstance = 0;
// We use this function to be able to write out zend_register_list_destructor_ex
// lines for most things in the type table
// NOTE: it's a function NOT A PHP::METHOD
-extern "C" void typetrace(SwigType *ty, String *mangled, String *clientdata) {
+extern "C" void typetrace(const SwigType *ty, String *mangled, String *clientdata) {
Node *class_node;
if (!zend_types) {
zend_types = NewHash();
diff --git a/Source/Modules/python.cxx b/Source/Modules/python.cxx
index fed5205e1..6d5f500a4 100644
--- a/Source/Modules/python.cxx
+++ b/Source/Modules/python.cxx
@@ -130,7 +130,7 @@ static const char *usage2 = (char *) "\
-nofastproxy - Use traditional proxy mechanism for member methods (default) \n\
-nofastquery - Use traditional query mechanism for types (default) \n\
-noh - Don't generate the output header file\n\
- -nomodern - Don't use modern python features which are not back compatible \n\
+ -nomodern - Don't use modern python features which are not backwards compatible \n\
-nomodernargs - Use classic ParseTuple/CallFunction methods to pack/unpack the function arguments (default) \n";
static const char *usage3 = (char *) "\
-noolddefs - Don't emit the old method definitions even when using fastproxy (default) \n\
@@ -1799,7 +1799,7 @@ public:
} while ((sibl = Getattr(sibl, "sym:nextSibling")));
Append(f->code, "fail:\n");
Printf(f->code, "SWIG_SetErrorMsg(PyExc_NotImplementedError,"
- "\"Wrong number of arguments for overloaded function '%s'.\\n\"" "\n\" Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes);
+ "\"Wrong number or type of arguments for overloaded function '%s'.\\n\"" "\n\" Possible C/C++ prototypes are:\\n\"%s);\n", symname, protoTypes);
Append(f->code, "return NULL;\n");
Delete(protoTypes);
}
@@ -2866,7 +2866,7 @@ public:
bool ignore = GetFlag(b.item, "feature:ignore") ? true : false;
if (!bname || ignore) {
if (!bname && !ignore) {
- Swig_warning(WARN_TYPE_UNDEFINED_CLASS, input_file, line_number,
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(n), Getline(n),
"Base class '%s' ignored - unknown module name for base. Either import the appropriate module interface file or specify the name of the module in the %%import directive.\n", SwigType_namestr(Getattr(b.item, "name")));
}
b = Next(b);
diff --git a/Source/Modules/r.cxx b/Source/Modules/r.cxx
index 749797c78..64583175b 100644
--- a/Source/Modules/r.cxx
+++ b/Source/Modules/r.cxx
@@ -300,7 +300,7 @@ public:
Printf(stderr, "<memberfunctionHandler> %s %s\n",
Getattr(n, "name"),
Getattr(n, "type"));
- member_name = Getattr(n, "name");
+ member_name = Getattr(n, "sym:name");
processing_class_member_function = 1;
int status = Language::memberfunctionHandler(n);
processing_class_member_function = 0;
@@ -1603,6 +1603,16 @@ void R::dispatchFunction(Node *n) {
j == 0 ? "" : " && ",
j+1);
}
+ else if (DohStrcmp(tm,"integer")==0) {
+ Printf(f->code, "%s(is.integer(argv[[%d]]) || is.numeric(argv[[%d]]))",
+ j == 0 ? "" : " && ",
+ j+1, j+1);
+ }
+ else if (DohStrcmp(tm,"character")==0) {
+ Printf(f->code, "%sis.character(argv[[%d]])",
+ j == 0 ? "" : " && ",
+ j+1);
+ }
else {
Printf(f->code, "%sextends(argtypes[%d], '%s')",
j == 0 ? "" : " && ",
@@ -1617,7 +1627,10 @@ void R::dispatchFunction(Node *n) {
}
}
if (cur_args != -1) {
- Printv(f->code, "}", NIL);
+ Printf(f->code, "} else {\n"
+ "stop(\"cannot find overloaded function for %s with argtypes (\","
+ "toString(argtypes),\")\");\n"
+ "}", sfname);
}
Printv(f->code, ";\nf(...)", NIL);
Printv(f->code, ";\n}", NIL);
diff --git a/Source/Modules/ruby.cxx b/Source/Modules/ruby.cxx
index bcdfd69d3..8461b8bef 100644
--- a/Source/Modules/ruby.cxx
+++ b/Source/Modules/ruby.cxx
@@ -2054,8 +2054,15 @@ public:
// Construct real method name
String* methodName = NewString("");
- if ( isMethod )
- Printv( methodName, Getattr(parentNode(sibl),"sym:name"), ".", NIL );
+ if ( isMethod ) {
+ // Sometimes a method node has no parent (SF#3034054).
+ // This value is used in an exception message, so just skip the class
+ // name in this case so at least we don't segfault. This is probably
+ // just working around a problem elsewhere though.
+ Node *parent_node = parentNode(sibl);
+ if (parent_node)
+ Printv( methodName, Getattr(parent_node,"sym:name"), ".", NIL );
+ }
Append( methodName, Getattr(sibl,"sym:name" ) );
if ( isCtor ) Append( methodName, ".new" );
@@ -2395,7 +2402,7 @@ public:
}
String *proxyclassname = SwigType_str(Getattr(n, "classtypeobj"), 0);
String *baseclassname = SwigType_str(Getattr(base.item, "name"), 0);
- Swig_warning(WARN_RUBY_MULTIPLE_INHERITANCE, input_file, line_number,
+ Swig_warning(WARN_RUBY_MULTIPLE_INHERITANCE, Getfile(n), Getline(n),
"Warning for %s proxy: Base %s ignored. Multiple inheritance is not supported in Ruby.\n", proxyclassname, baseclassname);
base = Next(base);
}
diff --git a/Source/Modules/swigmain.cxx b/Source/Modules/swigmain.cxx
index 844229a96..bcccf7a1b 100644
--- a/Source/Modules/swigmain.cxx
+++ b/Source/Modules/swigmain.cxx
@@ -53,6 +53,7 @@ extern "C" {
Language *swig_uffi(void);
Language *swig_r(void);
Language *swig_go(void);
+ Language *swig_d(void);
}
struct swig_module {
@@ -71,6 +72,7 @@ static swig_module modules[] = {
{"-clisp", swig_clisp, "CLISP"},
{"-cffi", swig_cffi, "CFFI"},
{"-csharp", swig_csharp, "C#"},
+ {"-d", swig_d, "D"},
{"-fortran", swig_fortran, "FORTRAN"},
{"-go", swig_go, "Go"},
{"-guile", swig_guile, "Guile"},
diff --git a/Source/Modules/swigmod.h b/Source/Modules/swigmod.h
index 693a67071..142130628 100644
--- a/Source/Modules/swigmod.h
+++ b/Source/Modules/swigmod.h
@@ -213,7 +213,7 @@ public:
virtual int addSymbol(const String *s, const Node *n, const_String_or_char_ptr scope = ""); /* Add symbol */
virtual void dumpSymbols();
virtual Node *symbolLookup(String *s, const_String_or_char_ptr scope = ""); /* Symbol lookup */
- virtual Node *classLookup(SwigType *s); /* Class lookup */
+ virtual Node *classLookup(const SwigType *s); /* Class lookup */
virtual Node *enumLookup(SwigType *s); /* Enum lookup */
virtual int abstractClassTest(Node *n); /* Is class really abstract? */
virtual int is_assignable(Node *n); /* Is variable assignable? */
@@ -382,9 +382,15 @@ void Wrapper_fast_dispatch_mode_set(int);
void Wrapper_cast_dispatch_mode_set(int);
void Wrapper_naturalvar_mode_set(int);
-
void clean_overloaded(Node *n);
+extern "C" {
+ const char *Swig_to_string(DOH *object, int count = -1);
+ const char *Swig_to_string_with_location(DOH *object, int count = -1);
+ void Swig_print(DOH *object, int count = -1);
+ void Swig_print_with_location(DOH *object, int count = -1);
+}
+
/* Contracts */
void Swig_contracts(Node *n);
@@ -397,5 +403,4 @@ void Swig_browser(Node *n, int);
void Swig_default_allocators(Node *n);
void Swig_process_types(Node *n);
-
#endif
diff --git a/Source/Modules/tcl8.cxx b/Source/Modules/tcl8.cxx
index b6b4c6965..dfdd71b64 100644
--- a/Source/Modules/tcl8.cxx
+++ b/Source/Modules/tcl8.cxx
@@ -783,10 +783,7 @@ public:
String *wrap_class = NewStringf("&_wrap_class_%s", mangled_classname);
SwigType_remember_clientdata(t, wrap_class);
- // t = Copy(Getattr(n,"classtype"));
- // SwigType_add_pointer(t);
-
- String *rt = Copy(Getattr(n, "classtype"));
+ String *rt = Copy(getClassType());
SwigType_add_pointer(rt);
// Register the class structure with the type checker
diff --git a/Source/Modules/typepass.cxx b/Source/Modules/typepass.cxx
index e0e06d54e..3e2c9ca1e 100644
--- a/Source/Modules/typepass.cxx
+++ b/Source/Modules/typepass.cxx
@@ -175,10 +175,10 @@ class TypePass:private Dispatcher {
}
}
if (Strcmp(nodeType(bcls), "classforward") != 0) {
- Swig_error(Getfile(cls), Getline(cls), "'%s' does not have a valid base class.\n", Getattr(cls, "name"));
- Swig_error(Getfile(bcls), Getline(bcls), "'%s' is not a valid base class.\n", SwigType_namestr(bname));
+ Swig_error(Getfile(bname), Getline(bname), "'%s' is not a valid base class.\n", SwigType_namestr(bname));
+ Swig_error(Getfile(bcls), Getline(bcls), "See definition of '%s'.\n", SwigType_namestr(bname));
} else {
- Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(cls), Getline(cls), "Base class '%s' is incomplete.\n", SwigType_namestr(bname));
+ Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(bname), Getline(bname), "Base class '%s' is incomplete.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_INCOMPLETE, Getfile(bcls), Getline(bcls), "Only forward declaration '%s' was found.\n", SwigType_namestr(bname));
clsforward = 1;
}
@@ -189,7 +189,7 @@ class TypePass:private Dispatcher {
ilist = alist = NewList();
Append(ilist, bcls);
} else {
- Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(cls), Getline(cls), "Base class '%s' undefined.\n", SwigType_namestr(bname));
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Base class '%s' undefined.\n", SwigType_namestr(bname));
Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bcls), Getline(bcls), "'%s' must be defined before it is used as a base class.\n", SwigType_namestr(bname));
}
}
@@ -202,10 +202,9 @@ class TypePass:private Dispatcher {
if (!bcls) {
if (!clsforward) {
if (ispublic && !Getmeta(bname, "already_warned")) {
- Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(cls), Getline(cls), "Nothing known about base class '%s'. Ignored.\n", SwigType_namestr(bname));
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Nothing known about base class '%s'. Ignored.\n", SwigType_namestr(bname));
if (Strchr(bname, '<')) {
- Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(cls), Getline(cls), "Maybe you forgot to instantiate '%s' using %%template.\n",
- SwigType_namestr(bname));
+ Swig_warning(WARN_TYPE_UNDEFINED_CLASS, Getfile(bname), Getline(bname), "Maybe you forgot to instantiate '%s' using %%template.\n", SwigType_namestr(bname));
}
Setmeta(bname, "already_warned", "1");
}
@@ -255,12 +254,17 @@ class TypePass:private Dispatcher {
Delete(smartnamestr);
/* setup inheritance relationship between smart pointer templates */
SwigType_inherit(smart, bsmart, 0, convcode);
+ if (!GetFlag(bclass, "feature:smartptr"))
+ Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Base class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(bclass, "name")), SwigType_namestr(Getattr(first, "name")));
Delete(convcode);
Delete(bsmart);
Delete(smart);
} else {
- Swig_error(Getfile(first), Getline(first), "Invalid type (%s) in 'smartptr' feature for class %s.\n", smartptr, clsname);
+ Swig_error(Getfile(first), Getline(first), "Invalid type (%s) in 'smartptr' feature for class %s.\n", SwigType_namestr(smartptr), SwigType_namestr(clsname));
}
+ } else {
+ if (GetFlag(bclass, "feature:smartptr"))
+ Swig_warning(WARN_LANG_SMARTPTR_MISSING, Getfile(first), Getline(first), "Derived class '%s' of '%s' is not similarly marked as a smart pointer.\n", SwigType_namestr(Getattr(first, "name")), SwigType_namestr(Getattr(bclass, "name")));
}
if (!importmode) {
String *btype = Copy(bname);
@@ -275,7 +279,7 @@ class TypePass:private Dispatcher {
Symtab *st = Getattr(cls, "symtab");
Symtab *bst = Getattr(bclass, "symtab");
if (st == bst) {
- Swig_warning(WARN_PARSE_REC_INHERITANCE, Getfile(cls), Getline(cls), "Recursive scope inheritance of '%s'.\n", Getattr(cls, "name"));
+ Swig_warning(WARN_PARSE_REC_INHERITANCE, Getfile(cls), Getline(cls), "Recursive scope inheritance of '%s'.\n", SwigType_namestr(Getattr(cls, "name")));
continue;
}
Symtab *s = Swig_symbol_current();
@@ -995,6 +999,7 @@ class TypePass:private Dispatcher {
}
Node *nn = copyNode(c);
Delattr(nn, "access"); // access might be different from the method in the base class
+ Setattr(nn, "access", Getattr(n, "access"));
if (!Getattr(nn, "sym:name"))
Setattr(nn, "sym:name", symname);
diff --git a/Source/Modules/utils.cxx b/Source/Modules/utils.cxx
index 3fe7a2709..13a504bcf 100644
--- a/Source/Modules/utils.cxx
+++ b/Source/Modules/utils.cxx
@@ -100,3 +100,116 @@ void clean_overloaded(Node *n) {
Delattr(n, "sym:overloaded");
}
}
+
+/* -----------------------------------------------------------------------------
+ * Swig_set_max_hash_expand()
+ *
+ * Controls how many Hash objects are displayed when displaying nested Hash objects.
+ * Makes DohSetMaxHashExpand an externally callable function (for debugger).
+ * ----------------------------------------------------------------------------- */
+
+void Swig_set_max_hash_expand(int count) {
+ SetMaxHashExpand(count);
+}
+
+extern "C" {
+
+/* -----------------------------------------------------------------------------
+ * Swig_get_max_hash_expand()
+ *
+ * Returns how many Hash objects are displayed when displaying nested Hash objects.
+ * Makes DohGetMaxHashExpand an externally callable function (for debugger).
+ * ----------------------------------------------------------------------------- */
+
+int Swig_get_max_hash_expand() {
+ return GetMaxHashExpand();
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_doh_string()
+ *
+ * DOH version of Swig_to_string()
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_to_doh_string(DOH *object, int count) {
+ int old_count = Swig_get_max_hash_expand();
+ if (count >= 0)
+ Swig_set_max_hash_expand(count);
+
+ String *debug_string = object ? NewStringf("%s", object) : NewString("NULL");
+
+ Swig_set_max_hash_expand(old_count);
+ return debug_string;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_doh_string_with_location()
+ *
+ * DOH version of Swig_to_string_with_location()
+ * ----------------------------------------------------------------------------- */
+
+static String *Swig_to_doh_string_with_location(DOH *object, int count) {
+ int old_count = Swig_get_max_hash_expand();
+ if (count >= 0)
+ Swig_set_max_hash_expand(count);
+
+ String *debug_string = Swig_stringify_with_location(object);
+
+ Swig_set_max_hash_expand(old_count);
+ return debug_string;
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_string()
+ *
+ * Swig debug - return C string representation of any DOH type.
+ * Nested Hash types expand count is value of Swig_get_max_hash_expand when count<0
+ * Note: leaks memory.
+ * ----------------------------------------------------------------------------- */
+
+const char *Swig_to_string(DOH *object, int count) {
+ return Char(Swig_to_doh_string(object, count));
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_string_with_location()
+ *
+ * Swig debug - return C string representation of any DOH type, within [] brackets
+ * for Hash and List types, prefixed by line and file information.
+ * Nested Hash types expand count is value of Swig_get_max_hash_expand when count<0
+ * Note: leaks memory.
+ * ----------------------------------------------------------------------------- */
+
+const char *Swig_to_string_with_location(DOH *object, int count) {
+ return Char(Swig_to_doh_string_with_location(object, count));
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_print()
+ *
+ * Swig debug - display string representation of any DOH type.
+ * Nested Hash types expand count is value of Swig_get_max_hash_expand when count<0
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print(DOH *object, int count) {
+ String *output = Swig_to_doh_string(object, count);
+ Printf(stdout, "%s\n", output);
+ Delete(output);
+}
+
+/* -----------------------------------------------------------------------------
+ * Swig_to_string_with_location()
+ *
+ * Swig debug - display string representation of any DOH type, within [] brackets
+ * for Hash and List types, prefixed by line and file information.
+ * Nested Hash types expand count is value of Swig_get_max_hash_expand when count<0
+ * ----------------------------------------------------------------------------- */
+
+void Swig_print_with_location(DOH *object, int count) {
+ String *output = Swig_to_doh_string_with_location(object, count);
+ Printf(stdout, "%s\n", output);
+ Delete(output);
+}
+
+} // extern "C"
+
diff --git a/Source/Preprocessor/cpp.c b/Source/Preprocessor/cpp.c
index 5dd320994..2da4944c9 100644
--- a/Source/Preprocessor/cpp.c
+++ b/Source/Preprocessor/cpp.c
@@ -33,6 +33,10 @@ static Hash *included_files = 0;
static List *dependencies = 0;
static Scanner *id_scan = 0;
static int error_as_warning = 0; /* Understand the cpp #error directive as a special #warning */
+static int expand_defined_operator = 0;
+static int macro_level = 0;
+static int macro_start_line = 0;
+static const String * macro_start_file = 0;
/* Test a character to see if it starts an identifier */
#define isidentifier(c) ((isalpha(c)) || (c == '_') || (c == '$'))
@@ -40,7 +44,7 @@ static int error_as_warning = 0; /* Understand the cpp #error directive as a spe
/* Test a character to see if it valid in an identifier (after the first letter) */
#define isidchar(c) ((isalnum(c)) || (c == '_') || (c == '$'))
-DOH *Preprocessor_replace(DOH *);
+static DOH *Preprocessor_replace(DOH *);
/* Skip whitespace */
static void skip_whitespace(String *s, String *out) {
@@ -148,6 +152,9 @@ static String *kpp_dextern = 0;
static String *kpp_LINE = 0;
static String *kpp_FILE = 0;
+static String *kpp_hash_if = 0;
+static String *kpp_hash_elif = 0;
+
void Preprocessor_init(void) {
Hash *s;
@@ -184,6 +191,9 @@ void Preprocessor_init(void) {
kpp_LINE = NewString("__LINE__");
kpp_FILE = NewString("__FILE__");
+ kpp_hash_if = NewString("#if");
+ kpp_hash_elif = NewString("#elif");
+
cpp = NewHash();
s = NewHash();
Setattr(cpp, kpp_symbols, s);
@@ -225,9 +235,12 @@ void Preprocessor_delete(void) {
Delete(kpp_ddefine);
Delete(kpp_dline);
-
Delete(kpp_LINE);
Delete(kpp_FILE);
+
+ Delete(kpp_hash_if);
+ Delete(kpp_hash_elif);
+
Delete(cpp);
Delete(included_files);
Preprocessor_expr_delete();
@@ -322,6 +335,7 @@ Hash *Preprocessor_define(const_String_or_char_ptr _str, int swigmacro) {
/* Now look for a macro name */
macroname = NewStringEmpty();
+ copy_location(str, macroname);
while ((c = Getc(str)) != EOF) {
if (c == '(') {
argstr = NewStringEmpty();
@@ -334,7 +348,7 @@ Hash *Preprocessor_define(const_String_or_char_ptr _str, int swigmacro) {
Putc(c, argstr);
}
if (c != ')') {
- Swig_error(Getfile(str), Getline(str), "Missing \')\' in macro parameters\n");
+ Swig_error(Getfile(argstr), Getline(argstr), "Missing \')\' in macro parameters\n");
goto macro_error;
}
break;
@@ -350,8 +364,6 @@ Hash *Preprocessor_define(const_String_or_char_ptr _str, int swigmacro) {
break;
}
} else {
- /*Swig_error(Getfile(str),Getline(str),"Illegal character in macro name\n");
- goto macro_error; */
Ungetc(c, str);
break;
}
@@ -359,6 +371,7 @@ Hash *Preprocessor_define(const_String_or_char_ptr _str, int swigmacro) {
if (!swigmacro)
skip_whitespace(str, 0);
macrovalue = NewStringEmpty();
+ copy_location(str, macrovalue);
while ((c = Getc(str)) != EOF) {
Putc(c, macrovalue);
}
@@ -371,10 +384,10 @@ Hash *Preprocessor_define(const_String_or_char_ptr _str, int swigmacro) {
argname = NewStringEmpty();
while ((c = Getc(argstr)) != EOF) {
if (c == ',') {
- varargname = Macro_vararg_name(argname, str);
+ varargname = Macro_vararg_name(argname, argstr);
if (varargname) {
Delete(varargname);
- Swig_error(Getfile(str), Getline(str), "Variable-length macro argument must be last parameter\n");
+ Swig_error(Getfile(argstr), Getline(argstr), "Variable length macro argument must be last parameter\n");
} else {
Append(arglist, argname);
}
@@ -384,13 +397,13 @@ Hash *Preprocessor_define(const_String_or_char_ptr _str, int swigmacro) {
Putc(c, argname);
} else if (!(isspace(c) || (c == '\\'))) {
Delete(argname);
- Swig_error(Getfile(str), Getline(str), "Illegal character in macro argument name\n");
+ Swig_error(Getfile(argstr), Getline(argstr), "Illegal character in macro argument name\n");
goto macro_error;
}
}
if (Len(argname)) {
/* Check for varargs */
- varargname = Macro_vararg_name(argname, str);
+ varargname = Macro_vararg_name(argname, argstr);
if (varargname) {
Append(arglist, varargname);
Delete(varargname);
@@ -508,7 +521,7 @@ Hash *Preprocessor_define(const_String_or_char_ptr _str, int swigmacro) {
symbols = Getattr(cpp, kpp_symbols);
if ((m1 = Getattr(symbols, macroname))) {
if (!Checkattr(m1, kpp_value, macrovalue)) {
- Swig_error(Getfile(str), Getline(str), "Macro '%s' redefined,\n", macroname);
+ Swig_error(Getfile(macroname), Getline(macroname), "Macro '%s' redefined,\n", macroname);
Swig_error(Getfile(m1), Getline(m1), "previous definition of '%s'.\n", macroname);
goto macro_error;
}
@@ -551,7 +564,7 @@ void Preprocessor_undef(const_String_or_char_ptr str) {
* Isolates macro arguments and returns them in a list. For each argument,
* leading and trailing whitespace is stripped (ala K&R, pg. 230).
* ----------------------------------------------------------------------------- */
-static List *find_args(String *s) {
+static List *find_args(String *s, int ismacro, String *macro_name) {
List *args;
String *str;
int c, level;
@@ -622,12 +635,15 @@ static List *find_args(String *s) {
c = Getc(s);
}
unterm:
- Swig_error(Getfile(args), Getline(args), "Unterminated macro call.\n");
+ if (ismacro)
+ Swig_error(Getfile(args), Getline(args), "Unterminated call invoking macro '%s'\n", macro_name);
+ else
+ Swig_error(Getfile(args), Getline(args), "Unterminated call to '%s'\n", macro_name);
return args;
}
/* -----------------------------------------------------------------------------
- * DOH *get_filename(DOH *str)
+ * DOH *get_filename()
*
* Read a filename from str. A filename can be enclosed in quotes, angle brackets,
* or bare.
@@ -637,7 +653,6 @@ static String *get_filename(String *str, int *sysfile) {
String *fn;
int c;
- skip_whitespace(str, 0);
fn = NewStringEmpty();
copy_location(str, fn);
c = Getc(str);
@@ -663,9 +678,7 @@ static String *get_filename(String *str, int *sysfile) {
}
static String *get_options(String *str) {
-
int c;
- skip_whitespace(str, 0);
c = Getc(str);
if (c == '(') {
String *opt;
@@ -694,9 +707,12 @@ static String *get_options(String *str) {
*
* Perform macro expansion and return a new string. Returns NULL if some sort
* of error occurred.
+ * name - name of the macro
+ * args - arguments passed to the macro
+ * line_file - only used for line/file name when reporting errors
* ----------------------------------------------------------------------------- */
-static String *expand_macro(String *name, List *args) {
+static String *expand_macro(String *name, List *args, String *line_file) {
String *ns;
DOH *symbols, *macro, *margs, *mvalue, *temp, *tempa, *e;
int i, l;
@@ -710,6 +726,14 @@ static String *expand_macro(String *name, List *args) {
macro = Getattr(symbols, name);
if (!macro)
return 0;
+
+ if (macro_level == 0) {
+ /* Store the start of the macro should the macro contain __LINE__ and __FILE__ for expansion */
+ macro_start_line = Getline(args ? args : line_file);
+ macro_start_file = Getfile(args ? args : line_file);
+ }
+ macro_level++;
+
if (Getattr(macro, kpp_expanded)) {
ns = NewStringEmpty();
Append(ns, name);
@@ -725,6 +749,7 @@ static String *expand_macro(String *name, List *args) {
if (i)
Putc(')', ns);
}
+ macro_level--;
return ns;
}
@@ -759,16 +784,18 @@ static String *expand_macro(String *name, List *args) {
/* If there are arguments, see if they match what we were given */
if (args && (margs) && (Len(margs) != Len(args))) {
if (Len(margs) > (1 + isvarargs))
- Swig_error(Getfile(args), Getline(args), "Macro '%s' expects %d arguments\n", name, Len(margs) - isvarargs);
+ Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects %d arguments\n", name, Len(margs) - isvarargs);
else if (Len(margs) == (1 + isvarargs))
- Swig_error(Getfile(args), Getline(args), "Macro '%s' expects 1 argument\n", name);
+ Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects 1 argument\n", name);
else
- Swig_error(Getfile(args), Getline(args), "Macro '%s' expects no arguments\n", name);
+ Swig_error(macro_start_file, macro_start_line, "Macro '%s' expects no arguments\n", name);
+ macro_level--;
return 0;
}
/* If the macro expects arguments, but none were supplied, we leave it in place */
if (!args && (margs) && Len(margs) > 0) {
+ macro_level--;
return NewString(name);
}
@@ -922,28 +949,13 @@ static String *expand_macro(String *name, List *args) {
Delete(e);
e = f;
}
+ macro_level--;
Delete(temp);
Delete(tempa);
return e;
}
/* -----------------------------------------------------------------------------
- * evaluate_args()
- *
- * Evaluate the arguments of a macro
- * ----------------------------------------------------------------------------- */
-
-List *evaluate_args(List *x) {
- Iterator i;
- List *nl = NewList();
-
- for (i = First(x); i.item; i = Next(i)) {
- Append(nl, Preprocessor_replace(i.item));
- }
- return nl;
-}
-
-/* -----------------------------------------------------------------------------
* DOH *Preprocessor_replace(DOH *s)
*
* Performs a macro substitution on a string s. Returns a new string with
@@ -954,10 +966,9 @@ List *evaluate_args(List *x) {
/* #define SWIG_PUT_BUFF */
-DOH *Preprocessor_replace(DOH *s) {
+static DOH *Preprocessor_replace(DOH *s) {
DOH *ns, *symbols, *m;
int c, i, state = 0;
-
String *id = NewStringEmpty();
assert(cpp);
@@ -971,10 +982,18 @@ DOH *Preprocessor_replace(DOH *s) {
while ((c = Getc(s)) != EOF) {
switch (state) {
case 0:
- if (isidentifier(c) || (c == '%')) {
+ if (isidentifier(c)) {
Clear(id);
Putc(c, id);
- state = 1;
+ state = 4;
+ } else if (c == '%') {
+ Clear(id);
+ Putc(c, id);
+ state = 2;
+ } else if (c == '#') {
+ Clear(id);
+ Putc(c, id);
+ state = 4;
} else if (c == '\"') {
Putc(c, ns);
skip_tochar(s, '\"', ns);
@@ -984,86 +1003,115 @@ DOH *Preprocessor_replace(DOH *s) {
} else if (c == '/') {
Putc(c, ns);
state = 10;
+ } else if (c == '\\') {
+ Putc(c, ns);
+ c = Getc(s);
+ if (c == '\n') {
+ Putc(c, ns);
+ } else {
+ Ungetc(c, s);
+ }
+ } else if (c == '\n') {
+ Putc(c, ns);
+ expand_defined_operator = 0;
} else {
Putc(c, ns);
}
break;
- case 1: /* An identifier */
+ case 2:
+ /* Found '%#' */
+ if (c == '#') {
+ Putc(c, id);
+ state = 4;
+ } else {
+ Ungetc(c, s);
+ state = 4;
+ }
+ break;
+ case 4: /* An identifier */
if (isidchar(c)) {
Putc(c, id);
- state = 1;
+ state = 4;
} else {
/* We found the end of a valid identifier */
Ungetc(c, s);
- /* See if this is the special "defined" macro */
- if (Equal(kpp_defined, id)) {
- int lenargs = 0;
- DOH *args = 0;
- /* See whether or not a paranthesis has been used */
- skip_whitespace(s, 0);
- c = Getc(s);
- if (c == '(') {
- Ungetc(c, s);
- args = find_args(s);
- } else if (isidchar(c)) {
- DOH *arg = NewStringEmpty();
- args = NewList();
- Putc(c, arg);
- while (((c = Getc(s)) != EOF)) {
- if (!isidchar(c)) {
- Ungetc(c, s);
+ /* See if this is the special "defined" operator */
+ if (Equal(kpp_defined, id)) {
+ if (expand_defined_operator) {
+ int lenargs = 0;
+ DOH *args = 0;
+ /* See whether or not a parenthesis has been used */
+ skip_whitespace(s, 0);
+ c = Getc(s);
+ if (c == '(') {
+ Ungetc(c, s);
+ args = find_args(s, 0, kpp_defined);
+ } else if (isidchar(c)) {
+ DOH *arg = NewStringEmpty();
+ args = NewList();
+ Putc(c, arg);
+ while (((c = Getc(s)) != EOF)) {
+ if (!isidchar(c)) {
+ Ungetc(c, s);
+ break;
+ }
+ Putc(c, arg);
+ }
+ if (Len(arg))
+ Append(args, arg);
+ Delete(arg);
+ } else {
+ Seek(s, -1, SEEK_CUR);
+ }
+ lenargs = Len(args);
+ if ((!args) || (!lenargs)) {
+ /* This is not a defined() operator. */
+ Append(ns, id);
+ state = 0;
+ break;
+ }
+ for (i = 0; i < lenargs; i++) {
+ DOH *o = Getitem(args, i);
+ if (!Getattr(symbols, o)) {
break;
}
- Putc(c, arg);
}
- if (Len(arg))
- Append(args, arg);
- Delete(arg);
+ if (i < lenargs)
+ Putc('0', ns);
+ else
+ Putc('1', ns);
+ Delete(args);
} else {
- Seek(s, -1, SEEK_CUR);
- }
- lenargs = Len(args);
- if ((!args) || (!lenargs)) {
- /* This is not a defined() macro. */
Append(ns, id);
- state = 0;
- break;
- }
- for (i = 0; i < lenargs; i++) {
- DOH *o = Getitem(args, i);
- if (!Getattr(symbols, o)) {
- break;
- }
}
- if (i < lenargs)
- Putc('0', ns);
- else
- Putc('1', ns);
- Delete(args);
state = 0;
break;
- }
- if (Equal(kpp_LINE, id)) {
- Printf(ns, "%d", Getline(s));
+ } else if (Equal(kpp_LINE, id)) {
+ Printf(ns, "%d", macro_level > 0 ? macro_start_line : Getline(s));
state = 0;
break;
- }
- if (Equal(kpp_FILE, id)) {
- String *fn = Copy(Getfile(s));
+ } else if (Equal(kpp_FILE, id)) {
+ String *fn = Copy(macro_level > 0 ? macro_start_file : Getfile(s));
Replaceall(fn, "\\", "\\\\");
Printf(ns, "\"%s\"", fn);
Delete(fn);
state = 0;
break;
- }
- /* See if the macro is defined in the preprocessor symbol table */
- if ((m = Getattr(symbols, id))) {
+ } else if (Equal(kpp_hash_if, id) || Equal(kpp_hash_elif, id)) {
+ expand_defined_operator = 1;
+ Append(ns, id);
+ } else if ((m = Getattr(symbols, id))) {
+ /* See if the macro is defined in the preprocessor symbol table */
DOH *args = 0;
DOH *e;
+ int macro_additional_lines = 0;
/* See if the macro expects arguments */
if (Getattr(m, kpp_args)) {
/* Yep. We need to go find the arguments and do a substitution */
- args = find_args(s);
+ int line = Getline(s);
+ args = find_args(s, 1, id);
+ macro_additional_lines = Getline(s) - line;
+ assert(macro_additional_lines >= 0);
if (!Len(args)) {
Delete(args);
args = 0;
@@ -1071,10 +1119,13 @@ DOH *Preprocessor_replace(DOH *s) {
} else {
args = 0;
}
- e = expand_macro(id, args);
+ e = expand_macro(id, args, s);
if (e) {
Append(ns, e);
}
+ while (macro_additional_lines--) {
+ Putc('\n', ns);
+ }
Delete(e);
Delete(args);
} else {
@@ -1096,11 +1147,15 @@ DOH *Preprocessor_replace(DOH *s) {
Putc(c, ns);
break;
case 11:
+ /* in C++ comment */
Putc(c, ns);
- if (c == '\n')
+ if (c == '\n') {
+ expand_defined_operator = 0;
state = 0;
+ }
break;
case 12:
+ /* in C comment */
Putc(c, ns);
if (c == '*')
state = 13;
@@ -1119,10 +1174,17 @@ DOH *Preprocessor_replace(DOH *s) {
}
/* Identifier at the end */
- if (state == 1) {
- /* See if this is the special "defined" macro */
+ if (state == 2 || state == 4) {
+ /* See if this is the special "defined" operator */
if (Equal(kpp_defined, id)) {
Swig_error(Getfile(s), Getline(s), "No arguments given to defined()\n");
+ } else if (Equal(kpp_LINE, id)) {
+ Printf(ns, "%d", macro_level > 0 ? macro_start_line : Getline(s));
+ } else if (Equal(kpp_FILE, id)) {
+ String *fn = Copy(macro_level > 0 ? macro_start_file : Getfile(s));
+ Replaceall(fn, "\\", "\\\\");
+ Printf(ns, "\"%s\"", fn);
+ Delete(fn);
} else if ((m = Getattr(symbols, id))) {
DOH *e;
/* Yes. There is a macro here */
@@ -1130,8 +1192,9 @@ DOH *Preprocessor_replace(DOH *s) {
/* if (Getattr(m,"args")) {
Swig_error(Getfile(id),Getline(id),"Macro arguments expected.\n");
} */
- e = expand_macro(id, 0);
- Append(ns, e);
+ e = expand_macro(id, 0, s);
+ if (e)
+ Append(ns, e);
Delete(e);
} else {
Append(ns, id);
@@ -1264,8 +1327,8 @@ String *Preprocessor_parse(String *s) {
case 0: /* Initial state - in first column */
/* Look for C preprocessor directives. Otherwise, go directly to state 1 */
if (c == '#') {
- add_chunk(ns, chunk, allow);
copy_location(s, chunk);
+ add_chunk(ns, chunk, allow);
cpp_lines = 1;
state = 40;
} else if (isspace(c)) {
@@ -1414,7 +1477,6 @@ String *Preprocessor_parse(String *s) {
else if (c == '\n') {
Putc('/', value);
Ungetc(c, s);
- cpp_lines++;
state = 50;
} else {
Putc('/', value);
@@ -1422,15 +1484,14 @@ String *Preprocessor_parse(String *s) {
state = 43;
}
break;
- case 46:
+ case 46: /* in C++ comment */
if (c == '\n') {
Ungetc(c, s);
- cpp_lines++;
state = 50;
} else
Putc(c, comment);
break;
- case 47:
+ case 47: /* in C comment */
if (c == '*')
state = 48;
else
@@ -1457,6 +1518,7 @@ String *Preprocessor_parse(String *s) {
m = Preprocessor_define(value, 0);
if ((m) && !(Getattr(m, kpp_args))) {
v = Copy(Getattr(m, kpp_value));
+ copy_location(m, v);
if (Len(v)) {
Swig_error_silent(1);
v1 = Preprocessor_replace(v);
@@ -1525,7 +1587,9 @@ String *Preprocessor_parse(String *s) {
level++;
if (allow) {
int val;
- String *sval = Preprocessor_replace(value);
+ String *sval;
+ expand_defined_operator = 1;
+ sval = Preprocessor_replace(value);
start_level = level;
Seek(sval, 0, SEEK_SET);
/* Printf(stdout,"Evaluating '%s'\n", sval); */
@@ -1541,6 +1605,7 @@ String *Preprocessor_parse(String *s) {
if (val == 0)
allow = 0;
}
+ expand_defined_operator = 0;
mask = 1;
}
} else if (Equal(id, kpp_elif)) {
@@ -1548,6 +1613,7 @@ String *Preprocessor_parse(String *s) {
Swig_error(Getfile(s), Getline(id), "Misplaced #elif.\n");
} else {
cond_lines[level - 1] = Getline(id);
+ expand_defined_operator = 1;
if (allow) {
allow = 0;
mask = 0;
@@ -1570,6 +1636,7 @@ String *Preprocessor_parse(String *s) {
allow = 0;
}
}
+ expand_defined_operator = 0;
}
} else if (Equal(id, kpp_warning)) {
if (allow) {
@@ -1589,12 +1656,14 @@ String *Preprocessor_parse(String *s) {
String *s1, *s2, *fn;
char *dirname;
int sysfile = 0;
+ String *filename_processed;
if (include_all && import_all) {
Swig_warning(WARN_PP_INCLUDEALL_IMPORTALL, Getfile(s), Getline(id), "Both includeall and importall are defined: using includeall\n");
import_all = 0;
}
- Seek(value, 0, SEEK_SET);
- fn = get_filename(value, &sysfile);
+ filename_processed = Preprocessor_replace(value);
+ Seek(filename_processed, 0, SEEK_SET);
+ fn = get_filename(filename_processed, &sysfile);
s1 = cpp_include(fn, sysfile);
if (s1) {
if (include_all)
@@ -1614,7 +1683,7 @@ String *Preprocessor_parse(String *s) {
}
s2 = Preprocessor_parse(s1);
addline(ns, s2, allow);
- Append(ns, "\n]");
+ Append(ns, "]");
if (dirname) {
Swig_pop_directory();
}
@@ -1622,8 +1691,8 @@ String *Preprocessor_parse(String *s) {
pop_imported();
}
Delete(s2);
+ Delete(s1);
}
- Delete(s1);
Delete(fn);
}
} else if (Equal(id, kpp_pragma)) {
@@ -1658,8 +1727,8 @@ String *Preprocessor_parse(String *s) {
/* %{,%} block */
if (c == '{') {
start_line = Getline(s);
- add_chunk(ns, chunk, allow);
copy_location(s, chunk);
+ add_chunk(ns, chunk, allow);
Putc('%', chunk);
Putc(c, chunk);
state = 105;
@@ -1720,9 +1789,13 @@ String *Preprocessor_parse(String *s) {
Ungetc(c, s);
/* Look for common SWIG directives */
if (Equal(decl, kpp_dinclude) || Equal(decl, kpp_dimport) || Equal(decl, kpp_dextern)) {
- /* Got some kind of file inclusion directive */
+ /* Got some kind of file inclusion directive, eg: %import(option1="value1") "filename" */
if (allow) {
DOH *s1, *s2, *fn, *opt;
+ String *options_whitespace = NewStringEmpty();
+ String *filename_whitespace = NewStringEmpty();
+ String *filename_unprocessed = NewStringEmpty();
+ String *filename_processed;
int sysfile = 0;
if (Equal(decl, kpp_dextern)) {
@@ -1730,14 +1803,25 @@ String *Preprocessor_parse(String *s) {
Clear(decl);
Append(decl, "%%import");
}
+ skip_whitespace(s, options_whitespace);
opt = get_options(s);
- fn = get_filename(s, &sysfile);
+
+ skip_whitespace(s, filename_whitespace);
+ copy_location(s, filename_unprocessed);
+ while (((c = Getc(s)) != EOF) && (!isspace(c)))
+ Putc(c, filename_unprocessed);
+ if (isspace(c))
+ Ungetc(c, s);
+ filename_processed = Preprocessor_replace(filename_unprocessed);
+ Seek(filename_processed, 0, SEEK_SET);
+
+ fn = get_filename(filename_processed, &sysfile);
s1 = cpp_include(fn, sysfile);
if (s1) {
char *dirname;
- add_chunk(ns, chunk, allow);
copy_location(s, chunk);
- Printf(ns, "%sfile%s \"%s\" [\n", decl, opt, Swig_filename_escape(Swig_last_file()));
+ add_chunk(ns, chunk, allow);
+ Printf(ns, "%sfile%s%s%s\"%s\" [\n", decl, options_whitespace, opt, filename_whitespace, Swig_filename_escape(Swig_last_file()));
if (Equal(decl, kpp_dimport)) {
push_imported();
}
@@ -1756,11 +1840,15 @@ String *Preprocessor_parse(String *s) {
pop_imported();
}
addline(ns, s2, allow);
- Append(ns, "\n]");
+ Append(ns, "]");
Delete(s2);
Delete(s1);
}
Delete(fn);
+ Delete(filename_processed);
+ Delete(filename_unprocessed);
+ Delete(filename_whitespace);
+ Delete(options_whitespace);
}
state = 1;
} else if (Equal(decl, kpp_dline)) {
@@ -1769,8 +1857,8 @@ String *Preprocessor_parse(String *s) {
} else if (Equal(decl, kpp_ddefine)) {
/* Got a define directive */
dlevel++;
- add_chunk(ns, chunk, allow);
copy_location(s, chunk);
+ add_chunk(ns, chunk, allow);
Clear(value);
copy_location(s, value);
state = 150;
@@ -1815,7 +1903,6 @@ String *Preprocessor_parse(String *s) {
Seek(value, 0, SEEK_SET);
Preprocessor_define(value, 1);
}
- /* Putc('\n',ns); */
addline(ns, value, 0);
state = 0;
}
@@ -1844,8 +1931,9 @@ String *Preprocessor_parse(String *s) {
if ((state >= 30) && (state < 40)) {
Swig_error(Getfile(s), -1, "Unterminated comment starting on line %d\n", start_line);
}
- add_chunk(ns, chunk, allow);
+
copy_location(s, chunk);
+ add_chunk(ns, chunk, allow);
/* DelScope(scp); */
Delete(decl);
@@ -1854,6 +1942,5 @@ String *Preprocessor_parse(String *s) {
Delete(comment);
Delete(chunk);
- /* fprintf(stderr,"cpp: %d\n", Len(Getattr(cpp,"symbols"))); */
return ns;
}
diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c
index b8812563e..28401f89f 100644
--- a/Source/Swig/cwrap.c
+++ b/Source/Swig/cwrap.c
@@ -216,7 +216,7 @@ int Swig_cargs(Wrapper *w, ParmList *p) {
SwigType_del_reference(tvalue);
tycode = SwigType_type(tvalue);
if (tycode != T_USER) {
- /* plain primitive type, we copy the the def value */
+ /* plain primitive type, we copy the def value */
String *lstr = SwigType_lstr(tvalue, defname);
defvalue = NewStringf("%s = %s", lstr, qvalue);
Delete(lstr);
@@ -783,15 +783,32 @@ int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parm
* ----------------------------------------------------------------------------- */
int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *classname, int flags, SwigType *director_type, int is_director) {
- String *name, *qualifier;
+ String *name;
ParmList *parms;
SwigType *type;
Parm *p;
String *self = 0;
-
- /* If smart pointer, change self dereferencing */
+ int is_smart_pointer_overload = 0;
+ String *qualifier = Getattr(n, "qualifier");
+
+ /* If smart pointer without const overload or mutable method, change self dereferencing */
if (flags & CWRAP_SMART_POINTER) {
- self = NewString("(*this)->");
+ if (flags & CWRAP_SMART_POINTER_OVERLOAD) {
+ String *cname = Getattr(n, "classname") ? Getattr(n, "classname") : classname;
+ if (qualifier && strncmp(Char(qualifier), "q(const)", 8) == 0) {
+ self = NewString("(*(this))->");
+ is_smart_pointer_overload = 1;
+ }
+ else if (Cmp(Getattr(n, "storage"), "static") == 0) {
+ self = NewStringf("(*(%s const *)this)->", cname);
+ is_smart_pointer_overload = 1;
+ }
+ else {
+ self = NewString("(*this)->");
+ }
+ } else {
+ self = NewString("(*this)->");
+ }
}
/* If node is a member template expansion, we don't allow added code */
@@ -799,7 +816,6 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas
flags &= ~(CWRAP_EXTEND);
name = Getattr(n, "name");
- qualifier = Getattr(n, "qualifier");
parms = CopyParmList(nonvoid_parms(Getattr(n, "parms")));
type = NewString(classname);
@@ -921,10 +937,16 @@ int Swig_MethodToFunction(Node *n, const_String_or_char_ptr nspace, String *clas
if (Cmp(Getattr(n, "storage"), "static") != 0) {
String *pname = Swig_cparm_name(pp, i);
- String *ctname = SwigType_namestr(cname);
- String *fadd = NewStringf("(%s*)(%s)->operator ->()", ctname, pname);
+ String *ctname = SwigType_namestr(cname);
+ String *fadd = 0;
+ if (is_smart_pointer_overload) {
+ fadd = NewStringf("(%s const *)((%s const *)%s)->operator ->()", ctname, classname, pname);
+ }
+ else {
+ fadd = NewStringf("(%s*)(%s)->operator ->()", ctname, pname);
+ }
Append(func, fadd);
- Delete(ctname);
+ Delete(ctname);
Delete(fadd);
Delete(pname);
pp = nextSibling(pp);
@@ -1310,6 +1332,8 @@ int Swig_MembergetToFunction(Node *n, String *classname, int flags) {
Node *sn = Getattr(n, "cplus:staticbase");
String *base = Getattr(sn, "name");
self = NewStringf("%s::", base);
+ } else if (flags & CWRAP_SMART_POINTER_OVERLOAD) {
+ self = NewStringf("(*(%s const *)this)->", classname);
} else {
self = NewString("(*this)->");
}
diff --git a/Source/Swig/error.c b/Source/Swig/error.c
index fa82ad8d9..5dfcf605b 100644
--- a/Source/Swig/error.c
+++ b/Source/Swig/error.c
@@ -285,6 +285,41 @@ static String *format_filename(const_String_or_char_ptr filename) {
}
/* -----------------------------------------------------------------------------
+ * Swig_stringify_with_location()
+ *
+ * Return a string representation of any DOH object with line and file location
+ * information in the appropriate error message format. The string representation
+ * is enclosed within [] brackets after the line and file information.
+ * ----------------------------------------------------------------------------- */
+
+String *Swig_stringify_with_location(DOH *object) {
+ String *str = NewStringEmpty();
+
+ if (!init_fmt)
+ Swig_error_msg_format(DEFAULT_ERROR_MSG_FORMAT);
+
+ if (object) {
+ int line = Getline(object);
+ String *formatted_filename = format_filename(Getfile(object));
+ if (line > 0) {
+ Printf(str, diag_line_fmt, formatted_filename, line);
+ } else {
+ Printf(str, diag_eof_fmt, formatted_filename);
+ }
+ if (Len(object) == 0) {
+ Printf(str, "[EMPTY]");
+ } else {
+ Printf(str, "[%s]", object);
+ }
+ Delete(formatted_filename);
+ } else {
+ Printf(str, "[NULL]");
+ }
+
+ return str;
+}
+
+/* -----------------------------------------------------------------------------
* Swig_diagnostic()
*
* Issue a diagnostic message on stdout.
diff --git a/Source/Swig/include.c b/Source/Swig/include.c
index baae44bb8..e3f256901 100644
--- a/Source/Swig/include.c
+++ b/Source/Swig/include.c
@@ -221,6 +221,8 @@ String *Swig_read_file(FILE *f) {
Append(str, buffer);
}
len = Len(str);
+ /* Add a newline if not present on last line -- the preprocessor seems to
+ * rely on \n and not EOF terminating lines */
if (len) {
char *cstr = Char(str);
if (cstr[len - 1] != '\n') {
diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c
index f0a9155eb..9868ee844 100644
--- a/Source/Swig/misc.c
+++ b/Source/Swig/misc.c
@@ -220,7 +220,14 @@ String *Swig_new_subdirectory(String *basedirectory, String *subdirectory) {
* ----------------------------------------------------------------------------- */
void Swig_filename_correct(String *filename) {
- (void)filename;
+ int network_path = 0;
+ if (Len(filename) >= 2) {
+ const char *fname = Char(filename);
+ if (fname[0] == '\\' && fname[1] == '\\')
+ network_path = 1;
+ if (fname[0] == '/' && fname[1] == '/')
+ network_path = 1;
+ }
#if defined(_WIN32) || defined(MACSWIG)
/* accept Unix path separator on non-Unix systems */
Replaceall(filename, "/", SWIG_FILE_DELIMITER);
@@ -232,6 +239,9 @@ void Swig_filename_correct(String *filename) {
/* remove all duplicate file name delimiters */
while (Replaceall(filename, SWIG_FILE_DELIMITER SWIG_FILE_DELIMITER, SWIG_FILE_DELIMITER)) {
}
+ /* Network paths can start with a double slash on Windows - unremove the duplicate slash we just removed */
+ if (network_path)
+ Insert(filename, 0, SWIG_FILE_DELIMITER);
}
/* -----------------------------------------------------------------------------
@@ -242,13 +252,11 @@ void Swig_filename_correct(String *filename) {
String *Swig_filename_escape(String *filename) {
String *adjusted_filename = Copy(filename);
+ Swig_filename_correct(adjusted_filename);
#if defined(_WIN32) /* Note not on Cygwin else filename is displayed with double '/' */
- /* remove all double '\' in case any already present */
- while (Replaceall(adjusted_filename, "\\\\", "\\")) {
- }
Replaceall(adjusted_filename, "\\", "\\\\");
#endif
- return adjusted_filename;
+ return adjusted_filename;
}
/* -----------------------------------------------------------------------------
@@ -527,7 +535,6 @@ String *Swig_string_schemify(String *s) {
return ns;
}
-
/* -----------------------------------------------------------------------------
* Swig_string_typecode()
*
@@ -1108,112 +1115,128 @@ String *Swig_string_strip(String *s) {
}
-/* -----------------------------------------------------------------------------
- * Swig_string_rxspencer()
- *
- * Executes a regexp substitution via the RxSpencer library. For example:
- *
- * Printf(stderr,"gsl%(rxspencer:[GSL_.*_][@1])s","GSL_Hello_") -> gslHello
- * ----------------------------------------------------------------------------- */
-#if defined(HAVE_RXSPENCER)
-#include <sys/types.h>
-#include <rxspencer/regex.h>
-#define USE_RXSPENCER
-#endif
+#ifdef HAVE_PCRE
+#include <pcre.h>
+
+static int split_regex_pattern_subst(String *s, String **pattern, String **subst, const char **input)
+{
+ const char *pats, *pate;
+ const char *subs, *sube;
+
+ /* Locate the search pattern */
+ const char *p = Char(s);
+ if (*p++ != '/') goto err_out;
+ pats = p;
+ p = strchr(p, '/');
+ if (!p) goto err_out;
+ pate = p;
+
+ /* Locate the substitution string */
+ subs = ++p;
+ p = strchr(p, '/');
+ if (!p) goto err_out;
+ sube = p;
+
+ *pattern = NewStringWithSize(pats, pate - pats);
+ *subst = NewStringWithSize(subs, sube - subs);
+ *input = p + 1;
+ return 1;
+
+err_out:
+ Swig_error("SWIG", Getline(s), "Invalid regex substitution: '%s'.\n", s);
+ exit(1);
+}
+
+String *replace_captures(const char *input, String *subst, int captures[])
+{
+ String *result = NewStringEmpty();
+ const char *p = Char(subst);
-const char *skip_delim(char pb, char pe, const char *ce) {
- int end = 0;
- int lb = 0;
- while (!end && *ce != '\0') {
- if (*ce == pb) {
- ++lb;
+ while (*p) {
+ /* Copy part without substitutions */
+ const char *q = strchr(p, '\\');
+ if (!q) {
+ Write(result, p, strlen(p));
+ break;
}
- if (*ce == pe) {
- if (!lb) {
- end = 1;
- --ce;
- } else {
- --lb;
+ Write(result, p, q - p);
+ p = q + 1;
+
+ /* Handle substitution */
+ if (*p == '\0') {
+ Putc('\\', result);
+ } else if (isdigit(*p)) {
+ int group = *p++ - '0';
+ int l = captures[group*2], r = captures[group*2 + 1];
+ if (l != -1) {
+ Write(result, input + l, r - l);
}
}
- ++ce;
}
- return end ? ce : 0;
+
+ return result;
}
+/* -----------------------------------------------------------------------------
+ * Swig_string_regex()
+ *
+ * Executes a regular expression substitution. For example:
+ *
+ * Printf(stderr,"gsl%(regex:/GSL_.*_/\\1/)s","GSL_Hello_") -> gslHello
+ * ----------------------------------------------------------------------------- */
+String *Swig_string_regex(String *s) {
+ const int pcre_options = 0;
-#if defined(USE_RXSPENCER)
-String *Swig_string_rxspencer(String *s) {
String *res = 0;
- if (Len(s)) {
- const char *cs = Char(s);
- const char *cb;
- const char *ce;
- if (*cs == '[') {
- int retval;
- regex_t compiled;
- cb = ++cs;
- ce = skip_delim('[', ']', cb);
- if (ce) {
- char bregexp[512];
- strncpy(bregexp, cb, ce - cb);
- bregexp[ce - cb] = '\0';
- ++ce;
- retval = regcomp(&compiled, bregexp, REG_EXTENDED);
- if (retval == 0) {
- cs = ce;
- if (*cs == '[') {
- cb = ++cs;
- ce = skip_delim('[', ']', cb);
- if (ce) {
- const char *cvalue = ce + 1;
- int nsub = (int) compiled.re_nsub + 1;
- regmatch_t *pmatch = (regmatch_t *) malloc(sizeof(regmatch_t) * (nsub));
- retval = regexec(&compiled, cvalue, nsub, pmatch, 0);
- if (retval != REG_NOMATCH) {
- char *spos = 0;
- res = NewStringWithSize(cb, ce - cb);
- spos = Strchr(res, '@');
- while (spos) {
- char cd = *(++spos);
- if (isdigit(cd)) {
- char arg[8];
- size_t len;
- int i = cd - '0';
- sprintf(arg, "@%d", i);
- if (i < nsub && (len = pmatch[i].rm_eo - pmatch[i].rm_so)) {
- char value[256];
- strncpy(value, cvalue + pmatch[i].rm_so, len);
- value[len] = 0;
- Replaceall(res, arg, value);
- } else {
- Replaceall(res, arg, "");
- }
- spos = Strchr(res, '@');
- } else if (cd == '@') {
- spos = strchr(spos + 1, '@');
- }
- }
- }
- free(pmatch);
- }
- }
- }
- regfree(&compiled);
- }
+ pcre *compiled_pat = 0;
+ const char *pcre_error, *input;
+ int pcre_errorpos;
+ String *pattern = 0, *subst = 0;
+ int captures[30];
+
+ if (split_regex_pattern_subst(s, &pattern, &subst, &input)) {
+ int rc;
+
+ compiled_pat = pcre_compile(
+ Char(pattern), pcre_options, &pcre_error, &pcre_errorpos, NULL);
+ if (!compiled_pat) {
+ Swig_error("SWIG", Getline(s), "PCRE compilation failed: '%s' in '%s':%i.\n",
+ pcre_error, Char(pattern), pcre_errorpos);
+ exit(1);
+ }
+ rc = pcre_exec(compiled_pat, NULL, input, strlen(input), 0, 0, captures, 30);
+ if (rc >= 0) {
+ res = replace_captures(input, subst, captures);
+ }
+ else if (rc != PCRE_ERROR_NOMATCH) {
+ Swig_error("SWIG", Getline(s), "PCRE execution failed: error %d while matching \"%s\" in \"%s\".\n",
+ rc, Char(pattern), input);
+ exit(1);
}
}
- if (!res)
- res = NewStringEmpty();
- return res;
+
+ DohDelete(pattern);
+ DohDelete(subst);
+ pcre_free(compiled_pat);
+ return res ? res : NewStringEmpty();
}
+
+String *Swig_pcre_version(void) {
+ return NewStringf("PCRE Version: %s", pcre_version());
+}
+
#else
-String *Swig_string_rxspencer(String *s) {
- (void) s;
- return NewStringEmpty();
+
+String *Swig_string_regex(String *s) {
+ Swig_error("SWIG", Getline(s), "PCRE regex support not enabled in this SWIG build.\n");
+ exit(1);
}
-#endif
+String *Swig_pcre_version(void) {
+ return NewStringf("PCRE not used");
+}
+
+#endif
/* -----------------------------------------------------------------------------
* Swig_init()
@@ -1233,9 +1256,9 @@ void Swig_init() {
DohEncoding("typecode", Swig_string_typecode);
DohEncoding("mangle", Swig_string_emangle);
DohEncoding("command", Swig_string_command);
- DohEncoding("rxspencer", Swig_string_rxspencer);
DohEncoding("schemify", Swig_string_schemify);
DohEncoding("strip", Swig_string_strip);
+ DohEncoding("regex", Swig_string_regex);
/* aliases for the case encoders */
DohEncoding("uppercase", Swig_string_upper);
diff --git a/Source/Swig/naming.c b/Source/Swig/naming.c
index 07e42f2d4..d4a7adf84 100644
--- a/Source/Swig/naming.c
+++ b/Source/Swig/naming.c
@@ -1000,7 +1000,7 @@ int Swig_need_redefined_warn(Node *a, Node *b, int InClass) {
* This is basically any protected members when the allprotected mode is set.
* Otherwise we take just the protected virtual methods and non-static methods
* (potentially virtual methods) as well as constructors/destructors.
- *
+ * Also any "using" statements in a class may potentially be virtual.
* ----------------------------------------------------------------------------- */
int Swig_need_protected(Node *n) {
@@ -1017,6 +1017,8 @@ int Swig_need_protected(Node *n) {
}
} else if (Equal(nodetype, "constructor") || Equal(nodetype, "destructor")) {
return 1;
+ } else if (Equal(nodetype, "using") && !Getattr(n, "namespace")) {
+ return 1;
}
}
return 0;
@@ -1061,25 +1063,21 @@ static void Swig_name_object_attach_keys(const char *keys[], Hash *nameobj) {
if (ckey) {
const char **rkey;
int isnotmatch = 0;
- int isrxsmatch = 0;
+ int isregexmatch = 0;
if ((strncmp(ckey, "match", 5) == 0)
|| (isnotmatch = (strncmp(ckey, "notmatch", 8) == 0))
- || (isrxsmatch = (strncmp(ckey, "rxsmatch", 8) == 0))
- || (isnotmatch = isrxsmatch = (strncmp(ckey, "notrxsmatch", 11) == 0))) {
+ || (isregexmatch = (strncmp(ckey, "regexmatch", 10) == 0))
+ || (isnotmatch = isregexmatch = (strncmp(ckey, "notregexmatch", 13) == 0))) {
Hash *mi = NewHash();
List *attrlist = Swig_make_attrlist(ckey);
if (!matchlist)
matchlist = NewList();
Setattr(mi, "value", Getattr(kw, "value"));
Setattr(mi, "attrlist", attrlist);
-#ifdef SWIG_DEBUG
- if (isrxsmatch)
- Printf(stdout, "rxsmatch to use: %s %s %s\n", ckey, Getattr(kw, "value"), attrlist);
-#endif
if (isnotmatch)
SetFlag(mi, "notmatch");
- if (isrxsmatch)
- SetFlag(mi, "rxsmatch");
+ if (isregexmatch)
+ SetFlag(mi, "regexmatch");
Delete(attrlist);
Append(matchlist, mi);
Delete(mi);
@@ -1114,7 +1112,7 @@ void Swig_name_nameobj_add(Hash *name_hash, List *name_list, String *prefix, Str
}
if (!nname || !Len(nname) || Getattr(nameobj, "fullname") || /* any of these options trigger a 'list' nameobj */
- Getattr(nameobj, "sourcefmt") || Getattr(nameobj, "matchlist")) {
+ Getattr(nameobj, "sourcefmt") || Getattr(nameobj, "matchlist") || Getattr(nameobj, "regextarget")) {
if (decl)
Setattr(nameobj, "decl", decl);
if (nname && Len(nname))
@@ -1155,36 +1153,50 @@ static DOH *Swig_get_lattr(Node *n, List *lattr) {
return res;
}
-#if defined(HAVE_RXSPENCER)
-#include <sys/types.h>
-#include <rxspencer/regex.h>
-#define USE_RXSPENCER
-#endif
+#ifdef HAVE_PCRE
+#include <pcre.h>
+
+int Swig_name_regexmatch_value(Node *n, String *pattern, String *s) {
+ pcre *compiled_pat;
+ const char *err;
+ int errpos;
+ int rc;
+
+ compiled_pat = pcre_compile(Char(pattern), 0, &err, &errpos, NULL);
+ if (!compiled_pat) {
+ Swig_error("SWIG", Getline(n),
+ "Invalid regex \"%s\": compilation failed at %d: %s\n",
+ Char(pattern), errpos, err);
+ exit(1);
+ }
-#if defined(USE_RXSPENCER)
-int Swig_name_rxsmatch_value(String *mvalue, String *value) {
- int match = 0;
- char *cvalue = Char(value);
- char *cmvalue = Char(mvalue);
- regex_t compiled;
- int retval = regcomp(&compiled, cmvalue, REG_EXTENDED | REG_NOSUB);
- if (retval != 0)
+ rc = pcre_exec(compiled_pat, NULL, Char(s), Len(s), 0, 0, NULL, 0);
+ pcre_free(compiled_pat);
+
+ if (rc == PCRE_ERROR_NOMATCH)
return 0;
- retval = regexec(&compiled, cvalue, 0, 0, 0);
- match = (retval == REG_NOMATCH) ? 0 : 1;
-#ifdef SWIG_DEBUG
- Printf(stdout, "rxsmatch_value: %s %s %d\n", cvalue, cmvalue, match);
-#endif
- regfree(&compiled);
- return match;
+
+ if (rc < 0 ) {
+ Swig_error("SWIG", Getline(n),
+ "Matching \"%s\" against regex \"%s\" failed: %d\n",
+ Char(s), Char(pattern), rc);
+ exit(1);
+ }
+
+ return 1;
}
-#else
-int Swig_name_rxsmatch_value(String *mvalue, String *value) {
- (void) mvalue;
- (void) value;
- return 0;
+
+#else /* !HAVE_PCRE */
+
+int Swig_name_regexmatch_value(Node *n, String *pattern, String *s) {
+ (void)pattern;
+ (void)s;
+ Swig_error("SWIG", Getline(n),
+ "PCRE regex matching is not available in this SWIG build.\n");
+ exit(1);
}
-#endif
+
+#endif /* HAVE_PCRE/!HAVE_PCRE */
int Swig_name_match_value(String *mvalue, String *value) {
#if defined(SWIG_USE_SIMPLE_MATCHOR)
@@ -1227,17 +1239,11 @@ int Swig_name_match_nameobj(Hash *rn, Node *n) {
List *lattr = Getattr(mi, "attrlist");
String *nval = Swig_get_lattr(n, lattr);
int notmatch = GetFlag(mi, "notmatch");
- int rxsmatch = GetFlag(mi, "rxsmatch");
-#ifdef SWIG_DEBUG
- Printf(stdout, "mi %d %s re %d not %d \n", i, nval, notmatch, rxsmatch);
- if (rxsmatch) {
- Printf(stdout, "rxsmatch %s\n", lattr);
- }
-#endif
+ int regexmatch = GetFlag(mi, "regexmatch");
match = 0;
if (nval) {
String *kwval = Getattr(mi, "value");
- match = rxsmatch ? Swig_name_rxsmatch_value(kwval, nval)
+ match = regexmatch ? Swig_name_regexmatch_value(n, kwval, nval)
: Swig_name_match_value(kwval, nval);
#ifdef SWIG_DEBUG
Printf(stdout, "val %s %s %d %d \n", nval, kwval, match, ilen);
@@ -1277,7 +1283,7 @@ Hash *Swig_name_nameobj_lget(List *namelist, Node *n, String *prefix, String *na
String *sfmt = Getattr(rn, "sourcefmt");
String *sname = 0;
int fullname = GetFlag(rn, "fullname");
- int rxstarget = GetFlag(rn, "rxstarget");
+ int regextarget = GetFlag(rn, "regextarget");
if (sfmt) {
if (fullname && prefix) {
String *pname = NewStringf("%s::%s", prefix, name);
@@ -1294,10 +1300,17 @@ Hash *Swig_name_nameobj_lget(List *namelist, Node *n, String *prefix, String *na
DohIncref(name);
}
}
- match = rxstarget ? Swig_name_rxsmatch_value(tname, sname) : Swig_name_match_value(tname, sname);
+ match = regextarget ? Swig_name_regexmatch_value(n, tname, sname)
+ : Swig_name_match_value(tname, sname);
Delete(sname);
} else {
- match = 1;
+ /* Applying the renaming rule may fail if it contains a %(regex)s expression that doesn't match the given name. */
+ String *sname = NewStringf(Getattr(rn, "name"), name);
+ if (sname) {
+ if (Len(sname))
+ match = 1;
+ Delete(sname);
+ }
}
}
if (match) {
@@ -1393,7 +1406,7 @@ void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *ne
ParmList *declparms = declaratorparms;
- const char *rename_keys[] = { "fullname", "sourcefmt", "targetfmt", "continue", "rxstarget", 0 };
+ const char *rename_keys[] = { "fullname", "sourcefmt", "targetfmt", "continue", "regextarget", 0 };
Swig_name_object_attach_keys(rename_keys, newname);
/* Add the name */
diff --git a/Source/Swig/scanner.c b/Source/Swig/scanner.c
index 9b5b35f96..0cdadaa7f 100644
--- a/Source/Swig/scanner.c
+++ b/Source/Swig/scanner.c
@@ -20,6 +20,7 @@ char cvsroot_scanner_c[] = "$Id$";
#include <ctype.h>
extern String *cparse_file;
+extern int cparse_line;
extern int cparse_cplusplus;
extern int cparse_start_line;
@@ -38,6 +39,13 @@ struct Scanner {
int freeze_line; /* Suspend line number updates */
};
+typedef struct Locator {
+ String *filename;
+ int line_number;
+ struct Locator *next;
+} Locator;
+static int follow_locators = 0;
+
/* -----------------------------------------------------------------------------
* NewScanner()
*
@@ -230,8 +238,7 @@ static void set_error(Scanner *s, int line, const_String_or_char_ptr msg) {
* Returns error information (if any)
* ----------------------------------------------------------------------------- */
-String *
-Scanner_errmsg(Scanner *s) {
+String *Scanner_errmsg(Scanner *s) {
return s->error;
}
@@ -241,13 +248,12 @@ Scanner_errline(Scanner *s) {
}
/* -----------------------------------------------------------------------------
- * Scanner_freeze_line()
+ * freeze_line()
*
* Freezes the current line number.
* ----------------------------------------------------------------------------- */
-void
-Scanner_freeze_line(Scanner *s, int val) {
+static void freeze_line(Scanner *s, int val) {
s->freeze_line = val;
}
@@ -1153,6 +1159,7 @@ int Scanner_skip_balanced(Scanner * s, int startchar, int endchar) {
int l;
int state = 0;
char temp[2] = { 0, 0 };
+ String *locator = 0;
l = s->line;
temp[0] = (char) startchar;
Clear(s->text);
@@ -1162,6 +1169,7 @@ int Scanner_skip_balanced(Scanner * s, int startchar, int endchar) {
Append(s->text, temp);
while (num_levels > 0) {
if ((c = nextchar(s)) == 0) {
+ Delete(locator);
return -1;
}
switch (state) {
@@ -1195,17 +1203,25 @@ int Scanner_skip_balanced(Scanner * s, int startchar, int endchar) {
else
state = 11;
break;
- case 12:
+ case 12: /* first character inside C comment */
if (c == '*')
+ state = 14;
+ else if (c == '@')
+ state = 40;
+ else
state = 13;
break;
case 13:
if (c == '*')
- state = 13;
+ state = 14;
+ break;
+ case 14: /* possible end of C comment */
+ if (c == '*')
+ state = 14;
else if (c == '/')
state = 0;
else
- state = 12;
+ state = 13;
break;
case 20:
if (c == '\"')
@@ -1225,10 +1241,43 @@ int Scanner_skip_balanced(Scanner * s, int startchar, int endchar) {
case 31:
state = 30;
break;
+ /* 40-45 SWIG locator checks - a C comment with contents starting: @SWIG */
+ case 40:
+ state = (c == 'S') ? 41 : (c == '*') ? 14 : 13;
+ break;
+ case 41:
+ state = (c == 'W') ? 42 : (c == '*') ? 14 : 13;
+ break;
+ case 42:
+ state = (c == 'I') ? 43 : (c == '*') ? 14 : 13;
+ break;
+ case 43:
+ state = (c == 'G') ? 44 : (c == '*') ? 14 : 13;
+ if (c == 'G') {
+ Delete(locator);
+ locator = NewString("/*@SWIG");
+ }
+ break;
+ case 44:
+ if (c == '*')
+ state = 45;
+ Putc(c, locator);
+ break;
+ case 45: /* end of SWIG locator in C comment */
+ if (c == '/') {
+ state = 0;
+ Putc(c, locator);
+ Scanner_locator(s, locator);
+ } else {
+ /* malformed locator */
+ state = (c == '*') ? 14 : 13;
+ }
+ break;
default:
break;
}
}
+ Delete(locator);
return 0;
}
@@ -1239,8 +1288,98 @@ int Scanner_skip_balanced(Scanner * s, int startchar, int endchar) {
* operator.
* ----------------------------------------------------------------------------- */
-int
-Scanner_isoperator(int tokval) {
+int Scanner_isoperator(int tokval) {
if (tokval >= 100) return 1;
return 0;
}
+
+/* ----------------------------------------------------------------------
+ * locator()
+ *
+ * Support for locator strings. These are strings of the form
+ * @SWIG:filename,line,id@ emitted by the SWIG preprocessor. They
+ * are primarily used for macro line number reporting.
+ * We just use the locator to mark when to activate/deactivate linecounting.
+ * ---------------------------------------------------------------------- */
+
+
+void Scanner_locator(Scanner *s, String *loc) {
+ static Locator *locs = 0;
+ static int expanding_macro = 0;
+
+ if (!follow_locators) {
+ if (Equal(loc, "/*@SWIG@*/")) {
+ /* End locator. */
+ if (expanding_macro)
+ --expanding_macro;
+ } else {
+ /* Begin locator. */
+ ++expanding_macro;
+ }
+ /* Freeze line number processing in Scanner */
+ freeze_line(s,expanding_macro);
+ } else {
+ int c;
+ Locator *l;
+ Seek(loc, 7, SEEK_SET);
+ c = Getc(loc);
+ if (c == '@') {
+ /* Empty locator. We pop the last location off */
+ if (locs) {
+ Scanner_set_location(s, locs->filename, locs->line_number);
+ cparse_file = locs->filename;
+ cparse_line = locs->line_number;
+ l = locs->next;
+ free(locs);
+ locs = l;
+ }
+ return;
+ }
+
+ /* We're going to push a new location */
+ l = (Locator *) malloc(sizeof(Locator));
+ l->filename = cparse_file;
+ l->line_number = cparse_line;
+ l->next = locs;
+ locs = l;
+
+ /* Now, parse the new location out of the locator string */
+ {
+ String *fn = NewStringEmpty();
+ /* Putc(c, fn); */
+
+ while ((c = Getc(loc)) != EOF) {
+ if ((c == '@') || (c == ','))
+ break;
+ Putc(c, fn);
+ }
+ cparse_file = Swig_copy_string(Char(fn));
+ Clear(fn);
+ cparse_line = 1;
+ /* Get the line number */
+ while ((c = Getc(loc)) != EOF) {
+ if ((c == '@') || (c == ','))
+ break;
+ Putc(c, fn);
+ }
+ cparse_line = atoi(Char(fn));
+ Clear(fn);
+
+ /* Get the rest of it */
+ while ((c = Getc(loc)) != EOF) {
+ if (c == '@')
+ break;
+ Putc(c, fn);
+ }
+ /* Swig_diagnostic(cparse_file, cparse_line, "Scanner_set_location\n"); */
+ Scanner_set_location(s, cparse_file, cparse_line);
+ Delete(fn);
+ }
+ }
+}
+
+void Swig_cparse_follow_locators(int v) {
+ follow_locators = v;
+}
+
+
diff --git a/Source/Swig/stype.c b/Source/Swig/stype.c
index dd2aea688..c2c17e515 100644
--- a/Source/Swig/stype.c
+++ b/Source/Swig/stype.c
@@ -177,7 +177,7 @@ void SwigType_push(SwigType *t, String *cons) {
* Testing functions for querying a raw datatype
* ----------------------------------------------------------------------------- */
-int SwigType_ispointer_return(SwigType *t) {
+int SwigType_ispointer_return(const SwigType *t) {
char *c;
int idx;
if (!t)
@@ -190,7 +190,7 @@ int SwigType_ispointer_return(SwigType *t) {
return 0;
}
-int SwigType_isreference_return(SwigType *t) {
+int SwigType_isreference_return(const SwigType *t) {
char *c;
int idx;
if (!t)
@@ -203,7 +203,7 @@ int SwigType_isreference_return(SwigType *t) {
return 0;
}
-int SwigType_isconst(SwigType *t) {
+int SwigType_isconst(const SwigType *t) {
char *c;
if (!t)
return 0;
@@ -229,7 +229,7 @@ int SwigType_isconst(SwigType *t) {
return 0;
}
-int SwigType_ismutable(SwigType *t) {
+int SwigType_ismutable(const SwigType *t) {
int r;
SwigType *qt = SwigType_typedef_resolve_all(t);
if (SwigType_isreference(qt) || SwigType_isarray(qt)) {
@@ -240,7 +240,7 @@ int SwigType_ismutable(SwigType *t) {
return r ? 0 : 1;
}
-int SwigType_isenum(SwigType *t) {
+int SwigType_isenum(const SwigType *t) {
char *c = Char(t);
if (!t)
return 0;
@@ -250,7 +250,7 @@ int SwigType_isenum(SwigType *t) {
return 0;
}
-int SwigType_issimple(SwigType *t) {
+int SwigType_issimple(const SwigType *t) {
char *c = Char(t);
if (!t)
return 0;
@@ -308,7 +308,7 @@ int SwigType_issimple(SwigType *t) {
* r.q(const).enum SWIGTYPE
* ----------------------------------------------------------------------------- */
-SwigType *SwigType_default_create(SwigType *ty) {
+SwigType *SwigType_default_create(const SwigType *ty) {
SwigType *r = 0;
List *l;
Iterator it;
@@ -366,7 +366,7 @@ SwigType *SwigType_default_create(SwigType *ty) {
* SwigType_default_create() before calling this function.
*
* Example deductions (matching the examples described in SwigType_default_create),
- * where the the most specialized matches are highest in the list:
+ * where the most specialized matches are highest in the list:
*
* a(ANY).a(ANY).SWIGTYPE
* a(ANY).a().SWIGTYPE
@@ -387,7 +387,7 @@ SwigType *SwigType_default_create(SwigType *ty) {
* SWIGTYPE
* ----------------------------------------------------------------------------- */
-SwigType *SwigType_default_deduce(SwigType *t) {
+SwigType *SwigType_default_deduce(const SwigType *t) {
SwigType *r = NewStringEmpty();
List *l;
Iterator it;
@@ -511,7 +511,7 @@ String *SwigType_namestr(const SwigType *t) {
* Create a C string representation of a datatype.
* ----------------------------------------------------------------------------- */
-String *SwigType_str(SwigType *s, const_String_or_char_ptr id) {
+String *SwigType_str(const SwigType *s, const_String_or_char_ptr id) {
String *result;
String *element = 0, *nextelement;
List *elements;
@@ -606,12 +606,12 @@ String *SwigType_str(SwigType *s, const_String_or_char_ptr id) {
}
/* -----------------------------------------------------------------------------
- * SwigType_ltype(SwigType *ty)
+ * SwigType_ltype(const SwigType *ty)
*
* Create a locally assignable type
* ----------------------------------------------------------------------------- */
-SwigType *SwigType_ltype(SwigType *s) {
+SwigType *SwigType_ltype(const SwigType *s) {
String *result;
String *element;
SwigType *td, *tc = 0;
@@ -709,7 +709,7 @@ SwigType *SwigType_ltype(SwigType *s) {
* with an equivalent assignable version.
* -------------------------------------------------------------------- */
-String *SwigType_lstr(SwigType *s, const_String_or_char_ptr id) {
+String *SwigType_lstr(const SwigType *s, const_String_or_char_ptr id) {
String *result;
SwigType *tc;
@@ -726,10 +726,11 @@ String *SwigType_lstr(SwigType *s, const_String_or_char_ptr id) {
* datatype printed by str().
* ----------------------------------------------------------------------------- */
-String *SwigType_rcaststr(SwigType *s, const_String_or_char_ptr name) {
+String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr name) {
String *result, *cast;
String *element = 0, *nextelement;
- SwigType *td, *rs, *tc = 0;
+ SwigType *td, *tc = 0;
+ const SwigType *rs;
List *elements;
int nelements, i;
int clear = 1;
@@ -873,7 +874,7 @@ String *SwigType_rcaststr(SwigType *s, const_String_or_char_ptr name) {
* Casts a variable from the real type to the local datatype.
* ----------------------------------------------------------------------------- */
-String *SwigType_lcaststr(SwigType *s, const_String_or_char_ptr name) {
+String *SwigType_lcaststr(const SwigType *s, const_String_or_char_ptr name) {
String *result;
result = NewStringEmpty();
@@ -899,27 +900,163 @@ String *SwigType_lcaststr(SwigType *s, const_String_or_char_ptr name) {
return result;
}
+#if 0
+/* Alternative implementation for manglestr_default. Mangling is similar to the original
+ except for a few subtle differences for example in templates:
+ namespace foo {
+ template<class T> class bar {};
+ typedef int Integer;
+ void test2(bar<Integer *> *x);
+ }
+ Mangling is more consistent and changes from
+ _p_foo__barT_int_p_t to
+ _p_foo__barT_p_int_t.
+*/
+static void mangle_stringcopy(String *destination, const char *source, int count) {
+ while (count-- > 0) {
+ char newc = '_';
+ if (!(*source == '.' || *source == ':' || *source == ' '))
+ newc = *source;
+ /* TODO: occasionally '*' or numerics need converting to '_', eg in array dimensions and template expressions */
+ Putc(newc, destination);
+ source++;
+ }
+}
+
+static void mangle_subtype(String *mangled, SwigType *s);
+
+/* -----------------------------------------------------------------------------
+ * mangle_namestr()
+ *
+ * Mangles a type taking care of template expansions. Similar to SwigType_namestr().
+ * The type may include a trailing '.', for example "p."
+ * ----------------------------------------------------------------------------- */
+
+static void mangle_namestr(String *mangled, SwigType *t) {
+ int length = Len(t);
+ if (SwigType_isqualifier(t)) {
+ Append(mangled, "q_");
+ mangle_stringcopy(mangled, Char(t)+2, length-4);
+ Append(mangled, "__");
+ } else if (SwigType_ismemberpointer(t)) {
+ Append(mangled, "m_");
+ mangle_stringcopy(mangled, Char(t)+2, length-4);
+ Append(mangled, "__");
+ } else if (SwigType_isarray(t)) {
+ Append(mangled, "a_");
+ mangle_stringcopy(mangled, Char(t)+2, length-4);
+ Append(mangled, "__");
+ } else if (SwigType_isfunction(t)) {
+ List *p = SwigType_parmlist(t);
+ int sz = Len(p);
+ int i;
+ Append(mangled, "f_");
+ for (i = 0; i < sz; i++) {
+ mangle_subtype(mangled, Getitem(p, i));
+ Putc('_', mangled);
+ }
+ Append(mangled, (sz > 0) ? "_" : "__");
+ } else if (SwigType_isvarargs(t)) {
+ Append(mangled, "___");
+ } else {
+ char *d = Char(t);
+ char *c = strstr(d, "<(");
+ if (!c || !strstr(c + 2, ")>")) {
+ /* not a template type */
+ mangle_stringcopy(mangled, Char(t), Len(t));
+ } else {
+ /* a template type */
+ String *suffix;
+ List *p;
+ int i, sz;
+ mangle_stringcopy(mangled, d, c-d);
+ Putc('T', mangled);
+ Putc('_', mangled);
+
+ p = SwigType_parmlist(c + 1);
+ sz = Len(p);
+ for (i = 0; i < sz; i++) {
+ mangle_subtype(mangled, Getitem(p, i));
+ Putc('_', mangled);
+ }
+ Putc('t', mangled);
+ suffix = SwigType_templatesuffix(t);
+ if (Len(suffix) > 0) {
+ mangle_namestr(mangled, suffix);
+ } else {
+ Append(mangled, suffix);
+ }
+ Delete(suffix);
+ Delete(p);
+ }
+ }
+}
+
+static void mangle_subtype(String *mangled, SwigType *s) {
+ List *elements;
+ int nelements, i;
+
+ assert(s);
+ elements = SwigType_split(s);
+ nelements = Len(elements);
+ for (i = 0; i < nelements; i++) {
+ SwigType *element = Getitem(elements, i);
+ mangle_namestr(mangled, element);
+ }
+ Delete(elements);
+}
+
+static String *manglestr_default(const SwigType *s) {
+ String *mangled = NewString("_");
+ SwigType *sr = SwigType_typedef_resolve_all(s);
+ SwigType *sq = SwigType_typedef_qualified(sr);
+ SwigType *ss = SwigType_remove_global_scope_prefix(sq);
+ SwigType *type = ss;
+ SwigType *lt;
+
+ if (SwigType_istemplate(ss)) {
+ SwigType *ty = Swig_symbol_template_deftype(ss, 0);
+ Delete(ss);
+ ss = ty;
+ type = ss;
+ }
+
+ lt = SwigType_ltype(type);
-/* keep old mangling since Java codes need it */
-String *SwigType_manglestr_default(SwigType *s) {
+ Replace(lt, "struct ", "", DOH_REPLACE_ANY);
+ Replace(lt, "class ", "", DOH_REPLACE_ANY);
+ Replace(lt, "union ", "", DOH_REPLACE_ANY);
+ Replace(lt, "enum ", "", DOH_REPLACE_ANY);
+
+ mangle_subtype(mangled, lt);
+
+ Delete(ss);
+ Delete(sq);
+ Delete(sr);
+
+ return mangled;
+}
+
+#else
+
+static String *manglestr_default(const SwigType *s) {
char *c;
String *result = 0;
String *base = 0;
SwigType *lt;
- SwigType *sr = SwigType_typedef_qualified(s);
- SwigType *ss = SwigType_typedef_resolve_all(sr);
-
- s = ss;
+ SwigType *sr = SwigType_typedef_resolve_all(s);
+ SwigType *sq = SwigType_typedef_qualified(sr);
+ SwigType *ss = SwigType_remove_global_scope_prefix(sq);
+ SwigType *type = ss;
if (SwigType_istemplate(ss)) {
SwigType *ty = Swig_symbol_template_deftype(ss, 0);
Delete(ss);
ss = ty;
- s = ss;
+ type = ss;
}
- Delete(sr);
- lt = SwigType_ltype(s);
+ lt = SwigType_ltype(type);
result = SwigType_prefix(lt);
base = SwigType_base(lt);
@@ -966,13 +1103,23 @@ String *SwigType_manglestr_default(SwigType *s) {
Insert(result, 0, "_");
Delete(lt);
Delete(base);
- if (ss)
- Delete(ss);
+ Delete(ss);
+ Delete(sq);
+ Delete(sr);
return result;
}
-
-String *SwigType_manglestr(SwigType *s) {
- return SwigType_manglestr_default(s);
+#endif
+
+String *SwigType_manglestr(const SwigType *s) {
+#if 0
+ /* Debugging checks to ensure a proper SwigType is passed in and not a stringified type */
+ String *angle = Strstr(s, "<");
+ if (angle && Strncmp(angle, "<(", 2) != 0)
+ Printf(stderr, "SwigType_manglestr error: %s\n", s);
+ else if (Strstr(s, "*") || Strstr(s, "&") || Strstr(s, "["))
+ Printf(stderr, "SwigType_manglestr error: %s\n", s);
+#endif
+ return manglestr_default(s);
}
/* -----------------------------------------------------------------------------
@@ -1091,7 +1238,7 @@ SwigType *SwigType_remove_global_scope_prefix(const SwigType *t) {
* Checks type declarators for a match
* ----------------------------------------------------------------------------- */
-int SwigType_check_decl(SwigType *ty, const SwigType *decl) {
+int SwigType_check_decl(const SwigType *ty, const SwigType *decl) {
SwigType *t, *t1, *t2;
int r;
t = SwigType_typedef_resolve_all(ty);
diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h
index f90a5ffb1..6607c333d 100644
--- a/Source/Swig/swig.h
+++ b/Source/Swig/swig.h
@@ -129,37 +129,37 @@ extern "C" {
extern SwigType *SwigType_add_function(SwigType *t, ParmList *parms);
extern SwigType *SwigType_add_template(SwigType *t, ParmList *parms);
extern SwigType *SwigType_pop_function(SwigType *t);
- extern ParmList *SwigType_function_parms(SwigType *t, Node *file_line_node);
+ extern ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node);
extern List *SwigType_split(const SwigType *t);
extern String *SwigType_pop(SwigType *t);
- extern void SwigType_push(SwigType *t, SwigType *s);
+ extern void SwigType_push(SwigType *t, String *s);
extern List *SwigType_parmlist(const SwigType *p);
- extern String *SwigType_parm(String *p);
- extern String *SwigType_str(SwigType *s, const_String_or_char_ptr id);
- extern String *SwigType_lstr(SwigType *s, const_String_or_char_ptr id);
- extern String *SwigType_rcaststr(SwigType *s, const_String_or_char_ptr id);
- extern String *SwigType_lcaststr(SwigType *s, const_String_or_char_ptr id);
- extern String *SwigType_manglestr(SwigType *t);
- extern SwigType *SwigType_ltype(SwigType *t);
- extern int SwigType_ispointer(SwigType *t);
- extern int SwigType_ispointer_return(SwigType *t);
- extern int SwigType_isfunctionpointer(SwigType *t);
- extern int SwigType_ismemberpointer(SwigType *t);
- extern int SwigType_isreference(SwigType *t);
- extern int SwigType_isreference_return(SwigType *t);
- extern int SwigType_isarray(SwigType *t);
- extern int SwigType_prefix_is_simple_1D_array(SwigType *t);
- extern int SwigType_isfunction(SwigType *t);
- extern int SwigType_isqualifier(SwigType *t);
- extern int SwigType_isconst(SwigType *t);
- extern int SwigType_issimple(SwigType *t);
- extern int SwigType_ismutable(SwigType *t);
+ extern String *SwigType_parm(const SwigType *p);
+ extern String *SwigType_str(const SwigType *s, const_String_or_char_ptr id);
+ extern String *SwigType_lstr(const SwigType *s, const_String_or_char_ptr id);
+ extern String *SwigType_rcaststr(const SwigType *s, const_String_or_char_ptr id);
+ extern String *SwigType_lcaststr(const SwigType *s, const_String_or_char_ptr id);
+ extern String *SwigType_manglestr(const SwigType *t);
+ extern SwigType *SwigType_ltype(const SwigType *t);
+ extern int SwigType_ispointer(const SwigType *t);
+ extern int SwigType_ispointer_return(const SwigType *t);
+ extern int SwigType_isfunctionpointer(const SwigType *t);
+ extern int SwigType_ismemberpointer(const SwigType *t);
+ extern int SwigType_isreference(const SwigType *t);
+ extern int SwigType_isreference_return(const SwigType *t);
+ extern int SwigType_isarray(const SwigType *t);
+ extern int SwigType_prefix_is_simple_1D_array(const SwigType *t);
+ extern int SwigType_isfunction(const SwigType *t);
+ extern int SwigType_isqualifier(const SwigType *t);
+ extern int SwigType_isconst(const SwigType *t);
+ extern int SwigType_issimple(const SwigType *t);
+ extern int SwigType_ismutable(const SwigType *t);
extern int SwigType_isvarargs(const SwigType *t);
extern int SwigType_istemplate(const SwigType *t);
- extern int SwigType_isenum(SwigType *t);
- extern int SwigType_check_decl(SwigType *t, const_String_or_char_ptr decl);
- extern SwigType *SwigType_strip_qualifiers(SwigType *t);
- extern SwigType *SwigType_strip_single_qualifier(SwigType *t);
+ extern int SwigType_isenum(const SwigType *t);
+ extern int SwigType_check_decl(const SwigType *t, const_String_or_char_ptr decl);
+ extern SwigType *SwigType_strip_qualifiers(const SwigType *t);
+ extern SwigType *SwigType_strip_single_qualifier(const SwigType *t);
extern SwigType *SwigType_functionpointer_decompose(SwigType *t);
extern String *SwigType_base(const SwigType *t);
extern String *SwigType_namestr(const SwigType *t);
@@ -168,27 +168,26 @@ extern "C" {
extern String *SwigType_istemplate_templateprefix(const SwigType *t);
extern String *SwigType_templateargs(const SwigType *t);
extern String *SwigType_prefix(const SwigType *t);
- extern int SwigType_array_ndim(SwigType *t);
- extern String *SwigType_array_getdim(SwigType *t, int n);
+ extern int SwigType_array_ndim(const SwigType *t);
+ extern String *SwigType_array_getdim(const SwigType *t, int n);
extern void SwigType_array_setdim(SwigType *t, int n, const_String_or_char_ptr rep);
- extern SwigType *SwigType_array_type(SwigType *t);
- extern String *SwigType_default(SwigType *t);
- extern SwigType *SwigType_default_create(SwigType *ty);
- extern SwigType *SwigType_default_deduce(SwigType *t);
+ extern SwigType *SwigType_array_type(const SwigType *t);
+ extern SwigType *SwigType_default_create(const SwigType *ty);
+ extern SwigType *SwigType_default_deduce(const SwigType *t);
extern void SwigType_typename_replace(SwigType *t, String *pat, String *rep);
extern SwigType *SwigType_remove_global_scope_prefix(const SwigType *t);
- extern SwigType *SwigType_alttype(SwigType *t, int ltmap);
+ extern SwigType *SwigType_alttype(const SwigType *t, int ltmap);
extern void SwigType_template_defargs(Parm *parms, Parm *targs, Symtab *tscope, Symtab *tsdecl);
extern SwigType *SwigType_template_deftype(const SwigType *type, Symtab *tscope);
/* --- Type-system managment --- */
extern void SwigType_typesystem_init(void);
- extern int SwigType_typedef(SwigType *type, const_String_or_char_ptr name);
+ extern int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name);
extern int SwigType_typedef_class(const_String_or_char_ptr name);
extern int SwigType_typedef_using(const_String_or_char_ptr qname);
extern void SwigType_inherit(String *subclass, String *baseclass, String *cast, String *conversioncode);
- extern int SwigType_issubtype(SwigType *subtype, SwigType *basetype);
+ extern int SwigType_issubtype(const SwigType *subtype, const SwigType *basetype);
extern void SwigType_scope_alias(String *aliasname, Typetab *t);
extern void SwigType_using_scope(Typetab *t);
extern void SwigType_new_scope(const_String_or_char_ptr name);
@@ -197,17 +196,17 @@ extern "C" {
extern Typetab *SwigType_set_scope(Typetab *h);
extern void SwigType_print_scope(Typetab *t);
extern SwigType *SwigType_typedef_resolve(const SwigType *t);
- extern SwigType *SwigType_typedef_resolve_all(SwigType *t);
- extern SwigType *SwigType_typedef_qualified(SwigType *t);
- extern int SwigType_istypedef(SwigType *t);
- extern int SwigType_isclass(SwigType *t);
+ extern SwigType *SwigType_typedef_resolve_all(const SwigType *t);
+ extern SwigType *SwigType_typedef_qualified(const SwigType *t);
+ extern int SwigType_istypedef(const SwigType *t);
+ extern int SwigType_isclass(const SwigType *t);
extern void SwigType_attach_symtab(Symtab *syms);
- extern void SwigType_remember(SwigType *t);
- extern void SwigType_remember_clientdata(SwigType *t, const_String_or_char_ptr clientdata);
+ extern void SwigType_remember(const SwigType *t);
+ extern void SwigType_remember_clientdata(const SwigType *t, const_String_or_char_ptr clientdata);
extern void SwigType_remember_mangleddata(String *mangled, const_String_or_char_ptr clientdata);
- extern void (*SwigType_remember_trace(void (*tf) (SwigType *, String *, String *))) (SwigType *, String *, String *);
+ extern void (*SwigType_remember_trace(void (*tf) (const SwigType *, String *, String *))) (const SwigType *, String *, String *);
extern void SwigType_emit_type_table(File *f_headers, File *f_table);
- extern int SwigType_type(SwigType *t);
+ extern int SwigType_type(const SwigType *t);
/* --- Symbol table module --- */
@@ -240,7 +239,7 @@ extern "C" {
extern void Swig_symbol_inherit(Symtab *tab);
extern SwigType *Swig_symbol_type_qualify(const SwigType *ty, Symtab *tab);
extern String *Swig_symbol_string_qualify(String *s, Symtab *tab);
- extern SwigType *Swig_symbol_typedef_reduce(SwigType *ty, Symtab *tab);
+ extern SwigType *Swig_symbol_typedef_reduce(const SwigType *ty, Symtab *tab);
extern ParmList *Swig_symbol_template_defargs(Parm *parms, Parm *targs, Symtab *tscope, Symtab *tsdecl);
extern SwigType *Swig_symbol_template_deftype(const SwigType *type, Symtab *tscope);
@@ -319,7 +318,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
extern String *Swig_string_lower(String *s);
extern String *Swig_string_upper(String *s);
extern String *Swig_string_title(String *s);
-
+ extern String *Swig_pcre_version(void);
extern void Swig_init(void);
extern int Swig_value_wrapper_mode(int mode);
@@ -334,6 +333,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
extern int Swig_warn_count(void);
extern void Swig_error_msg_format(ErrorMessageFormat format);
extern void Swig_diagnostic(const_String_or_char_ptr filename, int line, const char *fmt, ...);
+ extern String *Swig_stringify_with_location(DOH *object);
/* --- C Wrappers --- */
extern String *Swig_cparm_name(Parm *p, int i);
@@ -369,6 +369,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
#define CWRAP_DIRECTOR_ONE_CALL 0x08
#define CWRAP_DIRECTOR_TWO_CALLS 0x10
#define CWRAP_ALL_PROTECTED_ACCESS 0x20
+#define CWRAP_SMART_POINTER_OVERLOAD 0x40
/* --- Director Helpers --- */
extern Node *Swig_methodclass(Node *n);
@@ -408,6 +409,8 @@ extern int ParmList_is_compactdefargs(ParmList *p);
extern void Wrapper_director_protected_mode_set(int);
extern void Wrapper_all_protected_mode_set(int);
extern void Language_replace_special_variables(String *method, String *tm, Parm *parm);
+ extern void Swig_print(DOH *object, int count);
+ extern void Swig_print_with_location(DOH *object, int count);
/* -- template init -- */
diff --git a/Source/Swig/swigscan.h b/Source/Swig/swigscan.h
index b07812fbe..a2d5911bd 100644
--- a/Source/Swig/swigscan.h
+++ b/Source/Swig/swigscan.h
@@ -30,7 +30,7 @@ extern void Scanner_idstart(Scanner *, const char *idchar);
extern String *Scanner_errmsg(Scanner *);
extern int Scanner_errline(Scanner *);
extern int Scanner_isoperator(int tokval);
-extern void Scanner_freeze_line(Scanner *s, int val);
+extern void Scanner_locator(Scanner *, String *loc);
/* Note: Tokens in range 100+ are for C/C++ operators */
diff --git a/Source/Swig/symbol.c b/Source/Swig/symbol.c
index b5e114683..4ec18e8c7 100644
--- a/Source/Swig/symbol.c
+++ b/Source/Swig/symbol.c
@@ -1642,7 +1642,7 @@ SwigType *Swig_symbol_template_reduce(SwigType *qt, Symtab *ntab) {
* Chase a typedef through symbol tables looking for a match.
* ----------------------------------------------------------------------------- */
-SwigType *Swig_symbol_typedef_reduce(SwigType *ty, Symtab *tab) {
+SwigType *Swig_symbol_typedef_reduce(const SwigType *ty, Symtab *tab) {
SwigType *prefix, *base;
Node *n;
String *nt;
diff --git a/Source/Swig/tree.c b/Source/Swig/tree.c
index c76ac958e..e66670c7c 100644
--- a/Source/Swig/tree.c
+++ b/Source/Swig/tree.c
@@ -291,10 +291,10 @@ void Swig_require(const char *ns, Node *n, ...) {
if (view) {
if (Strcmp(view, ns) != 0) {
Setattr(n, NewStringf("%s:view", ns), view);
- Setattr(n, "view", ns);
+ Setattr(n, "view", NewString(ns));
}
} else {
- Setattr(n, "view", ns);
+ Setattr(n, "view", NewString(ns));
}
}
}
@@ -337,10 +337,10 @@ void Swig_save(const char *ns, Node *n, ...) {
if (view) {
if (Strcmp(view, ns) != 0) {
Setattr(n, NewStringf("%s:view", ns), view);
- Setattr(n, "view", ns);
+ Setattr(n, "view", NewString(ns));
}
} else {
- Setattr(n, "view", ns);
+ Setattr(n, "view", NewString(ns));
}
}
}
diff --git a/Source/Swig/typemap.c b/Source/Swig/typemap.c
index 607ab6d10..fe6a33641 100644
--- a/Source/Swig/typemap.c
+++ b/Source/Swig/typemap.c
@@ -963,7 +963,7 @@ static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, Swi
{
SwigType *star_type, *amp_type, *base_type, *lex_type;
SwigType *ltype, *star_ltype, *amp_ltype;
- String *mangle, *star_mangle, *amp_mangle, *base_mangle, *base_name;
+ String *mangle, *star_mangle, *amp_mangle, *base_mangle, *base_name, *base_type_str;
String *descriptor, *star_descriptor, *amp_descriptor;
String *ts;
char *sc;
@@ -1132,21 +1132,20 @@ static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, Swi
/* Base type */
if (SwigType_isarray(type)) {
- SwigType *bt = Copy(type);
- Delete(SwigType_pop_arrays(bt));
- base_type = SwigType_str(bt, 0);
- Delete(bt);
+ base_type = Copy(type);
+ Delete(SwigType_pop_arrays(base_type));
} else {
base_type = SwigType_base(type);
}
- base_name = SwigType_namestr(base_type);
+ base_type_str = SwigType_str(base_type, 0);
+ base_name = SwigType_namestr(base_type_str);
if (index == 1) {
Replace(s, "$basetype", base_name, DOH_REPLACE_ANY);
replace_local_types(locals, "$basetype", base_name);
}
strcpy(varname, "basetype");
- Replace(s, var, base_type, DOH_REPLACE_ANY);
+ Replace(s, var, base_type_str, DOH_REPLACE_ANY);
replace_local_types(locals, var, base_name);
base_mangle = SwigType_manglestr(base_type);
@@ -1155,8 +1154,9 @@ static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, Swi
strcpy(varname, "basemangle");
Replace(s, var, base_mangle, DOH_REPLACE_ANY);
Delete(base_mangle);
- Delete(base_type);
Delete(base_name);
+ Delete(base_type_str);
+ Delete(base_type);
lex_type = SwigType_base(rtype);
if (index == 1)
@@ -1440,8 +1440,8 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr tmap_method, No
num_substitutions = typemap_replace_vars(s, locals, type, type, pname, (char *) lname, 1);
}
if (optimal_substitution && num_substitutions > 1) {
- Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(node), Getline(node), "Multiple calls to %s might be generated due to optimal attribute usage in\n", Swig_name_decl(node));
- Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(s), Getline(s), "the out typemap.\n");
+ Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(node), Getline(node), "Multiple calls to %s might be generated due to\n", Swig_name_decl(node));
+ Swig_warning(WARN_TYPEMAP_OUT_OPTIMAL_MULTIPLE, Getfile(s), Getline(s), "optimal attribute usage in the out typemap.\n");
}
if (locals && f) {
diff --git a/Source/Swig/typeobj.c b/Source/Swig/typeobj.c
index 074bbf904..dd8d901e0 100644
--- a/Source/Swig/typeobj.c
+++ b/Source/Swig/typeobj.c
@@ -210,7 +210,7 @@ SwigType *SwigType_pop(SwigType *t) {
* Returns the parameter of an operator as a string
* ----------------------------------------------------------------------------- */
-String *SwigType_parm(SwigType *t) {
+String *SwigType_parm(const SwigType *t) {
char *start, *c;
int nparens = 0;
@@ -362,7 +362,7 @@ SwigType *SwigType_del_pointer(SwigType *t) {
return t;
}
-int SwigType_ispointer(SwigType *t) {
+int SwigType_ispointer(const SwigType *t) {
char *c;
if (!t)
return 0;
@@ -404,7 +404,7 @@ SwigType *SwigType_del_reference(SwigType *t) {
return t;
}
-int SwigType_isreference(SwigType *t) {
+int SwigType_isreference(const SwigType *t) {
char *c;
if (!t)
return 0;
@@ -494,7 +494,7 @@ SwigType *SwigType_del_qualifier(SwigType *t) {
return t;
}
-int SwigType_isqualifier(SwigType *t) {
+int SwigType_isqualifier(const SwigType *t) {
char *c;
if (!t)
return 0;
@@ -509,7 +509,7 @@ int SwigType_isqualifier(SwigType *t) {
* Function Pointers
* ----------------------------------------------------------------------------- */
-int SwigType_isfunctionpointer(SwigType *t) {
+int SwigType_isfunctionpointer(const SwigType *t) {
char *c;
if (!t)
return 0;
@@ -562,7 +562,7 @@ SwigType *SwigType_del_memberpointer(SwigType *t) {
return t;
}
-int SwigType_ismemberpointer(SwigType *t) {
+int SwigType_ismemberpointer(const SwigType *t) {
char *c;
if (!t)
return 0;
@@ -606,7 +606,7 @@ SwigType *SwigType_del_array(SwigType *t) {
return t;
}
-int SwigType_isarray(SwigType *t) {
+int SwigType_isarray(const SwigType *t) {
char *c;
if (!t)
return 0;
@@ -622,7 +622,7 @@ int SwigType_isarray(SwigType *t) {
* Determine if the type is a 1D array type that is treated as a pointer within SWIG
* eg Foo[], Foo[3] return true, but Foo[3][3], Foo*[], Foo*[3], Foo**[] return false
*/
-int SwigType_prefix_is_simple_1D_array(SwigType *t) {
+int SwigType_prefix_is_simple_1D_array(const SwigType *t) {
char *c = Char(t);
if (c && (strncmp(c, "a(", 2) == 0)) {
@@ -648,7 +648,7 @@ SwigType *SwigType_pop_arrays(SwigType *t) {
}
/* Return number of array dimensions */
-int SwigType_array_ndim(SwigType *t) {
+int SwigType_array_ndim(const SwigType *t) {
int ndim = 0;
char *c = Char(t);
@@ -661,7 +661,7 @@ int SwigType_array_ndim(SwigType *t) {
}
/* Get nth array dimension */
-String *SwigType_array_getdim(SwigType *t, int n) {
+String *SwigType_array_getdim(const SwigType *t, int n) {
char *c = Char(t);
while (c && (strncmp(c, "a(", 2) == 0) && (n > 0)) {
c = strchr(c, '.');
@@ -713,7 +713,7 @@ void SwigType_array_setdim(SwigType *t, int n, const_String_or_char_ptr rep) {
}
/* Return base type of an array */
-SwigType *SwigType_array_type(SwigType *ty) {
+SwigType *SwigType_array_type(const SwigType *ty) {
SwigType *t;
t = Copy(ty);
while (SwigType_isarray(t)) {
@@ -771,7 +771,7 @@ SwigType *SwigType_pop_function(SwigType *t) {
return g;
}
-int SwigType_isfunction(SwigType *t) {
+int SwigType_isfunction(const SwigType *t) {
char *c;
if (!t) {
return 0;
@@ -793,7 +793,7 @@ int SwigType_isfunction(SwigType *t) {
/* Create a list of parameters from the type t, using the file_line_node Node for
* file and line numbering for the parameters */
-ParmList *SwigType_function_parms(SwigType *t, Node *file_line_node) {
+ParmList *SwigType_function_parms(const SwigType *t, Node *file_line_node) {
List *l = SwigType_parmlist(t);
Hash *p, *pp = 0, *firstp = 0;
Iterator o;
@@ -1094,7 +1094,7 @@ String *SwigType_prefix(const SwigType *t) {
* Strip all qualifiers from a type and return a new type
* ----------------------------------------------------------------------------- */
-SwigType *SwigType_strip_qualifiers(SwigType *t) {
+SwigType *SwigType_strip_qualifiers(const SwigType *t) {
static Hash *memoize_stripped = 0;
SwigType *r;
List *l;
@@ -1138,7 +1138,7 @@ SwigType *SwigType_strip_qualifiers(SwigType *t) {
* r.p.int => r.p.int
* ----------------------------------------------------------------------------- */
-SwigType *SwigType_strip_single_qualifier(SwigType *t) {
+SwigType *SwigType_strip_single_qualifier(const SwigType *t) {
static Hash *memoize_stripped = 0;
SwigType *r = 0;
List *l;
diff --git a/Source/Swig/typesys.c b/Source/Swig/typesys.c
index 2436e005c..a1445f200 100644
--- a/Source/Swig/typesys.c
+++ b/Source/Swig/typesys.c
@@ -107,12 +107,12 @@ 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
+#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);
+static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix);
/* common attribute keys, to avoid calling find_key all the times */
@@ -167,7 +167,7 @@ void SwigType_typesystem_init() {
* already defined.
* ----------------------------------------------------------------------------- */
-int SwigType_typedef(SwigType *type, const_String_or_char_ptr name) {
+int SwigType_typedef(const SwigType *type, const_String_or_char_ptr name) {
if (Getattr(current_typetab, name))
return -1; /* Already defined */
if (Strcmp(type, name) == 0) { /* Can't typedef a name to itself */
@@ -414,7 +414,7 @@ void SwigType_print_scope(Typetab *t) {
}
}
-static Typetab *SwigType_find_scope(Typetab *s, String *nameprefix) {
+static Typetab *SwigType_find_scope(Typetab *s, const SwigType *nameprefix) {
Typetab *ss;
String *nnameprefix = 0;
static int check_parent = 1;
@@ -806,9 +806,10 @@ return_result:
* Fully resolve a type down to its most basic datatype
* ----------------------------------------------------------------------------- */
-SwigType *SwigType_typedef_resolve_all(SwigType *t) {
+SwigType *SwigType_typedef_resolve_all(const SwigType *t) {
SwigType *n;
SwigType *r;
+ int count = 0;
/* Check to see if the typedef resolve has been done before by checking the cache */
if (!typedef_all_cache) {
@@ -824,6 +825,10 @@ SwigType *SwigType_typedef_resolve_all(SwigType *t) {
while ((n = SwigType_typedef_resolve(r))) {
Delete(r);
r = n;
+ if (++count >= 512) {
+ Swig_error(Getfile(t), Getline(t), "Recursive typedef detected resolving '%s' to '%s' to '%s' and so on...\n", SwigType_str(t, 0), SwigType_str(SwigType_typedef_resolve(t), 0), SwigType_str(SwigType_typedef_resolve(SwigType_typedef_resolve(t)), 0));
+ break;
+ }
}
/* Add the typedef to the cache for next time it is looked up */
@@ -848,7 +853,7 @@ SwigType *SwigType_typedef_resolve_all(SwigType *t) {
* scope, it is left in place.
* ----------------------------------------------------------------------------- */
-SwigType *SwigType_typedef_qualified(SwigType *t) {
+SwigType *SwigType_typedef_qualified(const SwigType *t) {
List *elements;
String *result;
int i, len;
@@ -1049,7 +1054,7 @@ SwigType *SwigType_typedef_qualified(SwigType *t) {
* Checks a typename to see if it is a typedef.
* ----------------------------------------------------------------------------- */
-int SwigType_istypedef(SwigType *t) {
+int SwigType_istypedef(const SwigType *t) {
String *type;
type = SwigType_typedef_resolve(t);
@@ -1150,7 +1155,7 @@ int SwigType_typedef_using(const_String_or_char_ptr name) {
* a class.
* ----------------------------------------------------------------------------- */
-int SwigType_isclass(SwigType *t) {
+int SwigType_isclass(const SwigType *t) {
SwigType *qty, *qtys;
int isclass = 0;
@@ -1186,7 +1191,7 @@ int SwigType_isclass(SwigType *t) {
* everything is based on typemaps.
* ----------------------------------------------------------------------------- */
-int SwigType_type(SwigType *t) {
+int SwigType_type(const SwigType *t) {
char *c;
/* Check for the obvious stuff */
c = Char(t);
@@ -1295,7 +1300,7 @@ int SwigType_type(SwigType *t) {
* %feature("valuewrapper").
* ----------------------------------------------------------------------------- */
-SwigType *SwigType_alttype(SwigType *t, int local_tmap) {
+SwigType *SwigType_alttype(const SwigType *t, int local_tmap) {
Node *n;
SwigType *w = 0;
int use_wrapper = 0;
@@ -1413,7 +1418,7 @@ 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;
+static void (*r_tracefunc) (const SwigType *t, String *mangled, String *clientdata) = 0;
void SwigType_remember_mangleddata(String *mangled, const_String_or_char_ptr clientdata) {
if (!r_mangleddata) {
@@ -1423,7 +1428,7 @@ void SwigType_remember_mangleddata(String *mangled, const_String_or_char_ptr cli
}
-void SwigType_remember_clientdata(SwigType *t, const_String_or_char_ptr clientdata) {
+void SwigType_remember_clientdata(const SwigType *t, const_String_or_char_ptr clientdata) {
String *mt;
SwigType *lt;
Hash *h;
@@ -1536,12 +1541,12 @@ void SwigType_remember_clientdata(SwigType *t, const_String_or_char_ptr clientda
}
}
-void SwigType_remember(SwigType *ty) {
+void SwigType_remember(const 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;
+void (*SwigType_remember_trace(void (*tf) (const SwigType *, String *, String *))) (const SwigType *, String *, String *) {
+ void (*o) (const SwigType *, String *, String *) = r_tracefunc;
r_tracefunc = tf;
return o;
}
@@ -1713,7 +1718,7 @@ void SwigType_inherit(String *derived, String *base, String *cast, String *conve
* Determines if a t1 is a subtype of t2, ie, is t1 derived from t2
* ----------------------------------------------------------------------------- */
-int SwigType_issubtype(SwigType *t1, SwigType *t2) {
+int SwigType_issubtype(const SwigType *t1, const SwigType *t2) {
SwigType *ft1, *ft2;
String *b1, *b2;
Hash *h;