add initial regexp support based on the coptional rxspencer library. Active it using --with-rxspencer after installing the rxspencer library

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@8470 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Marcelo Matus 2006-01-17 00:32:21 +00:00
commit 33643d2273
7 changed files with 347 additions and 48 deletions

View file

@ -1,6 +1,85 @@
Version 1.3.28 (unreleased).
===========================
01/16/2006: mmatus
Add initial support for regexp via the external library
RxSpencer. SWIG doesn't require this library to compile
and/or run. But if you specify --with-rxspencer, and the
library is found during installation, then swig will use
it in three places:
- In %renames rules, via the new rxsmatch rules, for example:
%rename("%(lowercase)",rxsmatch$name="GSL_.*") "";
%rename("%(lowercase)",rxsmatch$nodeType="enum GSL_.*") "";
rxsmatch is similar to the match rule, it just uses
the RxSpencer regexp library to decide if there is a
match with the provided regexp. As with the match
rule, you can also use the negate rule notrxsmatch.
- In the %rename target name via the rxstarget option, for example:
%rename("%(lowercase)",rxstarget=1) "GSL_.*";
where the target name "GSL.*" is now understood as a
regexp to be matched.
- In the new encoder "rxspencer", which looks like:
%(rxspencer:[regexp][replace])s
where "regexp" is the regular expression and "replace"
is a string used as a replacement, where the @0,@1,...,@9
pseudo arguments are used to represent the
corresponding matching items in the reg expression.
For example:
%(rxspencer:[GSL.*][@0])s <- Hello ->
%(rxspencer:[GSL.*][@0])s <- GSLHello -> GSLHello
%(rxspencer:[GSL(.*)][@1])s <- GSLHello -> Hello
%(rxspencer:[GSL(.*)][gsl@1])s <- GSLHello -> gslHello
Another example could be:
%rename("%(lowercase)s",sourcefmt="%(rxspencer:[GSL_(.*)][@1])s",%$isfunction) "";
which take out the prefix "GSL_" and returns all the
function names in lower cases, as following:
void GSL_Hello(); -> hello();
void GSL_Hi(); -> hi();
const int GSL_MAX; -> GSL_MAX; // no change, is not a function
We use the RxSpencer as an initial test bed to
implemention while we decide which library will be
finally added to swig.
You can obtain the RxSpencer library from
http://arglist.com/regex (Unix)
or
http://gnuwin32.sourceforge.net/packages.html (Windows)
Once installed, use "man rxspencer" to get more info
about the regexp format, or just google rxspencer.
Since now you can enable the rxsmatch rules (see above),
the simple or '|' support for the match rules
(01/12/2006: mmatus) is disabled. Still, if you have
problems with the rxspencer library, you can re-enable
the simple 'match or' support using -DSWIG_USE_SIMPLE_MATCHOR.
01/16/2006: mmatus
Change the %rename predicates to use the prefix '%$', as in:
%rename("%(utitle)s",%$isfunction,%$ismember) "";
to avoid clashings with other swig macros/directives.
01/14/2006: cfisavage
Added support for Ruby bang! methods via a new %bang feature.
Bang methods end in exclamation points and indicate that the

View file

