too large to be in the parser. Centralize the swig keys to avoid replication and wrong spellings. Use more HashGetAttr where possible and other speed improvements to compensate for the extra work introduced by the new rename/namewarn mechanism. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@8170 626c5289-ae23-0410-ae9c-e8d60b6d4f22
717 lines
16 KiB
C
717 lines
16 KiB
C
/* -----------------------------------------------------------------------------
|
|
* misc.c
|
|
*
|
|
* Miscellaneous functions that don't really fit anywhere else.
|
|
*
|
|
* Author(s) : David Beazley (beazley@cs.uchicago.edu)
|
|
*
|
|
* Copyright (C) 1999-2000. The University of Chicago
|
|
* See the file LICENSE for information on usage and redistribution.
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
char cvsroot_misc_c[] = "$Header$";
|
|
|
|
#include "swig.h"
|
|
#include "swigkeys.h"
|
|
#include <errno.h>
|
|
#include <ctype.h>
|
|
#include <limits.h>
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* 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_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", PACKAGE_VERSION);
|
|
/* String too long for ISO compliance */
|
|
Printf(f,
|
|
" * ----------------------------------------------------------------------------- */\n\n");
|
|
|
|
}
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* 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_ctitle()
|
|
*
|
|
* Takes a string object and returns a copy that is lowercase with thefirst letter
|
|
* capitalized and the one following '_', which are removed.
|
|
*
|
|
* camel_case -> CamelCase
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
String *Swig_string_ctitle(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) : tolower(c),ns);
|
|
first = 0;
|
|
}
|
|
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 = StringChar(b);
|
|
while (*pc) {
|
|
char c = *pc;
|
|
if (isalnum((int)c) || (c == '_')) {
|
|
state = 1;
|
|
if (space && (space == state)) {
|
|
StringAppend(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')) {
|
|
StringAppend(result,"_");
|
|
++pc;
|
|
continue;
|
|
} else {
|
|
c = 'f';
|
|
}
|
|
break;
|
|
case ':':
|
|
if (*(pc + 1) == ':') {
|
|
StringAppend(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);
|
|
}
|
|
|
|
if ((co = strstr(cc,"operator "))) {
|
|
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;
|
|
if ((co = strstr(cc,"operator "))) {
|
|
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);
|
|
|
|
if ((co = strstr(cc,"operator "))) {
|
|
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;
|
|
if ((co = strstr(c,"operator "))) {
|
|
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;
|
|
if ((co = strstr(c,"operator "))) {
|
|
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 = 0;
|
|
if ((co = strstr(c,"operator "))) {
|
|
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()
|
|
*
|
|
* ----------------------------------------------------------------------------- */
|
|
|
|
#if defined(HAVE_POPEN)
|
|
extern FILE *popen(const char *command, const char *type);
|
|
extern int pclose(FILE *stream);
|
|
#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);
|
|
}
|
|
if (!fp || errno) {
|
|
Swig_error("SWIG",Getline(s), "Command encoder fails attempting '%s'.\n", s);
|
|
exit(1);
|
|
}
|
|
}
|
|
#endif
|
|
return res;
|
|
}
|
|
|
|
|
|
/* -----------------------------------------------------------------------------
|
|
* 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_ctitle);
|
|
DohEncoding("typecode",Swig_string_typecode);
|
|
DohEncoding("mangle",Swig_string_emangle);
|
|
DohEncoding("command",Swig_string_command);
|
|
|
|
/* Initialize the swig keys */
|
|
Swig_keys_init();
|
|
|
|
/* Initialize typemaps */
|
|
Swig_typemap_init();
|
|
|
|
/* Initialize symbol table */
|
|
Swig_symbol_init();
|
|
|
|
/* Initialize type system */
|
|
SwigType_typesystem_init();
|
|
|
|
/* Initialize template system */
|
|
SwigType_template_init();
|
|
}
|