/* ----------------------------------------------------------------------------- * This file is part of SWIG, which is licensed as a whole under version 3 * (or any later version) of the GNU General Public License. Some additional * terms also apply to certain portions of SWIG. The full details of the SWIG * license and copyrights can be found in the LICENSE and COPYRIGHT files * included with the SWIG source code as distributed by the SWIG developers * and at http://www.swig.org/legal.html. * * misc.c * * Miscellaneous functions that don't really fit anywhere else. * ----------------------------------------------------------------------------- */ char cvsroot_misc_c[] = "$Id: misc.c 12322 2010-12-06 20:43:56Z wsfulton $"; #include "swig.h" #include #include #include #include #include #ifdef _WIN32 #include #ifndef S_ISDIR #define S_ISDIR(mode) (((mode) & S_IFDIR) == S_IFDIR) #endif #endif static char *fake_version = 0; /* ----------------------------------------------------------------------------- * Swig_copy_string() * * Duplicate a NULL-terminate string given as a char *. * ----------------------------------------------------------------------------- */ char *Swig_copy_string(const char *s) { char *c = 0; if (s) { c = (char *) malloc(strlen(s) + 1); strcpy(c, s); } return c; } /* ----------------------------------------------------------------------------- * Swig_set_fakeversion() * * Version string override * ----------------------------------------------------------------------------- */ void Swig_set_fakeversion(const char *version) { fake_version = Swig_copy_string(version); } /* ----------------------------------------------------------------------------- * Swig_package_version() * * Return the package string containing the version number * ----------------------------------------------------------------------------- */ const char *Swig_package_version(void) { return fake_version ? fake_version : PACKAGE_VERSION; } /* ----------------------------------------------------------------------------- * Swig_banner() * * Emits the SWIG identifying banner for the C/C++ wrapper file. * ----------------------------------------------------------------------------- */ void Swig_banner(File *f) { Printf(f, "/* ----------------------------------------------------------------------------\n\ * This file was automatically generated by SWIG (http://www.swig.org).\n\ * Version %s\n\ * \n\ * This file is not intended to be easily readable and contains a number of \n\ * coding conventions designed to improve portability and efficiency. Do not make\n\ * changes to this file unless you know what you are doing--modify the SWIG \n\ * interface file instead. \n", Swig_package_version()); /* String too long for ISO compliance */ Printf(f, " * ----------------------------------------------------------------------------- */\n"); } /* ----------------------------------------------------------------------------- * Swig_banner_target_lang() * * Emits a SWIG identifying banner in the target language * ----------------------------------------------------------------------------- */ void Swig_banner_target_lang(File *f, const_String_or_char_ptr commentchar) { Printf(f, "%s This file was automatically generated by SWIG (http://www.swig.org).\n", commentchar); Printf(f, "%s Version %s\n", commentchar, Swig_package_version()); Printf(f, "%s\n", commentchar); Printf(f, "%s Do not make changes to this file unless you know what you are doing--modify\n", commentchar); Printf(f, "%s the SWIG interface file instead.\n", commentchar); } /* ----------------------------------------------------------------------------- * Swig_strip_c_comments() * * Return a new string with C comments stripped from the input string. NULL is * returned if there aren't any comments. * ----------------------------------------------------------------------------- */ String *Swig_strip_c_comments(const String *s) { const char *c = Char(s); const char *comment_begin = 0; const char *comment_end = 0; String *stripped = 0; while (*c) { if (!comment_begin && *c == '/') { ++c; if (!*c) break; if (*c == '*') comment_begin = c-1; } else if (comment_begin && !comment_end && *c == '*') { ++c; if (*c == '/') { comment_end = c; break; } } ++c; } if (comment_begin && comment_end) { int size = comment_begin - Char(s); String *stripmore = 0; stripped = NewStringWithSize(s, size); Printv(stripped, comment_end + 1, NIL); do { stripmore = Swig_strip_c_comments(stripped); if (stripmore) { Delete(stripped); stripped = stripmore; } } while (stripmore); } return stripped; } /* ----------------------------------------------------------------------------- * is_directory() * ----------------------------------------------------------------------------- */ static int is_directory(String *directory) { int last = Len(directory) - 1; int statres; struct stat st; char *dir = Char(directory); if (dir[last] == SWIG_FILE_DELIMITER[0]) { /* remove trailing slash - can cause S_ISDIR to fail on Windows, at least */ dir[last] = 0; statres = stat(dir, &st); dir[last] = SWIG_FILE_DELIMITER[0]; } else { statres = stat(dir, &st); } return (statres == 0 && S_ISDIR(st.st_mode)); } /* ----------------------------------------------------------------------------- * Swig_new_subdirectory() * * Create the subdirectory only if the basedirectory already exists as a directory. * basedirectory can be NULL or empty to indicate current directory. * ----------------------------------------------------------------------------- */ String *Swig_new_subdirectory(String *basedirectory, String *subdirectory) { String *error = 0; struct stat st; int current_directory = basedirectory ? (Len(basedirectory) == 0 ? 1 : 0) : 0; if (current_directory || is_directory(basedirectory)) { Iterator it; String *dir = basedirectory ? NewString(basedirectory) : NewString(""); List *subdirs = Split(subdirectory, SWIG_FILE_DELIMITER[0], INT_MAX); for (it = First(subdirs); it.item; it = Next(it)) { int statdir; String *subdirectory = it.item; Printf(dir, "%s", subdirectory); statdir = stat(Char(dir), &st); if (statdir == 0) { Printf(dir, SWIG_FILE_DELIMITER); if (S_ISDIR(st.st_mode)) { continue; } else { error = NewStringf("Cannot create directory %s", dir); break; } } else { #ifdef _WIN32 int result = _mkdir(Char(dir)); #else int result = mkdir(Char(dir), 0777); #endif Printf(dir, SWIG_FILE_DELIMITER); if (result != 0 && errno != EEXIST) { error = NewStringf("Cannot create directory %s", dir); break; } } } } else { error = NewStringf("Cannot create subdirectory %s under the base directory %s. Either the base does not exist as a directory or it is not readable.", subdirectory, basedirectory); } return error; } /* ----------------------------------------------------------------------------- * Swig_filename_correct() * * Corrects filename paths by removing duplicate delimeters and on non-unix * systems use the correct delimeter across the whole name. * ----------------------------------------------------------------------------- */ void Swig_filename_correct(String *filename) { int network_path = 0; if (Len(filename) >= 2) { const char *fname = Char(filename); if (fname[0] == '\\' && fname[1] == '\\') network_path = 1; if (fname[0] == '/' && fname[1] == '/') network_path = 1; } #if defined(_WIN32) || defined(MACSWIG) /* accept Unix path separator on non-Unix systems */ Replaceall(filename, "/", SWIG_FILE_DELIMITER); #endif #if defined(__CYGWIN__) /* accept Windows path separator in addition to Unix path separator */ Replaceall(filename, "\\", SWIG_FILE_DELIMITER); #endif /* remove all duplicate file name delimiters */ while (Replaceall(filename, SWIG_FILE_DELIMITER SWIG_FILE_DELIMITER, SWIG_FILE_DELIMITER)) { } /* Network paths can start with a double slash on Windows - unremove the duplicate slash we just removed */ if (network_path) Insert(filename, 0, SWIG_FILE_DELIMITER); } /* ----------------------------------------------------------------------------- * Swig_filename_escape() * * Escapes backslashes in filename - for Windows * ----------------------------------------------------------------------------- */ String *Swig_filename_escape(String *filename) { String *adjusted_filename = Copy(filename); Swig_filename_correct(adjusted_filename); #if defined(_WIN32) /* Note not on Cygwin else filename is displayed with double '/' */ Replaceall(adjusted_filename, "\\", "\\\\"); #endif return adjusted_filename; } /* ----------------------------------------------------------------------------- * Swig_filename_unescape() * * Remove double backslash escaping in filename - for Windows * ----------------------------------------------------------------------------- */ void Swig_filename_unescape(String *filename) { (void)filename; #if defined(_WIN32) Replaceall(filename, "\\\\", "\\"); #endif } /* ----------------------------------------------------------------------------- * Swig_string_escape() * * Takes a string object and produces a string with escape codes added to it. * ----------------------------------------------------------------------------- */ String *Swig_string_escape(String *s) { String *ns; int c; ns = NewStringEmpty(); while ((c = Getc(s)) != EOF) { if (c == '\n') { Printf(ns, "\\n"); } else if (c == '\r') { Printf(ns, "\\r"); } else if (c == '\t') { Printf(ns, "\\t"); } else if (c == '\\') { Printf(ns, "\\\\"); } else if (c == '\'') { Printf(ns, "\\'"); } else if (c == '\"') { Printf(ns, "\\\""); } else if (c == ' ') { Putc(c, ns); } else if (!isgraph(c)) { if (c < 0) c += UCHAR_MAX + 1; Printf(ns, "\\%o", c); } else { Putc(c, ns); } } return ns; } /* ----------------------------------------------------------------------------- * Swig_string_upper() * * Takes a string object and returns a copy that is uppercase * ----------------------------------------------------------------------------- */ String *Swig_string_upper(String *s) { String *ns; int c; ns = NewStringEmpty(); Seek(s, 0, SEEK_SET); while ((c = Getc(s)) != EOF) { Putc(toupper(c), ns); } return ns; } /* ----------------------------------------------------------------------------- * Swig_string_lower() * * Takes a string object and returns a copy that is lowercase * ----------------------------------------------------------------------------- */ String *Swig_string_lower(String *s) { String *ns; int c; ns = NewStringEmpty(); Seek(s, 0, SEEK_SET); while ((c = Getc(s)) != EOF) { Putc(tolower(c), ns); } return ns; } /* ----------------------------------------------------------------------------- * Swig_string_title() * * Takes a string object and returns a copy that is lowercase with first letter * capitalized * ----------------------------------------------------------------------------- */ String *Swig_string_title(String *s) { String *ns; int first = 1; int c; ns = NewStringEmpty(); Seek(s, 0, SEEK_SET); while ((c = Getc(s)) != EOF) { Putc(first ? toupper(c) : tolower(c), ns); first = 0; } return ns; } /* ----------------------------------------------------------------------------- * Swig_string_ccase() * * Takes a string object and returns a copy that is lowercase with the first * letter capitalized and the one following '_', which are removed. * * camel_case -> CamelCase * camelCase -> CamelCase * ----------------------------------------------------------------------------- */ String *Swig_string_ccase(String *s) { String *ns; int first = 1; int c; ns = NewStringEmpty(); Seek(s, 0, SEEK_SET); while ((c = Getc(s)) != EOF) { if (c == '_') { first = 1; continue; } Putc(first ? toupper(c) : c, ns); first = 0; } return ns; } /* ----------------------------------------------------------------------------- * Swig_string_lccase() * * Takes a string object and returns a copy with the character after * each '_' capitalised, and the '_' removed. The first character is * also forced to lowercase. * * camel_case -> camelCase * CamelCase -> camelCase * ----------------------------------------------------------------------------- */ String *Swig_string_lccase(String *s) { String *ns; int first = 1; int after_underscore = 0; int c; ns = NewStringEmpty(); Seek(s, 0, SEEK_SET); while ((c = Getc(s)) != EOF) { if (c == '_') { after_underscore = 1; continue; } if (first) { Putc(tolower(c), ns); first = 0; } else { Putc(after_underscore ? toupper(c) : c, ns); } after_underscore = 0; } return ns; } /* ----------------------------------------------------------------------------- * Swig_string_ucase() * * This is the reverse case of ccase, ie * * CamelCase -> camel_case * get2D -> get_2d * asFloat2 -> as_float2 * ----------------------------------------------------------------------------- */ String *Swig_string_ucase(String *s) { String *ns; int c; int lastC = 0; int nextC = 0; int underscore = 0; ns = NewStringEmpty(); /* We insert a underscore when: 1. Lower case char followed by upper case char getFoo > get_foo; getFOo > get_foo; GETFOO > getfoo 2. Number proceded by char and not end of string get2D > get_2d; get22D > get_22d; GET2D > get_2d but: asFloat2 > as_float2 */ Seek(s, 0, SEEK_SET); while ((c = Getc(s)) != EOF) { nextC = Getc(s); Ungetc(nextC, s); if (isdigit(c) && isalpha(lastC) && nextC != EOF) underscore = 1; else if (isupper(c) && isalpha(lastC) && !isupper(lastC)) underscore = 1; lastC = c; if (underscore) { Putc('_', ns); underscore = 0; } Putc(tolower(c), ns); } return ns; } /* ----------------------------------------------------------------------------- * Swig_string_first_upper() * * Make the first character in the string uppercase, leave all the * rest the same. This is used by the Ruby module to provide backwards * compatibility with the old way of naming classes and constants. For * more info see the Ruby documentation. * * firstUpper -> FirstUpper * ----------------------------------------------------------------------------- */ String *Swig_string_first_upper(String *s) { String *ns = NewStringEmpty(); char *cs = Char(s); if (cs && cs[0] != 0) { Putc(toupper((int)cs[0]), ns); Append(ns, cs + 1); } return ns; } /* ----------------------------------------------------------------------------- * Swig_string_first_lower() * * Make the first character in the string lowercase, leave all the * rest the same. This is used by the Ruby module to provide backwards * compatibility with the old way of naming classes and constants. For * more info see the Ruby documentation. * * firstLower -> FirstLower * ----------------------------------------------------------------------------- */ String *Swig_string_first_lower(String *s) { String *ns = NewStringEmpty(); char *cs = Char(s); if (cs && cs[0] != 0) { Putc(tolower((int)cs[0]), ns); Append(ns, cs + 1); } return ns; } /* ----------------------------------------------------------------------------- * Swig_string_schemify() * * Replace underscores with dashes, to make identifiers look nice to Schemers. * * under_scores -> under-scores * ----------------------------------------------------------------------------- */ String *Swig_string_schemify(String *s) { String *ns = NewString(s); Replaceall(ns, "_", "-"); return ns; } /* ----------------------------------------------------------------------------- * Swig_string_typecode() * * Takes a string with possible type-escapes in it and replaces them with * real C datatypes. * ----------------------------------------------------------------------------- */ String *Swig_string_typecode(String *s) { String *ns; int c; String *tc; ns = NewStringEmpty(); while ((c = Getc(s)) != EOF) { if (c == '`') { String *str = 0; tc = NewStringEmpty(); while ((c = Getc(s)) != EOF) { if (c == '`') break; Putc(c, tc); } str = SwigType_str(tc, 0); Append(ns, str); Delete(str); } else { Putc(c, ns); if (c == '\'') { while ((c = Getc(s)) != EOF) { Putc(c, ns); if (c == '\'') break; if (c == '\\') { c = Getc(s); Putc(c, ns); } } } else if (c == '\"') { while ((c = Getc(s)) != EOF) { Putc(c, ns); if (c == '\"') break; if (c == '\\') { c = Getc(s); Putc(c, ns); } } } } } return ns; } /* ----------------------------------------------------------------------------- * Swig_string_mangle() * * Take a string and mangle it by stripping all non-valid C identifier * characters. * * This routine skips unnecessary blank spaces, therefore mangling * 'char *' and 'char*', 'std::pair' and * 'std::pair', produce the same result. * * However, note that 'long long' and 'long_long' produce different * mangled strings. * * The mangling method still is not 'perfect', for example std::pair and * std_pair return the same mangling. This is just a little better * than before, but it seems to be enough for most of the purposes. * * Having a perfect mangling will break some examples and code which * assume, for example, that A::get_value will be mangled as * A_get_value. * ----------------------------------------------------------------------------- */ String *Swig_string_mangle(const String *s) { #if 0 /* old mangling, not suitable for using in macros */ String *t = Copy(s); char *c = Char(t); while (*c) { if (!isalnum(*c)) *c = '_'; c++; } return t; #else String *result = NewStringEmpty(); int space = 0; int state = 0; char *pc, *cb; String *b = Copy(s); if (SwigType_istemplate(b)) { String *st = Swig_symbol_template_deftype(b, 0); String *sq = Swig_symbol_type_qualify(st, 0); String *t = SwigType_namestr(sq); Delete(st); Delete(sq); Delete(b); b = t; } pc = cb = Char(b); while (*pc) { char c = *pc; if (isalnum((int) c) || (c == '_')) { state = 1; if (space && (space == state)) { Append(result, "_SS_"); } space = 0; Printf(result, "%c", (int) c); } else { if (isspace((int) c)) { space = state; ++pc; continue; } else { state = 3; space = 0; } switch (c) { case '.': if ((cb != pc) && (*(pc - 1) == 'p')) { Append(result, "_"); ++pc; continue; } else { c = 'f'; } break; case ':': if (*(pc + 1) == ':') { Append(result, "_"); ++pc; ++pc; continue; } break; case '*': c = 'm'; break; case '&': c = 'A'; break; case '<': c = 'l'; break; case '>': c = 'g'; break; case '=': c = 'e'; break; case ',': c = 'c'; break; case '(': c = 'p'; break; case ')': c = 'P'; break; case '[': c = 'b'; break; case ']': c = 'B'; break; case '^': c = 'x'; break; case '|': c = 'o'; break; case '~': c = 'n'; break; case '!': c = 'N'; break; case '%': c = 'M'; break; case '?': c = 'q'; break; case '+': c = 'a'; break; case '-': c = 's'; break; case '/': c = 'd'; break; default: break; } if (isalpha((int) c)) { Printf(result, "_S%c_", (int) c); } else { Printf(result, "_S%02X_", (int) c); } } ++pc; } Delete(b); return result; #endif } String *Swig_string_emangle(String *s) { return Swig_string_mangle(s); } /* ----------------------------------------------------------------------------- * Swig_scopename_prefix() * * Take a qualified name like "A::B::C" and return the scope name. * In this case, "A::B". Returns NULL if there is no base. * ----------------------------------------------------------------------------- */ void Swig_scopename_split(const String *s, String **rprefix, String **rlast) { char *tmp = Char(s); char *c = tmp; char *cc = c; char *co = 0; if (!strstr(c, "::")) { *rprefix = 0; *rlast = Copy(s); } co = strstr(cc, "operator "); if (co) { if (co == cc) { *rprefix = 0; *rlast = Copy(s); return; } else { *rprefix = NewStringWithSize(cc, co - cc - 2); *rlast = NewString(co); return; } } while (*c) { if ((*c == ':') && (*(c + 1) == ':')) { cc = c; c += 2; } else { if (*c == '<') { int level = 1; c++; while (*c && level) { if (*c == '<') level++; if (*c == '>') level--; c++; } } else { c++; } } } if (cc != tmp) { *rprefix = NewStringWithSize(tmp, cc - tmp); *rlast = NewString(cc + 2); return; } else { *rprefix = 0; *rlast = Copy(s); } } String *Swig_scopename_prefix(const String *s) { char *tmp = Char(s); char *c = tmp; char *cc = c; char *co = 0; if (!strstr(c, "::")) return 0; co = strstr(cc, "operator "); if (co) { if (co == cc) { return 0; } else { String *prefix = NewStringWithSize(cc, co - cc - 2); return prefix; } } while (*c) { if ((*c == ':') && (*(c + 1) == ':')) { cc = c; c += 2; } else { if (*c == '<') { int level = 1; c++; while (*c && level) { if (*c == '<') level++; if (*c == '>') level--; c++; } } else { c++; } } } if (cc != tmp) { return NewStringWithSize(tmp, cc - tmp); } else { return 0; } } /* ----------------------------------------------------------------------------- * Swig_scopename_last() * * Take a qualified name like "A::B::C" and returns the last. In this * case, "C". * ----------------------------------------------------------------------------- */ String *Swig_scopename_last(const String *s) { char *tmp = Char(s); char *c = tmp; char *cc = c; char *co = 0; if (!strstr(c, "::")) return NewString(s); co = strstr(cc, "operator "); if (co) { return NewString(co); } while (*c) { if ((*c == ':') && (*(c + 1) == ':')) { cc = c; c += 2; } else { if (*c == '<') { int level = 1; c++; while (*c && level) { if (*c == '<') level++; if (*c == '>') level--; c++; } } else { c++; } } } return NewString(cc + 2); } /* ----------------------------------------------------------------------------- * Swig_scopename_first() * * Take a qualified name like "A::B::C" and returns the first scope name. * In this case, "A". Returns NULL if there is no base. * ----------------------------------------------------------------------------- */ String *Swig_scopename_first(const String *s) { char *tmp = Char(s); char *c = tmp; char *co = 0; if (!strstr(c, "::")) return 0; co = strstr(c, "operator "); if (co) { if (co == c) { return 0; } } else { co = c + Len(s); } while (*c && (c != co)) { if ((*c == ':') && (*(c + 1) == ':')) { break; } else { if (*c == '<') { int level = 1; c++; while (*c && level) { if (*c == '<') level++; if (*c == '>') level--; c++; } } else { c++; } } } if (*c && (c != tmp)) { return NewStringWithSize(tmp, c - tmp); } else { return 0; } } /* ----------------------------------------------------------------------------- * Swig_scopename_suffix() * * Take a qualified name like "A::B::C" and returns the suffix. * In this case, "B::C". Returns NULL if there is no suffix. * ----------------------------------------------------------------------------- */ String *Swig_scopename_suffix(const String *s) { char *tmp = Char(s); char *c = tmp; char *co = 0; if (!strstr(c, "::")) return 0; co = strstr(c, "operator "); if (co) { if (co == c) return 0; } while (*c) { if ((*c == ':') && (*(c + 1) == ':')) { break; } else { if (*c == '<') { int level = 1; c++; while (*c && level) { if (*c == '<') level++; if (*c == '>') level--; c++; } } else { c++; } } } if (*c && (c != tmp)) { return NewString(c + 2); } else { return 0; } } /* ----------------------------------------------------------------------------- * Swig_scopename_check() * * Checks to see if a name is qualified with a scope name, examples: * foo -> 0 * ::foo -> 1 * foo::bar -> 1 * foo< ::bar > -> 0 * ----------------------------------------------------------------------------- */ int Swig_scopename_check(const String *s) { char *c = Char(s); char *co = strstr(c, "operator "); if (co) { if (co == c) return 0; } if (!strstr(c, "::")) return 0; while (*c) { if ((*c == ':') && (*(c + 1) == ':')) { return 1; } else { if (*c == '<') { int level = 1; c++; while (*c && level) { if (*c == '<') level++; if (*c == '>') level--; c++; } } else { c++; } } } return 0; } /* ----------------------------------------------------------------------------- * 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) # define popen _popen # define pclose _pclose # else extern FILE *popen(const char *command, const char *type); extern int pclose(FILE *stream); # endif #else # if defined(_MSC_VER) # define HAVE_POPEN 1 # define popen _popen # define pclose _pclose # endif #endif String *Swig_string_command(String *s) { String *res = NewStringEmpty(); #if defined(HAVE_POPEN) if (Len(s)) { char *command = Char(s); FILE *fp = popen(command, "r"); if (fp) { char buffer[1025]; while (fscanf(fp, "%1024s", buffer) != EOF) { Append(res, buffer); } pclose(fp); } else { Swig_error("SWIG", Getline(s), "Command encoder fails attempting '%s'.\n", s); exit(1); } } #endif return res; } /* ----------------------------------------------------------------------------- * Swig_string_strip() * * Strip given prefix from identifiers * * Printf(stderr,"%(strip:[wx])s","wxHello") -> Hello * ----------------------------------------------------------------------------- */ String *Swig_string_strip(String *s) { String *ns; if (!Len(s)) { ns = NewString(s); } else { const char *cs = Char(s); const char *ce = Strchr(cs, ']'); if (*cs != '[' || !ce) { ns = NewString(s); } else { String *fmt = NewStringf("%%.%ds", ce-cs-1); String *prefix = NewStringf(fmt, cs+1); if (0 == Strncmp(ce+1, prefix, Len(prefix))) { ns = NewString(ce+1+Len(prefix)); } else { ns = NewString(ce+1); } } } return ns; } #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 regular expression 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)) { int rc; 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); } rc = pcre_exec(compiled_pat, NULL, input, strlen(input), 0, 0, captures, 30); if (rc >= 0) { res = replace_captures(input, subst, captures); } else if (rc != PCRE_ERROR_NOMATCH) { Swig_error("SWIG", Getline(s), "PCRE execution failed: error %d while matching \"%s\" in \"%s\".\n", rc, Char(pattern), input); exit(1); } } DohDelete(pattern); DohDelete(subst); pcre_free(compiled_pat); return res ? res : NewStringEmpty(); } String *Swig_pcre_version(void) { return NewStringf("PCRE Version: %s", pcre_version()); } #else String *Swig_string_regex(String *s) { Swig_error("SWIG", Getline(s), "PCRE regex support not enabled in this SWIG build.\n"); exit(1); } String *Swig_pcre_version(void) { return NewStringf("PCRE not used"); } #endif /* ----------------------------------------------------------------------------- * Swig_init() * * Initialize the SWIG core * ----------------------------------------------------------------------------- */ void Swig_init() { /* Set some useful string encoding methods */ DohEncoding("escape", Swig_string_escape); DohEncoding("upper", Swig_string_upper); DohEncoding("lower", Swig_string_lower); DohEncoding("title", Swig_string_title); DohEncoding("ctitle", Swig_string_ccase); DohEncoding("lctitle", Swig_string_lccase); DohEncoding("utitle", Swig_string_ucase); DohEncoding("typecode", Swig_string_typecode); DohEncoding("mangle", Swig_string_emangle); DohEncoding("command", Swig_string_command); 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); DohEncoding("lowercase", Swig_string_lower); DohEncoding("camelcase", Swig_string_ccase); DohEncoding("lowercamelcase", Swig_string_lccase); DohEncoding("undercase", Swig_string_ucase); DohEncoding("firstuppercase", Swig_string_first_upper); DohEncoding("firstlowercase", Swig_string_first_lower); /* Initialize typemaps */ Swig_typemap_init(); /* Initialize symbol table */ Swig_symbol_init(); /* Initialize type system */ SwigType_typesystem_init(); /* Initialize template system */ SwigType_template_init(); }