@ -1,7 +1,7 @@
%module rename_camel
%rename("%(utitle)s",%isfunction,%ismember) "";
%rename("%(ctitle)s",%isvariable,%ismember) "";
%rename("%(utitle)s",%$isfunction,%$ismember) "";
%rename("%(ctitle)s",%$isvariable,%$ismember) "";
%inline {
struct GeometryFactory
@ -26,8 +26,6 @@
%rename(SedCmd) camel_case_2;
%rename("%(ctitle)s") camel_case_3;
%rename("%(title)s",match$parentNode$type="enum HelloEnum") "";
%rename("%(ctitle)s",match$parentNode$type="enum ChaoEnum") "";
%rename("%(utitle)s") CamelCase_5;
@ -35,6 +33,7 @@
%rename(awk_cmd) "";
%rename("%(title)s",rxsmatch$parentNode$type="enum .*") "";
%inline
{
@ -60,4 +59,10 @@
}
%rename("%(lowercase)s",sourcefmt="%(rxspencer:[GSL_(.*)][@1])s",%$isfunction) "";
%inline {
void GSL_Hello() {}
}

View file

@ -728,6 +728,10 @@ int Swig_scopename_check(String *s) {
/* -----------------------------------------------------------------------------
* Swig_string_command()
*
* Executes a external command via popen with the string as a command
* line parameter. For example:
*
* Printf(stderr,"%(command:sed 's/[a-z]/\U\\1/' <<<)s","hello") -> Hello
* ----------------------------------------------------------------------------- */
#if defined(HAVE_POPEN)
# if defined(_MSC_VER)
@ -768,6 +772,108 @@ String *Swig_string_command(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
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;
}
if (*ce == pe) {
if (!lb) {
end = 1;
--ce;
} else {
--lb;
}
}
++ce;
}
return end ? ce : 0;
}
String *Swig_string_rxspencer(String *s) {
String *res = 0;
#if defined(USE_RXSPENCER)
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 = Strstr(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 = Strstr(res,"@");
} else if (cd == '@') {
spos = strstr(spos + 1,"@");
}
}
}
free(pmatch);
}
}
}
regfree(&compiled);
}
}
}
#endif
if (!res) res = NewStringEmpty();
return res;
}
/* -----------------------------------------------------------------------------
* Swig_init()
*
@ -784,8 +890,9 @@ Swig_init() {
DohEncoding("ctitle", Swig_string_ccase);
DohEncoding("utitle", Swig_string_ucase);
DohEncoding("typecode",Swig_string_typecode);
DohEncoding("mangle",Swig_string_emangle);
DohEncoding("command",Swig_string_command);
DohEncoding("mangle", Swig_string_emangle);
DohEncoding("command", Swig_string_command);
DohEncoding("rxspencer", Swig_string_rxspencer);
/* aliases for the case encoders */
DohEncoding("uppercase", Swig_string_upper);
@ -795,6 +902,7 @@ Swig_init() {
DohEncoding("firstuppercase", Swig_string_first_upper);
DohEncoding("firstlowercase", Swig_string_first_lower);
/* Initialize the swig keys */
Swig_keys_init();

View file

@ -213,7 +213,7 @@ Swig_name_get(const String_or_char *vname) {
String *f;
#ifdef SWIG_DEBUG
Printf(stdout,"Swig_name_get: '%s'\n", vname);
Printf(stderr,"Swig_name_get: '%s'\n", vname);
#endif
r = NewStringEmpty();
@ -400,7 +400,7 @@ Swig_name_object_set(Hash *namehash, String *name, SwigType *decl, DOH *object)
DOH *n;
#ifdef SWIG_DEBUG
Printf(stdout,"Swig_name_object_set: '%s', '%s'\n", name, decl);
Printf(stderr,"Swig_name_object_set: '%s', '%s'\n", name, decl);
#endif
n = HashGetAttr(namehash,name);
if (!n) {
@ -465,7 +465,7 @@ Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType *dec
}
*/
#ifdef SWIG_DEBUG
Printf(stdout,"Swig_name_object_get: '%s', '%s'\n", name, decl);
Printf(stderr,"Swig_name_object_get: '%s', '%s'\n", name, decl);
#endif
/* Perform a class-based lookup (if class prefix supplied) */
@ -520,7 +520,7 @@ Swig_name_object_get(Hash *namehash, String *prefix, String *name, SwigType *dec
Delete(tname);
#ifdef SWIG_DEBUG
Printf(stdout,"Swig_name_object_get: found %d\n", rn ? 1 : 0);
Printf(stderr,"Swig_name_object_get: found %d\n", rn ? 1 : 0);
#endif
return rn;
@ -601,7 +601,7 @@ void features_get(Hash *features, String *tname, SwigType *decl, SwigType *ncdec
{
Node *n = Getattr(features,tname);
#ifdef SWIG_DEBUG
Printf(stdout," features_get: %s\n", tname);
Printf(stderr," features_get: %s\n", tname);
#endif
if (n) {
merge_features(get_object(n,0),node);
@ -651,7 +651,7 @@ Swig_features_get(Hash *features, String *prefix, String *name, SwigType *decl,
}
#ifdef SWIG_DEBUG
Printf(stdout,"Swig_features_get: %s %s %s\n", prefix, name, decl);
Printf(stderr,"Swig_features_get: %s %s %s\n", prefix, name, decl);
#endif
/* Global features */
@ -720,7 +720,7 @@ Swig_feature_set(Hash *features, const String_or_char *name, SwigType *decl, con
Hash *fhash;
#ifdef SWIG_DEBUG
Printf(stdout,"Swig_feature_set: %s %s %s %s\n", name, decl, featurename,value);
Printf(stderr,"Swig_feature_set: %s %s %s %s\n", name, decl, featurename,value);
#endif
n = Getattr(features,name);
@ -1009,13 +1009,22 @@ static void Swig_name_object_attach_keys(const char *keys[], Hash *nameobj)
char *ckey = kname ? Char(kname) : 0;
if (ckey) {
const char **rkey;
if ((strncmp(ckey,"match",5) == 0) || (strncmp(ckey,"notmatch",8) == 0)) {
int isnotmatch = 0;
int isrxsmatch = 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))) {
Hash *mi = NewHash();
List *attrlist = Swig_make_attrlist(ckey);
if (!matchlist) matchlist = NewList();
Setattr(mi,k_value,Getattr(kw,k_value));
Setattr(mi,k_attrlist,attrlist);
if (strncmp(ckey,"not",3) == 0) SetFlag(mi,k_notmatch);
#ifdef SWIG_DEBUG
if (isrxsmatch) Printf(stderr,"rxsmatch to use: %s %s %s\n", ckey, Getattr(kw,k_value), attrlist);
#endif
if (isnotmatch) SetFlag(mi,k_notmatch);
if (isrxsmatch) SetFlag(mi,k_rxsmatch);
Delete(attrlist);
Append(matchlist,mi);
Delete(mi);
@ -1083,7 +1092,6 @@ static DOH *Swig_get_lattr(Node *n, List *lattr)
res = Getattr(n,nattr);
#ifdef SWIG_DEBUG
if (!res) {
Node *pn = Getattr(n,k_parentnode);
Printf(stderr,"missing %s %s %s\n",nattr, Getattr(n,"name"), Getattr(n,"member"));
} else {
Printf(stderr,"lattr %d %s %s\n",i, nattr, DohIsString(res) ? res : Getattr(res,"name"));
@ -1094,8 +1102,34 @@ 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
int Swig_name_rxsmatch_value(String *mvalue, String *value)
{
int match = 0;
#if defined(USE_RXSPENCER)
char *cvalue = Char(value);
char *cmvalue = Char(mvalue);
regex_t compiled;
int retval = regcomp(&compiled, cmvalue, REG_EXTENDED|REG_NOSUB);
if(retval != 0) return 0;
retval = regexec(&compiled,cvalue,0,0,0);
match = (retval == REG_NOMATCH) ? 0 : 1;
#ifdef SWIG_DEBUG
Printf(stderr,"rxsmatch_value: %s %s %d\n",cvalue,cmvalue, match);
#endif
regfree(&compiled);
#endif
return match;
}
int Swig_name_match_value(String *mvalue, String *value)
{
#if defined(SWIG_USE_SIMPLE_MATCHOR)
int match = 0;
char *cvalue = Char(value);
char *cmvalue = Char(mvalue);
@ -1115,8 +1149,12 @@ int Swig_name_match_value(String *mvalue, String *value)
#endif
}
return match;
#else
return StringEqual(mvalue,value);
#endif
}
int Swig_name_match_nameobj(Hash *rn, Node *n) {
int match = 1;
List *matchlist = HashGetAttr(rn,k_matchlist);
@ -1127,14 +1165,22 @@ int Swig_name_match_nameobj(Hash *rn, Node *n) {
int ilen = Len(matchlist);
int i;
for (i = 0; match && (i < ilen); ++i) {
Node *kw = Getitem(matchlist,i);
List *lattr = Getattr(kw,k_attrlist);
Node *mi = Getitem(matchlist,i);
List *lattr = Getattr(mi,k_attrlist);
String *nval = Swig_get_lattr(n,lattr);
int notmatch = GetFlag(kw,k_notmatch);
int notmatch = GetFlag(mi,k_notmatch);
int rxsmatch = GetFlag(mi,k_rxsmatch);
#ifdef SWIG_DEBUG
Printf(stderr,"mi %d %s re %d not %d \n", i, nval, notmatch, rxsmatch);
if (rxsmatch) {
Printf(stderr,"rxsmatch %s\n",lattr);
}
#endif
match = 0;
if (nval) {
String *kwval = Getattr(kw,k_value);
match = Swig_name_match_value(kwval, nval);
String *kwval = Getattr(mi,k_value);
match = rxsmatch ? Swig_name_rxsmatch_value(kwval, nval)
: Swig_name_match_value(kwval, nval);
#ifdef SWIG_DEBUG
Printf(stderr,"val %s %s %d %d \n",nval, kwval,match, ilen);
#endif
@ -1168,25 +1214,33 @@ Hash *Swig_name_nameobj_lget(List *namelist, Node *n, String *prefix, String *na
continue;
} else if (Swig_name_match_nameobj(rn, n)) {
String *tname = HashGetAttr(rn,k_targetname);
String *sfmt = HashGetAttr(rn,k_sourcefmt);
String *sname = 0;
int fullname = GetFlag(rn,k_fullname);
if (sfmt) {
if (fullname && prefix) {
sname = NewStringf(sfmt, prefix, name);
if (tname) {
String *sfmt = HashGetAttr(rn,k_sourcefmt);
String *sname = 0;
int fullname = GetFlag(rn,k_fullname);
int rxstarget = GetFlag(rn,k_rxstarget);
if (sfmt) {
if (fullname && prefix) {
String *pname= NewStringf("%s::%s", prefix, name);
sname = NewStringf(sfmt, pname);
Delete(pname);
} else {
sname = NewStringf(sfmt, name);
}
} else {
sname = NewStringf(sfmt, name);
if (fullname && prefix) {
sname = NewStringf("%s::%s", prefix, name);
} else {
sname = name;
DohIncref(name);
}
}
match = rxstarget ? Swig_name_rxsmatch_value(tname,sname) :
Swig_name_match_value(tname,sname);
Delete(sname);
} else {
if (fullname && prefix) {
sname = NewStringf("%s::%s", prefix, name);
} else {
sname = name;
DohIncref(name);
}
match = 1;
}
match = !tname || StringEqual(sname,tname);
Delete(sname);
}
if (match) {
res = rn;
@ -1282,7 +1336,7 @@ void Swig_name_rename_add(String *prefix, String *name, SwigType *decl, Hash *ne
ParmList *declparms = declaratorparms;
const char *rename_keys[] = {"fullname", "sourcefmt", "targetfmt", 0};
const char *rename_keys[] = {"fullname", "sourcefmt", "targetfmt", "continue", "rxstarget",0};
Swig_name_object_attach_keys(rename_keys, newname);
/* Add the name */
@ -1334,10 +1388,6 @@ static String *apply_rename(String *newname, int fullname, String *prefix, Strin
if (cnewname) {
int destructor = name && (*(Char(name)) == '~');
String *fmt = newname;
String *tmp = 0;
if (destructor && (*cnewname != '~')) {
fmt = tmp = NewStringf("~%s", newname);
}
/* use name as a fmt, but avoid C++ "%" and "%=" operators */
if (Len(newname) > 1 && strstr(cnewname,"%") && !(strcmp(cnewname,"%=") == 0)) {
if (fullname && prefix) {
@ -1348,10 +1398,13 @@ static String *apply_rename(String *newname, int fullname, String *prefix, Strin
} else {
result = Copy(newname);
}
if (tmp) Delete(tmp);
if (destructor && result && (*(Char(result)) != '~')) {
Insert(result,0,"~");
}
}
}
}
return result;
}
@ -1365,6 +1418,21 @@ Swig_name_make(Node *n, String *prefix, String_or_char *cname, SwigType *decl, S
Hash *rn = Swig_name_object_get(Swig_name_rename_hash(), prefix, name, decl);
if (!rn || !Swig_name_match_nameobj(rn,n)) {
rn = Swig_name_nameobj_lget(Swig_name_rename_list(), n, prefix, name, decl);
if (rn) {
String *sfmt = HashGetAttr(rn,k_sourcefmt);
int fullname = GetFlag(rn,k_fullname);
if (fullname && prefix) {
String *sname = NewStringf("%s::%s", prefix, name);
Delete(name);
name = sname;
prefix = 0;
}
if (sfmt) {
String *sname = NewStringf(sfmt, name);
Delete(name);
name = sname;
}
}
}
if (rn) {
String *newname = HashGetAttr(rn,k_name);
@ -1421,9 +1489,8 @@ Swig_name_make(Node *n, String *prefix, String_or_char *cname, SwigType *decl, S
}
#ifdef SWIG_DEBUG
Printf(stdout,"Swig_name_make: '%s' '%s'\n", name, result);
Printf(stderr,"Swig_name_make: '%s' '%s'\n", cname, result);
#endif
return result;
}
@ -1435,7 +1502,7 @@ Swig_name_make(Node *n, String *prefix, String_or_char *cname, SwigType *decl, S
* ----------------------------------------------------------------------------- */
void Swig_name_inherit(String *base, String *derived) {
/* Printf(stdout,"base = '%s', derived = '%s'\n", base, derived); */
/* Printf(stderr,"base = '%s', derived = '%s'\n", base, derived); */
Swig_name_object_inherit(Swig_name_rename_hash(),base,derived);
Swig_name_object_inherit(Swig_name_namewarn_hash(),base,derived);
Swig_name_object_inherit(Swig_cparse_features(),base,derived);

View file

@ -22,6 +22,7 @@ String *k_coloncolon = 0;
String *k_compactdefargs = 0;
String *k_construct = 0;
String *k_constructor = 0;
String *k_continue = 0;
String *k_conversionoperator = 0;
String *k_csymnextSibling = 0;
String *k_csympreviousSibling = 0;
@ -69,6 +70,8 @@ String *k_protectedbaselist = 0;
String *k_public = 0;
String *k_qname = 0;
String *k_qualifier = 0;
String *k_rxsmatch = 0;
String *k_rxstarget = 0;
String *k_rename = 0;
String *k_result = 0;
String *k_scope = 0;
@ -142,6 +145,7 @@ void Swig_keys_init() {
k_compactdefargs = NewString("compactdefargs");
k_construct = NewString("construct");
k_constructor = NewString("constructor");
k_continue = NewString("continue");
k_conversionoperator = NewString("conversion_operator");
k_csymnextSibling = NewString("csym:nextSibling");
k_csympreviousSibling = NewString("csym:previousSibling");
@ -188,6 +192,8 @@ void Swig_keys_init() {
k_public = NewString("public");
k_qname = NewString("qname");
k_qualifier = NewString("qualifier");
k_rxsmatch = NewString("rxsmatch");
k_rxstarget = NewString("rxstarget");
k_rename = NewString("rename");
k_result = NewString("result");
k_scope = NewString("scope");

View file

@ -27,6 +27,7 @@ extern String *k_coloncolon;
extern String *k_compactdefargs;
extern String *k_construct;
extern String *k_constructor;
extern String *k_continue;
extern String *k_conversionoperator;
extern String *k_csymnextSibling;
extern String *k_csympreviousSibling;
@ -74,6 +75,8 @@ extern String *k_protectedbaselist;
extern String *k_public;
extern String *k_qname;
extern String *k_qualifier;
extern String *k_rxsmatch;
extern String *k_rxstarget;
extern String *k_rename;
extern String *k_result;
extern String *k_scope;

View file

@ -51,9 +51,6 @@ AC_CHECK_TYPES([bool])
AC_LANG_POP([C++])
# Check for functions
AC_CHECK_FUNC(popen, AC_DEFINE(HAVE_POPEN, 1, [Define if popen is available]))
# Set info about shared libraries.
AC_SUBST(SO)
AC_SUBST(LDSHARED)
@ -284,6 +281,40 @@ echo "Checking for installed packages."
echo "Note : None of the following packages are required to compile SWIG"
echo ""
#----------------------------------------------------------------
# Look for popen
#----------------------------------------------------------------
AC_ARG_WITH(popen, AS_HELP_STRING([--without-popen], [Disable popen]), with_popen="$withval")
if test x"${with_popen}" = xno ; then
AC_MSG_NOTICE([Disabling popen])
else
AC_CHECK_FUNC(popen, AC_DEFINE(HAVE_POPEN, 1, [Define if popen is available]), AC_MSG_NOTICE([Disabling popen]))
fi
#----------------------------------------------------------------
# Look for RxSpencer
#----------------------------------------------------------------
AC_ARG_WITH(rxspencer, AS_HELP_STRING([--with-rxspencer], [Enable RxSpencer]), with_rxspencer="yes")
if test x"${with_rxspencer}" = xyes ; then
#check first for the header
AC_CHECK_HEADER(rxspencer/regex.h,with_rxspencer="yes",with_rxspencer="no")
if test x"${with_rxspencer}" = xyes ; then
# now check for the library
AC_CHECK_LIB(rxspencer, regcomp,with_rxspencer="yes",with_rxspencer="no")
fi
if test x"${with_rxspencer}" = xyes ; then
# library and header are available
AC_DEFINE(HAVE_RXSPENCER, 1,[Define if rxspencer is available])
LIBS="$LIBS -lrxspencer"
else
AC_MSG_NOTICE([RxSpencer not found. Obtain it at http://arglist.com/regex or http://gnuwin32.sourceforge.net/packages.html])
fi
fi
#----------------------------------------------------------------
# Check for specific libraries. Used for SWIG examples
AC_CHECK_LIB(dl, dlopen) # Dynamic linking for SunOS/Solaris and SYSV
AC_CHECK_LIB(dld, shl_load) # Dynamic linking for HP-UX