special cases and other things in wxPython, and since I plan on making several more, I've decided to put the SWIG sources in wxPython's CVS instead of relying on maintaining patches. This effectivly becomes a fork of an obsolete version of SWIG, :-( but since SWIG 1.3 still doesn't have some things I rely on in 1.1, not to mention that my custom patches would all have to be redone, I felt that this is the easier road to take. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@15307 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
		
			
				
	
	
		
			588 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			588 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/*******************************************************************************
 | 
						|
 * Simplified Wrapper and Interface Generator  (SWIG)
 | 
						|
 * 
 | 
						|
 * Author : David Beazley
 | 
						|
 *
 | 
						|
 * Department of Computer Science        
 | 
						|
 * University of Chicago
 | 
						|
 * 1100 E 58th Street
 | 
						|
 * Chicago, IL  60637
 | 
						|
 * beazley@cs.uchicago.edu
 | 
						|
 *
 | 
						|
 * Please read the file LICENSE for the copyright and terms by which SWIG
 | 
						|
 * can be used and distributed.
 | 
						|
 *******************************************************************************/
 | 
						|
 | 
						|
#include "internal.h"
 | 
						|
#include <ctype.h>
 | 
						|
 | 
						|
//-----------------------------------------------------------------------
 | 
						|
// char *copy_string(char *str)
 | 
						|
//
 | 
						|
// Makes a copy of string str.  Returns a pointer to it.
 | 
						|
//-----------------------------------------------------------------------
 | 
						|
 | 
						|
char *copy_string(char *str) {
 | 
						|
  char *res = 0;
 | 
						|
  if (str) {
 | 
						|
    res = new char[strlen(str)+1];
 | 
						|
    strcpy(res,str);
 | 
						|
  }
 | 
						|
  return res;
 | 
						|
}
 | 
						|
 | 
						|
//-----------------------------------------------------------------------
 | 
						|
// void format_string(char *str)
 | 
						|
//
 | 
						|
// Replace all of the escape sequences in the string str.   It is
 | 
						|
// assumed that the new string is smaller than the original!
 | 
						|
//-----------------------------------------------------------------------
 | 
						|
 | 
						|
void format_string(char *str) {
 | 
						|
  char *newstr, *c,*c1;
 | 
						|
  int  state;
 | 
						|
  if (!str) return;
 | 
						|
  newstr = copy_string(str);
 | 
						|
  c = newstr;
 | 
						|
  c1 = str;
 | 
						|
  state = 0;
 | 
						|
  while (*c) {
 | 
						|
    switch(state) {
 | 
						|
    case 0:
 | 
						|
      if (*c == '\\') 
 | 
						|
	state = 1;
 | 
						|
      else {
 | 
						|
	*(c1++) = *c;
 | 
						|
	state = 0;
 | 
						|
      }
 | 
						|
      break;
 | 
						|
   case 1:
 | 
						|
      // We're in a simple escape sequence figure out what to do
 | 
						|
      switch(*c) {
 | 
						|
      case 'n':
 | 
						|
	*(c1++) = '\n';
 | 
						|
	break;
 | 
						|
      case 'f':
 | 
						|
	*(c1++) = '\f';
 | 
						|
	break;
 | 
						|
      case 'r':
 | 
						|
	*(c1++) = '\r';
 | 
						|
	break;
 | 
						|
      case 't':
 | 
						|
	*(c1++) = '\t';
 | 
						|
	break;
 | 
						|
      case '\\':
 | 
						|
	*(c1++) = '\\';
 | 
						|
      break;
 | 
						|
      case '\"':
 | 
						|
	*(c1++) = '\"';
 | 
						|
      break;
 | 
						|
      case '\'':
 | 
						|
	*(c1++) = '\'';
 | 
						|
      break;
 | 
						|
      default:
 | 
						|
	*(c1++) = '\\';
 | 
						|
        *(c1++) = *c;
 | 
						|
      }
 | 
						|
      state = 0;
 | 
						|
      break;
 | 
						|
    default:
 | 
						|
      *(c1++) = *c;
 | 
						|
      state = 0;
 | 
						|
    }
 | 
						|
    c++;
 | 
						|
  }
 | 
						|
  *c1 = 0;
 | 
						|
  delete newstr;
 | 
						|
}
 | 
						|
 | 
						|
// ---------------------------------------------------------------------------
 | 
						|
// $Header$
 | 
						|
// sstring.cxx
 | 
						|
//
 | 
						|
// SWIG String class.
 | 
						|
// This class is used to construct long strings when writing 
 | 
						|
// wrapper functions.  It also "mimicks" the C++ streams I/O
 | 
						|
// library for creating strings.  For example :
 | 
						|
//
 | 
						|
//     str << "hi there" << 3 << "\n";
 | 
						|
// 
 | 
						|
// Will append the given strings to str.
 | 
						|
//
 | 
						|
// The idea here is to provide a mechanism for writing wrapper
 | 
						|
// functions as strings before writing them out to a file.
 | 
						|
//
 | 
						|
// ---------------------------------------------------------------------------
 | 
						|
#define INIT_MAXSIZE  64
 | 
						|
 | 
						|
// ---------------------------------------------------------------
 | 
						|
// Pools. This is a list of available strings for memory allocation
 | 
						|
// and deletion.
 | 
						|
// ---------------------------------------------------------------
 | 
						|
 | 
						|
struct StrMem {
 | 
						|
  char  *str;
 | 
						|
  int    len;
 | 
						|
};
 | 
						|
 | 
						|
#define POOLSIZE 100
 | 
						|
 | 
						|
static StrMem pool[POOLSIZE];
 | 
						|
static int pool_index = 0;
 | 
						|
 | 
						|
// Returns an item from the pool that can accomodate len
 | 
						|
static char *get_pool(int len, int &newlen) {
 | 
						|
  int i,j;
 | 
						|
  char *nc;
 | 
						|
  if (pool_index < 1) {
 | 
						|
    newlen = len;
 | 
						|
    return new char[len];
 | 
						|
  }
 | 
						|
  i = pool_index-1;
 | 
						|
  j = 0;
 | 
						|
  while(i >= 0) {
 | 
						|
    if ((pool[i].len >= len) && (pool[i].len <= 4*len)) {
 | 
						|
      nc = pool[i].str;
 | 
						|
      newlen = pool[i].len;
 | 
						|
      pool[i].str = pool[pool_index-1].str;
 | 
						|
      pool[i].len = pool[pool_index-1].len;
 | 
						|
      pool_index--;
 | 
						|
      return nc;
 | 
						|
    }
 | 
						|
    j++;
 | 
						|
    i--;
 | 
						|
  }
 | 
						|
  newlen = len;
 | 
						|
  return new char[len];
 | 
						|
}
 | 
						|
 | 
						|
// Puts an item onto the pool
 | 
						|
 | 
						|
static void put_pool(char *str, int len) {
 | 
						|
  if (len < INIT_MAXSIZE) {
 | 
						|
    delete [] str;
 | 
						|
    return;
 | 
						|
  }
 | 
						|
  if (pool_index == POOLSIZE) {
 | 
						|
    delete [] pool[pool_index-1].str;
 | 
						|
    pool_index--;
 | 
						|
  }
 | 
						|
  pool[pool_index].str = str;
 | 
						|
  pool[pool_index].len = len;
 | 
						|
  if (pool_index != POOLSIZE) 
 | 
						|
    pool_index++;
 | 
						|
}
 | 
						|
 | 
						|
// ---------------------------------------------------------------
 | 
						|
// String::String()
 | 
						|
//
 | 
						|
// Create a new string with nothing in it
 | 
						|
// ---------------------------------------------------------------
 | 
						|
 | 
						|
String::String() {
 | 
						|
  maxsize = INIT_MAXSIZE;
 | 
						|
  str = get_pool(maxsize,maxsize);   // May return a pool that is larger
 | 
						|
  str[0] = 0;
 | 
						|
  len = 0;
 | 
						|
}
 | 
						|
 | 
						|
// ---------------------------------------------------------------
 | 
						|
// String::String(const char *s)
 | 
						|
//
 | 
						|
// Create a new string copied from a normal C-style string
 | 
						|
// ---------------------------------------------------------------
 | 
						|
 | 
						|
String::String(const char *s) {
 | 
						|
  int  max = INIT_MAXSIZE;
 | 
						|
  int  l = 0;
 | 
						|
  if (s) {
 | 
						|
    l = (int) strlen(s);
 | 
						|
    if ((l+1) > max) max = l+1;
 | 
						|
  }
 | 
						|
  str = get_pool(max,maxsize);
 | 
						|
  if (s) {
 | 
						|
    strcpy(str,s);
 | 
						|
    len = l;
 | 
						|
  } else {
 | 
						|
    str[0] = 0;
 | 
						|
    len = 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
// ---------------------------------------------------------------
 | 
						|
// String::~String(const char *s)
 | 
						|
//
 | 
						|
// Destroy a string
 | 
						|
// ---------------------------------------------------------------
 | 
						|
 | 
						|
String::~String() {
 | 
						|
  put_pool(str,maxsize);
 | 
						|
}
 | 
						|
 | 
						|
// ---------------------------------------------------------------
 | 
						|
// String::add(const char *newstr)
 | 
						|
//
 | 
						|
// Concatenate newstr onto the current string
 | 
						|
// ---------------------------------------------------------------
 | 
						|
 | 
						|
void String::add(const char *newstr) {
 | 
						|
  int   newlen;
 | 
						|
  char  *nstr = 0;
 | 
						|
  int   newmaxsize;
 | 
						|
  int   l;
 | 
						|
 | 
						|
  l = (int) strlen(newstr);
 | 
						|
  newlen = len+l + 1;
 | 
						|
  if (newlen >= maxsize-1) {
 | 
						|
    newmaxsize = 2*maxsize;
 | 
						|
    if (newlen >= newmaxsize -1) newmaxsize = newlen + 1;
 | 
						|
    nstr = get_pool(newmaxsize,newmaxsize);
 | 
						|
    strcpy(nstr,str);
 | 
						|
    put_pool(str,maxsize);
 | 
						|
    maxsize = newmaxsize;
 | 
						|
    str = nstr;
 | 
						|
  }
 | 
						|
  strcpy(str+len,newstr);
 | 
						|
  len += l;
 | 
						|
}
 | 
						|
 | 
						|
// ---------------------------------------------------------------
 | 
						|
// String::add(char)
 | 
						|
//
 | 
						|
// Adds a single character to the current string
 | 
						|
// ---------------------------------------------------------------
 | 
						|
 | 
						|
void String::add(char nc) {
 | 
						|
  int   newlen;
 | 
						|
  char  *nstr = 0;
 | 
						|
  int   newmaxsize;
 | 
						|
 | 
						|
  newlen = len+ 1;
 | 
						|
  if (newlen >= maxsize-1) {
 | 
						|
    newmaxsize = 2*maxsize;
 | 
						|
    if (newlen >= newmaxsize -1) newmaxsize = newlen + 1;
 | 
						|
    nstr = get_pool(newmaxsize,newmaxsize);
 | 
						|
    strcpy(nstr,str);
 | 
						|
    put_pool(str,maxsize);
 | 
						|
    maxsize = newmaxsize;
 | 
						|
    str = nstr;
 | 
						|
  }
 | 
						|
  str[len++] = nc;
 | 
						|
  str[len] = 0;
 | 
						|
}
 | 
						|
 | 
						|
// -----------------------------------------------------------------
 | 
						|
// String::insert(const char *newstr)
 | 
						|
//
 | 
						|
// Inserts a string into the front of a string.  (Primarily used
 | 
						|
// for documentation generation)
 | 
						|
// -----------------------------------------------------------------
 | 
						|
 | 
						|
void String::insert(const char *newstr) {
 | 
						|
  int  newlen;
 | 
						|
  char *nstr = 0;
 | 
						|
  int  newmaxsize;
 | 
						|
  int  i,l;
 | 
						|
 | 
						|
  l = strlen(newstr);
 | 
						|
  newlen = len + l + 1;
 | 
						|
  if (newlen >= maxsize-1) {
 | 
						|
    newmaxsize = 2*maxsize;
 | 
						|
    if (newlen >= newmaxsize -1) newmaxsize = newlen + 1;
 | 
						|
    nstr = get_pool(newmaxsize,newmaxsize);
 | 
						|
    strcpy(nstr,str);
 | 
						|
    put_pool(str,maxsize);
 | 
						|
    maxsize = newmaxsize;
 | 
						|
    str = nstr;
 | 
						|
  }
 | 
						|
  
 | 
						|
  /* Shift all of the characters over */
 | 
						|
 | 
						|
  for (i = len -1; i >= 0; i--) {
 | 
						|
    str[i+l] = str[i];
 | 
						|
  }
 | 
						|
  
 | 
						|
  /* Now insert the new string */
 | 
						|
 | 
						|
  strncpy(str,newstr,l);
 | 
						|
  len += l;
 | 
						|
  str[len] = 0;                         
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
// -----------------------------------------------------------------
 | 
						|
// char *String::get()
 | 
						|
//
 | 
						|
// Get the current value of the string
 | 
						|
// -----------------------------------------------------------------
 | 
						|
 | 
						|
char *String::get() const {
 | 
						|
  return str;
 | 
						|
}
 | 
						|
 | 
						|
// -----------------------------------------------------------------
 | 
						|
// String &operator<<(...)
 | 
						|
//
 | 
						|
// Shorthand for appending to the end of a string
 | 
						|
// -----------------------------------------------------------------
 | 
						|
 | 
						|
String &operator<<(String &t,const char *s) {
 | 
						|
  t.add(s);
 | 
						|
  return t;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
String &operator<<(String &t,const char s) {
 | 
						|
  t.add(s);
 | 
						|
  return t;
 | 
						|
}
 | 
						|
 | 
						|
String &operator<<(String &t,const int a) {
 | 
						|
  char  temp[64];
 | 
						|
  sprintf(temp,"%d",a);
 | 
						|
  t.add(temp);
 | 
						|
  return t;
 | 
						|
}
 | 
						|
 | 
						|
String &operator<<(String &t, String &s) {
 | 
						|
  t.add(s.get());
 | 
						|
  return t;
 | 
						|
}
 | 
						|
 | 
						|
String &String::operator=(const char *s) {
 | 
						|
  int newlen;
 | 
						|
 | 
						|
  if (s) {
 | 
						|
    newlen = strlen(s);
 | 
						|
    if ((newlen >= maxsize) && (str)) {
 | 
						|
      put_pool(str,maxsize);
 | 
						|
      str = get_pool(newlen+1,maxsize);
 | 
						|
      maxsize = newlen+1;
 | 
						|
    }
 | 
						|
    strcpy(str,s);
 | 
						|
    len = newlen;
 | 
						|
  } else {
 | 
						|
    str[0] = 0;
 | 
						|
    len = 0;
 | 
						|
  }
 | 
						|
  return *this;
 | 
						|
}
 | 
						|
 | 
						|
// -----------------------------------------------------------------
 | 
						|
// String &operator>>(...)
 | 
						|
//
 | 
						|
// Shorthand for inserting into the beginning of a string
 | 
						|
// -----------------------------------------------------------------
 | 
						|
 | 
						|
String &operator>>(const char *s, String &t) {
 | 
						|
  t.insert(s);
 | 
						|
  return t;
 | 
						|
}
 | 
						|
 | 
						|
String &operator>>(String &s, String &t) {
 | 
						|
  t.insert(s.get());
 | 
						|
  return t;
 | 
						|
}
 | 
						|
 | 
						|
// -----------------------------------------------------------------
 | 
						|
// void String::untabify()
 | 
						|
//
 | 
						|
// Expand all tabs into spaces.   This is useful for producing
 | 
						|
// documentation and other things.
 | 
						|
// -----------------------------------------------------------------
 | 
						|
 | 
						|
void String::untabify() {
 | 
						|
  char *s;
 | 
						|
  char *c;
 | 
						|
  int   pos;
 | 
						|
  int   i;
 | 
						|
  int   oldmaxsize;
 | 
						|
  // Copy the current string representation
 | 
						|
 | 
						|
  s = str;
 | 
						|
  oldmaxsize = maxsize;
 | 
						|
 | 
						|
  // Reset the internal state of this string
 | 
						|
 | 
						|
  len = 0;
 | 
						|
  str = get_pool(maxsize,maxsize);
 | 
						|
  str[0]= 0;
 | 
						|
 | 
						|
  // Now walk down the old string and expand tabs.  Tabs are usually place
 | 
						|
  // every 8 characters.
 | 
						|
 | 
						|
  pos = 0;
 | 
						|
  c = s;
 | 
						|
  while (*c) {
 | 
						|
    if (*c == '\n') {
 | 
						|
      pos = -1;
 | 
						|
    }
 | 
						|
    if (*c == '\t') {
 | 
						|
      // Expand the character
 | 
						|
      for (i = 0; i < (8 - (pos % 8)); i++) {
 | 
						|
	this->add(' ');
 | 
						|
      }
 | 
						|
      pos+=(8-(pos % 8));
 | 
						|
    } else {
 | 
						|
      this->add(*c);
 | 
						|
      pos++;
 | 
						|
    }
 | 
						|
    c++;
 | 
						|
  }
 | 
						|
 | 
						|
  // Blow away the old string
 | 
						|
  put_pool(s,oldmaxsize);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// -----------------------------------------------------------------
 | 
						|
// void String::replace(const char *token, const char *rep)
 | 
						|
//
 | 
						|
// Search for tokens in a string and replace them with rep.
 | 
						|
// This probably isn't the fastest implementation, but fortunately
 | 
						|
// SWIG rarely calls this function.
 | 
						|
// -----------------------------------------------------------------
 | 
						|
 | 
						|
void String::replace(const char *token, const char *rep) {
 | 
						|
  char *s, *c, *t;
 | 
						|
  int  oldmaxsize = maxsize;
 | 
						|
  // Copy the current string representation
 | 
						|
 | 
						|
  s = str;
 | 
						|
 | 
						|
  // Now walk down the old string and search for tokens
 | 
						|
 | 
						|
  c = s;
 | 
						|
  t = strstr(c,token);
 | 
						|
  if (t) {
 | 
						|
    len = 0;
 | 
						|
    str = get_pool(maxsize,maxsize);
 | 
						|
    while (t) {
 | 
						|
      // Found a token in string s
 | 
						|
      // Dump characters into our string
 | 
						|
      char temp;
 | 
						|
      temp = *t;
 | 
						|
      *t = 0;
 | 
						|
      this->add(c);
 | 
						|
      c = t;
 | 
						|
      *t = temp;
 | 
						|
 | 
						|
      // Now dump the replacement string into place
 | 
						|
 | 
						|
      this->add(rep);
 | 
						|
      
 | 
						|
      // Jump over the token
 | 
						|
      
 | 
						|
      c+=strlen(token);
 | 
						|
      t = strstr(c,token);
 | 
						|
    }
 | 
						|
    // Attach rest of the string
 | 
						|
    if (*c) 
 | 
						|
      this->add(c);
 | 
						|
    put_pool(s,oldmaxsize);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// -----------------------------------------------------------------
 | 
						|
// void String::replaceid(char *token, char *rep)
 | 
						|
//
 | 
						|
// Searches for valid identifiers matching token and replaces
 | 
						|
// them with rep.    Unlike replace() tokens must be a valid C
 | 
						|
// identifier (surrounded by whitespace).
 | 
						|
// -----------------------------------------------------------------
 | 
						|
 | 
						|
void String::replaceid(const char *token, const char *rep) {
 | 
						|
  char *s, *c, *t;
 | 
						|
  int  whitespace, tokenlen;
 | 
						|
  int  oldmaxsize = maxsize;
 | 
						|
  // Copy the current string representation
 | 
						|
 | 
						|
  s = str;
 | 
						|
 | 
						|
  // Reset the internal state of this string
 | 
						|
 | 
						|
  tokenlen = strlen(token);
 | 
						|
 | 
						|
  // Now walk down the old string and search for tokens
 | 
						|
 | 
						|
  c = s;
 | 
						|
  t = strstr(c,token);
 | 
						|
  if (t) {
 | 
						|
    len = 0;
 | 
						|
    str = get_pool(maxsize,maxsize);
 | 
						|
    while (t) {
 | 
						|
      // Found a token in string s
 | 
						|
      // Dump characters into our string
 | 
						|
 | 
						|
      whitespace = 1;
 | 
						|
      while (c != t) {
 | 
						|
	this->add(*c);
 | 
						|
	if (!(isalpha(*c) || (*c == '_') || (*c == '$'))) whitespace = 1;
 | 
						|
	else whitespace = 0;
 | 
						|
	c++;
 | 
						|
      }
 | 
						|
    
 | 
						|
      if (whitespace) {
 | 
						|
	// Check to see if there is whitespace afterwards
 | 
						|
	if ((!c[tokenlen]) || (!(isalnum(c[tokenlen]) || (c[tokenlen] == '_') || (c[tokenlen] == '$')))) {
 | 
						|
	  this->add(rep);
 | 
						|
	} else {
 | 
						|
	  this->add(token);
 | 
						|
	}
 | 
						|
	c+=tokenlen;
 | 
						|
      } else {
 | 
						|
	this->add(*c);
 | 
						|
	c++;
 | 
						|
      }
 | 
						|
      t = strstr(c,token);
 | 
						|
    }
 | 
						|
 | 
						|
    // Attach rest of the string
 | 
						|
    if (*c) 
 | 
						|
      this->add(c);
 | 
						|
 | 
						|
    // Delete the old string
 | 
						|
    put_pool(s,oldmaxsize);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
// -----------------------------------------------------------------
 | 
						|
// void String::strip()
 | 
						|
//
 | 
						|
// Intelligently strips whitespace from a string.    Will not strip
 | 
						|
// whitespace if it is between two characters that are part of a
 | 
						|
// legal C identifier. For example 'unsigned int'.
 | 
						|
// -----------------------------------------------------------------
 | 
						|
 | 
						|
void String::strip() {
 | 
						|
  char *s = str;          // Old pointer value
 | 
						|
  char *c, lastchar = 0;    
 | 
						|
  int   whitespace = 0;
 | 
						|
  int   oldmaxsize = maxsize;
 | 
						|
 | 
						|
  str = get_pool(maxsize,maxsize);   // Get a new string.
 | 
						|
  len = 0;
 | 
						|
 | 
						|
  c = s;
 | 
						|
  while(*c) {
 | 
						|
    if (!isspace(*c)) {
 | 
						|
      // See if this character doesn't violate our whitespace rules
 | 
						|
      if (whitespace) {
 | 
						|
	if (isalnum(lastchar) || (lastchar == '_') || (lastchar == '$')) {
 | 
						|
	  if (isalnum(*c) || (*c == '_') || (*c == '$')) 
 | 
						|
	    this->add(' ');
 | 
						|
	}
 | 
						|
      }
 | 
						|
      this->add(*c);
 | 
						|
      lastchar = *c;
 | 
						|
      whitespace = 0;
 | 
						|
    } else {
 | 
						|
      whitespace = 1;
 | 
						|
    }
 | 
						|
    c++;
 | 
						|
  }
 | 
						|
  put_pool(s,oldmaxsize);
 | 
						|
}
 |