diff --git a/CHANGES.current b/CHANGES.current index 63af7206d..9954ae05b 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -9,6 +9,18 @@ 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 the new "regex" encoder that can be used in %rename, e.g. + + %rename("regex:/(\\w+)_(.*)/\\2/") ""; + + to remove any alphabetical prefix from all identifiers. The syntax + of the regular expressions is Perl-like and PCRE library + (http://www.pcre.org/) is used to implement this feature but notice + that backslashes need to be escaped as usual inside C strings. + + Original patch from Torsten Landschoff. + 2010-07-08: wsfulton Fix #3024875 - shared_ptr of classes with non-public destructors. This also fixes the "unref" feature when used on classes with non-public destructors. diff --git a/Doc/Manual/SWIG.html b/Doc/Manual/SWIG.html index e68003325..3fb1e86cc 100644 --- a/Doc/Manual/SWIG.html +++ b/Doc/Manual/SWIG.html @@ -1871,6 +1871,18 @@ and a more descriptive one, but the two functions are otherwise equivalent): literally, e.g. %rename("strip:[wx]") wxPrintPrint + + regex:/pattern/subst/ + String after (Perl-like) regex substitution operation. This function + allows to apply arbitrary regular expressions to the identifier names. The + pattern part is a regular expression in Perl syntax (as supported + by PCRE) and the subst string + can contain back-references introduced by '\' or, as backslashes need + to be escaped in C strings, rather by "\\". For example, to remove + any alphabetic prefix before an underscore you could use the following directive: + %rename("regex:/(\\w+)_(.*)/\\2/") + Prefix_PrintPrint + command:cmd Output of an external command cmd with the string passed to 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 + +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);