blob: d2925051726a9f2c5f33f1e14c3810d9089aa266 [file] [log] [blame]
/* -----------------------------------------------------------------------------
* See the LICENSE file for information on copyright, usage and redistribution
* of SWIG, and the README file for authors - http://www.swig.org/release.html.
*
* misc.c
*
* Miscellaneous functions that don't really fit anywhere else.
* ----------------------------------------------------------------------------- */
char cvsroot_misc_c[] = "$Id$";
#include "swig.h"
#include <errno.h>
#include <ctype.h>
#include <limits.h>
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.
* ----------------------------------------------------------------------------- */
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\n");
}
/* -----------------------------------------------------------------------------
* Swig_strip_c_comments()
*
* Return a new string with C comments stripped from the input string. Null is
* returned if there aren't any.
* ----------------------------------------------------------------------------- */
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;
}
/* -----------------------------------------------------------------------------
* 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<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(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(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(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(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(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
* ----------------------------------------------------------------------------- */
int Swig_scopename_check(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_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;
}
#if defined(USE_RXSPENCER)
String *Swig_string_rxspencer(String *s) {
String *res = 0;
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 = Strchr(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 = Strchr(res, '@');
} else if (cd == '@') {
spos = strchr(spos + 1, '@');
}
}
}
free(pmatch);
}
}
}
regfree(&compiled);
}
}
}
if (!res)
res = NewStringEmpty();
return res;
}
#else
String *Swig_string_rxspencer(String *s) {
(void) s;
return NewStringEmpty();
}
#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("rxspencer", Swig_string_rxspencer);
DohEncoding("schemify", Swig_string_schemify);
/* 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();
}