(method, typelist) special variable macro fixed/enhanced and made official

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@11470 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2009-07-29 20:50:39 +00:00
commit bf0ee4471c
17 changed files with 532 additions and 161 deletions

View file

@ -2766,6 +2766,16 @@ public:
Delete(func_name);
}
/*----------------------------------------------------------------------
* replaceSpecialVariables()
*--------------------------------------------------------------------*/
virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
(void)method;
SwigType *type = Getattr(parm, "type");
substituteClassname(type, tm);
}
/*----------------------------------------------------------------------
* decodeEnumFeature()
* Decode the possible enum features, which are one of:
@ -2859,15 +2869,15 @@ public:
/* -----------------------------------------------------------------------------
* substituteClassname()
*
* Substitute $csclassname with the proxy class name for classes/structs/unions that SWIG knows about.
* Also substitutes enums with enum name.
* Substitute the special variable $csclassname with the proxy class name for classes/structs/unions
* that SWIG knows about. Also substitutes enums with enum name.
* Otherwise use the $descriptor name for the C# class name. Note that the $&csclassname substitution
* is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
* Inputs:
* pt - parameter type
* tm - cstype typemap
* tm - typemap contents that might contain the special variable to be replaced
* Outputs:
* tm - cstype typemap with $csclassname substitution
* tm - typemap contents complete with the special variable substitution
* Return:
* substitution_performed - flag indicating if a substitution was performed
* ----------------------------------------------------------------------------- */

View file

@ -2603,6 +2603,16 @@ public:
Delete(func_name);
}
/*----------------------------------------------------------------------
* replaceSpecialVariables()
*--------------------------------------------------------------------*/
virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
(void)method;
SwigType *type = Getattr(parm, "type");
substituteClassname(type, tm);
}
/*----------------------------------------------------------------------
* decodeEnumFeature()
* Decode the possible enum features, which are one of:
@ -2700,16 +2710,16 @@ public:
/* -----------------------------------------------------------------------------
* substituteClassname()
*
* Substitute $javaclassname with the proxy class name for classes/structs/unions that SWIG knows about.
* Also substitutes enums with enum name.
* Substitute the special variable $javaclassname with the proxy class name for classes/structs/unions
* that SWIG knows about. Also substitutes enums with enum name.
* Otherwise use the $descriptor name for the Java class name. Note that the $&javaclassname substitution
* is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
* Inputs:
* pt - parameter type
* tm - jstype typemap
* tm - typemap contents that might contain the special variable to be replaced
* jnidescriptor - if set, inner class names are separated with '$' otherwise a '.'
* Outputs:
* tm - jstype typemap with $javaclassname substitution
* tm - typemap contents complete with the special variable substitution
* Return:
* substitution_performed - flag indicating if a substitution was performed
* ----------------------------------------------------------------------------- */

View file

