diff options
Diffstat (limited to 'Source')
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; |