Merge trunk (up to just after swig 2.0.5 release - rev 13009) to gsoc2008-cherylfoil
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/branches/gsoc2008-cherylfoil@13017 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
commit
af1c6ac3c3
1811 changed files with 94580 additions and 35569 deletions
|
|
@ -11,8 +11,6 @@
|
|||
* SWIG parser module.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
/* $Id$ */
|
||||
|
||||
#ifndef SWIG_CPARSE_H_
|
||||
#define SWIG_CPARSE_H_
|
||||
|
||||
|
|
@ -38,16 +36,18 @@ extern "C" {
|
|||
extern void scanner_ignore_typedef(void);
|
||||
extern void scanner_last_id(int);
|
||||
extern void scanner_clear_rename(void);
|
||||
extern void scanner_set_location(String_or_char *, int line);
|
||||
extern void scanner_set_location(String *file, int line);
|
||||
extern void scanner_set_main_input_file(String *file);
|
||||
extern String *scanner_get_main_input_file();
|
||||
extern void Swig_cparse_follow_locators(int);
|
||||
extern void start_inline(char *, int);
|
||||
extern String *scanner_ccode;
|
||||
extern int yylex();
|
||||
extern int yylex(void);
|
||||
|
||||
/* parser.y */
|
||||
extern SwigType *Swig_cparse_type(String *);
|
||||
extern Node *Swig_cparse(File *);
|
||||
extern Hash *Swig_cparse_features();
|
||||
extern Hash *Swig_cparse_features(void);
|
||||
extern void SWIG_cparse_set_compact_default_args(int defargs);
|
||||
extern int SWIG_cparse_template_reduce(int treduce);
|
||||
|
||||
|
|
@ -55,7 +55,7 @@ extern "C" {
|
|||
extern void Swig_cparse_replace_descriptor(String *s);
|
||||
extern void cparse_normalize_void(Node *);
|
||||
extern Parm *Swig_cparse_parm(String *s);
|
||||
extern ParmList *Swig_cparse_parms(String *s);
|
||||
extern ParmList *Swig_cparse_parms(String *s, Node *file_line_node);
|
||||
|
||||
|
||||
/* templ.c */
|
||||
|
|
|
|||
|
|
@ -26,7 +26,10 @@ char cvsroot_cscanner_c[] = "$Id$";
|
|||
static Scanner *scan = 0;
|
||||
|
||||
/* Global string containing C code. Used by the parser to grab code blocks */
|
||||
DOHString *scanner_ccode = 0;
|
||||
String *scanner_ccode = 0;
|
||||
|
||||
/* The main file being parsed */
|
||||
static String *main_input_file = 0;
|
||||
|
||||
/* Error reporting/location information */
|
||||
int cparse_line = 1;
|
||||
|
|
@ -42,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()
|
||||
|
|
@ -53,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);
|
||||
}
|
||||
/* Printf(stderr,"location: %s:%d\n",cparse_file,cparse_line); */
|
||||
Scanner_set_location(scan,cparse_file,cparse_line);
|
||||
Delete(fn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Swig_cparse_follow_locators(int v) {
|
||||
follow_locators = v;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* scanner_init()
|
||||
*
|
||||
|
|
@ -258,17 +164,15 @@ void skip_decl(void) {
|
|||
* Lexical scanner.
|
||||
* ------------------------------------------------------------------------- */
|
||||
|
||||
int yylook(void) {
|
||||
static int yylook(void) {
|
||||
|
||||
int tok = 0;
|
||||
|
||||
while (1) {
|
||||
if ((tok = Scanner_token(scan)) == 0)
|
||||
return 0;
|
||||
if (tok == SWIG_TOKEN_ERROR) {
|
||||
Swig_error(Scanner_file(scan), Scanner_errline(scan), Scanner_errmsg(scan));
|
||||
continue;
|
||||
}
|
||||
if (tok == SWIG_TOKEN_ERROR)
|
||||
return 0;
|
||||
cparse_start_line = Scanner_start_line(scan);
|
||||
cparse_line = Scanner_line(scan);
|
||||
cparse_file = Scanner_file(scan);
|
||||
|
|
@ -413,6 +317,9 @@ int yylook(void) {
|
|||
case SWIG_TOKEN_FLOAT:
|
||||
return NUM_FLOAT;
|
||||
|
||||
case SWIG_TOKEN_BOOL:
|
||||
return NUM_BOOL;
|
||||
|
||||
case SWIG_TOKEN_POUND:
|
||||
Scanner_skip_line(scan);
|
||||
yylval.id = Swig_copy_string(Char(Scanner_text(scan)));
|
||||
|
|
@ -428,7 +335,7 @@ 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);
|
||||
}
|
||||
if (strncmp(loc, "/**<", 4) == 0 || strncmp(loc, "///<", 4) == 0||strncmp(loc, "/*!<", 4) == 0||strncmp(loc, "//!<", 4) == 0) {
|
||||
/* printf("Doxygen Post Comment: %s lines %d-%d [%s]\n", Char(Scanner_file(scan)), Scanner_start_line(scan), Scanner_line(scan), loc); */
|
||||
|
|
@ -455,7 +362,7 @@ int yylook(void) {
|
|||
|
||||
static int check_typedef = 0;
|
||||
|
||||
void scanner_set_location(String_or_char *file, int line) {
|
||||
void scanner_set_location(String *file, int line) {
|
||||
Scanner_set_location(scan,file,line-1);
|
||||
}
|
||||
|
||||
|
|
@ -481,6 +388,14 @@ void scanner_next_token(int tok) {
|
|||
next_token = tok;
|
||||
}
|
||||
|
||||
void scanner_set_main_input_file(String *file) {
|
||||
main_input_file = file;
|
||||
}
|
||||
|
||||
String *scanner_get_main_input_file() {
|
||||
return main_input_file;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------------------
|
||||
* int yylex()
|
||||
*
|
||||
|
|
@ -504,7 +419,7 @@ int yylex(void) {
|
|||
|
||||
l = yylook();
|
||||
|
||||
/* Printf(stdout, "%s:%d:::%d: '%s'\n", cparse_file, cparse_line, l, Scanner_text(scan)); */
|
||||
/* Swig_diagnostic(cparse_file, cparse_line, ":::%d: '%s'\n", l, Scanner_text(scan)); */
|
||||
|
||||
if (l == NONID) {
|
||||
last_id = 1;
|
||||
|
|
@ -530,6 +445,7 @@ int yylex(void) {
|
|||
case NUM_UNSIGNED:
|
||||
case NUM_LONGLONG:
|
||||
case NUM_ULONGLONG:
|
||||
case NUM_BOOL:
|
||||
if (l == NUM_INT)
|
||||
yylval.dtype.type = T_INT;
|
||||
if (l == NUM_FLOAT)
|
||||
|
|
@ -544,6 +460,8 @@ int yylex(void) {
|
|||
yylval.dtype.type = T_LONGLONG;
|
||||
if (l == NUM_ULONGLONG)
|
||||
yylval.dtype.type = T_ULONGLONG;
|
||||
if (l == NUM_BOOL)
|
||||
yylval.dtype.type = T_BOOL;
|
||||
yylval.dtype.val = NewString(Scanner_text(scan));
|
||||
yylval.dtype.bitfield = 0;
|
||||
yylval.dtype.throws = 0;
|
||||
|
|
@ -706,7 +624,7 @@ int yylex(void) {
|
|||
break;
|
||||
} else if (nexttok == SWIG_TOKEN_CODEBLOCK) {
|
||||
termtoken = SWIG_TOKEN_CODEBLOCK;
|
||||
termvalue = Scanner_text(scan);
|
||||
termvalue = Char(Scanner_text(scan));
|
||||
break;
|
||||
} else if (nexttok == SWIG_TOKEN_LBRACE) {
|
||||
termtoken = SWIG_TOKEN_LBRACE;
|
||||
|
|
@ -716,6 +634,10 @@ int yylex(void) {
|
|||
termtoken = SWIG_TOKEN_SEMI;
|
||||
termvalue = ";";
|
||||
break;
|
||||
} else if (nexttok == SWIG_TOKEN_STRING) {
|
||||
termtoken = SWIG_TOKEN_STRING;
|
||||
termvalue = Swig_copy_string(Char(Scanner_text(scan)));
|
||||
break;
|
||||
} else if (nexttok == SWIG_TOKEN_ID) {
|
||||
if (needspace) {
|
||||
Append(s," ");
|
||||
|
|
@ -782,7 +704,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) {
|
||||
|
|
@ -824,7 +746,7 @@ int yylex(void) {
|
|||
return (SIZEOF);
|
||||
|
||||
if (strcmp(yytext, "typedef") == 0) {
|
||||
yylval.ivalue = 0;
|
||||
yylval.intvalue = 0;
|
||||
return (TYPEDEF);
|
||||
}
|
||||
|
||||
|
|
@ -855,6 +777,10 @@ int yylex(void) {
|
|||
}
|
||||
if (strcmp(yytext, "%includefile") == 0)
|
||||
return (INCLUDE);
|
||||
if (strcmp(yytext, "%beginfile") == 0)
|
||||
return (BEGINFILE);
|
||||
if (strcmp(yytext, "%endoffile") == 0)
|
||||
return (ENDOFFILE);
|
||||
if (strcmp(yytext, "%val") == 0) {
|
||||
Swig_warning(WARN_DEPRECATED_VAL, cparse_file, cparse_line, "%%val directive deprecated (ignored).\n");
|
||||
return (yylex());
|
||||
|
|
@ -866,7 +792,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)
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -19,7 +19,7 @@ char cvsroot_templ_c[] = "$Id$";
|
|||
static int template_debug = 0;
|
||||
|
||||
|
||||
String *baselists[3];
|
||||
const char *baselists[3];
|
||||
|
||||
void SwigType_template_init() {
|
||||
baselists[0] = "baselist";
|
||||
|
|
@ -266,7 +266,7 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
|
|||
/* Look for partial specialization matching */
|
||||
if (Getattr(n, "partialargs")) {
|
||||
Parm *p, *tp;
|
||||
ParmList *ptargs = SwigType_function_parms(Getattr(n, "partialargs"));
|
||||
ParmList *ptargs = SwigType_function_parms(Getattr(n, "partialargs"), n);
|
||||
p = ptargs;
|
||||
tp = tparms;
|
||||
while (p && tp) {
|
||||
|
|
@ -426,6 +426,70 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
|
|||
return 0;
|
||||
}
|
||||
|
||||
typedef enum { ExactNoMatch = -2, PartiallySpecializedNoMatch = -1, PartiallySpecializedMatch = 1, ExactMatch = 2 } EMatch;
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* does_parm_match()
|
||||
*
|
||||
* Template argument deduction - check if a template type matches a partially specialized
|
||||
* template parameter type. Typedef reduce 'partial_parm_type' to see if it matches 'type'.
|
||||
*
|
||||
* type - template parameter type to match against
|
||||
* partial_parm_type - partially specialized template type - a possible match
|
||||
* partial_parm_type_base - base type of partial_parm_type
|
||||
* tscope - template scope
|
||||
* specialization_priority - (output) contains a value indicating how good the match is
|
||||
* (higher is better) only set if return is set to PartiallySpecializedMatch or ExactMatch.
|
||||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static EMatch does_parm_match(SwigType *type, SwigType *partial_parm_type, const char *partial_parm_type_base, Symtab *tscope, int *specialization_priority) {
|
||||
static const int EXACT_MATCH_PRIORITY = 99999; /* a number bigger than the length of any conceivable type */
|
||||
int matches;
|
||||
int substitutions;
|
||||
EMatch match;
|
||||
SwigType *ty = Swig_symbol_typedef_reduce(type, tscope);
|
||||
String *base = SwigType_base(ty);
|
||||
SwigType *t = Copy(partial_parm_type);
|
||||
substitutions = Replaceid(t, partial_parm_type_base, base); /* eg: Replaceid("p.$1", "$1", "int") returns t="p.int" */
|
||||
matches = Equal(ty, t);
|
||||
*specialization_priority = -1;
|
||||
if (substitutions == 1) {
|
||||
/* we have a non-explicit specialized parameter (in partial_parm_type) because a substitution for $1, $2... etc has taken place */
|
||||
SwigType *tt = Copy(partial_parm_type);
|
||||
int len;
|
||||
/*
|
||||
check for match to partial specialization type, for example, all of the following could match the type in the %template:
|
||||
template <typename T> struct XX {};
|
||||
template <typename T> struct XX<T &> {}; // r.$1
|
||||
template <typename T> struct XX<T const&> {}; // r.q(const).$1
|
||||
template <typename T> struct XX<T *const&> {}; // r.q(const).p.$1
|
||||
%template(XXX) XX<int *const&>; // r.q(const).p.int
|
||||
|
||||
where type="r.q(const).p.int" will match either of tt="r.", tt="r.q(const)" tt="r.q(const).p"
|
||||
*/
|
||||
Replaceid(tt, partial_parm_type_base, ""); /* remove the $1, $2 etc, eg tt="p.$1" => "p." */
|
||||
len = Len(tt);
|
||||
if (Strncmp(tt, ty, len) == 0) {
|
||||
match = PartiallySpecializedMatch;
|
||||
*specialization_priority = len;
|
||||
} else {
|
||||
match = PartiallySpecializedNoMatch;
|
||||
}
|
||||
Delete(tt);
|
||||
} else {
|
||||
match = matches ? ExactMatch : ExactNoMatch;
|
||||
if (matches)
|
||||
*specialization_priority = EXACT_MATCH_PRIORITY; /* exact matches always take precedence */
|
||||
}
|
||||
/*
|
||||
Printf(stdout, " does_parm_match %2d %5d [%s] [%s]\n", match, *specialization_priority, type, partial_parm_type);
|
||||
*/
|
||||
Delete(t);
|
||||
Delete(base);
|
||||
Delete(ty);
|
||||
return match;
|
||||
}
|
||||
|
||||
/* -----------------------------------------------------------------------------
|
||||
* template_locate()
|
||||
*
|
||||
|
|
@ -433,175 +497,294 @@ int Swig_cparse_template_expand(Node *n, String *rname, ParmList *tparms, Symtab
|
|||
* ----------------------------------------------------------------------------- */
|
||||
|
||||
static Node *template_locate(String *name, Parm *tparms, Symtab *tscope) {
|
||||
Node *n;
|
||||
String *tname, *rname = 0;
|
||||
Node *n = 0;
|
||||
String *tname = 0;
|
||||
Node *templ;
|
||||
List *mpartials = 0;
|
||||
Symtab *primary_scope = 0;
|
||||
List *possiblepartials = 0;
|
||||
Parm *p;
|
||||
Parm *parms;
|
||||
Parm *parms = 0;
|
||||
Parm *targs;
|
||||
ParmList *expandedparms;
|
||||
int *priorities_matrix = 0;
|
||||
int max_possible_partials = 0;
|
||||
int posslen = 0;
|
||||
|
||||
tname = Copy(name);
|
||||
parms = CopyParmList(tparms);
|
||||
|
||||
/* Search for generic template */
|
||||
/* Search for primary (unspecialized) template */
|
||||
templ = Swig_symbol_clookup(name, 0);
|
||||
|
||||
/* Add default values from generic template */
|
||||
if (templ) {
|
||||
Symtab *tsdecl = Getattr(templ, "sym:symtab");
|
||||
if (template_debug) {
|
||||
tname = Copy(name);
|
||||
SwigType_add_template(tname, tparms);
|
||||
Printf(stdout, "\n");
|
||||
Swig_diagnostic(cparse_file, cparse_line, "template_debug: Searching for match to: '%s'\n", tname);
|
||||
Delete(tname);
|
||||
tname = 0;
|
||||
}
|
||||
|
||||
if (templ) {
|
||||
tname = Copy(name);
|
||||
parms = CopyParmList(tparms);
|
||||
|
||||
/* All template specializations must be in the primary template's scope, store the symbol table for this scope for specialization lookups */
|
||||
primary_scope = Getattr(templ, "sym:symtab");
|
||||
|
||||
/* Add default values from primary template */
|
||||
targs = Getattr(templ, "templateparms");
|
||||
expandedparms = Swig_symbol_template_defargs(parms, targs, tscope, tsdecl);
|
||||
} else {
|
||||
expandedparms = parms;
|
||||
}
|
||||
expandedparms = Swig_symbol_template_defargs(parms, targs, tscope, primary_scope);
|
||||
|
||||
|
||||
/* reduce the typedef */
|
||||
p = expandedparms;
|
||||
while (p) {
|
||||
SwigType *ty = Getattr(p, "type");
|
||||
if (ty) {
|
||||
SwigType *nt = Swig_symbol_type_qualify(ty, tscope);
|
||||
Setattr(p, "type", nt);
|
||||
Delete(nt);
|
||||
}
|
||||
p = nextSibling(p);
|
||||
}
|
||||
|
||||
SwigType_add_template(tname, expandedparms);
|
||||
|
||||
if (template_debug) {
|
||||
Printf(stdout, "\n%s:%d: template_debug: Searching for %s\n", cparse_file, cparse_line, tname);
|
||||
}
|
||||
|
||||
/* Search for an exact specialization.
|
||||
Example: template<> class name<int> { ... } */
|
||||
{
|
||||
if (template_debug) {
|
||||
Printf(stdout, " searching: '%s' (exact specialization)\n", tname);
|
||||
}
|
||||
n = Swig_symbol_clookup_local(tname, 0);
|
||||
if (!n) {
|
||||
SwigType *rname = Swig_symbol_typedef_reduce(tname, tscope);
|
||||
if (!Equal(rname, tname)) {
|
||||
if (template_debug) {
|
||||
Printf(stdout, " searching: '%s' (exact specialization)\n", rname);
|
||||
}
|
||||
n = Swig_symbol_clookup_local(rname, 0);
|
||||
/* reduce the typedef */
|
||||
p = expandedparms;
|
||||
while (p) {
|
||||
SwigType *ty = Getattr(p, "type");
|
||||
if (ty) {
|
||||
SwigType *nt = Swig_symbol_type_qualify(ty, tscope);
|
||||
Setattr(p, "type", nt);
|
||||
Delete(nt);
|
||||
}
|
||||
Delete(rname);
|
||||
p = nextSibling(p);
|
||||
}
|
||||
if (n) {
|
||||
Node *tn;
|
||||
String *nodeType = nodeType(n);
|
||||
if (Equal(nodeType, "template"))
|
||||
goto success;
|
||||
tn = Getattr(n, "template");
|
||||
if (tn) {
|
||||
n = tn;
|
||||
goto success; /* Previously wrapped by a template return that */
|
||||
SwigType_add_template(tname, expandedparms);
|
||||
|
||||
/* Search for an explicit (exact) specialization. Example: template<> class name<int> { ... } */
|
||||
{
|
||||
if (template_debug) {
|
||||
Printf(stdout, " searching for : '%s' (explicit specialization)\n", tname);
|
||||
}
|
||||
Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n));
|
||||
Delete(tname);
|
||||
Delete(parms);
|
||||
return 0; /* Found a match, but it's not a template of any kind. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Search for partial specialization.
|
||||
Example: template<typename T> class name<T *> { ... } */
|
||||
|
||||
/* Generate reduced template name (stripped of extraneous pointers, etc.) */
|
||||
|
||||
rname = NewStringf("%s<(", name);
|
||||
p = parms;
|
||||
while (p) {
|
||||
String *t;
|
||||
t = Getattr(p, "type");
|
||||
if (!t)
|
||||
t = Getattr(p, "value");
|
||||
if (t) {
|
||||
String *ty = Swig_symbol_typedef_reduce(t, tscope);
|
||||
String *tb = SwigType_base(ty);
|
||||
String *td = SwigType_default(ty);
|
||||
Replaceid(td, "enum SWIGTYPE", tb);
|
||||
Replaceid(td, "SWIGTYPE", tb);
|
||||
Append(rname, td);
|
||||
Delete(tb);
|
||||
Delete(ty);
|
||||
Delete(td);
|
||||
}
|
||||
p = nextSibling(p);
|
||||
if (p) {
|
||||
Append(rname, ",");
|
||||
}
|
||||
}
|
||||
Append(rname, ")>");
|
||||
|
||||
mpartials = NewList();
|
||||
if (templ) {
|
||||
/* First, we search using an exact type prototype */
|
||||
Parm *p;
|
||||
char tmp[32];
|
||||
int i;
|
||||
List *partials;
|
||||
String *ss;
|
||||
Iterator pi;
|
||||
|
||||
partials = Getattr(templ, "partials");
|
||||
if (partials) {
|
||||
for (pi = First(partials); pi.item; pi = Next(pi)) {
|
||||
ss = Copy(pi.item);
|
||||
p = parms;
|
||||
i = 1;
|
||||
while (p) {
|
||||
String *t, *tn;
|
||||
sprintf(tmp, "$%d", i);
|
||||
t = Getattr(p, "type");
|
||||
if (!t)
|
||||
t = Getattr(p, "value");
|
||||
if (t) {
|
||||
String *ty = Swig_symbol_typedef_reduce(t, tscope);
|
||||
tn = SwigType_base(ty);
|
||||
Replaceid(ss, tmp, tn);
|
||||
Delete(tn);
|
||||
Delete(ty);
|
||||
n = Swig_symbol_clookup_local(tname, primary_scope);
|
||||
if (!n) {
|
||||
SwigType *rname = Swig_symbol_typedef_reduce(tname, tscope);
|
||||
if (!Equal(rname, tname)) {
|
||||
if (template_debug) {
|
||||
Printf(stdout, " searching for : '%s' (explicit specialization with typedef reduction)\n", rname);
|
||||
}
|
||||
i++;
|
||||
p = nextSibling(p);
|
||||
n = Swig_symbol_clookup_local(rname, primary_scope);
|
||||
}
|
||||
if (template_debug) {
|
||||
Printf(stdout, " searching: '%s' (partial specialization - %s)\n", ss, pi.item);
|
||||
}
|
||||
if ((Equal(ss, tname)) || (Equal(ss, rname))) {
|
||||
Append(mpartials, pi.item);
|
||||
}
|
||||
Delete(ss);
|
||||
Delete(rname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (template_debug) {
|
||||
Printf(stdout, " Matched partials: %s\n", mpartials);
|
||||
}
|
||||
|
||||
if (Len(mpartials)) {
|
||||
String *s = Getitem(mpartials, 0);
|
||||
n = Swig_symbol_clookup_local(s, 0);
|
||||
if (Len(mpartials) > 1) {
|
||||
if (n) {
|
||||
Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, cparse_file, cparse_line, "Instantiation of template '%s' is ambiguous,\n", SwigType_namestr(tname));
|
||||
Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, Getfile(n), Getline(n), " instantiation '%s' is used.\n", SwigType_namestr(Getattr(n, "name")));
|
||||
Node *tn;
|
||||
String *nodeType = nodeType(n);
|
||||
if (Equal(nodeType, "template")) {
|
||||
if (template_debug) {
|
||||
Printf(stdout, " explicit specialization found: '%s'\n", Getattr(n, "name"));
|
||||
}
|
||||
goto success;
|
||||
}
|
||||
tn = Getattr(n, "template");
|
||||
if (tn) {
|
||||
if (template_debug) {
|
||||
Printf(stdout, " previous instantiation found: '%s'\n", Getattr(n, "name"));
|
||||
}
|
||||
n = tn;
|
||||
goto success; /* Previously wrapped by a template instantiation */
|
||||
}
|
||||
Swig_error(cparse_file, cparse_line, "'%s' is not defined as a template. (%s)\n", name, nodeType(n));
|
||||
Delete(tname);
|
||||
Delete(parms);
|
||||
return 0; /* Found a match, but it's not a template of any kind. */
|
||||
}
|
||||
}
|
||||
|
||||
/* Search for partial specializations.
|
||||
* Example: template<typename T> class name<T *> { ... }
|
||||
|
||||
* There are 3 types of template arguments:
|
||||
* (1) Template type arguments
|
||||
* (2) Template non type arguments
|
||||
* (3) Template template arguments
|
||||
* only (1) is really supported for partial specializations
|
||||
*/
|
||||
|
||||
/* Rank each template parameter against the desired template parameters then build a matrix of best matches */
|
||||
possiblepartials = NewList();
|
||||
{
|
||||
char tmp[32];
|
||||
List *partials;
|
||||
|
||||
partials = Getattr(templ, "partials"); /* note that these partial specializations do not include explicit specializations */
|
||||
if (partials) {
|
||||
Iterator pi;
|
||||
int parms_len = ParmList_len(parms);
|
||||
int *priorities_row;
|
||||
max_possible_partials = Len(partials);
|
||||
priorities_matrix = (int *)malloc(sizeof(int) * max_possible_partials * parms_len); /* slightly wasteful allocation for max possible matches */
|
||||
priorities_row = priorities_matrix;
|
||||
for (pi = First(partials); pi.item; pi = Next(pi)) {
|
||||
Parm *p = parms;
|
||||
int all_parameters_match = 1;
|
||||
int i = 1;
|
||||
Parm *partialparms = Getattr(pi.item, "partialparms");
|
||||
Parm *pp = partialparms;
|
||||
String *templcsymname = Getattr(pi.item, "templcsymname");
|
||||
if (template_debug) {
|
||||
Printf(stdout, " checking match: '%s' (partial specialization)\n", templcsymname);
|
||||
}
|
||||
if (ParmList_len(partialparms) == parms_len) {
|
||||
while (p && pp) {
|
||||
SwigType *t;
|
||||
sprintf(tmp, "$%d", i);
|
||||
t = Getattr(p, "type");
|
||||
if (!t)
|
||||
t = Getattr(p, "value");
|
||||
if (t) {
|
||||
EMatch match = does_parm_match(t, Getattr(pp, "type"), tmp, tscope, priorities_row + i - 1);
|
||||
if (match < (int)PartiallySpecializedMatch) {
|
||||
all_parameters_match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
p = nextSibling(p);
|
||||
pp = nextSibling(pp);
|
||||
}
|
||||
if (all_parameters_match) {
|
||||
Append(possiblepartials, pi.item);
|
||||
priorities_row += parms_len;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
posslen = Len(possiblepartials);
|
||||
if (template_debug) {
|
||||
int i;
|
||||
if (posslen == 0)
|
||||
Printf(stdout, " matched partials: NONE\n");
|
||||
else if (posslen == 1)
|
||||
Printf(stdout, " chosen partial: '%s'\n", Getattr(Getitem(possiblepartials, 0), "templcsymname"));
|
||||
else {
|
||||
Printf(stdout, " possibly matched partials:\n");
|
||||
for (i = 0; i < posslen; i++) {
|
||||
Printf(stdout, " '%s'\n", Getattr(Getitem(possiblepartials, i), "templcsymname"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (posslen > 1) {
|
||||
/* Now go through all the possibly matched partial specialization templates and look for a non-ambiguous match.
|
||||
* Exact matches rank the highest and deduced parameters are ranked by how specialized they are, eg looking for
|
||||
* a match to const int *, the following rank (highest to lowest):
|
||||
* const int * (exact match)
|
||||
* const T *
|
||||
* T *
|
||||
* T
|
||||
*
|
||||
* An ambiguous example when attempting to match as either specialization could match: %template() X<int *, double *>;
|
||||
* template<typename T1, typename T2> X class {}; // primary template
|
||||
* template<typename T1> X<T1, double *> class {}; // specialization (1)
|
||||
* template<typename T2> X<int *, T2> class {}; // specialization (2)
|
||||
*/
|
||||
if (template_debug) {
|
||||
int row, col;
|
||||
int parms_len = ParmList_len(parms);
|
||||
Printf(stdout, " parameter priorities matrix (%d parms):\n", parms_len);
|
||||
for (row = 0; row < posslen; row++) {
|
||||
int *priorities_row = priorities_matrix + row*parms_len;
|
||||
Printf(stdout, " ");
|
||||
for (col = 0; col < parms_len; col++) {
|
||||
Printf(stdout, "%5d ", priorities_row[col]);
|
||||
}
|
||||
Printf(stdout, "\n");
|
||||
}
|
||||
}
|
||||
{
|
||||
int row, col;
|
||||
int parms_len = ParmList_len(parms);
|
||||
/* Printf(stdout, " parameter priorities inverse matrix (%d parms):\n", parms_len); */
|
||||
for (col = 0; col < parms_len; col++) {
|
||||
int *priorities_col = priorities_matrix + col;
|
||||
int maxpriority = -1;
|
||||
/*
|
||||
Printf(stdout, "max_possible_partials: %d col:%d\n", max_possible_partials, col);
|
||||
Printf(stdout, " ");
|
||||
*/
|
||||
/* determine the highest rank for this nth parameter */
|
||||
for (row = 0; row < posslen; row++) {
|
||||
int *element_ptr = priorities_col + row*parms_len;
|
||||
int priority = *element_ptr;
|
||||
if (priority > maxpriority)
|
||||
maxpriority = priority;
|
||||
/* Printf(stdout, "%5d ", priority); */
|
||||
}
|
||||
/* Printf(stdout, "\n"); */
|
||||
/* flag all the parameters which equal the highest rank */
|
||||
for (row = 0; row < posslen; row++) {
|
||||
int *element_ptr = priorities_col + row*parms_len;
|
||||
int priority = *element_ptr;
|
||||
*element_ptr = (priority >= maxpriority) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
int row, col;
|
||||
int parms_len = ParmList_len(parms);
|
||||
Iterator pi = First(possiblepartials);
|
||||
Node *chosenpartials = NewList();
|
||||
if (template_debug)
|
||||
Printf(stdout, " priority flags matrix:\n");
|
||||
for (row = 0; row < posslen; row++) {
|
||||
int *priorities_row = priorities_matrix + row*parms_len;
|
||||
int highest_count = 0; /* count of highest priority parameters */
|
||||
for (col = 0; col < parms_len; col++) {
|
||||
highest_count += priorities_row[col];
|
||||
}
|
||||
if (template_debug) {
|
||||
Printf(stdout, " ");
|
||||
for (col = 0; col < parms_len; col++) {
|
||||
Printf(stdout, "%5d ", priorities_row[col]);
|
||||
}
|
||||
Printf(stdout, "\n");
|
||||
}
|
||||
if (highest_count == parms_len) {
|
||||
Append(chosenpartials, pi.item);
|
||||
}
|
||||
pi = Next(pi);
|
||||
}
|
||||
if (Len(chosenpartials) > 0) {
|
||||
/* one or more best match found */
|
||||
Delete(possiblepartials);
|
||||
possiblepartials = chosenpartials;
|
||||
posslen = Len(possiblepartials);
|
||||
} else {
|
||||
/* no best match found */
|
||||
Delete(chosenpartials);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (posslen > 0) {
|
||||
String *s = Getattr(Getitem(possiblepartials, 0), "templcsymname");
|
||||
n = Swig_symbol_clookup_local(s, primary_scope);
|
||||
if (posslen > 1) {
|
||||
int i;
|
||||
if (n) {
|
||||
Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, cparse_file, cparse_line, "Instantiation of template '%s' is ambiguous,\n", SwigType_namestr(tname));
|
||||
Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, Getfile(n), Getline(n), " instantiation '%s' used,\n", SwigType_namestr(Getattr(n, "name")));
|
||||
}
|
||||
for (i = 1; i < posslen; i++) {
|
||||
String *templcsymname = Getattr(Getitem(possiblepartials, i), "templcsymname");
|
||||
Node *ignored_node = Swig_symbol_clookup_local(templcsymname, primary_scope);
|
||||
Swig_warning(WARN_PARSE_TEMPLATE_AMBIG, Getfile(ignored_node), Getline(ignored_node), " instantiation '%s' ignored.\n", SwigType_namestr(Getattr(ignored_node, "name")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!n) {
|
||||
if (template_debug) {
|
||||
Printf(stdout, " chosen primary template: '%s'\n", Getattr(templ, "name"));
|
||||
}
|
||||
n = templ;
|
||||
}
|
||||
} else {
|
||||
if (template_debug) {
|
||||
Printf(stdout, " primary template not found\n");
|
||||
}
|
||||
/* Give up if primary (unspecialized) template not found as specializations will only exist if there is a primary template */
|
||||
n = 0;
|
||||
}
|
||||
|
||||
if (!n) {
|
||||
n = templ;
|
||||
}
|
||||
if (!n) {
|
||||
Swig_error(cparse_file, cparse_line, "Template '%s' undefined.\n", name);
|
||||
} else if (n) {
|
||||
|
|
@ -613,13 +796,16 @@ static Node *template_locate(String *name, Parm *tparms, Symtab *tscope) {
|
|||
}
|
||||
success:
|
||||
Delete(tname);
|
||||
Delete(rname);
|
||||
Delete(mpartials);
|
||||
Delete(possiblepartials);
|
||||
if ((template_debug) && (n)) {
|
||||
/*
|
||||
Printf(stdout, "Node: %p\n", n);
|
||||
Swig_print_node(n);
|
||||
*/
|
||||
Printf(stdout, " chosen template:'%s'\n", Getattr(n, "name"));
|
||||
}
|
||||
Delete(parms);
|
||||
free(priorities_matrix);
|
||||
return n;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue