swig/Source/Swig/misc.c
William S Fulton ac495d5c66 Merge branch 'char-escaping'
* char-escaping:
  Add missing string_constant.i testcase
  changes file update for char wrappers
  C# char wrappers fixes for enum values, static const member char values and %csconst
  D testing added for %dmanifestconst and char constants
  Fix wrapping D constants using %dmanifestconst
  Php fix for enum value of '\0'
  Fix static const char member variables wrappers with %javaconst(1).
  Expand char testing in enums and %constant
  Java char changes file update
  Java enum and static member variable escaping fix for chars
  Add tests for enum values and static const member variables chars containing escape sequences
  Minor documentation tweak

Conflicts:
	CHANGES.current
2016-03-12 23:27:51 +00:00

1501 lines
38 KiB
C

/* -----------------------------------------------------------------------------
* 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.
* ----------------------------------------------------------------------------- */
#include "swig.h"
#include <errno.h>
#include <ctype.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef _WIN32
#include <direct.h>
#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 = (int)(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 empty to indicate current directory but not NULL.
* ----------------------------------------------------------------------------- */
String *Swig_new_subdirectory(String *basedirectory, String *subdirectory) {
String *error = 0;
int current_directory = Len(basedirectory) == 0;
if (current_directory || is_directory(basedirectory)) {
Iterator it;
String *dir = NewString(basedirectory);
List *subdirs = Split(subdirectory, SWIG_FILE_DELIMITER[0], INT_MAX);
for (it = First(subdirs); it.item; it = Next(it)) {
int result;
String *subdirectory = it.item;
Printf(dir, "%s", subdirectory);
#ifdef _WIN32
result = _mkdir(Char(dir));
#else
result = mkdir(Char(dir), 0777);
#endif
if (result != 0 && errno != EEXIST) {
error = NewStringf("Cannot create directory %s: %s", dir, strerror(errno));
break;
}
if (!is_directory(dir)) {
error = NewStringf("Cannot create directory %s: it may already exist but not be a directory", dir);
break;
}
Printf(dir, SWIG_FILE_DELIMITER);
}
} 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 delimiters and on non-unix
* systems use the correct delimiter 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_storage_isextern()
*
* Determine if the storage class specifier is extern (but not externc)
* ----------------------------------------------------------------------------- */
int Swig_storage_isextern(Node *n) {
const String *storage = Getattr(n, "storage");
return storage ? Strcmp(storage, "extern") == 0 || Strncmp(storage, "extern ", 7) == 0 : 0;
}
/* -----------------------------------------------------------------------------
* Swig_storage_isexternc()
*
* Determine if the storage class specifier is externc (but not plain extern)
* ----------------------------------------------------------------------------- */
int Swig_storage_isexternc(Node *n) {
const String *storage = Getattr(n, "storage");
return storage ? Strcmp(storage, "externc") == 0 || Strncmp(storage, "externc ", 8) == 0 : 0;
}
/* -----------------------------------------------------------------------------
* Swig_storage_isstatic_custom()
*
* Determine if the storage class specifier is static
* ----------------------------------------------------------------------------- */
int Swig_storage_isstatic_custom(Node *n, const_String_or_char_ptr storage_name) {
const String *storage = Getattr(n, storage_name);
return storage ? Strncmp(storage, "static", 6) == 0 : 0;
}
/* -----------------------------------------------------------------------------
* Swig_storage_isstatic()
*
* Determine if the storage class specifier is static
* ----------------------------------------------------------------------------- */
int Swig_storage_isstatic(Node *n) {
return Swig_storage_isstatic_custom(n, "storage");
}
/* -----------------------------------------------------------------------------
* Swig_string_escape()
*
* Takes a string object and produces a string with escape codes added to it.
* Octal escaping is used.
* ----------------------------------------------------------------------------- */
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_hexescape()
*
* Takes a string object and produces a string with escape codes added to it.
* Hex escaping is used.
* ----------------------------------------------------------------------------- */
String *Swig_string_hexescape(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, "\\x%X", 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<int, int >' and
* 'std::pair<int,int>', 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, (int)(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, (int)(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, (int)(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, (int)(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) == ':')) {
c += 2;
cc = c;
} else {
if (*c == '<') {
int level = 1;
c++;
while (*c && level) {
if (*c == '<')
level++;
if (*c == '>')
level--;
c++;
}
} else {
c++;
}
}
}
return NewString(cc);
}
/* -----------------------------------------------------------------------------
* 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, (int)(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;
}
/* -----------------------------------------------------------------------------
* Swig_string_rstrip()
*
* Strip given suffix from identifiers
*
* Printf(stderr,"%(rstrip:[Cls])s","HelloCls") -> Hello
* ----------------------------------------------------------------------------- */
String *Swig_string_rstrip(String *s) {
String *ns;
int len = Len(s);
if (!len) {
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 *suffix = NewStringf(fmt, cs+1);
int suffix_len = Len(suffix);
if (0 == Strncmp(cs+len-suffix_len, suffix, suffix_len)) {
int copy_len = len-suffix_len-(ce+1-cs);
ns = NewStringWithSize(ce+1, copy_len);
} else {
ns = NewString(ce+1);
}
}
}
return ns;
}
/* -----------------------------------------------------------------------------
* Swig_offset_string()
*
* Insert number tabs before each new line in s
* ----------------------------------------------------------------------------- */
void Swig_offset_string(String *s, int number) {
char *res, *p, *end, *start;
/* count a number of lines in s */
int lines = 1;
int len = Len(s);
if (len == 0)
return;
start = strchr(Char(s), '\n');
while (start) {
++lines;
start = strchr(start + 1, '\n');
}
/* do not count pending new line */
if ((Char(s))[len-1] == '\n')
--lines;
/* allocate a temporary storage for a padded string */
res = (char*)malloc(len + lines * number * 2 + 1);
res[len + lines * number * 2] = 0;
/* copy lines to res, prepending tabs to each line */
p = res; /* output pointer */
start = Char(s); /* start of a current line */
end = strchr(start, '\n'); /* end of a current line */
while (end) {
memset(p, ' ', number*2);
p += number*2;
memcpy(p, start, end - start + 1);
p += end - start + 1;
start = end + 1;
end = strchr(start, '\n');
}
/* process the last line */
if (*start) {
memset(p, ' ', number*2);
p += number*2;
strcpy(p, start);
}
/* replace 's' contents with 'res' */
Clear(s);
Append(s, res);
free(res);
}
#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, (int)(pate - pats));
*subst = NewStringWithSize(subs, (int)(sube - subs));
*input = p + 1;
return 1;
err_out:
Swig_error("SWIG", Getline(s), "Invalid regex substitution: '%s'.\n", s);
exit(1);
}
/* This function copies len characters from src to dst, possibly applying case conversions to them: if convertCase is 1, to upper case and if it is -1, to lower
* case. If convertNextOnly is 1, only a single character is converted (and convertCase is reset), otherwise all of them are. */
static void copy_with_maybe_case_conversion(String *dst, const char *src, int len, int *convertCase, int convertNextOnly)
{
/* Deal with the trivial cases first. */
if (!len)
return;
if (!*convertCase) {
Write(dst, src, len);
return;
}
/* If we must convert only the first character, do it and write the rest at once. */
if (convertNextOnly) {
int src_char = *src;
Putc(*convertCase == 1 ? toupper(src_char) : tolower(src_char), dst);
*convertCase = 0;
if (len > 1) {
Write(dst, src + 1, len - 1);
}
} else {
/* We need to convert all characters. */
int i;
for (i = 0; i < len; i++, src++) {
int src_char = *src;
Putc(*convertCase == 1 ? toupper(src_char) : tolower(src_char), dst);
}
}
}
String *replace_captures(int num_captures, const char *input, String *subst, int captures[], String *pattern, String *s)
{
int convertCase = 0, convertNextOnly = 0;
String *result = NewStringEmpty();
const char *p = Char(subst);
while (*p) {
/* Copy part without substitutions */
const char *q = strchr(p, '\\');
if (!q) {
copy_with_maybe_case_conversion(result, p, (int)strlen(p), &convertCase, convertNextOnly);
break;
}
copy_with_maybe_case_conversion(result, p, (int)(q - p), &convertCase, convertNextOnly);
p = q + 1;
/* Handle substitution */
if (*p == '\0') {
Putc('\\', result);
} else if (isdigit((unsigned char)*p)) {
int group = *p++ - '0';
if (group < num_captures) {
int l = captures[group*2], r = captures[group*2 + 1];
if (l != -1) {
copy_with_maybe_case_conversion(result, input + l, r - l, &convertCase, convertNextOnly);
}
} else {
Swig_error("SWIG", Getline(s), "PCRE capture replacement failed while matching \"%s\" using \"%s\" - request for group %d is greater than the number of captures %d.\n",
Char(pattern), input, group, num_captures-1);
}
} else {
/* Handle Perl-like case conversion escapes. */
switch (*p) {
case 'u':
convertCase = 1;
convertNextOnly = 1;
break;
case 'U':
convertCase = 1;
convertNextOnly = 0;
break;
case 'l':
convertCase = -1;
convertNextOnly = 1;
break;
case 'L':
convertCase = -1;
convertNextOnly = 0;
break;
case 'E':
convertCase = 0;
break;
default:
Swig_error("SWIG", Getline(s), "Unrecognized escape character '%c' in the replacement string \"%s\".\n",
*p, Char(subst));
}
p++;
}
}
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, (int)strlen(input), 0, 0, captures, 30);
if (rc >= 0) {
res = replace_captures(rc, input, subst, captures, pattern, s);
} else if (rc != PCRE_ERROR_NOMATCH) {
Swig_error("SWIG", Getline(s), "PCRE execution failed: error %d while matching \"%s\" using \"%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("hexescape", Swig_string_hexescape);
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("rstrip", Swig_string_rstrip);
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();
}