diff options
author | Vadim Zeitlin <vz-swig@zeitlins.org> | 2010-07-22 17:00:37 +0000 |
---|---|---|
committer | Vadim Zeitlin <vz-swig@zeitlins.org> | 2010-07-22 17:00:37 +0000 |
commit | c4e9043288e2136dd7ae9e0515ad79164ad00d95 (patch) | |
tree | 8edb6efbc41258628753254dbc2d2036655bd08f /Source | |
parent | 6399502719dcc04c816536d7a4231e0164b4402f (diff) | |
download | swig-c4e9043288e2136dd7ae9e0515ad79164ad00d95.tar.gz |
Add support for regex encoder for %rename.
This allows to write %rename("%(regex:/pattern/subst/)s") to apply a
regex-based replacement to a declaration name.
git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@12170 626c5289-ae23-0410-ae9c-e8d60b6d4f22
Diffstat (limited to 'Source')
-rw-r--r-- | Source/Swig/misc.c | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/Source/Swig/misc.c b/Source/Swig/misc.c index f0a9155eb..b23a99b60 100644 --- a/Source/Swig/misc.c +++ b/Source/Swig/misc.c @@ -1214,6 +1214,111 @@ String *Swig_string_rxspencer(String *s) { } #endif +#ifdef HAVE_PCRE +#include <pcre.h> + +static int split_regex_pattern_subst(String *s, String **pattern, String **subst, const char **input) +{ + const char *pats, *pate; + const char *subs, *sube; + + /* Locate the search pattern */ + const char *p = Char(s); + if (*p++ != '/') goto err_out; + pats = p; + p = strchr(p, '/'); + if (!p) goto err_out; + pate = p; + + /* Locate the substitution string */ + subs = ++p; + p = strchr(p, '/'); + if (!p) goto err_out; + sube = p; + + *pattern = NewStringWithSize(pats, pate - pats); + *subst = NewStringWithSize(subs, sube - subs); + *input = p + 1; + return 1; + +err_out: + Swig_error("SWIG", Getline(s), "Invalid regex substitution: '%s'.\n", s); + exit(1); +} + +String *replace_captures(const char *input, String *subst, int captures[]) +{ + String *result = NewStringEmpty(); + const char *p = Char(subst); + + while (*p) { + /* Copy part without substitutions */ + const char *q = strchr(p, '\\'); + if (!q) { + Write(result, p, strlen(p)); + break; + } + Write(result, p, q - p); + p = q + 1; + + /* Handle substitution */ + if (*p == '\0') { + Putc('\\', result); + } else if (isdigit(*p)) { + int group = *p++ - '0'; + int l = captures[group*2], r = captures[group*2 + 1]; + if (l != -1) { + Write(result, input + l, r - l); + } + } + } + + return result; +} + +/* ----------------------------------------------------------------------------- + * Swig_string_regex() + * + * Executes a regexp substitution. For example: + * + * Printf(stderr,"gsl%(regex:/GSL_.*_/\\1/)s","GSL_Hello_") -> gslHello + * ----------------------------------------------------------------------------- */ +String *Swig_string_regex(String *s) { + const int pcre_options = 0; + + String *res = 0; + pcre *compiled_pat = 0; + const char *pcre_error, *input; + int pcre_errorpos; + String *pattern = 0, *subst = 0; + int captures[30]; + + if (split_regex_pattern_subst(s, &pattern, &subst, &input)) { + compiled_pat = pcre_compile( + Char(pattern), pcre_options, &pcre_error, &pcre_errorpos, NULL); + if (!compiled_pat) { + Swig_error("SWIG", Getline(s), "PCRE compilation failed: '%s' in '%s':%i.\n", + pcre_error, Char(pattern), pcre_errorpos); + exit(1); + } + pcre_exec(compiled_pat, NULL, input, strlen(input), 0, 0, captures, 30); + res = replace_captures(input, subst, captures); + } + + DohDelete(pattern); + DohDelete(subst); + pcre_free(compiled_pat); + return res ? res : NewStringEmpty(); +} + +#else + +String *Swig_string_regex(String *s) { + Swig_error("SWIG", Getline(s), "PCRE regex support not enabled in this SWIG build.\n"); + exit(1); +} + +#endif /* ----------------------------------------------------------------------------- * Swig_init() @@ -1236,6 +1341,7 @@ void Swig_init() { DohEncoding("rxspencer", Swig_string_rxspencer); DohEncoding("schemify", Swig_string_schemify); DohEncoding("strip", Swig_string_strip); + DohEncoding("regex", Swig_string_regex); /* aliases for the case encoders */ DohEncoding("uppercase", Swig_string_upper); |