From b17a77c6ea34cb022d1206111bd7e40d7b292ce2 Mon Sep 17 00:00:00 2001 From: William S Fulton Date: Thu, 11 Oct 2012 19:28:02 +0000 Subject: [PATCH] Support special variable expansion in %extend. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@13871 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- CHANGES.current | 15 ++++-- Doc/Manual/Customization.html | 5 ++ Doc/Manual/SWIGPlus.html | 6 +++ Examples/test-suite/common.mk | 1 + .../test-suite/extend_special_variables.i | 21 ++++++++ .../java/extend_special_variables_runme.java | 25 +++++++++ Source/Modules/emit.cxx | 32 +----------- Source/Swig/cwrap.c | 51 +++++++++++++++++-- Source/Swig/swig.h | 1 + 9 files changed, 117 insertions(+), 40 deletions(-) create mode 100644 Examples/test-suite/extend_special_variables.i create mode 100644 Examples/test-suite/java/extend_special_variables_runme.java diff --git a/CHANGES.current b/CHANGES.current index 08603bd5d..fac0897cb 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -4,16 +4,21 @@ See the RELEASENOTES file for a summary of changes in each release. Version 2.0.9 (in progress) =========================== +2012-10-11: wsfulton + Most of the special variables available for use in %exception are now also available for expansion in + %extend blocks. These are: $name $symname $overname $decl $fulldecl $parentname $parentsymname, see docs + on "Class extension" in SWIGPlus.html. Patch based on submission from Kris Thielemans. + +2012-10-10: wsfulton + Additional new special variables in %exception are expanded as follows: + $parentname - The parent class name (if any) for a method. + $parentsymname - The target language parent class name (if any) for a method. + 2012-10-08: iant [Go] Generating Go code now requires using the -intgosize option to indicate the size of the 'int' type in Go. This is because the size of the type is changing from Go 1.0 to Go 1.1 for x86_64. -2012-09-14: wsfulton - Additional new special variables in %exception are expanded as follows: - $parentname - The parent class name (if any) for a method. - $parentsymname - The target language parent class name (if any) for a method. - 2012-09-14: wsfulton Add new warning if the empty template instantiation is used as a base class, for example: diff --git a/Doc/Manual/Customization.html b/Doc/Manual/Customization.html index c903f24fa..b75eda9c4 100644 --- a/Doc/Manual/Customization.html +++ b/Doc/Manual/Customization.html @@ -454,6 +454,11 @@ variables are replaced with. The actual operation to be performed (a function call, method invocation, variable access, etc.) + +$name +The C/C++ symbol name for the function. + + $symname The symbol name used internally by SWIG diff --git a/Doc/Manual/SWIGPlus.html b/Doc/Manual/SWIGPlus.html index 9ecf0aa5a..716882f53 100644 --- a/Doc/Manual/SWIGPlus.html +++ b/Doc/Manual/SWIGPlus.html @@ -2838,6 +2838,12 @@ struct Derived : Base { } +

+The following special variables are expanded if used within a %extend block: +$name, $symname, $overname, $decl, $fulldecl, $parentname and $parentsymname. +The Special variables section provides more information each of these special variables. +

+