@ -18,6 +18,7 @@ static int director_mode = 0;
static int director_protected_mode = 1;
static int all_protected_mode = 0;
static int naturalvar_mode = 0;
Language* Language::this_ = 0;
/* Set director_protected_mode */
void Wrapper_director_mode_set(int flag) {
@ -46,6 +47,9 @@ extern "C" {
int Swig_all_protected_mode() {
return all_protected_mode;
}
void Language_replace_special_variables(String *method, String *tm, Parm *parm) {
Language::instance()->replaceSpecialVariables(method, tm, parm);
}
}
/* Some status variables used during parsing */
@ -323,6 +327,8 @@ directors(0) {
director_prot_ctor_code = 0;
director_multiple_inheritance = 1;
director_language = 0;
assert(!this_);
this_ = this;
}
Language::~Language() {
@ -331,6 +337,7 @@ Language::~Language() {
Delete(enumtypes);
Delete(director_ctor_code);
Delete(none_comparison);
this_ = 0;
}
/* ----------------------------------------------------------------------
@ -3423,6 +3430,24 @@ String *Language::defaultExternalRuntimeFilename() {
return 0;
}
/* -----------------------------------------------------------------------------
* Language::replaceSpecialVariables()
* Language modules should implement this if special variables are to be handled
* correctly in the $typemap(...) special variable macro.
* method - typemap method name
* tm - string containing typemap contents
* parm - a parameter describing the typemap type to be handled
* ----------------------------------------------------------------------------- */
void Language::replaceSpecialVariables(String *method, String *tm, Parm *parm) {
(void)method;
(void)tm;
(void)parm;
}
Language *Language::instance() {
return this_;
}
Hash *Language::getClassHash() const {
return classhash;
}

View file

@ -3581,17 +3581,28 @@ MODULA3():
Delete(throws_hash);
}
/*----------------------------------------------------------------------
* replaceSpecialVariables()
*--------------------------------------------------------------------*/
virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm) {
(void)method;
SwigType *type = Getattr(parm, "type");
substituteClassname(type, tm);
}
/* -----------------------------------------------------------------------------
* substituteClassname()
*
* Substitute $m3classname with the proxy class name for classes/structs/unions that SWIG knows about.
* Substitute the special variable $m3classname with the proxy class name for classes/structs/unions
* that SWIG knows about.
* Otherwise use the $descriptor name for the Modula 3 class name. Note that the $&m3classname substitution
* is the same as a $&descriptor substitution, ie one pointer added to descriptor name.
* Inputs:
* pt - parameter type
* tm - m3wraptype typemap
* tm - typemap contents that might contain the special variable to be replaced
* Outputs:
* tm - m3wraptype typemap with $m3classname substitution
* tm - typemap contents complete with the special variable substitution
* Return:
* substitution_performed - flag indicating if a substitution was performed
* ----------------------------------------------------------------------------- */

View file

@ -216,6 +216,7 @@ public:
virtual int is_assignable(Node *n); /* Is variable assignable? */
virtual String *runtimeCode(); /* returns the language specific runtime code */
virtual String *defaultExternalRuntimeFilename(); /* the default filename for the external runtime */
virtual void replaceSpecialVariables(String *method, String *tm, Parm *parm); /* Language specific special variable substitutions for $typemap() */
/* Runtime is C++ based, so extern "C" header section */
void enable_cplus_runtime_mode();
@ -250,6 +251,9 @@ public:
/* Set overload variable templates argc and argv */
void setOverloadResolutionTemplates(String *argc, String *argv);
/* Language instance is a singleton - get instance */
static Language* instance();
protected:
/* Allow multiple-input typemaps */
void allow_multiple_input(int val = 1);
@ -307,6 +311,7 @@ private:
int multiinput;
int cplus_runtime;
int directors;
static Language *this_;
};
int SWIG_main(int, char **, Language *);
@ -347,7 +352,9 @@ void Swig_director_emit_dynamic_cast(Node *n, Wrapper *f);
extern "C" {
void SWIG_typemap_lang(const char *);
typedef Language *(*ModuleFactory) (void);
} void Swig_register_module(const char *name, ModuleFactory fac);
}
void Swig_register_module(const char *name, ModuleFactory fac);
ModuleFactory Swig_find_module(const char *name);
/* Utilities */

View file

@ -85,6 +85,7 @@ void Scanner_clear(Scanner * s) {
Clear(s->text);
Clear(s->scanobjs);
Delete(s->error);
s->str = 0;
s->error = 0;
s->line = 1;
s->nexttoken = -1;

View file

@ -390,6 +390,7 @@ extern int ParmList_is_compactdefargs(ParmList *p);
extern void Wrapper_director_mode_set(int);
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);
/* -- template init -- */

View file

