mirror of https://github.com/swig/swig
Add support for "[not]regexmatch" and "regextarget" to %rename.
"regexmatch" and "notregexmatch" can be used with anonymous %renames in the same way as "match" and "notmatch" while "regextarget" specifies that the argument of a non-anonymous %rename should be interpreted as a regular expression. Document the new functions. Also add a new unit test for %regex also testing regexmatch &c and provide test code for C# and Java verifying that it works as intended. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12174 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
48a2e0bdea
commit
70c5bb5a47
|
@ -9,6 +9,24 @@ Version 2.0.1 (in progress)
|
|||
Fix wrapping of function pointers and member function pointers when the function
|
||||
returns by reference.
|
||||
|
||||
2010-07-13: vadz
|
||||
Add "regexmatch", "regextarget" and "notregexmatch" which can be
|
||||
used to apply %rename directives to the declarations matching the
|
||||
specified regular expression only. The first two can be used
|
||||
interchangeably, both of the %renames below do the same thing:
|
||||
|
||||
%rename("$ignore", regexmatch$name="Old$") "";
|
||||
%rename("$ignore", regextarget=1) "Old$";
|
||||
|
||||
(namely ignore the declarations having "Old" suffix).
|
||||
|
||||
"notregexmatch" restricts the match to only the declarations which
|
||||
do not match the regular expression, e.g. here is how to rename to
|
||||
lower case versions all declarations except those consisting from
|
||||
capital letters only:
|
||||
|
||||
%rename("$(lower)s", notregexmatch$name="^[A-Z]+$") "";
|
||||
|
||||
2010-07-13: vadz
|
||||
Add the new "regex" encoder that can be used in %rename, e.g.
|
||||
|
||||
|
|
|
@ -1949,10 +1949,12 @@ can be used to achieve the same effect as the simpler
|
|||
</pre>
|
||||
</div>
|
||||
<p>
|
||||
However <tt>match</tt> can also be applied to the declaration type, for
|
||||
example <tt>match="class"</tt> restricts the match to class declarations only
|
||||
(in C++) and <tt>match="enumitem"</tt> restricts it to the enum elements. SWIG
|
||||
also provides convenience macros for such match expressions, for example
|
||||
and so is not very interesting on its own. However <tt>match</tt> can also be
|
||||
applied to the declaration type, for example <tt>match="class"</tt> restricts
|
||||
the match to class declarations only (in C++) and <tt>match="enumitem"</tt>
|
||||
restricts it to the enum elements. SWIG also provides convenience macros for
|
||||
such match expressions, for example
|
||||
</p>
|
||||
<div class="code">
|
||||
<pre>
|
||||
%rename("%(title)s", %$isenumitem) "";
|
||||
|
@ -1983,7 +1985,40 @@ to rename all enums nested in the given class to lower case.
|
|||
</p>
|
||||
|
||||
<p>
|
||||
Finally, even more powerful variants of <tt>%rename</tt> and <tt>%ignore</tt> directives can be used to help
|
||||
And in addition to literally matching some string with <tt>match</tt> you can
|
||||
also use <tt>regexmatch</tt> or <tt>notregexmatch</tt>to match a string
|
||||
against a regular expression. For example, to ignore all functions having
|
||||
"Old" suffix you could use
|
||||
</p>
|
||||
<div class="code">
|
||||
<pre>
|
||||
%rename("$ignore", regexmatch$name="Old$") "";
|
||||
</pre>
|
||||
</div>
|
||||
<p>
|
||||
For simple cases like this, specifying the regular expression for the
|
||||
declaration name directly can be preferable and can be done using
|
||||
<tt>regextarget</tt>:
|
||||
</p>
|
||||
<div class="code">
|
||||
<pre>
|
||||
%rename("$ignore", regextarget=1) "Old$";
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
As for <tt>notregexmatch</tt>, it restricts the match only to the strings not
|
||||
matching the specified regular expression. So to rename to lower case versions
|
||||
all declarations except those consisting from capital letters only:
|
||||
</p>
|
||||
<div class="code">
|
||||
<pre>
|
||||
%rename("$(lower)s", notregexmatch$name="^[A-Z]+$") "";
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
Finally, variants of <tt>%rename</tt> and <tt>%ignore</tt> directives can be used to help
|
||||
wrap C++ overloaded functions and methods or C++ methods which use default arguments. This is described in the
|
||||
<a href="SWIGPlus.html#SWIGPlus_ambiguity_resolution_renaming">Ambiguity resolution and renaming</a> section in the C++ chapter.
|
||||
</p>
|
||||
|
|
|
@ -285,6 +285,7 @@ CPP_TEST_CASES += \
|
|||
rename_scope \
|
||||
rename_strip_encoder \
|
||||
rename_pcre_encoder \
|
||||
rename_pcre_enum \
|
||||
restrict_cplusplus \
|
||||
return_const_value \
|
||||
return_value_scope \
|
||||
|
|
|
@ -0,0 +1,24 @@
|
|||
using System;
|
||||
using rename_pcre_enumNamespace;
|
||||
|
||||
public class runme {
|
||||
static void Main() {
|
||||
Foo foo = Foo.First;
|
||||
if ( foo == Foo.Second )
|
||||
throw new Exception("Enum values should be different");
|
||||
|
||||
// Check that Foo_Max enum element was ignored.
|
||||
int numFooEnumElements = Enum.GetValues(typeof(Foo)).Length;
|
||||
if ( numFooEnumElements != 2 )
|
||||
throw new Exception(String.Format("Enum should have 2 elements, not {0}",
|
||||
numFooEnumElements));
|
||||
|
||||
BoundaryCondition bc = BoundaryCondition.MaxMax;
|
||||
if ( (int)bc != 2 )
|
||||
throw new Exception("Wrong enum value");
|
||||
|
||||
Colour c = Colour.red;
|
||||
if ( c == Colour.blue )
|
||||
throw new Exception("Enum values should be different");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
import rename_pcre_enum.*;
|
||||
|
||||
public class rename_pcre_enum_runme {
|
||||
static { System.loadLibrary("rename_pcre_enum"); }
|
||||
|
||||
public static void main(String argv[])
|
||||
{
|
||||
Foo foo = Foo.First;
|
||||
if ( foo == Foo.Second )
|
||||
throw new RuntimeException("Enum values should be different");
|
||||
|
||||
// Check that Foo_Max enum element was ignored.
|
||||
int numFooEnumElements = Foo.values().length;
|
||||
if ( numFooEnumElements != 2 )
|
||||
throw new RuntimeException(String.format("Enum should have 2 elements, not %d",
|
||||
numFooEnumElements));
|
||||
|
||||
BoundaryCondition bc = BoundaryCondition.MaxMax;
|
||||
if ( bc.ordinal() != 2 )
|
||||
throw new RuntimeException("Wrong enum value");
|
||||
|
||||
Colour c = Colour.red;
|
||||
if ( c == Colour.blue )
|
||||
throw new RuntimeException("Enum values should be different");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
%module rename_pcre_enum
|
||||
|
||||
// This file is needed for proper enum support in C#/Java backends
|
||||
#if defined(SWIGCSHARP) || defined(SWIGJAVA)
|
||||
%include "enums.swg"
|
||||
#endif
|
||||
|
||||
// Apply a rule for renaming the enum elements to avoid the common prefixes
|
||||
// redundant in C#/Java
|
||||
%rename("%(regex:/([A-Z][a-z]+)+_(.*)/\\2/)s",%$isenumitem) "";
|
||||
|
||||
// Also don't export special end of enum markers which are often used in C++
|
||||
// code to just have a symbolic name for the number of enum elements but are
|
||||
// not needed in target language.
|
||||
%rename("$ignore", regexmatch$name="([A-Z][a-z]+)+_Max$",%$isenumitem) "";
|
||||
|
||||
// Test another way of doing the same thing with regextarget:
|
||||
%rename("$ignore", %$isenumitem, regextarget=1) "([A-Z][a-z]+)+_Internal$";
|
||||
|
||||
// Apply this renaming rule to all enum elements that don't contain more than
|
||||
// one capital letter.
|
||||
%rename("%(lower)s", notregexmatch$name="[A-Z]\\w*[A-Z]", %$isenumitem) "";
|
||||
|
||||
%inline %{
|
||||
|
||||
// Foo_Internal and Foo_Max won't be exported.
|
||||
enum Foo {
|
||||
Foo_Internal = -1,
|
||||
Foo_First,
|
||||
Foo_Second,
|
||||
Foo_Max
|
||||
};
|
||||
|
||||
// All elements of this enum will be exported because they do not match the
|
||||
// excluding regex.
|
||||
enum BoundaryCondition {
|
||||
BoundaryCondition_MinMax,
|
||||
BoundaryCondition_MaxMin,
|
||||
BoundaryCondition_MaxMax
|
||||
};
|
||||
|
||||
// The elements of this enum will have lower-case names.
|
||||
enum Colour {
|
||||
Red,
|
||||
Blue,
|
||||
Green
|
||||
};
|
||||
|
||||
%}
|
|
@ -1062,10 +1062,13 @@ static void Swig_name_object_attach_keys(const char *keys[], Hash *nameobj) {
|
|||
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 = isrxsmatch = (strncmp(ckey, "notrxsmatch", 11) == 0))
|
||||
|| (isnotmatch = isregexmatch = (strncmp(ckey, "notregexmatch", 13) == 0))) {
|
||||
Hash *mi = NewHash();
|
||||
List *attrlist = Swig_make_attrlist(ckey);
|
||||
if (!matchlist)
|
||||
|
@ -1080,6 +1083,8 @@ static void Swig_name_object_attach_keys(const char *keys[], Hash *nameobj) {
|
|||
SetFlag(mi, "notmatch");
|
||||
if (isrxsmatch)
|
||||
SetFlag(mi, "rxsmatch");
|
||||
if (isregexmatch)
|
||||
SetFlag(mi, "regexmatch");
|
||||
Delete(attrlist);
|
||||
Append(matchlist, mi);
|
||||
Delete(mi);
|
||||
|
@ -1155,6 +1160,51 @@ static DOH *Swig_get_lattr(Node *n, List *lattr) {
|
|||
return res;
|
||||
}
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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 /* !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 /* HAVE_PCRE/!HAVE_PCRE */
|
||||
|
||||
#if defined(HAVE_RXSPENCER)
|
||||
#include <sys/types.h>
|
||||
#include <rxspencer/regex.h>
|
||||
|
@ -1228,6 +1278,7 @@ int Swig_name_match_nameobj(Hash *rn, Node *n) {
|
|||
String *nval = Swig_get_lattr(n, lattr);
|
||||
int notmatch = GetFlag(mi, "notmatch");
|
||||
int rxsmatch = GetFlag(mi, "rxsmatch");
|
||||
int regexmatch = GetFlag(mi, "regexmatch");
|
||||
#ifdef SWIG_DEBUG
|
||||
Printf(stdout, "mi %d %s re %d not %d \n", i, nval, notmatch, rxsmatch);
|
||||
if (rxsmatch) {
|
||||
|
@ -1238,6 +1289,7 @@ int Swig_name_match_nameobj(Hash *rn, Node *n) {
|
|||
if (nval) {
|
||||
String *kwval = Getattr(mi, "value");
|
||||
match = rxsmatch ? Swig_name_rxsmatch_value(kwval, nval)
|
||||
: 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);
|
||||
|
@ -1278,6 +1330,7 @@ Hash *Swig_name_nameobj_lget(List *namelist, Node *n, String *prefix, String *na
|
|||
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,7 +1347,9 @@ 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 = rxstarget ? Swig_name_rxsmatch_value(tname, sname)
|
||||
: regextarget ? Swig_name_regexmatch_value(n, tname, sname)
|
||||
: Swig_name_match_value(tname, sname);
|
||||
Delete(sname);
|
||||
} else {
|
||||
match = 1;
|
||||
|
@ -1393,7 +1448,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", "rxstarget", "regextarget", 0 };
|
||||
Swig_name_object_attach_keys(rename_keys, newname);
|
||||
|
||||
/* Add the name */
|
||||
|
|
Loading…
Reference in New Issue