The %extend directive follows all of the same conventions as its use with C structures. Please refer to the Adding member functions to C structures diff --git a/Examples/test-suite/common.mk b/Examples/test-suite/common.mk index eaef4980b..bf318d304 100644 --- a/Examples/test-suite/common.mk +++ b/Examples/test-suite/common.mk @@ -204,6 +204,7 @@ CPP_TEST_CASES += \ extend_constructor_destructor \ extend_default \ extend_placement \ + extend_special_variables \ extend_template \ extend_template_ns \ extend_typedef_class \ diff --git a/Examples/test-suite/extend_special_variables.i b/Examples/test-suite/extend_special_variables.i new file mode 100644 index 000000000..dd68e7531 --- /dev/null +++ b/Examples/test-suite/extend_special_variables.i @@ -0,0 +1,21 @@ +%module extend_special_variables + +%rename(ForExtensionNewName) ForExtension; +%rename(extended_renamed) ForExtension::extended; + +%extend ForExtension { + ForExtension() { + return new ForExtension(); + } + const char* extended() { + return "name:$name symname:$symname wrapname:$wrapname overname:$overname decl:$decl fulldecl:$fulldecl parentclasssymname:$parentclasssymname parentclassname:$parentclassname"; + } + const char* extended(int) { + return "name:$name symname:$symname wrapname:$wrapname overname:$overname decl:$decl fulldecl:$fulldecl parentclasssymname:$parentclasssymname parentclassname:$parentclassname"; + } +} + +%inline %{ +struct ForExtension { +}; +%} diff --git a/Examples/test-suite/java/extend_special_variables_runme.java b/Examples/test-suite/java/extend_special_variables_runme.java new file mode 100644 index 000000000..cf2304e6a --- /dev/null +++ b/Examples/test-suite/java/extend_special_variables_runme.java @@ -0,0 +1,25 @@ + +import extend_special_variables.*; + +public class extend_special_variables_runme { + + static { + try { + System.loadLibrary("extend_special_variables"); + } catch (UnsatisfiedLinkError e) { + System.err.println("Native code library failed to load. See the chapter on Dynamic Linking Problems in the SWIG Java documentation for help.\n" + e); + System.exit(1); + } + } + + public static void main(String argv[]) + { + ForExtensionNewName f = new ForExtensionNewName(); + verify(f.extended_renamed(), "name:extended symname:extended_renamed wrapname: overname:__SWIG_0 decl:ForExtension::extended() fulldecl:char const * ForExtension::extended() parentclasssymname:ForExtensionNewName parentclassname:ForExtension"); + verify(f.extended_renamed(10), "name:extended symname:extended_renamed wrapname: overname:__SWIG_1 decl:ForExtension::extended(int) fulldecl:char const * ForExtension::extended(int) parentclasssymname:ForExtensionNewName parentclassname:ForExtension"); + } + static void verify(String received, String expected) { + if (!received.equals(expected)) + throw new RuntimeException("Incorrect, received: " + received); + } +} diff --git a/Source/Modules/emit.cxx b/Source/Modules/emit.cxx index 5c81a17cd..c16eaac0f 100644 --- a/Source/Modules/emit.cxx +++ b/Source/Modules/emit.cxx @@ -363,39 +363,9 @@ int emit_action_code(Node *n, String *wrappercode, String *eaction) { tm = Copy(tm); if ((tm) && Len(tm) && (Strcmp(tm, "1") != 0)) { if (Strstr(tm, "$")) { - Replaceall(tm, "$name", Getattr(n, "name")); - Replaceall(tm, "$symname", Getattr(n, "sym:name")); + Swig_replace_special_variables(n, parentNode(n), tm); Replaceall(tm, "$function", eaction); // deprecated Replaceall(tm, "$action", eaction); - Replaceall(tm, "$wrapname", Getattr(n, "wrap:name")); - String *overloaded = Getattr(n, "sym:overloaded"); - Replaceall(tm, "$overname", overloaded ? Char(Getattr(n, "sym:overname")) : ""); - - if (Strstr(tm, "$decl")) { - String *decl = Swig_name_decl(n); - Replaceall(tm, "$decl", decl); - Delete(decl); - } - if (Strstr(tm, "$fulldecl")) { - String *fulldecl = Swig_name_fulldecl(n); - Replaceall(tm, "$fulldecl", fulldecl); - Delete(fulldecl); - } - - Node *parentnode = parentNode(n); - Node *parentclass = (parentnode && Equal(nodeType(parentnode), "class")) ? parentnode : 0; - if (Strstr(tm, "$parentclasssymname")) { - String *parentclasssymname = 0; - if (parentclass) - parentclasssymname = Getattr(parentclass, "sym:name"); - Replaceall(tm, "$parentclasssymname", parentclasssymname ? parentclasssymname : ""); - } - if (Strstr(tm, "$parentclassname")) { - String *parentclassname = 0; - if (parentclass) - parentclassname = Getattr(parentclass, "name"); - Replaceall(tm, "$parentclassname", parentclassname ? parentclassname : ""); - } } Printv(wrappercode, tm, "\n", NIL); Delete(tm); diff --git a/Source/Swig/cwrap.c b/Source/Swig/cwrap.c index 5e2e6367d..a032de746 100644 --- a/Source/Swig/cwrap.c +++ b/Source/Swig/cwrap.c @@ -759,6 +759,46 @@ String *Swig_cmemberget_call(const_String_or_char_ptr name, SwigType *t, String return func; } +/* ----------------------------------------------------------------------------- + * Swig_replace_special_variables() + * + * Replaces special variables with a value from the supplied node + * ----------------------------------------------------------------------------- */ +void Swig_replace_special_variables(Node *n, Node *parentnode, String *code) { + Node *parentclass = parentnode; + String *overloaded = Getattr(n, "sym:overloaded"); + Replaceall(code, "$name", Getattr(n, "name")); + Replaceall(code, "$symname", Getattr(n, "sym:name")); + Replaceall(code, "$wrapname", Getattr(n, "wrap:name")); + Replaceall(code, "$overname", overloaded ? Char(Getattr(n, "sym:overname")) : ""); + + if (Strstr(code, "$decl")) { + String *decl = Swig_name_decl(n); + Replaceall(code, "$decl", decl); + Delete(decl); + } + if (Strstr(code, "$fulldecl")) { + String *fulldecl = Swig_name_fulldecl(n); + Replaceall(code, "$fulldecl", fulldecl); + Delete(fulldecl); + } + + if (parentclass && !Equal(nodeType(parentclass), "class")) + parentclass = 0; + if (Strstr(code, "$parentclasssymname")) { + String *parentclasssymname = 0; + if (parentclass) + parentclasssymname = Getattr(parentclass, "sym:name"); + Replaceall(code, "$parentclasssymname", parentclasssymname ? parentclasssymname : ""); + } + if (Strstr(code, "$parentclassname")) { + String *parentclassname = 0; + if (parentclass) + parentclassname = Getattr(parentclass, "name"); + Replaceall(code, "$parentclassname", parentclassname ? parentclassname : ""); + } +} + /* ----------------------------------------------------------------------------- * extension_code() * @@ -767,14 +807,17 @@ String *Swig_cmemberget_call(const_String_or_char_ptr name, SwigType *t, String * return_type function_name(parms) code * * ----------------------------------------------------------------------------- */ -static String *extension_code(const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self) { +static String *extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self) { String *parms_str = cplusplus ? ParmList_str_defaultargs(parms) : ParmList_str(parms); String *sig = NewStringf("%s(%s)", function_name, parms_str); String *rt_sig = SwigType_str(return_type, sig); String *body = NewStringf("SWIGINTERN %s", rt_sig); Printv(body, code, "\n", NIL); - if (self) - Replaceall(body, "$self", self); + if (Strstr(body, "$")) { + Swig_replace_special_variables(n, parentNode(parentNode(n)), body); + if (self) + Replaceall(body, "$self", self); + } Delete(parms_str); Delete(sig); Delete(rt_sig); @@ -791,7 +834,7 @@ static String *extension_code(const String *function_name, ParmList *parms, Swig * * ----------------------------------------------------------------------------- */ int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self) { - String *body = extension_code(function_name, parms, return_type, code, cplusplus, self); + String *body = extension_code(n, function_name, parms, return_type, code, cplusplus, self); Setattr(n, "wrap:code", body); Delete(body); return SWIG_OK; diff --git a/Source/Swig/swig.h b/Source/Swig/swig.h index a85334e55..42fd9238e 100644 --- a/Source/Swig/swig.h +++ b/Source/Swig/swig.h @@ -354,6 +354,7 @@ extern int ParmList_is_compactdefargs(ParmList *p); extern String *Swig_cmemberget_call(const_String_or_char_ptr name, SwigType *t, String *self, int varcref); extern int Swig_add_extension_code(Node *n, const String *function_name, ParmList *parms, SwigType *return_type, const String *code, int cplusplus, const String *self); + extern void Swig_replace_special_variables(Node *n, Node *parentnode, String *code); /* --- Transformations --- */