@ -17,7 +17,7 @@ char cvsroot_typemap_c[] = "$Id$";
#define SWIG_DEBUG
#endif
static void replace_embedded_typemap(String *s);
static void replace_embedded_typemap(String *s, String *lname, Wrapper *f);
/* -----------------------------------------------------------------------------
* Typemaps are stored in a collection of nested hash tables. Something like
@ -31,14 +31,24 @@ static void replace_embedded_typemap(String *s);
* different typemap methods. These are referenced by names such as
* "tmap:in", "tmap:out", "tmap:argout", and so forth.
*
* The object corresponding to a specific method has the following
* attributes:
* The object corresponding to a specific typemap method has the following attributes:
*
* "type" - Typemap type
* "pname" - Parameter name
* "code" - Typemap code
* "typemap" - Descriptive text describing the actual map
* "locals" - Local variables (if any)
* "kwargs" - Typemap attributes
*
* Example for a typemap method named "in":
* %typemap(in, warning="987:my warning", noblock=1) int &my_int (int tmp) "$1 = $input;"
*
* "type" - r.int
* "pname" - my_int
* "code" - $1 = $input;
* "typemap" - typemap(in) int &my_int
* "locals" - int tmp
* "kwargs" - warning="987:my typemap warning", foo=123
*
* ----------------------------------------------------------------------------- */
@ -163,7 +173,7 @@ Hash *Swig_typemap_pop_scope() {
/* -----------------------------------------------------------------------------
* Swig_typemap_register()
*
* Add a new multi-valued typemap
* Add a new multi-argument typemap
* ----------------------------------------------------------------------------- */
void Swig_typemap_register(const_String_or_char_ptr op, ParmList *parms, const_String_or_char_ptr code, ParmList *locals, ParmList *kwargs) {
@ -210,7 +220,7 @@ void Swig_typemap_register(const_String_or_char_ptr op, ParmList *parms, const_S
Delete(tm2);
}
/* For a multi-valued typemap, the typemap code and information
/* For a multi-argument typemap, the typemap code and information
is really only stored in the last argument. However, to
make this work, we perform a really neat trick using
the typemap operator name.
@ -346,7 +356,7 @@ int Swig_typemap_copy(const_String_or_char_ptr op, ParmList *srcparms, ParmList
/* -----------------------------------------------------------------------------
* Swig_typemap_clear()
*
* Delete a multi-valued typemap
* Delete a multi-argument typemap
* ----------------------------------------------------------------------------- */
void Swig_typemap_clear(const_String_or_char_ptr op, ParmList *parms) {
@ -735,7 +745,7 @@ ret_result:
/* -----------------------------------------------------------------------------
* typemap_search_multi()
*
* Search for a multi-valued typemap.
* Search for a multi-argument typemap.
* ----------------------------------------------------------------------------- */
static Hash *typemap_search_multi(const_String_or_char_ptr op, ParmList *parms, int *nmatch) {
@ -806,7 +816,7 @@ static int typemap_replace_vars(String *s, ParmList *locals, SwigType *type, Swi
SwigType *ftype;
int bare_substitution_count = 0;
Replaceall(s, "$typemap", "$TYPEMAP");
Replaceall(s, "$typemap", "$TYPEMAP"); /* workaround for $type substitution below */
ftype = SwigType_typedef_resolve_all(type);
@ -1162,8 +1172,18 @@ static void typemap_locals(DOHString * s, ParmList *l, Wrapper *f, int argnum) {
*
* Attach one or more typemaps to a node and optionally generate the typemap contents
* into the wrapper.
* op - typemap name, eg "out", "newfree"
* node - the node to attach the typemaps to
*
* Looks for a typemap matching the given type and name and attaches the typemap code
* and any typemap attributes to the provided node.
*
* The node should contain the "type" and "name" attributes for the typemap match on.
* input. The typemap code and typemap attribute values are attached onto the node
* prefixed with "tmap:". For example with op="in", the typemap code can be retrieved
* with a call to Getattr(node, "tmap:in") (this is also the string returned) and the
* "noblock" attribute can be retrieved with a call to Getattr(node, "tmap:in:noblock").
*
* op - typemap method, eg "in", "out", "newfree"
* node - the node to attach the typemap and typemap attributes to
* lname - name of variable to substitute $1, $2 etc for
* f - wrapper code to generate into if non null
* actioncode - code to generate into f before the out typemap code, unless
@ -1242,10 +1262,10 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node,
kw = Getattr(tm, "kwargs");
while (kw) {
String *value = Copy(Getattr(kw, "value"));
String *type = Getattr(kw, "type");
String *kwtype = Getattr(kw, "type");
char *ckwname = Char(Getattr(kw, "name"));
if (type) {
String *mangle = Swig_string_mangle(type);
if (kwtype) {
String *mangle = Swig_string_mangle(kwtype);
Append(value, mangle);
Delete(mangle);
}
@ -1324,7 +1344,7 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node,
if (locals && f) {
typemap_locals(s, locals, f, -1);
}
replace_embedded_typemap(s);
replace_embedded_typemap(s, NewString(lname), f);
Replace(s, "$name", pname, DOH_REPLACE_ANY);
@ -1357,11 +1377,11 @@ static String *Swig_typemap_lookup_impl(const_String_or_char_ptr op, Node *node,
/* Look for code fragments */
{
String *f;
String *fragment;
sprintf(temp, "%s:fragment", cop);
f = Getattr(node, tmop_name(temp));
if (f) {
String *fname = Copy(f);
fragment = Getattr(node, tmop_name(temp));
if (fragment) {
String *fname = Copy(fragment);
Setfile(fname, Getfile(node));
Setline(fname, Getline(node));
Swig_fragment_emit(fname);
@ -1457,13 +1477,6 @@ static void typemap_emit_code_fragments(const_String_or_char_ptr op, Parm *p) {
Delete(temp);
}
/* -----------------------------------------------------------------------------
* Swig_typemap_attach_parms()
*
* Given a parameter list, this function attaches all of the typemaps for a
* given typemap type
* ----------------------------------------------------------------------------- */
static String *typemap_get_option(Hash *tm, const_String_or_char_ptr name) {
Parm *kw = Getattr(tm, "kwargs");
while (kw) {
@ -1476,6 +1489,22 @@ static String *typemap_get_option(Hash *tm, const_String_or_char_ptr name) {
return 0;
}
/* -----------------------------------------------------------------------------
* Swig_typemap_attach_parms()
*
* Given a parameter list, this function attaches all of the typemaps and typemap
* attributes to the parameter for each type in the parameter list.
*
* This function basically provides the typemap code and typemap attribute values as
* attributes on each parameter prefixed with "tmap:". For example with op="in", the typemap
* code can be retrieved for the first parameter with a call to Getattr(parm, "tmap:in")
* and the "numinputs" attribute can be retrieved with a call to Getattr(parm, "tmap:in:numinputs").
*
* op - typemap method, eg "in", "out", "newfree"
* parms - parameter list to attach each typemap and all typemap attributes
* f - wrapper code to generate into if non null
* ----------------------------------------------------------------------------- */
void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wrapper *f) {
Parm *p, *firstp;
Hash *tm;
@ -1614,7 +1643,7 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra
typemap_locals(s, locals, f, argnum);
}
replace_embedded_typemap(s);
replace_embedded_typemap(s, Getattr(firstp, "lname"), f);
/* Replace the argument number */
sprintf(temp, "%d", argnum);
@ -1659,23 +1688,8 @@ void Swig_typemap_attach_parms(const_String_or_char_ptr op, ParmList *parms, Wra
}
/* -----------------------------------------------------------------------------
* split_embedded()
*
* This function replaces the special variable $typemap(....) with typemap
* code. The general form of $typemap is as follows:
*
* $TYPEMAP(method, $var1=value, $var2=value, $var3=value,...)
*
* For example:
*
* $TYPEMAP(in, $1=int x, $input=y, ...)
*
* Note: this was added as an experiment and could be removed
* ----------------------------------------------------------------------------- */
/* Splits the arguments of an embedded typemap */
static List *split_embedded(String *s) {
static List *split_embedded_typemap(String *s) {
List *args = 0;
char *c, *start;
int level = 0;
@ -1683,6 +1697,7 @@ static List *split_embedded(String *s) {
args = NewList();
c = strchr(Char(s), '(');
assert(c);
c++;
start = c;
@ -1723,41 +1738,36 @@ static List *split_embedded(String *s) {
return args;
}
static void split_var(String *s, String **name, String **value) {
char *eq;
char *c;
/* -----------------------------------------------------------------------------
* replace_embedded_typemap()
*
* This function replaces the special variable macro $typemap(...) with typemap
* code. The general form of $typemap is as follows:
*
* $typemap(method, typelist, var1=value, var2=value, ...)
*
* where varx parameters are optional and undocumented; they were used in an earlier version of $typemap.
* A search is made using the typemap matching rules of form:
*
* %typemap(method) typelist {...}
*
* and if found will substitute in the typemap contents, making appropriate variable replacements.
*
* For example:
* $typemap(in, int) # simple usage matching %typemap(in) int { ... }
* $typemap(in, int b) # simple usage matching %typemap(in) int b { ... } or above %typemap
* $typemap(in, (Foo<int, bool> a, int b)) # multi-argument typemap matching %typemap(in) (Foo<int, bool> a, int b) {...}
* ----------------------------------------------------------------------------- */
eq = strchr(Char(s), '=');
if (!eq) {
*name = 0;
*value = 0;
return;
}
c = Char(s);
*name = NewStringWithSize(c, eq - c);
/* Look for $n variables */
if (isdigit((int) *(c))) {
/* Parse the value as a type */
String *v;
Parm *p;
v = NewString(eq + 1);
p = Swig_cparse_parm(v);
Delete(v);
*value = p;
} else {
*value = NewString(eq + 1);
}
}
static void replace_embedded_typemap(String *s) {
static void replace_embedded_typemap(String *s, String *lname, Wrapper *f) {
char *start = 0;
while ((start = strstr(Char(s), "$TYPEMAP("))) {
while ((start = strstr(Char(s), "$TYPEMAP("))) { /* note $typemap capitalisation to $TYPEMAP hack */
/* Gather the argument */
/* Gather the parameters */
char *end = 0, *c;
int level = 0;
String *tmp;
String *dollar_typemap;
int syntax_error = 1;
c = start;
while (*c) {
if (*c == '(')
@ -1772,103 +1782,119 @@ static void replace_embedded_typemap(String *s) {
c++;
}
if (end) {
tmp = NewStringWithSize(start, (end - start));
dollar_typemap = NewStringWithSize(start, (end - start));
syntax_error = 0;
} else {
tmp = 0;
dollar_typemap = NewStringWithSize(start, (c - start));
}
/* Got a substitution. Split it apart into pieces */
if (tmp) {
if (!syntax_error) {
List *l;
String *op;
Hash *vars;
String *method;
int i, ilen;
syntax_error = 1;
l = split_embedded(tmp);
vars = NewHash();
ilen = Len(l);
for (i = 1; i < ilen; i++) {
String *n, *v;
split_var(Getitem(l, i), &n, &v);
if (n && v) {
Insert(n, 0, "$");
Setattr(vars, n, v);
}
Delete(n);
Delete(v);
}
/* Split apart each parameter in $typemap(...) */
l = split_embedded_typemap(dollar_typemap);
method = Getitem(l, 0);
/* Generate the parameter list for matching typemaps */
if (Len(l) >= 2) {
ParmList *to_match_parms;
op = Getitem(l, 0);
{
Parm *p = 0;
Parm *first = 0;
char temp[32];
int n = 1;
while (1) {
Hash *v;
sprintf(temp, "$%d", n);
v = Getattr(vars, temp);
if (v) {
if (p) {
set_nextSibling(p, v);
set_previousSibling(v, p);
}
p = v;
Setattr(p, "lname", Getattr(p, "name"));
if (Getattr(p, "value")) {
Setattr(p, "name", Getattr(p, "value"));
}
if (!first)
first = p;
DohIncref(p);
Delattr(vars, temp);
} else {
break;
/* the second parameter might contain multiple sub-parameters for multi-argument
* typemap matching, so split these parameters apart */
to_match_parms = Swig_cparse_parms(Getitem(l, 1));
if (to_match_parms) {
Parm *p = to_match_parms;;
while (p) {
Setattr(p, "lname", lname);
p = nextSibling(p);
}
n++;
}
/* process optional extra parameters - the variable replacements (undocumented) */
vars = NewHash();
{
int i, ilen;
ilen = Len(l);
for (i = 2; i < ilen; i++) {
String *parm = Getitem(l, i);
char *eq = strchr(Char(parm), '=');
char *c = Char(parm);
if (eq && (eq - c > 0)) {
String *name = NewStringWithSize(c, eq - c);
String *value = NewString(eq + 1);
Insert(name, 0, "$");
Setattr(vars, name, value);
} else {
to_match_parms = 0; /* error - variable replacement parameters must be of form varname=value */
}
}
}
/* Perform a typemap search */
if (first) {
if (to_match_parms) {
static int already_substituting = 0;
String *tm;
String *attr;
int match = 0;
#ifdef SWIG_DEBUG
Printf(stdout, "Swig_typemap_attach_parms: embedded\n");
#endif
Swig_typemap_attach_parms(method, first, 0);
{
String *tm;
int match = 0;
char attr[64];
sprintf(attr, "tmap:%s", Char(method));
if (!already_substituting) {
already_substituting = 1;
Swig_typemap_attach_parms(op, to_match_parms, f);
already_substituting = 0;
/* Look for the typemap code */
tm = Getattr(first, attr);
attr = NewStringf("tmap:%s", op);
tm = Getattr(to_match_parms, attr);
if (tm) {
sprintf(attr, "tmap:%s:next", Char(method));
if (!Getattr(first, attr)) {
/* Should be no more matches. Hack??? */
/* Replace all of the remaining variables */
Printf(attr, "%s", ":next");
/* fail if multi-argument lookup requested in $typemap(...) and the lookup failed */
if (!Getattr(to_match_parms, attr)) {
/* Replace parameter variables */
Iterator ki;
for (ki = First(vars); ki.key; ki = Next(ki)) {
Replace(tm, ki.key, ki.item, DOH_REPLACE_ANY);
}
/* Do the replacement */
Replace(s, tmp, tm, DOH_REPLACE_ANY);
/* offer the target language module the chance to make special variable substitutions */
Language_replace_special_variables(op, tm, to_match_parms);
/* finish up - do the substitution */
Replace(s, dollar_typemap, tm, DOH_REPLACE_ANY);
Delete(tm);
match = 1;
}
}
if (!match) {
Swig_error(Getfile(s), Getline(s), "No typemap found for %s\n", tmp);
String *dtypemap = NewString(dollar_typemap);
Replaceall(dtypemap, "$TYPEMAP", "$typemap");
Swig_error(Getfile(s), Getline(s), "No typemap found for %s\n", dtypemap);
Delete(dtypemap);
}
Delete(attr);
} else {
/* simple recursive call check, but prevents using an embedded typemap that contains another embedded typemap */
String *dtypemap = NewString(dollar_typemap);
Replaceall(dtypemap, "$TYPEMAP", "$typemap");
Swig_error(Getfile(s), Getline(s), "Recursive $typemap calls not supported - %s\n", dtypemap);
Delete(dtypemap);
}
syntax_error = 0;
}
Delete(vars);
}
Replace(s, tmp, "<embedded typemap>", DOH_REPLACE_ANY);
Delete(vars);
Delete(tmp);
Delete(l);
}
if (syntax_error) {
String *dtypemap = NewString(dollar_typemap);
Replaceall(dtypemap, "$TYPEMAP", "$typemap");
Swig_error(Getfile(s), Getline(s), "Syntax error in: %s\n", dtypemap);
Delete(dtypemap);
}
Replace(s, dollar_typemap, "<error in embedded typemap>", DOH_REPLACE_ANY);
Delete(dollar_typemap);
}
}