Kaynağa Gözat

Some fixes from squirrel 3.1 and convert to only LF.

mingodad 10 yıl önce
ebeveyn
işleme
d626a01129

+ 659 - 661
SquiLu/sqstdlib/sqstdrex.cpp

@@ -1,667 +1,665 @@
-/* see copyright notice in squirrel.h */
-#include <squirrel.h>
-#include <string.h>
-#include <ctype.h>
-#include <setjmp.h>
-#include <sqstdstring.h>
-
-#ifdef _UINCODE
-#define scisprint iswprint
-#else
-#define scisprint isprint
-#endif
-
-#ifdef _DEBUG
-#include <stdio.h>
-
-static const SQChar *g_nnames[] =
-{
-	_SC("NONE"),_SC("OP_GREEDY"),	_SC("OP_OR"),
-	_SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"),	_SC("OP_CLASS"),
-	_SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),
-	_SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB"),_C("OP_MB")
-};
-
-#endif
-
-#define OP_GREEDY		(MAX_CHAR+1) // * + ? {n}
-#define OP_OR			(MAX_CHAR+2)
-#define OP_EXPR			(MAX_CHAR+3) //parentesis ()
-#define OP_NOCAPEXPR	(MAX_CHAR+4) //parentesis (?:)
-#define OP_DOT			(MAX_CHAR+5)
-#define OP_CLASS		(MAX_CHAR+6)
-#define OP_CCLASS		(MAX_CHAR+7)
-#define OP_NCLASS		(MAX_CHAR+8) //negates class the [^
-#define OP_RANGE		(MAX_CHAR+9)
-#define OP_CHAR			(MAX_CHAR+10)
-#define OP_EOL			(MAX_CHAR+11)
-#define OP_BOL			(MAX_CHAR+12)
-#define OP_WB			(MAX_CHAR+13)
-#define OP_MB           (MAX_CHAR+14) //match balanced
-
-#define SQREX_SYMBOL_ANY_CHAR ('.')
-#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
-#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*')
-#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?')
-#define SQREX_SYMBOL_BRANCH ('|')
-#define SQREX_SYMBOL_END_OF_STRING ('$')
-#define SQREX_SYMBOL_BEGINNING_OF_STRING ('^')
-#define SQREX_SYMBOL_ESCAPE_CHAR ('\\')
-
-
-typedef int SQRexNodeType;
-
-typedef struct tagSQRexNode{
-	SQRexNodeType type;
-	SQInteger left;
-	SQInteger right;
-	SQInteger next;
-}SQRexNode;
-
-struct SQRex{
-	const SQChar *_eol;
-	const SQChar *_bol;
-	const SQChar *_p;
-	SQInteger _first;
-	SQInteger _op;
-	SQRexNode *_nodes;
-	SQInteger _nallocated;
-	SQInteger _nsize;
-	SQInteger _nsubexpr;
-	SQRexMatch *_matches;
-	SQInteger _currsubexp;
-	void *_jmpbuf;
-	const SQChar **_error;
-};
-
-static SQInteger sqstd_rex_list(SQRex *exp);
-
-static SQInteger sqstd_rex_newnode(SQRex *exp, SQRexNodeType type)
-{
-	SQRexNode n;
-	n.type = type;
-	n.next = n.right = n.left = -1;
-	if(type == OP_EXPR)
-		n.right = exp->_nsubexpr++;
-	if(exp->_nallocated < (exp->_nsize + 1)) {
-		SQInteger oldsize = exp->_nallocated;
-		exp->_nallocated *= 2;
-		exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode));
-	}
-	exp->_nodes[exp->_nsize++] = n;
-	SQInteger newid = exp->_nsize - 1;
-	return (SQInteger)newid;
-}
-
-static void sqstd_rex_error(SQRex *exp,const SQChar *error)
-{
-	if(exp->_error) *exp->_error = error;
-	longjmp(*((jmp_buf*)exp->_jmpbuf),-1);
-}
-
-static void sqstd_rex_expect(SQRex *exp, SQInteger n){
-	if((*exp->_p) != n)
-		sqstd_rex_error(exp, _SC("expected paren"));
-	exp->_p++;
-}
-
-static SQChar sqstd_rex_escapechar(SQRex *exp)
-{
-	if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){
-		exp->_p++;
-		switch(*exp->_p) {
-		case 'v': exp->_p++; return '\v';
-		case 'n': exp->_p++; return '\n';
-		case 't': exp->_p++; return '\t';
-		case 'r': exp->_p++; return '\r';
-		case 'f': exp->_p++; return '\f';
-		default: return (*exp->_p++);
-		}
-	} else if(!scisprint(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected"));
-	return (*exp->_p++);
-}
-
-static SQInteger sqstd_rex_charclass(SQRex *exp,SQInteger classid)
-{
-	SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS);
-	exp->_nodes[n].left = classid;
-	return n;
-}
-
-static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass)
-{
-	SQChar t;
-	if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) {
-		exp->_p++;
-		switch(*exp->_p) {
-			case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n');
-			case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t');
-			case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r');
-			case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f');
-			case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v');
-			case 'a': case 'A': case 'w': case 'W': case 's': case 'S':
-			case 'd': case 'D': case 'x': case 'X': case 'c': case 'C':
-			case 'p': case 'P': case 'l': case 'u':
-				{
-				t = *exp->_p; exp->_p++;
-				return sqstd_rex_charclass(exp,t);
-				}
-            case 'm':
-                {
-                     SQChar cb, ce; //cb = character begin match ce = character end match
-                     cb = *++exp->_p; //skip 'm'
-                     ce = *++exp->_p;
-                     exp->_p++; //points to the next char to be parsed
-                     if ((!cb) || (!ce)) sqstd_rex_error(exp,_SC("balanced chars expected"));
-                     if ( cb == ce ) sqstd_rex_error(exp,_SC("open/close char can't be the same"));
-                     SQInteger node =  sqstd_rex_newnode(exp,OP_MB);
-                     exp->_nodes[node].left = cb;
-                     exp->_nodes[node].right = ce;
-                     return node;
-                }
-			case 'b':
-			case 'B':
-				if(!isclass) {
-					SQInteger node = sqstd_rex_newnode(exp,OP_WB);
-					exp->_nodes[node].left = *exp->_p;
-					exp->_p++;
-					return node;
-				} //else default
-			default:
-				t = *exp->_p; exp->_p++;
-				return sqstd_rex_newnode(exp,t);
-		}
-	}
-	else if(!scisprint(*exp->_p)) {
-
-		sqstd_rex_error(exp,_SC("letter expected"));
-	}
-	t = *exp->_p; exp->_p++;
-	return sqstd_rex_newnode(exp,t);
-}
-static SQInteger sqstd_rex_class(SQRex *exp)
-{
-	SQInteger ret = -1;
-	SQInteger first = -1,chain;
-	if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){
-		ret = sqstd_rex_newnode(exp,OP_NCLASS);
-		exp->_p++;
-	}else ret = sqstd_rex_newnode(exp,OP_CLASS);
-
-	if(*exp->_p == ']') sqstd_rex_error(exp,_SC("empty class"));
-	chain = ret;
-	while(*exp->_p != ']' && exp->_p != exp->_eol) {
-		if(*exp->_p == '-' && first != -1){
-			SQInteger r;
-			if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range"));
-			r = sqstd_rex_newnode(exp,OP_RANGE);
-			if(exp->_nodes[first].type>*exp->_p) sqstd_rex_error(exp,_SC("invalid range"));
-			if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges"));
-			exp->_nodes[r].left = exp->_nodes[first].type;
-			SQInteger t = sqstd_rex_escapechar(exp);
-			exp->_nodes[r].right = t;
-            exp->_nodes[chain].next = r;
-			chain = r;
-			first = -1;
-		}
-		else{
-			if(first!=-1){
-				SQInteger c = first;
-				exp->_nodes[chain].next = c;
-				chain = c;
-				first = sqstd_rex_charnode(exp,SQTrue);
-			}
-			else{
-				first = sqstd_rex_charnode(exp,SQTrue);
-			}
-		}
-	}
-	if(first!=-1){
-		SQInteger c = first;
-		exp->_nodes[chain].next = c;
-		//chain = c;
-		//first = -1;
-	}
-	/* hack? */
-	exp->_nodes[ret].left = exp->_nodes[ret].next;
-	exp->_nodes[ret].next = -1;
-	return ret;
-}
-
-static SQInteger sqstd_rex_parsenumber(SQRex *exp)
-{
-	SQInteger ret = *exp->_p-'0';
-	SQInteger positions = 10;
-	exp->_p++;
-	while(isdigit(*exp->_p)) {
-		ret = ret*10+(*exp->_p++-'0');
-		if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant"));
-		positions *= 10;
-	};
-	return ret;
-}
-
-static SQInteger sqstd_rex_element(SQRex *exp)
-{
-	SQInteger ret = -1;
-	switch(*exp->_p)
-	{
-	case '(': {
-		SQInteger expr;
-		exp->_p++;
-
-
-		if(*exp->_p =='?') {
-			exp->_p++;
-			sqstd_rex_expect(exp,':');
-			expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR);
-		}
-		else
-			expr = sqstd_rex_newnode(exp,OP_EXPR);
-		SQInteger newn = sqstd_rex_list(exp);
-		exp->_nodes[expr].left = newn;
-		ret = expr;
-		sqstd_rex_expect(exp,')');
-			  }
-			  break;
-	case '[':
-		exp->_p++;
-		ret = sqstd_rex_class(exp);
-		sqstd_rex_expect(exp,']');
-		break;
-	case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break;
-	case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break;
-	default:
-		ret = sqstd_rex_charnode(exp,SQFalse);
-		break;
-	}
-
-
-	SQBool isgreedy = SQFalse;
-	unsigned short p0 = 0, p1 = 0;
-	switch(*exp->_p){
-		case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
-		case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
-		case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = SQTrue; break;
-		case '{':
-			exp->_p++;
-			if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected"));
-			p0 = (unsigned short)sqstd_rex_parsenumber(exp);
-			/*******************************/
-			switch(*exp->_p) {
-		case '}':
-			p1 = p0; exp->_p++;
-			break;
-		case ',':
-			exp->_p++;
-			p1 = 0xFFFF;
-			if(isdigit(*exp->_p)){
-				p1 = (unsigned short)sqstd_rex_parsenumber(exp);
-			}
-			sqstd_rex_expect(exp,'}');
-			break;
-		default:
-			sqstd_rex_error(exp,_SC(", or } expected"));
-			}
-			/*******************************/
-			isgreedy = SQTrue;
-			break;
-
-	}
-	if(isgreedy) {
-		SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY);
-		exp->_nodes[nnode].left = ret;
-		exp->_nodes[nnode].right = ((p0)<<16)|p1;
-		ret = nnode;
-	}
-
-	if((*exp->_p != SQREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) {
-		SQInteger nnode = sqstd_rex_element(exp);
-		exp->_nodes[ret].next = nnode;
-	}
-
-	return ret;
-}
-
-static SQInteger sqstd_rex_list(SQRex *exp)
-{
-	SQInteger ret=-1,e;
-	if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) {
-		exp->_p++;
-		ret = sqstd_rex_newnode(exp,OP_BOL);
-	}
-	e = sqstd_rex_element(exp);
-	if(ret != -1) {
-		exp->_nodes[ret].next = e;
-	}
-	else ret = e;
-
-	if(*exp->_p == SQREX_SYMBOL_BRANCH) {
-		SQInteger temp,tright;
-		exp->_p++;
-		temp = sqstd_rex_newnode(exp,OP_OR);
-		exp->_nodes[temp].left = ret;
-		tright = sqstd_rex_list(exp);
-		exp->_nodes[temp].right = tright;
-		ret = temp;
-	}
-	return ret;
-}
-
-static SQBool sqstd_rex_matchcclass(SQInteger cclass,SQChar c)
-{
-	switch(cclass) {
-	case 'a': return isalpha(c)?SQTrue:SQFalse;
-	case 'A': return !isalpha(c)?SQTrue:SQFalse;
-	case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse;
-	case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse;
-	case 's': return isspace(c)?SQTrue:SQFalse;
-	case 'S': return !isspace(c)?SQTrue:SQFalse;
-	case 'd': return isdigit(c)?SQTrue:SQFalse;
-	case 'D': return !isdigit(c)?SQTrue:SQFalse;
-	case 'x': return isxdigit(c)?SQTrue:SQFalse;
-	case 'X': return !isxdigit(c)?SQTrue:SQFalse;
-	case 'c': return iscntrl(c)?SQTrue:SQFalse;
-	case 'C': return !iscntrl(c)?SQTrue:SQFalse;
-	case 'p': return ispunct(c)?SQTrue:SQFalse;
-	case 'P': return !ispunct(c)?SQTrue:SQFalse;
-	case 'l': return islower(c)?SQTrue:SQFalse;
-	case 'u': return isupper(c)?SQTrue:SQFalse;
-	}
-	return SQFalse; /*cannot happen*/
-}
-
-static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c)
-{
-	do {
-		switch(node->type) {
-			case OP_RANGE:
-				if(c >= node->left && c <= node->right) return SQTrue;
-				break;
-			case OP_CCLASS:
-				if(sqstd_rex_matchcclass(node->left,c)) return SQTrue;
-				break;
-			default:
-				if(c == node->type)return SQTrue;
-		}
-	} while((node->next != -1) && (node = &exp->_nodes[node->next]));
-	return SQFalse;
-}
-
-static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str,SQRexNode *next)
-{
-
-	SQRexNodeType type = node->type;
-	switch(type) {
-	case OP_GREEDY: {
-		//SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL;
-		SQRexNode *greedystop = NULL;
-		SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
-		const SQChar *s=str, *good = str;
-
-		if(node->next != -1) {
-			greedystop = &exp->_nodes[node->next];
-		}
-		else {
-			greedystop = next;
-		}
-
-		while((nmaches == 0xFFFF || nmaches < p1)) {
-
-			const SQChar *stop;
-			if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop)))
-				break;
-			nmaches++;
-			good=s;
-			if(greedystop) {
-				//checks that 0 matches satisfy the expression(if so skips)
-				//if not would always stop(for instance if is a '?')
-				if(greedystop->type != OP_GREEDY ||
-				(greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0))
-				{
-					SQRexNode *gnext = NULL;
-					if(greedystop->next != -1) {
-						gnext = &exp->_nodes[greedystop->next];
-					}else if(next && next->next != -1){
-						gnext = &exp->_nodes[next->next];
-					}
-					stop = sqstd_rex_matchnode(exp,greedystop,s,gnext);
-					if(stop) {
-						//if satisfied stop it
-						if(p0 == p1 && p0 == nmaches) break;
-						else if(nmaches >= p0 && p1 == 0xFFFF) break;
-						else if(nmaches >= p0 && nmaches <= p1) break;
-					}
-				}
-			}
-
-			if(s >= exp->_eol)
-				break;
-		}
-		if(p0 == p1 && p0 == nmaches) return good;
-		else if(nmaches >= p0 && p1 == 0xFFFF) return good;
-		else if(nmaches >= p0 && nmaches <= p1) return good;
-		return NULL;
-	}
-	case OP_OR: {
-			const SQChar *asd = str;
-			SQRexNode *temp=&exp->_nodes[node->left];
-			while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) {
-				if(temp->next != -1)
-					temp = &exp->_nodes[temp->next];
-				else
-					return asd;
-			}
-			asd = str;
-			temp = &exp->_nodes[node->right];
-			while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) {
-				if(temp->next != -1)
-					temp = &exp->_nodes[temp->next];
-				else
-					return asd;
-			}
-			return NULL;
-			break;
-	}
-	case OP_EXPR:
-	case OP_NOCAPEXPR:{
-			SQRexNode *n = &exp->_nodes[node->left];
-			const SQChar *cur = str;
-			SQInteger capture = -1;
-			if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
-				capture = exp->_currsubexp;
-				exp->_matches[capture].begin = cur;
-				exp->_currsubexp++;
-			}
-			int tempcap = exp->_currsubexp;
-			do {
-				SQRexNode *subnext = NULL;
-				if(n->next != -1) {
-					subnext = &exp->_nodes[n->next];
-				}else {
-					subnext = next;
-				}
-				if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) {
-					if(capture != -1){
-						exp->_matches[capture].begin = 0;
-						exp->_matches[capture].len = 0;
-					}
-					return NULL;
-				}
-			} while((n->next != -1) && (n = &exp->_nodes[n->next]));
-
-			exp->_currsubexp = tempcap;
-			if(capture != -1)
-				exp->_matches[capture].len = cur - exp->_matches[capture].begin;
-			return cur;
-	}
-	case OP_WB:
-		if((str == exp->_bol && !isspace(*str))
-		 || (str == exp->_eol && !isspace(*(str-1)))
-		 || (!isspace(*str) && isspace(*(str+1)))
-		 || (isspace(*str) && !isspace(*(str+1))) ) {
-			return (node->left == 'b')?str:NULL;
-		}
-		return (node->left == 'b')?NULL:str;
-	case OP_BOL:
-		if(str == exp->_bol) return str;
-		return NULL;
-	case OP_EOL:
-		if(str == exp->_eol) return str;
-		return NULL;
-	case OP_DOT:{
-		str++;
-				}
-		return str;
-	case OP_NCLASS:
-	case OP_CLASS:
-		if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) {
-			str++;
-			return str;
-		}
-		return NULL;
-	case OP_CCLASS:
-		if(sqstd_rex_matchcclass(node->left,*str)) {
-			str++;
-			return str;
-		}
-		return NULL;
-    case OP_MB:
-        {
-            int cb = node->left; //char that opens a balanced expression
-            if(*str != cb) return NULL; // string doesnt start with open char
-            int ce = node->right; //char that closes a balanced expression
-            int cont = 1;
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <string.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <sqstdstring.h>
+
+#ifdef _UINCODE
+#define scisprint iswprint
+#else
+#define scisprint isprint
+#endif
+
+#ifdef _DEBUG
+#include <stdio.h>
+
+static const SQChar *g_nnames[] =
+{
+	_SC("NONE"),_SC("OP_GREEDY"),	_SC("OP_OR"),
+	_SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"),	_SC("OP_CLASS"),
+	_SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),
+	_SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB"),_C("OP_MB")
+};
+
+#endif
+
+#define OP_GREEDY		(MAX_CHAR+1) // * + ? {n}
+#define OP_OR			(MAX_CHAR+2)
+#define OP_EXPR			(MAX_CHAR+3) //parentesis ()
+#define OP_NOCAPEXPR	(MAX_CHAR+4) //parentesis (?:)
+#define OP_DOT			(MAX_CHAR+5)
+#define OP_CLASS		(MAX_CHAR+6)
+#define OP_CCLASS		(MAX_CHAR+7)
+#define OP_NCLASS		(MAX_CHAR+8) //negates class the [^
+#define OP_RANGE		(MAX_CHAR+9)
+#define OP_CHAR			(MAX_CHAR+10)
+#define OP_EOL			(MAX_CHAR+11)
+#define OP_BOL			(MAX_CHAR+12)
+#define OP_WB			(MAX_CHAR+13)
+#define OP_MB           (MAX_CHAR+14) //match balanced
+
+#define SQREX_SYMBOL_ANY_CHAR ('.')
+#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
+#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*')
+#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?')
+#define SQREX_SYMBOL_BRANCH ('|')
+#define SQREX_SYMBOL_END_OF_STRING ('$')
+#define SQREX_SYMBOL_BEGINNING_OF_STRING ('^')
+#define SQREX_SYMBOL_ESCAPE_CHAR ('\\')
+
+
+typedef int SQRexNodeType;
+
+typedef struct tagSQRexNode{
+	SQRexNodeType type;
+	SQInteger left;
+	SQInteger right;
+	SQInteger next;
+}SQRexNode;
+
+struct SQRex{
+	const SQChar *_eol;
+	const SQChar *_bol;
+	const SQChar *_p;
+	SQInteger _first;
+	SQInteger _op;
+	SQRexNode *_nodes;
+	SQInteger _nallocated;
+	SQInteger _nsize;
+	SQInteger _nsubexpr;
+	SQRexMatch *_matches;
+	SQInteger _currsubexp;
+	void *_jmpbuf;
+	const SQChar **_error;
+};
+
+static SQInteger sqstd_rex_list(SQRex *exp);
+
+static SQInteger sqstd_rex_newnode(SQRex *exp, SQRexNodeType type)
+{
+	SQRexNode n;
+	n.type = type;
+	n.next = n.right = n.left = -1;
+	if(type == OP_EXPR)
+		n.right = exp->_nsubexpr++;
+	if(exp->_nallocated < (exp->_nsize + 1)) {
+		SQInteger oldsize = exp->_nallocated;
+		exp->_nallocated *= 2;
+		exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode));
+	}
+	exp->_nodes[exp->_nsize++] = n;
+	SQInteger newid = exp->_nsize - 1;
+	return (SQInteger)newid;
+}
+
+static void sqstd_rex_error(SQRex *exp,const SQChar *error)
+{
+	if(exp->_error) *exp->_error = error;
+	longjmp(*((jmp_buf*)exp->_jmpbuf),-1);
+}
+
+static void sqstd_rex_expect(SQRex *exp, SQInteger n){
+	if((*exp->_p) != n)
+		sqstd_rex_error(exp, _SC("expected paren"));
+	exp->_p++;
+}
+
+static SQChar sqstd_rex_escapechar(SQRex *exp)
+{
+	if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){
+		exp->_p++;
+		switch(*exp->_p) {
+		case 'v': exp->_p++; return '\v';
+		case 'n': exp->_p++; return '\n';
+		case 't': exp->_p++; return '\t';
+		case 'r': exp->_p++; return '\r';
+		case 'f': exp->_p++; return '\f';
+		default: return (*exp->_p++);
+		}
+	} else if(!scisprint(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected"));
+	return (*exp->_p++);
+}
+
+static SQInteger sqstd_rex_charclass(SQRex *exp,SQInteger classid)
+{
+	SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS);
+	exp->_nodes[n].left = classid;
+	return n;
+}
+
+static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass)
+{
+	SQChar t;
+	if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) {
+		exp->_p++;
+		switch(*exp->_p) {
+			case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n');
+			case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t');
+			case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r');
+			case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f');
+			case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v');
+			case 'a': case 'A': case 'w': case 'W': case 's': case 'S':
+			case 'd': case 'D': case 'x': case 'X': case 'c': case 'C':
+			case 'p': case 'P': case 'l': case 'u':
+				{
+				t = *exp->_p; exp->_p++;
+				return sqstd_rex_charclass(exp,t);
+				}
+            case 'm':
+                {
+                     SQChar cb, ce; //cb = character begin match ce = character end match
+                     cb = *++exp->_p; //skip 'm'
+                     ce = *++exp->_p;
+                     exp->_p++; //points to the next char to be parsed
+                     if ((!cb) || (!ce)) sqstd_rex_error(exp,_SC("balanced chars expected"));
+                     if ( cb == ce ) sqstd_rex_error(exp,_SC("open/close char can't be the same"));
+                     SQInteger node =  sqstd_rex_newnode(exp,OP_MB);
+                     exp->_nodes[node].left = cb;
+                     exp->_nodes[node].right = ce;
+                     return node;
+                }
+			case 'b':
+			case 'B':
+				if(!isclass) {
+					SQInteger node = sqstd_rex_newnode(exp,OP_WB);
+					exp->_nodes[node].left = *exp->_p;
+					exp->_p++;
+					return node;
+				} //else default
+			default:
+				t = *exp->_p; exp->_p++;
+				return sqstd_rex_newnode(exp,t);
+		}
+	}
+	else if(!scisprint(*exp->_p)) {
+
+		sqstd_rex_error(exp,_SC("letter expected"));
+	}
+	t = *exp->_p; exp->_p++;
+	return sqstd_rex_newnode(exp,t);
+}
+static SQInteger sqstd_rex_class(SQRex *exp)
+{
+	SQInteger ret = -1;
+	SQInteger first = -1,chain;
+	if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){
+		ret = sqstd_rex_newnode(exp,OP_NCLASS);
+		exp->_p++;
+	}else ret = sqstd_rex_newnode(exp,OP_CLASS);
+
+	if(*exp->_p == ']') sqstd_rex_error(exp,_SC("empty class"));
+	chain = ret;
+	while(*exp->_p != ']' && exp->_p != exp->_eol) {
+		if(*exp->_p == '-' && first != -1){
+			SQInteger r;
+			if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range"));
+			r = sqstd_rex_newnode(exp,OP_RANGE);
+			if(exp->_nodes[first].type>*exp->_p) sqstd_rex_error(exp,_SC("invalid range"));
+			if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges"));
+			exp->_nodes[r].left = exp->_nodes[first].type;
+			SQInteger t = sqstd_rex_escapechar(exp);
+			exp->_nodes[r].right = t;
+            exp->_nodes[chain].next = r;
+			chain = r;
+			first = -1;
+		}
+		else{
+			if(first!=-1){
+				SQInteger c = first;
+				exp->_nodes[chain].next = c;
+				chain = c;
+				first = sqstd_rex_charnode(exp,SQTrue);
+			}
+			else{
+				first = sqstd_rex_charnode(exp,SQTrue);
+			}
+		}
+	}
+	if(first!=-1){
+		SQInteger c = first;
+		exp->_nodes[chain].next = c;
+	}
+	/* hack? */
+	exp->_nodes[ret].left = exp->_nodes[ret].next;
+	exp->_nodes[ret].next = -1;
+	return ret;
+}
+
+static SQInteger sqstd_rex_parsenumber(SQRex *exp)
+{
+	SQInteger ret = *exp->_p-'0';
+	SQInteger positions = 10;
+	exp->_p++;
+	while(isdigit(*exp->_p)) {
+		ret = ret*10+(*exp->_p++-'0');
+		if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant"));
+		positions *= 10;
+	};
+	return ret;
+}
+
+static SQInteger sqstd_rex_element(SQRex *exp)
+{
+	SQInteger ret = -1;
+	switch(*exp->_p)
+	{
+	case '(': {
+		SQInteger expr;
+		exp->_p++;
+
+
+		if(*exp->_p =='?') {
+			exp->_p++;
+			sqstd_rex_expect(exp,':');
+			expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR);
+		}
+		else
+			expr = sqstd_rex_newnode(exp,OP_EXPR);
+		SQInteger newn = sqstd_rex_list(exp);
+		exp->_nodes[expr].left = newn;
+		ret = expr;
+		sqstd_rex_expect(exp,')');
+			  }
+			  break;
+	case '[':
+		exp->_p++;
+		ret = sqstd_rex_class(exp);
+		sqstd_rex_expect(exp,']');
+		break;
+	case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break;
+	case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break;
+	default:
+		ret = sqstd_rex_charnode(exp,SQFalse);
+		break;
+	}
+
+
+	SQBool isgreedy = SQFalse;
+	unsigned short p0 = 0, p1 = 0;
+	switch(*exp->_p){
+		case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
+		case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
+		case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = SQTrue; break;
+		case '{':
+			exp->_p++;
+			if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected"));
+			p0 = (unsigned short)sqstd_rex_parsenumber(exp);
+			/*******************************/
+			switch(*exp->_p) {
+		case '}':
+			p1 = p0; exp->_p++;
+			break;
+		case ',':
+			exp->_p++;
+			p1 = 0xFFFF;
+			if(isdigit(*exp->_p)){
+				p1 = (unsigned short)sqstd_rex_parsenumber(exp);
+			}
+			sqstd_rex_expect(exp,'}');
+			break;
+		default:
+			sqstd_rex_error(exp,_SC(", or } expected"));
+			}
+			/*******************************/
+			isgreedy = SQTrue;
+			break;
+
+	}
+	if(isgreedy) {
+		SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY);
+		exp->_nodes[nnode].left = ret;
+		exp->_nodes[nnode].right = ((p0)<<16)|p1;
+		ret = nnode;
+	}
+
+	if((*exp->_p != SQREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) {
+		SQInteger nnode = sqstd_rex_element(exp);
+		exp->_nodes[ret].next = nnode;
+	}
+
+	return ret;
+}
+
+static SQInteger sqstd_rex_list(SQRex *exp)
+{
+	SQInteger ret=-1,e;
+	if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) {
+		exp->_p++;
+		ret = sqstd_rex_newnode(exp,OP_BOL);
+	}
+	e = sqstd_rex_element(exp);
+	if(ret != -1) {
+		exp->_nodes[ret].next = e;
+	}
+	else ret = e;
+
+	if(*exp->_p == SQREX_SYMBOL_BRANCH) {
+		SQInteger temp,tright;
+		exp->_p++;
+		temp = sqstd_rex_newnode(exp,OP_OR);
+		exp->_nodes[temp].left = ret;
+		tright = sqstd_rex_list(exp);
+		exp->_nodes[temp].right = tright;
+		ret = temp;
+	}
+	return ret;
+}
+
+static SQBool sqstd_rex_matchcclass(SQInteger cclass,SQChar c)
+{
+	switch(cclass) {
+	case 'a': return isalpha(c)?SQTrue:SQFalse;
+	case 'A': return !isalpha(c)?SQTrue:SQFalse;
+	case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse;
+	case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse;
+	case 's': return isspace(c)?SQTrue:SQFalse;
+	case 'S': return !isspace(c)?SQTrue:SQFalse;
+	case 'd': return isdigit(c)?SQTrue:SQFalse;
+	case 'D': return !isdigit(c)?SQTrue:SQFalse;
+	case 'x': return isxdigit(c)?SQTrue:SQFalse;
+	case 'X': return !isxdigit(c)?SQTrue:SQFalse;
+	case 'c': return iscntrl(c)?SQTrue:SQFalse;
+	case 'C': return !iscntrl(c)?SQTrue:SQFalse;
+	case 'p': return ispunct(c)?SQTrue:SQFalse;
+	case 'P': return !ispunct(c)?SQTrue:SQFalse;
+	case 'l': return islower(c)?SQTrue:SQFalse;
+	case 'u': return isupper(c)?SQTrue:SQFalse;
+	}
+	return SQFalse; /*cannot happen*/
+}
+
+static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c)
+{
+	do {
+		switch(node->type) {
+			case OP_RANGE:
+				if(c >= node->left && c <= node->right) return SQTrue;
+				break;
+			case OP_CCLASS:
+				if(sqstd_rex_matchcclass(node->left,c)) return SQTrue;
+				break;
+			default:
+				if(c == node->type)return SQTrue;
+		}
+	} while((node->next != -1) && (node = &exp->_nodes[node->next]));
+	return SQFalse;
+}
+
+static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str,SQRexNode *next)
+{
+
+	SQRexNodeType type = node->type;
+	switch(type) {
+	case OP_GREEDY: {
+		//SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL;
+		SQRexNode *greedystop = NULL;
+		SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
+		const SQChar *s=str, *good = str;
+
+		if(node->next != -1) {
+			greedystop = &exp->_nodes[node->next];
+		}
+		else {
+			greedystop = next;
+		}
+
+		while((nmaches == 0xFFFF || nmaches < p1)) {
+
+			const SQChar *stop;
+			if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop)))
+				break;
+			nmaches++;
+			good=s;
+			if(greedystop) {
+				//checks that 0 matches satisfy the expression(if so skips)
+				//if not would always stop(for instance if is a '?')
+				if(greedystop->type != OP_GREEDY ||
+				(greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0))
+				{
+					SQRexNode *gnext = NULL;
+					if(greedystop->next != -1) {
+						gnext = &exp->_nodes[greedystop->next];
+					}else if(next && next->next != -1){
+						gnext = &exp->_nodes[next->next];
+					}
+					stop = sqstd_rex_matchnode(exp,greedystop,s,gnext);
+					if(stop) {
+						//if satisfied stop it
+						if(p0 == p1 && p0 == nmaches) break;
+						else if(nmaches >= p0 && p1 == 0xFFFF) break;
+						else if(nmaches >= p0 && nmaches <= p1) break;
+					}
+				}
+			}
+
+			if(s >= exp->_eol)
+				break;
+		}
+		if(p0 == p1 && p0 == nmaches) return good;
+		else if(nmaches >= p0 && p1 == 0xFFFF) return good;
+		else if(nmaches >= p0 && nmaches <= p1) return good;
+		return NULL;
+	}
+	case OP_OR: {
+			const SQChar *asd = str;
+			SQRexNode *temp=&exp->_nodes[node->left];
+			while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) {
+				if(temp->next != -1)
+					temp = &exp->_nodes[temp->next];
+				else
+					return asd;
+			}
+			asd = str;
+			temp = &exp->_nodes[node->right];
+			while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) {
+				if(temp->next != -1)
+					temp = &exp->_nodes[temp->next];
+				else
+					return asd;
+			}
+			return NULL;
+			break;
+	}
+	case OP_EXPR:
+	case OP_NOCAPEXPR:{
+			SQRexNode *n = &exp->_nodes[node->left];
+			const SQChar *cur = str;
+			SQInteger capture = -1;
+			if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
+				capture = exp->_currsubexp;
+				exp->_matches[capture].begin = cur;
+				exp->_currsubexp++;
+			}
+			int tempcap = exp->_currsubexp;
+			do {
+				SQRexNode *subnext = NULL;
+				if(n->next != -1) {
+					subnext = &exp->_nodes[n->next];
+				}else {
+					subnext = next;
+				}
+				if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) {
+					if(capture != -1){
+						exp->_matches[capture].begin = 0;
+						exp->_matches[capture].len = 0;
+					}
+					return NULL;
+				}
+			} while((n->next != -1) && (n = &exp->_nodes[n->next]));
+
+			exp->_currsubexp = tempcap;
+			if(capture != -1)
+				exp->_matches[capture].len = cur - exp->_matches[capture].begin;
+			return cur;
+	}
+	case OP_WB:
+		if((str == exp->_bol && !isspace(*str))
+		 || (str == exp->_eol && !isspace(*(str-1)))
+		 || (!isspace(*str) && isspace(*(str+1)))
+		 || (isspace(*str) && !isspace(*(str+1))) ) {
+			return (node->left == 'b')?str:NULL;
+		}
+		return (node->left == 'b')?NULL:str;
+	case OP_BOL:
+		if(str == exp->_bol) return str;
+		return NULL;
+	case OP_EOL:
+		if(str == exp->_eol) return str;
+		return NULL;
+	case OP_DOT:{
+		str++;
+				}
+		return str;
+	case OP_NCLASS:
+	case OP_CLASS:
+		if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) {
+			str++;
+			return str;
+		}
+		return NULL;
+	case OP_CCLASS:
+		if(sqstd_rex_matchcclass(node->left,*str)) {
+			str++;
+			return str;
+		}
+		return NULL;
+    case OP_MB:
+        {
+            int cb = node->left; //char that opens a balanced expression
+            if(*str != cb) return NULL; // string doesnt start with open char
+            int ce = node->right; //char that closes a balanced expression
+            int cont = 1;
             const SQChar *strEol = exp->_eol;
             const SQChar *strEol = exp->_eol;
             while (++str < strEol) {
             while (++str < strEol) {
               if (*str == ce) {
               if (*str == ce) {
-                if (--cont == 0) {
-                    return ++str;
+                if (--cont == 0) {
+                    return ++str;
                 }
                 }
               }
               }
               else if (*str == cb) cont++;
               else if (*str == cb) cont++;
-            }
-        }
-        return NULL; // string ends out of balance
-	default: /* char */
-		if(*str != node->type) return NULL;
-		str++;
-		return str;
-	}
-	return NULL;
-}
-
-/* public api */
-SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error)
-{
-	SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex));
-	exp->_eol = exp->_bol = NULL;
-	exp->_p = pattern;
-	exp->_nallocated = (SQInteger)scstrlen(pattern) * sizeof(SQChar);
-	exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode));
-	exp->_nsize = 0;
-	exp->_matches = 0;
-	exp->_nsubexpr = 0;
-	exp->_first = sqstd_rex_newnode(exp,OP_EXPR);
-	exp->_error = error;
-	exp->_jmpbuf = sq_malloc(sizeof(jmp_buf));
-	if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {
-		SQInteger res = sqstd_rex_list(exp);
-		exp->_nodes[exp->_first].left = res;
-		if(*exp->_p!='\0')
-			sqstd_rex_error(exp,_SC("unexpected character"));
-#ifdef _DEBUG
-		{
-			SQInteger nsize,i;
-			SQRexNode *t;
-			nsize = exp->_nsize;
-			t = &exp->_nodes[0];
-			scprintf(_SC("\n"));
-			for(i = 0;i < nsize; i++) {
-				if(exp->_nodes[i].type>MAX_CHAR)
-					scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);
-				else
-					scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type);
-				scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next);
-			}
-			scprintf(_SC("\n"));
-		}
-#endif
-		exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch));
-		memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch));
-	}
-	else{
-		sqstd_rex_free(exp);
-		return NULL;
-	}
-	return exp;
-}
-
-void sqstd_rex_free(SQRex *exp)
-{
-	if(exp)	{
-		if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode));
-		if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf));
-		if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch));
-		sq_free(exp,sizeof(SQRex));
-	}
-}
-
-SQBool sqstd_rex_match(SQRex* exp,const SQChar* text)
-{
-	const SQChar* res = NULL;
-	exp->_bol = text;
-	exp->_eol = text + scstrlen(text);
-	exp->_currsubexp = 0;
-	res = sqstd_rex_matchnode(exp,exp->_nodes,text,NULL);
-	if(res == NULL || res != exp->_eol)
-		return SQFalse;
-	return SQTrue;
-}
-
-SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end)
-{
-	const SQChar *cur = NULL;
-	SQInteger node = exp->_first;
-	if(text_begin >= text_end) return SQFalse;
-	exp->_bol = text_begin;
-	exp->_eol = text_end;
-	do {
-		cur = text_begin;
-		while(node != -1) {
-			exp->_currsubexp = 0;
-			cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,NULL);
-			if(!cur)
-				break;
-			node = exp->_nodes[node].next;
-		}
-		text_begin++;
-	} while(cur == NULL && text_begin != text_end);
-
-	if(cur == NULL)
-		return SQFalse;
-
-	--text_begin;
-
-	if(out_begin) *out_begin = text_begin;
-	if(out_end) *out_end = cur;
-	return SQTrue;
-}
-
-SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end)
-{
-	return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end);
-}
-
-SQInteger sqstd_rex_getsubexpcount(SQRex* exp)
-{
-	return exp->_nsubexpr;
-}
-
-SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp)
-{
-	if( n<0 || n >= exp->_nsubexpr) return SQFalse;
-	*subexp = exp->_matches[n];
-	return SQTrue;
-}
-
+            }
+        }
+        return NULL; // string ends out of balance
+	default: /* char */
+		if(*str != node->type) return NULL;
+		str++;
+		return str;
+	}
+	return NULL;
+}
+
+/* public api */
+SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error)
+{
+	SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex));
+	exp->_eol = exp->_bol = NULL;
+	exp->_p = pattern;
+	exp->_nallocated = (SQInteger)scstrlen(pattern) * sizeof(SQChar);
+	exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode));
+	exp->_nsize = 0;
+	exp->_matches = 0;
+	exp->_nsubexpr = 0;
+	exp->_first = sqstd_rex_newnode(exp,OP_EXPR);
+	exp->_error = error;
+	exp->_jmpbuf = sq_malloc(sizeof(jmp_buf));
+	if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {
+		SQInteger res = sqstd_rex_list(exp);
+		exp->_nodes[exp->_first].left = res;
+		if(*exp->_p!='\0')
+			sqstd_rex_error(exp,_SC("unexpected character"));
+#ifdef _DEBUG
+		{
+			SQInteger nsize,i;
+			SQRexNode *t;
+			nsize = exp->_nsize;
+			t = &exp->_nodes[0];
+			scprintf(_SC("\n"));
+			for(i = 0;i < nsize; i++) {
+				if(exp->_nodes[i].type>MAX_CHAR)
+					scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);
+				else
+					scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type);
+				scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next);
+			}
+			scprintf(_SC("\n"));
+		}
+#endif
+		exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch));
+		memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch));
+	}
+	else{
+		sqstd_rex_free(exp);
+		return NULL;
+	}
+	return exp;
+}
+
+void sqstd_rex_free(SQRex *exp)
+{
+	if(exp)	{
+		if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode));
+		if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf));
+		if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch));
+		sq_free(exp,sizeof(SQRex));
+	}
+}
+
+SQBool sqstd_rex_match(SQRex* exp,const SQChar* text)
+{
+	const SQChar* res = NULL;
+	exp->_bol = text;
+	exp->_eol = text + scstrlen(text);
+	exp->_currsubexp = 0;
+	res = sqstd_rex_matchnode(exp,exp->_nodes,text,NULL);
+	if(res == NULL || res != exp->_eol)
+		return SQFalse;
+	return SQTrue;
+}
+
+SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end)
+{
+	const SQChar *cur = NULL;
+	SQInteger node = exp->_first;
+	if(text_begin >= text_end) return SQFalse;
+	exp->_bol = text_begin;
+	exp->_eol = text_end;
+	do {
+		cur = text_begin;
+		while(node != -1) {
+			exp->_currsubexp = 0;
+			cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,NULL);
+			if(!cur)
+				break;
+			node = exp->_nodes[node].next;
+		}
+		text_begin++;
+	} while(cur == NULL && text_begin != text_end);
+
+	if(cur == NULL)
+		return SQFalse;
+
+	--text_begin;
+
+	if(out_begin) *out_begin = text_begin;
+	if(out_end) *out_end = cur;
+	return SQTrue;
+}
+
+SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end)
+{
+	return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end);
+}
+
+SQInteger sqstd_rex_getsubexpcount(SQRex* exp)
+{
+	return exp->_nsubexpr;
+}
+
+SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp)
+{
+	if( n<0 || n >= exp->_nsubexpr) return SQFalse;
+	*subexp = exp->_matches[n];
+	return SQTrue;
+}
+

+ 381 - 371
SquiLu/sqstdlib/sqstdstring.cpp

@@ -1,104 +1,114 @@
-/* see copyright notice in squirrel.h */
-#include <squirrel.h>
-#include <sqstdstring.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <assert.h>
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <sqstdstring.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <assert.h>
 #include <stddef.h>
 #include <stddef.h>
 
 
 #ifdef _WIN32_WCE
 #ifdef _WIN32_WCE
 extern "C" {
 extern "C" {
 int _wtoi (const wchar_t *);
 int _wtoi (const wchar_t *);
 }
 }
-#endif // _WINCE
-
-#define MAX_FORMAT_LEN	20
-#define MAX_WFORMAT_LEN	3
-#define ADDITIONAL_FORMAT_SPACE (100*sizeof(SQChar))
-
-static SQRESULT validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, SQInteger n,SQInteger &width)
-{
-	SQChar swidth[MAX_WFORMAT_LEN];
-	SQInteger wc = 0;
-	SQInteger start = n;
-	fmt[0] = _SC('%');
-	while (scstrchr(_SC("-+ #0"), src[n])) n++;
-	while (scisdigit(src[n])) {
-		swidth[wc] = src[n];
-		n++;
-		wc++;
-		if(wc>=MAX_WFORMAT_LEN)
-			return sq_throwerror(v,_SC("width format too long"));
-	}
-	swidth[wc] = _SC('\0');
-	if(wc > 0) {
-		width = scatoi(swidth);
-	}
-	else
-		width = 0;
-	if (src[n] == _SC('.')) {
-	    n++;
-
-		wc = 0;
-		while (scisdigit(src[n])) {
-			swidth[wc] = src[n];
-			n++;
-			wc++;
-			if(wc>=MAX_WFORMAT_LEN)
-				return sq_throwerror(v,_SC("precision format too long"));
-		}
-		swidth[wc] = _SC('\0');
-		if(wc > 0) {
-			width += scatoi(swidth);
-		}
-	}
-	if (n-start > MAX_FORMAT_LEN )
-		return sq_throwerror(v,_SC("format too long"));
-	memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar));
-	fmt[(n-start)+2] = _SC('\0');
-	return n;
-}
-
-SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output)
-{
-	const SQChar *format;
-	SQChar *dest;
-	SQChar fmt[MAX_FORMAT_LEN];
+#endif // _WINCE
+
+#define MAX_FORMAT_LEN	20
+#define MAX_WFORMAT_LEN	3
+#define ADDITIONAL_FORMAT_SPACE (100*sizeof(SQChar))
+
+static SQBool isfmtchr(SQChar ch)
+{
+	switch(ch) {
+	case '-': case '+': case ' ': case '#': case '0': return SQTrue;
+	}
+	return SQFalse;
+}
+
+static SQRESULT validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, SQInteger n,SQInteger &width)
+{
+	SQChar *dummy;
+	SQChar swidth[MAX_WFORMAT_LEN];
+	SQInteger wc = 0;
+	SQInteger start = n;
+	fmt[0] = _SC('%');
+	while (isfmtchr(src[n])) n++;
+	while (scisdigit(src[n])) {
+		swidth[wc] = src[n];
+		n++;
+		wc++;
+		if(wc>=MAX_WFORMAT_LEN)
+			return sq_throwerror(v,_SC("width format too long"));
+	}
+	swidth[wc] = _SC('\0');
+	if(wc > 0) {
+		width = scstrtol(swidth,&dummy,10);
+	}
+	else
+		width = 0;
+	if (src[n] == _SC('.')) {
+	    n++;
+
+		wc = 0;
+		while (scisdigit(src[n])) {
+			swidth[wc] = src[n];
+			n++;
+			wc++;
+			if(wc>=MAX_WFORMAT_LEN)
+				return sq_throwerror(v,_SC("precision format too long"));
+		}
+		swidth[wc] = _SC('\0');
+		if(wc > 0) {
+			width += scstrtol(swidth,&dummy,10);
+
+		}
+	}
+	if (n-start > MAX_FORMAT_LEN )
+		return sq_throwerror(v,_SC("format too long"));
+	memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar));
+	fmt[(n-start)+2] = _SC('\0');
+	return n;
+}
+
+SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output)
+{
+	const SQChar *format;
+	SQChar *dest;
+	SQChar fmt[MAX_FORMAT_LEN];
 	sq_getstring(v,nformatstringidx,&format);
 	sq_getstring(v,nformatstringidx,&format);
-	SQInteger format_size = sq_getsize(v,nformatstringidx);
-	SQInteger allocated = (format_size+2)*sizeof(SQChar);
-	dest = sq_getscratchpad(v,allocated);
-	SQInteger n = 0,i = 0, nparam = nformatstringidx+1, w = 0;
-	while(n < format_size) {
-		if(format[n] != _SC('%')) {
-			assert(i < allocated);
-			dest[i++] = format[n];
-			n++;
-		}
-		else if(format[n+1] == _SC('%')) { //handles %%
-				dest[i++] = _SC('%');
-				n += 2;
-		}
-		else {
-			n++;
-			if( nparam > sq_gettop(v) )
-				return sq_throwerror(v,_SC("not enough paramters for the given format string"));
-			n = validate_format(v,fmt,format,n,w);
-			if(n < 0) return -1;
-			SQInteger addlen = 0;
-			SQInteger valtype = 0;
-			const SQChar *ts;
-			SQInteger ti;
-			SQFloat tf;
-			SQInteger fc = format[n];
-			switch(fc) {
+	SQInteger format_size = sq_getsize(v,nformatstringidx);
+	SQInteger allocated = (format_size+2)*sizeof(SQChar);
+	dest = sq_getscratchpad(v,allocated);
+	SQInteger n = 0,i = 0, nparam = nformatstringidx+1, w = 0;
+	while(n < format_size) {
+		if(format[n] != _SC('%')) {
+			assert(i < allocated);
+			dest[i++] = format[n];
+			n++;
+		}
+		else if(format[n+1] == _SC('%')) { //handles %%
+				dest[i++] = _SC('%');
+				n += 2;
+		}
+		else {
+			n++;
+			if( nparam > sq_gettop(v) )
+				return sq_throwerror(v,_SC("not enough paramters for the given format string"));
+			n = validate_format(v,fmt,format,n,w);
+			if(n < 0) return -1;
+			SQInteger addlen = 0;
+			SQInteger valtype = 0;
+			const SQChar *ts;
+			SQInteger ti;
+			SQFloat tf;
+			SQInteger fc = format[n];
+			switch(fc) {
             case _SC('q'):
             case _SC('q'):
-			case _SC('s'):
-				if(SQ_FAILED(sq_getstring(v,nparam,&ts)))
-					return sq_throwerror(v,_SC("string expected for the specified format"));
+			case _SC('s'):
+				if(SQ_FAILED(sq_getstring(v,nparam,&ts)))
+					return sq_throwerror(v,_SC("string expected for the specified format"));
                 if(fc == _SC('q')){
                 if(fc == _SC('q')){
                     addlen = 2; //quotes before and after
                     addlen = 2; //quotes before and after
                     SQInteger size = sq_getsize(v,nparam);
                     SQInteger size = sq_getsize(v,nparam);
@@ -121,7 +131,7 @@ SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen
 
 
                       ts2 = (SQChar*)i; //save the i position using pointer as integer
                       ts2 = (SQChar*)i; //save the i position using pointer as integer
                       i += addlen;
                       i += addlen;
-                      allocated += addlen;
+                      allocated += addlen;
                       dest = sq_getscratchpad(v,allocated);
                       dest = sq_getscratchpad(v,allocated);
                       size = sq_getsize(v,nparam);
                       size = sq_getsize(v,nparam);
 
 
@@ -154,118 +164,118 @@ SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen
                         ++ts;
                         ++ts;
                       }
                       }
                       *ts2++ = _SC('"');
                       *ts2++ = _SC('"');
-
+
                       ++n;
                       ++n;
                       ++nparam;
                       ++nparam;
                       continue;
                       continue;
                 }
                 }
                 else
                 else
                 {
                 {
-                    addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar));
+                    addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar));
                     valtype = _SC('s');
                     valtype = _SC('s');
-                }
-				break;
-			case _SC('i'): case _SC('d'): case _SC('o'): case _SC('u'):  case _SC('x'):  case _SC('X'):
-#ifdef _SQ64
-				{
-				size_t flen = scstrlen(fmt);
-				SQInteger fpos = flen - 1;
-				SQChar f = fmt[fpos];
-				SQChar *prec = (SQChar *)_PRINT_INT_PREC;
-				while(*prec != _SC('\0')) {
-					fmt[fpos++] = *prec++;
-				}
-				fmt[fpos++] = f;
-				fmt[fpos++] = _SC('\0');
-				}
-#endif
-			case _SC('c'):
-				if(SQ_FAILED(sq_getinteger(v,nparam,&ti)))
-					return sq_throwerror(v,_SC("integer expected for the specified format"));
-				addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
-				valtype = _SC('i');
-				break;
-			case _SC('f'): case _SC('g'): case _SC('G'): case _SC('e'):  case _SC('E'):
-				if(SQ_FAILED(sq_getfloat(v,nparam,&tf)))
-					return sq_throwerror(v,_SC("float expected for the specified format"));
-				addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
-				valtype = _SC('f');
-				break;
-			default:
-				return sq_throwerror(v,_SC("invalid format"));
-			}
-			n++;
-			allocated += addlen + sizeof(SQChar);
-			dest = sq_getscratchpad(v,allocated);
-			switch(valtype) {
-			case _SC('s'): i += scsprintf(&dest[i],fmt,ts); break;
-			case _SC('i'): i += scsprintf(&dest[i],fmt,ti); break;
-			case _SC('f'): i += scsprintf(&dest[i],fmt,tf); break;
-			};
-			nparam ++;
-		}
-	}
-	*outlen = i;
-	dest[i] = _SC('\0');
-	*output = dest;
-	return SQ_OK;
-}
-
-static SQRESULT _string_format(HSQUIRRELVM v)
-{
-	SQChar *dest = NULL;
-	SQInteger length = 0;
-	if(SQ_FAILED(sqstd_format(v,2,&length,&dest)))
-		return -1;
-	sq_pushstring(v,dest,length);
-	return 1;
-}
-
-static SQRESULT _string_printf(HSQUIRRELVM v)
-{
-	SQChar *dest = NULL;
+                }
+				break;
+			case _SC('i'): case _SC('d'): case _SC('o'): case _SC('u'):  case _SC('x'):  case _SC('X'):
+#ifdef _SQ64
+				{
+				size_t flen = scstrlen(fmt);
+				SQInteger fpos = flen - 1;
+				SQChar f = fmt[fpos];
+				SQChar *prec = (SQChar *)_PRINT_INT_PREC;
+				while(*prec != _SC('\0')) {
+					fmt[fpos++] = *prec++;
+				}
+				fmt[fpos++] = f;
+				fmt[fpos++] = _SC('\0');
+				}
+#endif
+			case _SC('c'):
+				if(SQ_FAILED(sq_getinteger(v,nparam,&ti)))
+					return sq_throwerror(v,_SC("integer expected for the specified format"));
+				addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
+				valtype = _SC('i');
+				break;
+			case _SC('f'): case _SC('g'): case _SC('G'): case _SC('e'):  case _SC('E'):
+				if(SQ_FAILED(sq_getfloat(v,nparam,&tf)))
+					return sq_throwerror(v,_SC("float expected for the specified format"));
+				addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
+				valtype = _SC('f');
+				break;
+			default:
+				return sq_throwerror(v,_SC("invalid format"));
+			}
+			n++;
+			allocated += addlen + sizeof(SQChar);
+			dest = sq_getscratchpad(v,allocated);
+			switch(valtype) {
+			case _SC('s'): i += scsprintf(&dest[i],fmt,ts); break;
+			case _SC('i'): i += scsprintf(&dest[i],fmt,ti); break;
+			case _SC('f'): i += scsprintf(&dest[i],fmt,tf); break;
+			};
+			nparam ++;
+		}
+	}
+	*outlen = i;
+	dest[i] = _SC('\0');
+	*output = dest;
+	return SQ_OK;
+}
+
+static SQRESULT _string_format(HSQUIRRELVM v)
+{
+	SQChar *dest = NULL;
 	SQInteger length = 0;
 	SQInteger length = 0;
-	SQPRINTFUNCTION sqprint = sq_getprintfunc(v);
+	if(SQ_FAILED(sqstd_format(v,2,&length,&dest)))
+		return -1;
+	sq_pushstring(v,dest,length);
+	return 1;
+}
+
+static SQRESULT _string_printf(HSQUIRRELVM v)
+{
+	SQChar *dest = NULL;
+	SQInteger length = 0;
+	SQPRINTFUNCTION sqprint = sq_getprintfunc(v);
     if(sqprint){
     if(sqprint){
-        if(SQ_FAILED(sqstd_format(v,2,&length,&dest)))
+        if(SQ_FAILED(sqstd_format(v,2,&length,&dest)))
             return -1;
             return -1;
         sqprint(v,_SC("%s"),dest);
         sqprint(v,_SC("%s"),dest);
         sq_pushinteger(v, length);
         sq_pushinteger(v, length);
         return 1;
         return 1;
-    }
-	return 0;
-}
-
-#define SETUP_REX(v) \
-	SQRex *self = NULL; \
-	sq_getinstanceup(v,1,(SQUserPointer *)&self,0);
-
-static SQRESULT _rexobj_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
-{
-	SQRex *self = ((SQRex *)p);
-	sqstd_rex_free(self);
-	return 1;
-}
-
-static SQRESULT _regexp_match(HSQUIRRELVM v)
-{
-	SETUP_REX(v);
-	const SQChar *str;
-	sq_getstring(v,2,&str);
-	if(sqstd_rex_match(self,str) == SQTrue)
-	{
-		sq_pushbool(v,SQTrue);
-		return 1;
-	}
-	sq_pushbool(v,SQFalse);
-	return 1;
-}
+    }
+	return 0;
+}
+
+#define SETUP_REX(v) \
+	SQRex *self = NULL; \
+	sq_getinstanceup(v,1,(SQUserPointer *)&self,0);
 
 
-static SQRESULT _regexp_gmatch(HSQUIRRELVM v)
-{
-	SETUP_REX(v);
+static SQRESULT _rexobj_releasehook(SQUserPointer p, SQInteger size, HSQUIRRELVM v)
+{
+	SQRex *self = ((SQRex *)p);
+	sqstd_rex_free(self);
+	return 1;
+}
+
+static SQRESULT _regexp_match(HSQUIRRELVM v)
+{
+	SETUP_REX(v);
 	const SQChar *str;
 	const SQChar *str;
-	SQInteger str_size;
+	sq_getstring(v,2,&str);
+	if(sqstd_rex_match(self,str) == SQTrue)
+	{
+		sq_pushbool(v,SQTrue);
+		return 1;
+	}
+	sq_pushbool(v,SQFalse);
+	return 1;
+}
+
+static SQRESULT _regexp_gmatch(HSQUIRRELVM v)
+{
+	SETUP_REX(v);
+	const SQChar *str;
+	SQInteger str_size;
 	sq_getstring(v,2,&str);
 	sq_getstring(v,2,&str);
 	str_size = sq_getsize(v, 2);
 	str_size = sq_getsize(v, 2);
 	const SQChar *begin,*end;
 	const SQChar *begin,*end;
@@ -278,23 +288,23 @@ static SQRESULT _regexp_gmatch(HSQUIRRELVM v)
             sqstd_rex_getsubexp(self,i,&match);
             sqstd_rex_getsubexp(self,i,&match);
             if(i > 0){ //skip whole match
             if(i > 0){ //skip whole match
                 sq_pushstring(v, match.begin, match.len);
                 sq_pushstring(v, match.begin, match.len);
-            }
+            }
 		}
 		}
 		i = sq_call(v, n, SQFalse, SQTrue);
 		i = sq_call(v, n, SQFalse, SQTrue);
 		if(i < 0) return i;
 		if(i < 0) return i;
 		str_size -= end-str;
 		str_size -= end-str;
 		str = end;
 		str = end;
-	}
-	sq_pushbool(v,SQFalse);
-	return 1;
-}
-
-#include "sqstdblobimpl.h"
-static SQRESULT _regexp_gsub(HSQUIRRELVM v)
-{
-	SETUP_REX(v);
+	}
+	sq_pushbool(v,SQFalse);
+	return 1;
+}
+
+#include "sqstdblobimpl.h"
+static SQRESULT _regexp_gsub(HSQUIRRELVM v)
+{
+	SETUP_REX(v);
 	const SQChar *str;
 	const SQChar *str;
-	SQInteger str_size;
+	SQInteger str_size;
 	sq_getstring(v,2,&str);
 	sq_getstring(v,2,&str);
 	str_size = sq_getsize(v, 2);
 	str_size = sq_getsize(v, 2);
 	const SQChar *begin,*end;
 	const SQChar *begin,*end;
@@ -314,7 +324,7 @@ static SQRESULT _regexp_gsub(HSQUIRRELVM v)
                     sqstd_rex_getsubexp(self,i,&match);
                     sqstd_rex_getsubexp(self,i,&match);
                     if(i > 0){ //skip whole match
                     if(i > 0){ //skip whole match
                         sq_pushstring(v, match.begin, match.len);
                         sq_pushstring(v, match.begin, match.len);
-                    }
+                    }
                 }
                 }
                 i = sq_call(v, n, SQTrue, SQTrue);
                 i = sq_call(v, n, SQTrue, SQTrue);
                 if(i < 0) return i;
                 if(i < 0) return i;
@@ -336,7 +346,7 @@ static SQRESULT _regexp_gsub(HSQUIRRELVM v)
                             blob.Write(replacement, replacement_size);
                             blob.Write(replacement, replacement_size);
                             sq_pop(v, 1); //remove value
                             sq_pop(v, 1); //remove value
                         }
                         }
-                    }
+                    }
                 }
                 }
 	        }
 	        }
 	        break;
 	        break;
@@ -350,7 +360,7 @@ static SQRESULT _regexp_gsub(HSQUIRRELVM v)
                             blob.Write(replacement, replacement_size);
                             blob.Write(replacement, replacement_size);
                             sq_pop(v, 1); //remove value
                             sq_pop(v, 1); //remove value
                         }
                         }
-                    }
+                    }
                 }
                 }
 	        }
 	        }
 	        break;
 	        break;
@@ -360,169 +370,169 @@ static SQRESULT _regexp_gsub(HSQUIRRELVM v)
 		str_size -= end-str;
 		str_size -= end-str;
 		str = end;
 		str = end;
 	}
 	}
-    if(str_size) blob.Write(str, str_size);
-	sq_pushstring(v, (const SQChar *)blob.GetBuf(), blob.Len());
-	return 1;
-}
-
-static void _addrexmatch(HSQUIRRELVM v,const SQChar *str,const SQChar *begin,const SQChar *end)
-{
-	sq_newtable(v);
-	sq_pushstring(v,_SC("begin"),-1);
-	sq_pushinteger(v,begin - str);
-	sq_rawset(v,-3);
-	sq_pushstring(v,_SC("end"),-1);
-	sq_pushinteger(v,end - str);
-	sq_rawset(v,-3);
-}
-
-static SQRESULT _regexp_search(HSQUIRRELVM v)
-{
-	SETUP_REX(v);
-	const SQChar *str,*begin,*end;
-	SQInteger start = 0;
-	sq_getstring(v,2,&str);
-	if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
-	if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
-		_addrexmatch(v,str,begin,end);
-		return 1;
-	}
-	return 0;
-}
-
-static SQRESULT _regexp_capture(HSQUIRRELVM v)
-{
-	SETUP_REX(v);
-	const SQChar *str,*begin,*end;
-	SQInteger start = 0;
-	sq_getstring(v,2,&str);
-	if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
-	if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
-		SQInteger n = sqstd_rex_getsubexpcount(self);
-		SQRexMatch match;
-		sq_newarray(v,0);
-		for(SQInteger i = 0;i < n; i++) {
-			sqstd_rex_getsubexp(self,i,&match);
-			if(match.len > 0)
-				_addrexmatch(v,str,match.begin,match.begin+match.len);
-			else
-				_addrexmatch(v,str,str,str); //empty match
-			sq_arrayappend(v,-2);
-		}
-		return 1;
-	}
-	return 0;
-}
-
-static SQRESULT _regexp_xcapture(HSQUIRRELVM v)
-{
-	SETUP_REX(v);
-	const SQChar *str,*begin,*end;
-	SQInteger start = 0;
-	sq_getstring(v,2,&str);
-	if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
-	if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
-	    sq_pushbool(v, SQTrue);
-		return 1;
-	}
-	return 0;
-}
-
-static SQRESULT _regexp_getxcapture(HSQUIRRELVM v)
-{
-	SETUP_REX(v);
-	SQInteger n, start;
-	const SQChar *str;
-	sq_getstring(v,2,&str);
-	sq_getinteger(v,3,&n);
-	SQRexMatch match;
-    sqstd_rex_getsubexp(self,n,&match);
-    if(match.len > 0){
-        start = match.begin-str;
-        sq_pushinteger(v, start);
-	    sq_arrayappend(v,-2);
-        sq_pushinteger(v, start+match.len);
-	    sq_arrayappend(v,-2);
-	    sq_pushbool(v, SQTrue);
-		return 1;
-    }
-	return 0;
-}
-
-static SQRESULT _regexp_subexpcount(HSQUIRRELVM v)
-{
-	SETUP_REX(v);
-	sq_pushinteger(v,sqstd_rex_getsubexpcount(self));
-	return 1;
-}
-
-static SQRESULT _regexp_constructor(HSQUIRRELVM v)
-{
-	const SQChar *error,*pattern;
-	sq_getstring(v,2,&pattern);
-	SQRex *rex = sqstd_rex_compile(pattern,&error);
-	if(!rex) return sq_throwerror(v,error);
-	sq_setinstanceup(v,1,rex);
-	sq_setreleasehook(v,1,_rexobj_releasehook);
-	return 0;
-}
-
-static SQRESULT _regexp__typeof(HSQUIRRELVM v)
-{
-	sq_pushstring(v,_SC("regexp"),-1);
-	return 1;
-}
-
-#define _DECL_REX_FUNC(name,nparams,pmask) {_SC(#name),_regexp_##name,nparams,pmask}
-static SQRegFunction rexobj_funcs[]={
-	_DECL_REX_FUNC(constructor,2,_SC(".s")),
-	_DECL_REX_FUNC(search,-2,_SC("xsn")),
-	_DECL_REX_FUNC(match,2,_SC("xs")),
-	_DECL_REX_FUNC(gmatch,3,_SC("xsc")),
-	_DECL_REX_FUNC(gsub,3,_SC("xs c|a|t")),
-	_DECL_REX_FUNC(capture,-2,_SC("xsn")),
-	_DECL_REX_FUNC(xcapture,-2,_SC("xsn")),
-	_DECL_REX_FUNC(getxcapture,4,_SC("xsna")),
-	_DECL_REX_FUNC(subexpcount,1,_SC("x")),
-	_DECL_REX_FUNC(_typeof,1,_SC("x")),
-	{0,0}
-};
-#undef _DECL_REX_FUNC
-
-#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask}
-static SQRegFunction stringlib_funcs[]={
-	_DECL_FUNC(printf,-2,_SC(".s")),
-	_DECL_FUNC(format,-2,_SC(".s")),
-	{0,0}
-};
-#undef _DECL_FUNC
-
-
-SQInteger sqstd_register_stringlib(HSQUIRRELVM v)
-{
-	sq_pushstring(v,_SC("regexp"),-1);
-	sq_newclass(v,SQFalse);
-	SQInteger i = 0;
-	while(rexobj_funcs[i].name != 0) {
-		SQRegFunction &f = rexobj_funcs[i];
-		sq_pushstring(v,f.name,-1);
-		sq_newclosure(v,f.f,0);
-		sq_setparamscheck(v,f.nparamscheck,f.typemask);
-		sq_setnativeclosurename(v,-1,f.name);
-		sq_newslot(v,-3,SQFalse);
-		i++;
-	}
-	sq_newslot(v,-3,SQFalse);
-
-	i = 0;
-	while(stringlib_funcs[i].name!=0)
-	{
-		sq_pushstring(v,stringlib_funcs[i].name,-1);
-		sq_newclosure(v,stringlib_funcs[i].f,0);
-		sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask);
-		sq_setnativeclosurename(v,-1,stringlib_funcs[i].name);
-		sq_newslot(v,-3,SQFalse);
-		i++;
-	}
-	return 1;
-}
+    if(str_size) blob.Write(str, str_size);
+	sq_pushstring(v, (const SQChar *)blob.GetBuf(), blob.Len());
+	return 1;
+}
+
+static void _addrexmatch(HSQUIRRELVM v,const SQChar *str,const SQChar *begin,const SQChar *end)
+{
+	sq_newtable(v);
+	sq_pushstring(v,_SC("begin"),-1);
+	sq_pushinteger(v,begin - str);
+	sq_rawset(v,-3);
+	sq_pushstring(v,_SC("end"),-1);
+	sq_pushinteger(v,end - str);
+	sq_rawset(v,-3);
+}
+
+static SQRESULT _regexp_search(HSQUIRRELVM v)
+{
+	SETUP_REX(v);
+	const SQChar *str,*begin,*end;
+	SQInteger start = 0;
+	sq_getstring(v,2,&str);
+	if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
+	if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
+		_addrexmatch(v,str,begin,end);
+		return 1;
+	}
+	return 0;
+}
+
+static SQRESULT _regexp_capture(HSQUIRRELVM v)
+{
+	SETUP_REX(v);
+	const SQChar *str,*begin,*end;
+	SQInteger start = 0;
+	sq_getstring(v,2,&str);
+	if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
+	if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
+		SQInteger n = sqstd_rex_getsubexpcount(self);
+		SQRexMatch match;
+		sq_newarray(v,0);
+		for(SQInteger i = 0;i < n; i++) {
+			sqstd_rex_getsubexp(self,i,&match);
+			if(match.len > 0)
+				_addrexmatch(v,str,match.begin,match.begin+match.len);
+			else
+				_addrexmatch(v,str,str,str); //empty match
+			sq_arrayappend(v,-2);
+		}
+		return 1;
+	}
+	return 0;
+}
+
+static SQRESULT _regexp_xcapture(HSQUIRRELVM v)
+{
+	SETUP_REX(v);
+	const SQChar *str,*begin,*end;
+	SQInteger start = 0;
+	sq_getstring(v,2,&str);
+	if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
+	if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
+	    sq_pushbool(v, SQTrue);
+		return 1;
+	}
+	return 0;
+}
+
+static SQRESULT _regexp_getxcapture(HSQUIRRELVM v)
+{
+	SETUP_REX(v);
+	SQInteger n, start;
+	const SQChar *str;
+	sq_getstring(v,2,&str);
+	sq_getinteger(v,3,&n);
+	SQRexMatch match;
+    sqstd_rex_getsubexp(self,n,&match);
+    if(match.len > 0){
+        start = match.begin-str;
+        sq_pushinteger(v, start);
+	    sq_arrayappend(v,-2);
+        sq_pushinteger(v, start+match.len);
+	    sq_arrayappend(v,-2);
+	    sq_pushbool(v, SQTrue);
+		return 1;
+    }
+	return 0;
+}
+
+static SQRESULT _regexp_subexpcount(HSQUIRRELVM v)
+{
+	SETUP_REX(v);
+	sq_pushinteger(v,sqstd_rex_getsubexpcount(self));
+	return 1;
+}
+
+static SQRESULT _regexp_constructor(HSQUIRRELVM v)
+{
+	const SQChar *error,*pattern;
+	sq_getstring(v,2,&pattern);
+	SQRex *rex = sqstd_rex_compile(pattern,&error);
+	if(!rex) return sq_throwerror(v,error);
+	sq_setinstanceup(v,1,rex);
+	sq_setreleasehook(v,1,_rexobj_releasehook);
+	return 0;
+}
+
+static SQRESULT _regexp__typeof(HSQUIRRELVM v)
+{
+	sq_pushstring(v,_SC("regexp"),-1);
+	return 1;
+}
+
+#define _DECL_REX_FUNC(name,nparams,pmask) {_SC(#name),_regexp_##name,nparams,pmask}
+static SQRegFunction rexobj_funcs[]={
+	_DECL_REX_FUNC(constructor,2,_SC(".s")),
+	_DECL_REX_FUNC(search,-2,_SC("xsn")),
+	_DECL_REX_FUNC(match,2,_SC("xs")),
+	_DECL_REX_FUNC(gmatch,3,_SC("xsc")),
+	_DECL_REX_FUNC(gsub,3,_SC("xs c|a|t")),
+	_DECL_REX_FUNC(capture,-2,_SC("xsn")),
+	_DECL_REX_FUNC(xcapture,-2,_SC("xsn")),
+	_DECL_REX_FUNC(getxcapture,4,_SC("xsna")),
+	_DECL_REX_FUNC(subexpcount,1,_SC("x")),
+	_DECL_REX_FUNC(_typeof,1,_SC("x")),
+	{0,0}
+};
+#undef _DECL_REX_FUNC
+
+#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask}
+static SQRegFunction stringlib_funcs[]={
+	_DECL_FUNC(printf,-2,_SC(".s")),
+	_DECL_FUNC(format,-2,_SC(".s")),
+	{0,0}
+};
+#undef _DECL_FUNC
+
+
+SQInteger sqstd_register_stringlib(HSQUIRRELVM v)
+{
+	sq_pushstring(v,_SC("regexp"),-1);
+	sq_newclass(v,SQFalse);
+	SQInteger i = 0;
+	while(rexobj_funcs[i].name != 0) {
+		SQRegFunction &f = rexobj_funcs[i];
+		sq_pushstring(v,f.name,-1);
+		sq_newclosure(v,f.f,0);
+		sq_setparamscheck(v,f.nparamscheck,f.typemask);
+		sq_setnativeclosurename(v,-1,f.name);
+		sq_newslot(v,-3,SQFalse);
+		i++;
+	}
+	sq_newslot(v,-3,SQFalse);
+
+	i = 0;
+	while(stringlib_funcs[i].name!=0)
+	{
+		sq_pushstring(v,stringlib_funcs[i].name,-1);
+		sq_newclosure(v,stringlib_funcs[i].f,0);
+		sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask);
+		sq_setnativeclosurename(v,-1,stringlib_funcs[i].name);
+		sq_newslot(v,-3,SQFalse);
+		i++;
+	}
+	return 1;
+}

+ 13 - 8
SquiLu/squirrel/sqbaselib.cpp

@@ -237,9 +237,11 @@ static SQRESULT get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,S
 	sidx=0;
 	sidx=0;
 	eidx=0;
 	eidx=0;
 	o=stack_get(v,1);
 	o=stack_get(v,1);
-	SQObjectPtr &start=stack_get(v,2);
-	if(type(start)!=OT_NULL && sq_isnumeric(start)){
-		sidx=tointeger(start);
+	if(top>1){
+		SQObjectPtr &start=stack_get(v,2);
+		if(type(start)!=OT_NULL && sq_isnumeric(start)){
+			sidx=tointeger(start);
+		}
 	}
 	}
 	if(top>2){
 	if(top>2){
 		SQObjectPtr &end=stack_get(v,3);
 		SQObjectPtr &end=stack_get(v,3);
@@ -574,10 +576,9 @@ static SQRESULT default_delegate_tointeger(HSQUIRRELVM v)
 
 
 static SQRESULT default_delegate_tostring(HSQUIRRELVM v)
 static SQRESULT default_delegate_tostring(HSQUIRRELVM v)
 {
 {
-    if(SQ_SUCCEEDED(sq_tostring(v,1))) {
-        return 1;
-    }
-    return SQ_ERROR;
+	if(SQ_FAILED(sq_tostring(v,1)))
+		return SQ_ERROR;
+	return 1;
 }
 }
 
 
 static SQRESULT obj_delegate_weakref(HSQUIRRELVM v)
 static SQRESULT obj_delegate_weakref(HSQUIRRELVM v)
@@ -615,7 +616,11 @@ static SQRESULT table_rawdelete(HSQUIRRELVM v)
 
 
 static SQRESULT container_rawexists(HSQUIRRELVM v)
 static SQRESULT container_rawexists(HSQUIRRELVM v)
 {
 {
-	sq_pushbool(v, sq_rawexists(v,-2));
+	if(SQ_SUCCEEDED(sq_rawget(v,-2))) {
+		sq_pushbool(v,SQTrue);
+		return 1;
+	}
+	sq_pushbool(v,SQFalse);
 	return 1;
 	return 1;
 }
 }
 
 

+ 605 - 595
SquiLu/squirrel/sqfuncstate.cpp

@@ -1,602 +1,612 @@
-/*
-	see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#ifndef NO_COMPILER
-#include "sqcompiler.h"
-#include "sqstring.h"
-#include "sqfuncproto.h"
-#include "sqtable.h"
-#include "sqopcodes.h"
-#include "sqfuncstate.h"
-
+/*
+	see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#ifndef NO_COMPILER
+#include "sqcompiler.h"
+#include "sqstring.h"
+#include "sqfuncproto.h"
+#include "sqtable.h"
+#include "sqopcodes.h"
+#include "sqfuncstate.h"
+
 #ifdef _DEBUG_DUMP
 #ifdef _DEBUG_DUMP
-#define ENUM_OP(a,b) {_SC(#a)},
+#define ENUM_OP(a,b) {_SC(#a)},
 SQInstructionDesc g_InstrDesc[]={
 SQInstructionDesc g_InstrDesc[]={
-    SQ_OP_CODE_LIST()
+    SQ_OP_CODE_LIST()
 };
 };
-#undef ENUM_OP
-#endif
-void DumpLiteral(SQObjectPtr &o)
-{
-	switch(type(o)){
-		case OT_STRING:	scprintf(_SC("\"%s\""),_stringval(o));break;
-		case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
-		case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break;
-		case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
-		default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler
-	}
-}
-
-SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
-{
-		_nliterals = 0;
-		_literals = SQTable::Create(ss,0);
-		_strings =  SQTable::Create(ss,0);
-		_sharedstate = ss;
-		_lastline = 0;
-		_optimization = true;
-		_parent = parent;
-		_stacksize = 0;
-		_traps = 0;
-		_returnexp = 0;
-		_varparams = false;
-		_errfunc = efunc;
-		_errtarget = ed;
-		_bgenerator = false;
-		_outers = 0;
-		_ss = ss;
-
-}
-
-void SQFuncState::Error(const SQChar *err)
-{
-	_errfunc(_errtarget,err);
-}
-
-#ifdef _DEBUG_DUMP
-void SQFuncState::Dump(SQFunctionProto *func)
-{
-	SQUnsignedInteger n=0,i;
-	SQInteger si;
-	scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
-	scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
-	scprintf(_SC("--------------------------------------------------------------------\n"));
-	scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
-	scprintf(_SC("-----LITERALS\n"));
-	SQObjectPtr refidx,key,val;
-	SQInteger idx;
-	SQObjectPtrVec templiterals;
-	templiterals.resize(_nliterals);
-	while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
-		refidx=idx;
-		templiterals[_integer(val)]=key;
-	}
-	for(i=0;i<templiterals.size();i++){
-		scprintf(_SC("[%d] "),n);
-		DumpLiteral(templiterals[i]);
-		scprintf(_SC("\n"));
-		n++;
-	}
-	scprintf(_SC("-----PARAMS\n"));
-	if(_varparams)
-		scprintf(_SC("<<VARPARAMS>>\n"));
-	n=0;
-	for(i=0;i<_parameters.size();i++){
-		scprintf(_SC("[%d] "),n);
-		DumpLiteral(_parameters[i]);
-		scprintf(_SC("\n"));
-		n++;
-	}
-	scprintf(_SC("-----LOCALS\n"));
-	for(si=0;si<func->_nlocalvarinfos;si++){
-		SQLocalVarInfo lvi=func->_localvarinfos[si];
-		scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
-		n++;
-	}
-	scprintf(_SC("-----LINE INFO\n"));
-	for(i=0;i<_lineinfos.size();i++){
-		SQLineInfo li=_lineinfos[i];
-		scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
-		n++;
-	}
-	scprintf(_SC("-----dump\n"));
-	n=0;
-	for(i=0;i<_instructions.size();i++){
-		SQInstruction &inst=_instructions[i];
-		if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
-
-			SQInteger lidx = inst._arg1;
-			scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
-			if(lidx >= 0xFFFFFFFF)
-				scprintf(_SC("null"));
-			else {
-				SQInteger refidx;
-				SQObjectPtr val,key,refo;
-				while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
-					refo = refidx;
-				}
-				DumpLiteral(key);
-			}
-			if(inst.op != _OP_DLOAD) {
-				scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
-			}
-			else {
-				scprintf(_SC(" %d "),inst._arg2);
-				lidx = inst._arg3;
-				if(lidx >= 0xFFFFFFFF)
-					scprintf(_SC("null"));
-				else {
-					SQInteger refidx;
-					SQObjectPtr val,key,refo;
-					while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
-						refo = refidx;
-				}
-				DumpLiteral(key);
-				scprintf(_SC("\n"));
-			}
-			}
-		}
-		else if(inst.op==_OP_LOADFLOAT) {
-			scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3);
-		}
-	/*	else if(inst.op==_OP_ARITH){
-			scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
-		}*/
-		else {
-			scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
-		}
-		n++;
-	}
-	scprintf(_SC("-----\n"));
-	scprintf(_SC("stack size[%d]\n"),func->_stacksize);
-	scprintf(_SC("--------------------------------------------------------------------\n\n"));
-}
-#endif
-
-SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
-{
-	return GetConstant(SQObjectPtr(cons));
-}
-
-SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
-{
-	return GetConstant(SQObjectPtr(cons));
-}
-
-SQInteger SQFuncState::GetConstant(const SQObject &cons)
-{
-	SQObjectPtr val;
-	if(!_table(_literals)->Get(cons,val))
-	{
-		val = _nliterals;
-		_table(_literals)->NewSlot(cons,val);
-		_nliterals++;
-		if(_nliterals > MAX_LITERALS) {
-			val.Null();
-			Error(_SC("internal compiler error: too many literals"));
-		}
-	}
-	return _integer(val);
-}
-
-void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
-{
-	_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
-	_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
-	_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
-	_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
-}
-
-void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
-{
-	switch(arg){
-		case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
-		case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
-		case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
-		case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
-	};
-}
-
-SQInteger SQFuncState::AllocStackPos()
-{
-	SQInteger npos=_vlocals.size();
-	_vlocals.push_back(SQLocalVarInfo());
-	if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
-		if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
-		_stacksize=_vlocals.size();
-	}
-	return npos;
-}
-
-SQInteger SQFuncState::PushTarget(SQInteger n)
-{
-	if(n!=-1){
-		_targetstack.push_back(n);
-		return n;
-	}
-	n=AllocStackPos();
-	_targetstack.push_back(n);
-	return n;
-}
-
-SQInteger SQFuncState::GetUpTarget(SQInteger n){
-	return _targetstack[((_targetstack.size()-1)-n)];
-}
-
-SQInteger SQFuncState::TopTarget(){
-	return _targetstack.back();
-}
-SQInteger SQFuncState::PopTarget()
-{
-	SQUnsignedInteger npos=_targetstack.back();
-	assert(npos < _vlocals.size());
-	SQLocalVarInfo &t = _vlocals[npos];
-	if(type(t._name)==OT_NULL){
-		_vlocals.pop_back();
-	}
-	_targetstack.pop_back();
-	return npos;
-}
-
-SQInteger SQFuncState::GetStackSize()
-{
-	return _vlocals.size();
-}
-
-SQInteger SQFuncState::CountOuters(SQInteger stacksize)
-{
-	SQInteger outers = 0;
-	SQInteger k = _vlocals.size() - 1;
-	while(k >= stacksize) {
-		SQLocalVarInfo &lvi = _vlocals[k];
-		k--;
-		if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
-			outers++;
-		}
-	}
-	return outers;
-}
-
-void SQFuncState::SetStackSize(SQInteger n)
-{
-	SQInteger size=_vlocals.size();
-	while(size>n){
-		size--;
-		SQLocalVarInfo lvi = _vlocals.back();
-		if(type(lvi._name)!=OT_NULL){
-			if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
-				_outers--;
-			}
-			lvi._end_op = GetCurrentPos();
-			_localvarinfos.push_back(lvi);
-		}
-		_vlocals.pop_back();
-	}
-}
-
-bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
-{
-	if(stkpos>=_vlocals.size())return false;
-	else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
-	return false;
-}
-
-SQInteger SQFuncState::PushLocalVariable(const SQObject &name, SQInteger scope, SQInteger type)
-{
-	SQInteger pos=_vlocals.size();
-	SQLocalVarInfo lvi;
-	lvi._name=name;
-	lvi._start_op=GetCurrentPos()+1;
-	lvi._pos=_vlocals.size();
+#undef ENUM_OP
+#endif
+void DumpLiteral(SQObjectPtr &o)
+{
+	switch(type(o)){
+		case OT_STRING:	scprintf(_SC("\"%s\""),_stringval(o));break;
+		case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
+		case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break;
+		case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
+		default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler
+	}
+}
+
+SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
+{
+		_nliterals = 0;
+		_literals = SQTable::Create(ss,0);
+		_strings =  SQTable::Create(ss,0);
+		_sharedstate = ss;
+		_lastline = 0;
+		_optimization = true;
+		_parent = parent;
+		_stacksize = 0;
+		_traps = 0;
+		_returnexp = 0;
+		_varparams = false;
+		_errfunc = efunc;
+		_errtarget = ed;
+		_bgenerator = false;
+		_outers = 0;
+		_ss = ss;
+
+}
+
+void SQFuncState::Error(const SQChar *err)
+{
+	_errfunc(_errtarget,err);
+}
+
+#ifdef _DEBUG_DUMP
+void SQFuncState::Dump(SQFunctionProto *func)
+{
+	SQUnsignedInteger n=0,i;
+	SQInteger si;
+	scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
+	scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
+	scprintf(_SC("--------------------------------------------------------------------\n"));
+	scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
+	scprintf(_SC("-----LITERALS\n"));
+	SQObjectPtr refidx,key,val;
+	SQInteger idx;
+	SQObjectPtrVec templiterals;
+	templiterals.resize(_nliterals);
+	while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
+		refidx=idx;
+		templiterals[_integer(val)]=key;
+	}
+	for(i=0;i<templiterals.size();i++){
+		scprintf(_SC("[%d] "),n);
+		DumpLiteral(templiterals[i]);
+		scprintf(_SC("\n"));
+		n++;
+	}
+	scprintf(_SC("-----PARAMS\n"));
+	if(_varparams)
+		scprintf(_SC("<<VARPARAMS>>\n"));
+	n=0;
+	for(i=0;i<_parameters.size();i++){
+		scprintf(_SC("[%d] "),n);
+		DumpLiteral(_parameters[i]);
+		scprintf(_SC("\n"));
+		n++;
+	}
+	scprintf(_SC("-----LOCALS\n"));
+	for(si=0;si<func->_nlocalvarinfos;si++){
+		SQLocalVarInfo lvi=func->_localvarinfos[si];
+		scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
+		n++;
+	}
+	scprintf(_SC("-----LINE INFO\n"));
+	for(i=0;i<_lineinfos.size();i++){
+		SQLineInfo li=_lineinfos[i];
+		scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
+		n++;
+	}
+	scprintf(_SC("-----dump\n"));
+	n=0;
+	for(i=0;i<_instructions.size();i++){
+		SQInstruction &inst=_instructions[i];
+		if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
+
+			SQInteger lidx = inst._arg1;
+			scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
+			if(lidx >= 0xFFFFFFFF)
+				scprintf(_SC("null"));
+			else {
+				SQInteger refidx;
+				SQObjectPtr val,key,refo;
+				while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
+					refo = refidx;
+				}
+				DumpLiteral(key);
+			}
+			if(inst.op != _OP_DLOAD) {
+				scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
+			}
+			else {
+				scprintf(_SC(" %d "),inst._arg2);
+				lidx = inst._arg3;
+				if(lidx >= 0xFFFFFFFF)
+					scprintf(_SC("null"));
+				else {
+					SQInteger refidx;
+					SQObjectPtr val,key,refo;
+					while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
+						refo = refidx;
+				}
+				DumpLiteral(key);
+				scprintf(_SC("\n"));
+			}
+			}
+		}
+		else if(inst.op==_OP_LOADFLOAT) {
+			scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3);
+		}
+	/*	else if(inst.op==_OP_ARITH){
+			scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
+		}*/
+		else {
+			scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
+		}
+		n++;
+	}
+	scprintf(_SC("-----\n"));
+	scprintf(_SC("stack size[%d]\n"),func->_stacksize);
+	scprintf(_SC("--------------------------------------------------------------------\n\n"));
+}
+#endif
+
+SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
+{
+	return GetConstant(SQObjectPtr(cons));
+}
+
+SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
+{
+	return GetConstant(SQObjectPtr(cons));
+}
+
+SQInteger SQFuncState::GetConstant(const SQObject &cons)
+{
+	SQObjectPtr val;
+	if(!_table(_literals)->Get(cons,val))
+	{
+		val = _nliterals;
+		_table(_literals)->NewSlot(cons,val);
+		_nliterals++;
+		if(_nliterals > MAX_LITERALS) {
+			val.Null();
+			Error(_SC("internal compiler error: too many literals"));
+		}
+	}
+	return _integer(val);
+}
+
+void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
+{
+	_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
+	_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
+	_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
+	_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
+}
+
+void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
+{
+	switch(arg){
+		case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
+		case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
+		case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
+		case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
+	};
+}
+
+SQInteger SQFuncState::AllocStackPos()
+{
+	SQInteger npos=_vlocals.size();
+	_vlocals.push_back(SQLocalVarInfo());
+	if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
+		if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
+		_stacksize=_vlocals.size();
+	}
+	return npos;
+}
+
+SQInteger SQFuncState::PushTarget(SQInteger n)
+{
+	if(n!=-1){
+		_targetstack.push_back(n);
+		return n;
+	}
+	n=AllocStackPos();
+	_targetstack.push_back(n);
+	return n;
+}
+
+SQInteger SQFuncState::GetUpTarget(SQInteger n){
+	return _targetstack[((_targetstack.size()-1)-n)];
+}
+
+SQInteger SQFuncState::TopTarget(){
+	return _targetstack.back();
+}
+SQInteger SQFuncState::PopTarget()
+{
+	SQUnsignedInteger npos=_targetstack.back();
+	assert(npos < _vlocals.size());
+	SQLocalVarInfo &t = _vlocals[npos];
+	if(type(t._name)==OT_NULL){
+		_vlocals.pop_back();
+	}
+	_targetstack.pop_back();
+	return npos;
+}
+
+SQInteger SQFuncState::GetStackSize()
+{
+	return _vlocals.size();
+}
+
+SQInteger SQFuncState::CountOuters(SQInteger stacksize)
+{
+	SQInteger outers = 0;
+	SQInteger k = _vlocals.size() - 1;
+	while(k >= stacksize) {
+		SQLocalVarInfo &lvi = _vlocals[k];
+		k--;
+		if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
+			outers++;
+		}
+	}
+	return outers;
+}
+
+void SQFuncState::SetStackSize(SQInteger n)
+{
+	SQInteger size=_vlocals.size();
+	while(size>n){
+		size--;
+		SQLocalVarInfo lvi = _vlocals.back();
+		if(type(lvi._name)!=OT_NULL){
+			if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
+				_outers--;
+			}
+			lvi._end_op = GetCurrentPos();
+			_localvarinfos.push_back(lvi);
+		}
+		_vlocals.pop_back();
+	}
+}
+
+bool SQFuncState::IsConstant(const SQObject &name,SQObject &e)
+{
+	SQObjectPtr val;
+	if(_table(_sharedstate->_consts)->Get(name,val)) {
+		e = val;
+		return true;
+	}
+	return false;
+}
+
+bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
+{
+	if(stkpos>=_vlocals.size())return false;
+	else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
+	return false;
+}
+
+SQInteger SQFuncState::PushLocalVariable(const SQObject &name, SQInteger scope, SQInteger type)
+{
+	SQInteger pos=_vlocals.size();
+	SQLocalVarInfo lvi;
+	lvi._name=name;
+	lvi._start_op=GetCurrentPos()+1;
+	lvi._pos=_vlocals.size();
 	lvi._scope=scope;
 	lvi._scope=scope;
 	lvi._type=type;
 	lvi._type=type;
-	_vlocals.push_back(lvi);
-	if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
-//printf("%d %d %d %d %d %s\n", __LINE__, scope, type, pos, lvi._start_op, _stringval(lvi._name));
-	return pos;
-}
-
-
-
-SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
-{
-	SQInteger locals=_vlocals.size();
-	while(locals>=1){
-		SQLocalVarInfo &lvi = _vlocals[locals-1];
-		if(type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){
-			return locals-1;
-		}
-		locals--;
+	_vlocals.push_back(lvi);
+	if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
+//printf("%d %d %d %d %d %s\n", __LINE__, scope, type, pos, lvi._start_op, _stringval(lvi._name));
+	return pos;
+}
+
+
+
+SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
+{
+	SQInteger locals=_vlocals.size();
+	while(locals>=1){
+		SQLocalVarInfo &lvi = _vlocals[locals-1];
+		if(type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){
+			return locals-1;
+		}
+		locals--;
 	}
 	}
-	return -1;
-}
-
-void SQFuncState::MarkLocalAsOuter(SQInteger pos)
-{
-	SQLocalVarInfo &lvi = _vlocals[pos];
-	lvi._end_op = UINT_MINUS_ONE;
-	_outers++;
-}
-
-SQInteger SQFuncState::FindOuterVariable(const SQObject &name)
-{
-	SQInteger pos=-1;
-	if(_parent) {
-		pos = _parent->GetLocalVariable(name);
-		if(pos == -1) {
-			pos = _parent->FindOuterVariable(name);
-		}
-	}
-	return pos;
-}
-
-SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
-{
-	SQInteger outers = _outervalues.size();
-	for(SQInteger i = 0; i<outers; i++) {
-		if(_string(_outervalues[i]._name) == _string(name))
-			return i;
-	}
-	SQInteger pos=-1;
-	if(_parent) {
-		pos = _parent->GetLocalVariable(name);
-		if(pos == -1) {
-			pos = _parent->GetOuterVariable(name);
-			if(pos != -1) {
-				_outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
-				return _outervalues.size() - 1;
-			}
-		}
-		else {
-			_parent->MarkLocalAsOuter(pos);
-			_outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
-			return _outervalues.size() - 1;
-		}
-	}
-	return -1;
-}
-
-void SQFuncState::AddParameter(const SQObject &name, SQInteger scope, SQInteger type)
-{
-	PushLocalVariable(name, scope, type);
-	_parameters.push_back(name);
-}
-
-void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
-{
-	if(_lastline!=line || force){
-		SQLineInfo li;
-		li._line=line;li._op=(GetCurrentPos()+1);
-		if(lineop)AddInstruction(_OP_LINE,0,line);
-		if(_lastline!=line) {
-			_lineinfos.push_back(li);
-		}
-		_lastline=line;
-	}
-}
-
-void SQFuncState::DiscardTarget()
-{
-	SQInteger discardedtarget = PopTarget();
-	SQInteger size = _instructions.size();
-	if(size > 0 && _optimization){
-		SQInstruction &pi = _instructions[size-1];//previous instruction
-		switch(pi.op) {
-		case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL:
-			if(pi._arg0 == discardedtarget) {
-				pi._arg0 = 0xFF;
-			}
-		}
-	}
-}
-
-void SQFuncState::AddInstruction(SQInstruction &i)
-{
-	SQInteger size = _instructions.size();
-	if(size > 0 && _optimization){ //simple optimizer
-		SQInstruction &pi = _instructions[size-1];//previous instruction
-		switch(i.op) {
-		case _OP_JZ:
-			if( pi.op == _OP_CMP && pi._arg1 < 0xFF) {
-				pi.op = _OP_JCMP;
-				pi._arg0 = (unsigned char)pi._arg1;
-				pi._arg1 = i._arg1;
-				return;
+	return -1;
+}
+
+void SQFuncState::MarkLocalAsOuter(SQInteger pos)
+{
+	SQLocalVarInfo &lvi = _vlocals[pos];
+	lvi._end_op = UINT_MINUS_ONE;
+	_outers++;
+}
+
+SQInteger SQFuncState::FindOuterVariable(const SQObject &name)
+{
+	SQInteger pos=-1;
+	if(_parent) {
+		pos = _parent->GetLocalVariable(name);
+		if(pos == -1) {
+			pos = _parent->FindOuterVariable(name);
+		}
+	}
+	return pos;
+}
+
+SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
+{
+	SQInteger outers = _outervalues.size();
+	for(SQInteger i = 0; i<outers; i++) {
+		if(_string(_outervalues[i]._name) == _string(name))
+			return i;
+	}
+	SQInteger pos=-1;
+	if(_parent) {
+		pos = _parent->GetLocalVariable(name);
+		if(pos == -1) {
+			pos = _parent->GetOuterVariable(name);
+			if(pos != -1) {
+				_outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
+				return _outervalues.size() - 1;
+			}
+		}
+		else {
+			_parent->MarkLocalAsOuter(pos);
+			_outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
+			return _outervalues.size() - 1;
+		}
+	}
+	return -1;
+}
+
+void SQFuncState::AddParameter(const SQObject &name, SQInteger scope, SQInteger type)
+{
+	PushLocalVariable(name, scope, type);
+	_parameters.push_back(name);
+}
+
+void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
+{
+	if(_lastline!=line || force){
+		SQLineInfo li;
+		li._line=line;li._op=(GetCurrentPos()+1);
+		if(lineop)AddInstruction(_OP_LINE,0,line);
+		if(_lastline!=line) {
+			_lineinfos.push_back(li);
+		}
+		_lastline=line;
+	}
+}
+
+void SQFuncState::DiscardTarget()
+{
+	SQInteger discardedtarget = PopTarget();
+	SQInteger size = _instructions.size();
+	if(size > 0 && _optimization){
+		SQInstruction &pi = _instructions[size-1];//previous instruction
+		switch(pi.op) {
+		case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL:
+			if(pi._arg0 == discardedtarget) {
+				pi._arg0 = 0xFF;
+			}
+		}
+	}
+}
+
+void SQFuncState::AddInstruction(SQInstruction &i)
+{
+	SQInteger size = _instructions.size();
+	if(size > 0 && _optimization){ //simple optimizer
+		SQInstruction &pi = _instructions[size-1];//previous instruction
+		switch(i.op) {
+		case _OP_JZ:
+			if( pi.op == _OP_CMP && pi._arg1 < 0xFF) {
+				pi.op = _OP_JCMP;
+				pi._arg0 = (unsigned char)pi._arg1;
+				pi._arg1 = i._arg1;
+				return;
+			}
+			break;
+		case _OP_SET:
+		case _OP_NEWSLOT:
+			if(i._arg0 == i._arg3) {
+				i._arg0 = 0xFF;
+			}
+			break;
+		case _OP_SETOUTER:
+			if(i._arg0 == i._arg2) {
+				i._arg0 = 0xFF;
+			}
+			break;
+		case _OP_RETURN:
+			if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
+				pi.op = _OP_TAILCALL;
+			} else if(pi.op == _OP_CLOSE){
+				pi = i;
+				return;
 			}
 			}
-			break;
-		case _OP_SET:
-		case _OP_NEWSLOT:
-			if(i._arg0 == i._arg3) {
-				i._arg0 = 0xFF;
-			}
-			break;
-		case _OP_SETOUTER:
-			if(i._arg0 == i._arg2) {
-				i._arg0 = 0xFF;
-			}
-			break;
-		case _OP_RETURN:
-			if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
-				pi.op = _OP_TAILCALL;
-			} else if(pi.op == _OP_CLOSE){
-				pi = i;
-				return;
-			}
-		break;
-		case _OP_GET:
-			if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
-				//pi._arg1 = pi._arg1;
-				pi._arg2 = (unsigned char)i._arg1;
-				pi.op = _OP_GETK;
-				pi._arg0 = i._arg0;
-
-				return;
-			}
-		break;
-		case _OP_PREPCALL:
-			if( pi.op == _OP_LOAD  && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
-				pi.op = _OP_PREPCALLK;
-				pi._arg0 = i._arg0;
-				//pi._arg1 = pi._arg1;
-				pi._arg2 = i._arg2;
-				pi._arg3 = i._arg3;
-				return;
-			}
-			break;
-		case _OP_APPENDARRAY: {
-			SQInteger aat = -1;
-			switch(pi.op) {
-			case _OP_LOAD: aat = AAT_LITERAL; break;
-			case _OP_LOADINT: aat = AAT_INT; break;
-			case _OP_LOADBOOL: aat = AAT_BOOL; break;
-			case _OP_LOADFLOAT: aat = AAT_FLOAT; break;
-			default: break;
-			}
-			if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
-				pi.op = _OP_APPENDARRAY;
-				pi._arg0 = i._arg0;
-				//pi._arg1 = pi._arg1;
-				pi._arg2 = (unsigned char)aat;
-				pi._arg3 = MAX_FUNC_STACKSIZE;
-				return;
-			}
-							  }
-			break;
-		case _OP_MOVE:
-			switch(pi.op) {
-			case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW:
-			case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD:
-
-				if(pi._arg0 == i._arg1)
-				{
-					pi._arg0 = i._arg0;
-					_optimization = false;
-					//_result_elimination = false;
-					return;
-				}
-			}
-
-			if(pi.op == _OP_MOVE)
-			{
-				pi.op = _OP_DMOVE;
-				pi._arg2 = i._arg0;
-				pi._arg3 = (unsigned char)i._arg1;
-				return;
-			}
-			break;
-		case _OP_LOAD:
-			if(pi.op == _OP_LOAD && i._arg1 < 256) {
-				pi.op = _OP_DLOAD;
-				pi._arg2 = i._arg0;
-				pi._arg3 = (unsigned char)i._arg1;
-				return;
-			}
-			break;
-		case _OP_EQ:case _OP_NE:
-			if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
-			{
-				pi.op = i.op;
-				pi._arg0 = i._arg0;
-				//pi._arg1 = pi._arg1;
-				pi._arg2 = i._arg2;
-				pi._arg3 = MAX_FUNC_STACKSIZE;
-				return;
-			}
-			break;
-		case _OP_LOADNULLS:
-			if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
-
-				pi._arg1 = pi._arg1 + 1;
-				pi.op = _OP_LOADNULLS;
-				return;
-			}
-            break;
-		case _OP_LINE:
-			if(pi.op == _OP_LINE) {
-				_instructions.pop_back();
-				_lineinfos.pop_back();
-			}
-			break;
-		}
-	}
-	_optimization = true;
-	_instructions.push_back(i);
-}
-
-SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
-{
-	SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
-	_table(_strings)->NewSlot(ns,(SQInteger)1);
-	return ns;
-}
-
-SQObject SQFuncState::CreateTable()
-{
-	SQObjectPtr nt(SQTable::Create(_sharedstate,0));
-	_table(_strings)->NewSlot(nt,(SQInteger)1);
-	return nt;
-}
-
-SQFunctionProto *SQFuncState::BuildProto()
-{
-
-	SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(),
-		_nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
-		_lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
-
-	SQObjectPtr refidx,key,val;
-	SQInteger idx;
-
-	f->_stacksize = _stacksize;
-	f->_sourcename = _sourcename;
-	f->_bgenerator = _bgenerator;
-	f->_name = _name;
-
-	while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
-		f->_literals[_integer(val)]=key;
-		refidx=idx;
-	}
-
-	for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];
-	for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];
-	for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];
-	for(SQUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl];
-	for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni];
-	for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd];
-
-	memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
-
-	f->_varparams = _varparams;
-
-#ifdef SQ_JIT_LLVM
-	f->JitCompile();
-#endif
-
-	return f;
-}
-
-SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
-{
-	SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
-	new (child) SQFuncState(ss,this,_errfunc,_errtarget);
-	_childstates.push_back(child);
-	return child;
-}
-
-void SQFuncState::PopChildState()
-{
-	SQFuncState *child = _childstates.back();
-	sq_delete(child,SQFuncState);
-	_childstates.pop_back();
-}
-
-SQFuncState::~SQFuncState()
-{
-	while(_childstates.size() > 0)
-	{
-		PopChildState();
-	}
-}
-
-#endif
+		break;
+		case _OP_GET:
+			if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
+				//pi._arg1 = pi._arg1;
+				pi._arg2 = (unsigned char)i._arg1;
+				pi.op = _OP_GETK;
+				pi._arg0 = i._arg0;
+
+				return;
+			}
+		break;
+		case _OP_PREPCALL:
+			if( pi.op == _OP_LOAD  && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
+				pi.op = _OP_PREPCALLK;
+				pi._arg0 = i._arg0;
+				//pi._arg1 = pi._arg1;
+				pi._arg2 = i._arg2;
+				pi._arg3 = i._arg3;
+				return;
+			}
+			break;
+		case _OP_APPENDARRAY: {
+			SQInteger aat = -1;
+			switch(pi.op) {
+			case _OP_LOAD: aat = AAT_LITERAL; break;
+			case _OP_LOADINT: aat = AAT_INT; break;
+			case _OP_LOADBOOL: aat = AAT_BOOL; break;
+			case _OP_LOADFLOAT: aat = AAT_FLOAT; break;
+			default: break;
+			}
+			if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
+				pi.op = _OP_APPENDARRAY;
+				pi._arg0 = i._arg0;
+				//pi._arg1 = pi._arg1;
+				pi._arg2 = (unsigned char)aat;
+				pi._arg3 = MAX_FUNC_STACKSIZE;
+				return;
+			}
+							  }
+			break;
+		case _OP_MOVE:
+			switch(pi.op) {
+			case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW:
+			case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD:
+
+				if(pi._arg0 == i._arg1)
+				{
+					pi._arg0 = i._arg0;
+					_optimization = false;
+					//_result_elimination = false;
+					return;
+				}
+			}
+
+			if(pi.op == _OP_MOVE)
+			{
+				pi.op = _OP_DMOVE;
+				pi._arg2 = i._arg0;
+				pi._arg3 = (unsigned char)i._arg1;
+				return;
+			}
+			break;
+		case _OP_LOAD:
+			if(pi.op == _OP_LOAD && i._arg1 < 256) {
+				pi.op = _OP_DLOAD;
+				pi._arg2 = i._arg0;
+				pi._arg3 = (unsigned char)i._arg1;
+				return;
+			}
+			break;
+		case _OP_EQ:case _OP_NE:
+			if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
+			{
+				pi.op = i.op;
+				pi._arg0 = i._arg0;
+				//pi._arg1 = pi._arg1;
+				pi._arg2 = i._arg2;
+				pi._arg3 = MAX_FUNC_STACKSIZE;
+				return;
+			}
+			break;
+		case _OP_LOADNULLS:
+			if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
+
+				pi._arg1 = pi._arg1 + 1;
+				pi.op = _OP_LOADNULLS;
+				return;
+			}
+            break;
+		case _OP_LINE:
+			if(pi.op == _OP_LINE) {
+				_instructions.pop_back();
+				_lineinfos.pop_back();
+			}
+			break;
+		}
+	}
+	_optimization = true;
+	_instructions.push_back(i);
+}
+
+SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
+{
+	SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
+	_table(_strings)->NewSlot(ns,(SQInteger)1);
+	return ns;
+}
+
+SQObject SQFuncState::CreateTable()
+{
+	SQObjectPtr nt(SQTable::Create(_sharedstate,0));
+	_table(_strings)->NewSlot(nt,(SQInteger)1);
+	return nt;
+}
+
+SQFunctionProto *SQFuncState::BuildProto()
+{
+
+	SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(),
+		_nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
+		_lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
+
+	SQObjectPtr refidx,key,val;
+	SQInteger idx;
+
+	f->_stacksize = _stacksize;
+	f->_sourcename = _sourcename;
+	f->_bgenerator = _bgenerator;
+	f->_name = _name;
+
+	while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
+		f->_literals[_integer(val)]=key;
+		refidx=idx;
+	}
+
+	for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];
+	for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];
+	for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];
+	for(SQUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl];
+	for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni];
+	for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd];
+
+	memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
+
+	f->_varparams = _varparams;
+
+#ifdef SQ_JIT_LLVM
+	f->JitCompile();
+#endif
+
+	return f;
+}
+
+SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
+{
+	SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
+	new (child) SQFuncState(ss,this,_errfunc,_errtarget);
+	_childstates.push_back(child);
+	return child;
+}
+
+void SQFuncState::PopChildState()
+{
+	SQFuncState *child = _childstates.back();
+	sq_delete(child,SQFuncState);
+	_childstates.pop_back();
+}
+
+SQFuncState::~SQFuncState()
+{
+	while(_childstates.size() > 0)
+	{
+		PopChildState();
+	}
+}
+
+#endif

+ 91 - 90
SquiLu/squirrel/sqfuncstate.h

@@ -1,91 +1,92 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQFUNCSTATE_H_
-#define _SQFUNCSTATE_H_
-///////////////////////////////////
-#include "squtils.h"
-
-struct SQFuncState
-{
-	SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed);
-	~SQFuncState();
-#ifdef _DEBUG_DUMP
-	void Dump(SQFunctionProto *func);
-#endif
-	void Error(const SQChar *err);
-	SQFuncState *PushChildState(SQSharedState *ss);
-	void PopChildState();
-	void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}
-	void AddInstruction(SQInstruction &i);
-	void SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2=0,SQInteger arg3=0);
-	void SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val);
-	SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];}
-	void PopInstructions(SQInteger size){for(SQInteger i=0;i<size;i++)_instructions.pop_back();}
-	void SetStackSize(SQInteger n);
-	SQInteger CountOuters(SQInteger stacksize);
-	void SnoozeOpt(){_optimization=false;}
-	void AddDefaultParam(SQInteger trg) { _defaultparams.push_back(trg); }
-	SQInteger GetDefaultParamCount() { return _defaultparams.size(); }
-	SQInteger GetCurrentPos(){return _instructions.size()-1;}
-	SQInteger GetNumericConstant(const SQInteger cons);
-	SQInteger GetNumericConstant(const SQFloat cons);
-	SQInteger PushLocalVariable(const SQObject &name, SQInteger scope, SQInteger type=_VAR_ANY);
-	void AddParameter(const SQObject &name, SQInteger scope, SQInteger type=_VAR_ANY);
-	//void AddOuterValue(const SQObject &name);
-	SQInteger GetLocalVariable(const SQObject &name);
+/*	see copyright notice in squirrel.h */
+#ifndef _SQFUNCSTATE_H_
+#define _SQFUNCSTATE_H_
+///////////////////////////////////
+#include "squtils.h"
+
+struct SQFuncState
+{
+	SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed);
+	~SQFuncState();
+#ifdef _DEBUG_DUMP
+	void Dump(SQFunctionProto *func);
+#endif
+	void Error(const SQChar *err);
+	SQFuncState *PushChildState(SQSharedState *ss);
+	void PopChildState();
+	void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}
+	void AddInstruction(SQInstruction &i);
+	void SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2=0,SQInteger arg3=0);
+	void SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val);
+	SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];}
+	void PopInstructions(SQInteger size){for(SQInteger i=0;i<size;i++)_instructions.pop_back();}
+	void SetStackSize(SQInteger n);
+	SQInteger CountOuters(SQInteger stacksize);
+	void SnoozeOpt(){_optimization=false;}
+	void AddDefaultParam(SQInteger trg) { _defaultparams.push_back(trg); }
+	SQInteger GetDefaultParamCount() { return _defaultparams.size(); }
+	SQInteger GetCurrentPos(){return _instructions.size()-1;}
+	SQInteger GetNumericConstant(const SQInteger cons);
+	SQInteger GetNumericConstant(const SQFloat cons);
+	SQInteger PushLocalVariable(const SQObject &name, SQInteger scope, SQInteger type=_VAR_ANY);
+	void AddParameter(const SQObject &name, SQInteger scope, SQInteger type=_VAR_ANY);
+	//void AddOuterValue(const SQObject &name);
+	SQInteger GetLocalVariable(const SQObject &name);
 	void MarkLocalAsOuter(SQInteger pos);
 	void MarkLocalAsOuter(SQInteger pos);
-	SQInteger FindOuterVariable(const SQObject &name);
-	SQInteger GetOuterVariable(const SQObject &name);
-	SQInteger GenerateCode();
-	SQInteger GetStackSize();
-	SQInteger CalcStackFrameSize();
-	void AddLineInfos(SQInteger line,bool lineop,bool force=false);
-	SQFunctionProto *BuildProto();
-	SQInteger AllocStackPos();
-	SQInteger PushTarget(SQInteger n=-1);
-	SQInteger PopTarget();
-	SQInteger TopTarget();
-	SQInteger GetUpTarget(SQInteger n);
-	void DiscardTarget();
-	bool IsLocal(SQUnsignedInteger stkpos);
-	SQObject CreateString(const SQChar *s,SQInteger len = -1);
-	SQObject CreateTable();
-	SQInteger _returnexp;
-	SQLocalVarInfoVec _vlocals;
-	SQIntVec _targetstack;
-	SQInteger _stacksize;
-	bool _varparams;
-	bool _bgenerator;
-	SQIntVec _unresolvedbreaks;
-	SQIntVec _unresolvedcontinues;
-	SQObjectPtrVec _functions;
-	SQObjectPtrVec _parameters;
-	SQOuterVarVec _outervalues;
-	SQInstructionVec _instructions;
-	SQLocalVarInfoVec _localvarinfos;
-	SQObjectPtr _literals;
-	SQObjectPtr _strings;
-	SQObjectPtr _name;
-	SQObjectPtr _sourcename;
-	SQInteger _nliterals;
-	SQLineInfoVec _lineinfos;
-	SQFuncState *_parent;
-	SQIntVec _scope_blocks;
-	SQIntVec _breaktargets;
-	SQIntVec _continuetargets;
-	SQIntVec _defaultparams;
-	SQInteger _lastline;
-	SQInteger _traps; //contains number of nested exception traps
-	SQInteger _outers;
-	bool _optimization;
-	SQSharedState *_sharedstate;
-	sqvector<SQFuncState*> _childstates;
-	SQInteger GetConstant(const SQObject &cons);
-private:
-	CompilerErrorFunc _errfunc;
-	void *_errtarget;
-	SQSharedState *_ss;
-};
-
-
-#endif //_SQFUNCSTATE_H_
-
+	SQInteger FindOuterVariable(const SQObject &name);
+	SQInteger GetOuterVariable(const SQObject &name);
+	SQInteger GenerateCode();
+	SQInteger GetStackSize();
+	SQInteger CalcStackFrameSize();
+	void AddLineInfos(SQInteger line,bool lineop,bool force=false);
+	SQFunctionProto *BuildProto();
+	SQInteger AllocStackPos();
+	SQInteger PushTarget(SQInteger n=-1);
+	SQInteger PopTarget();
+	SQInteger TopTarget();
+	SQInteger GetUpTarget(SQInteger n);
+	void DiscardTarget();
+	bool IsLocal(SQUnsignedInteger stkpos);
+	SQObject CreateString(const SQChar *s,SQInteger len = -1);
+	SQObject CreateTable();
+	bool IsConstant(const SQObject &name,SQObject &e);
+	SQInteger _returnexp;
+	SQLocalVarInfoVec _vlocals;
+	SQIntVec _targetstack;
+	SQInteger _stacksize;
+	bool _varparams;
+	bool _bgenerator;
+	SQIntVec _unresolvedbreaks;
+	SQIntVec _unresolvedcontinues;
+	SQObjectPtrVec _functions;
+	SQObjectPtrVec _parameters;
+	SQOuterVarVec _outervalues;
+	SQInstructionVec _instructions;
+	SQLocalVarInfoVec _localvarinfos;
+	SQObjectPtr _literals;
+	SQObjectPtr _strings;
+	SQObjectPtr _name;
+	SQObjectPtr _sourcename;
+	SQInteger _nliterals;
+	SQLineInfoVec _lineinfos;
+	SQFuncState *_parent;
+	SQIntVec _scope_blocks;
+	SQIntVec _breaktargets;
+	SQIntVec _continuetargets;
+	SQIntVec _defaultparams;
+	SQInteger _lastline;
+	SQInteger _traps; //contains number of nested exception traps
+	SQInteger _outers;
+	bool _optimization;
+	SQSharedState *_sharedstate;
+	sqvector<SQFuncState*> _childstates;
+	SQInteger GetConstant(const SQObject &cons);
+private:
+	CompilerErrorFunc _errfunc;
+	void *_errtarget;
+	SQSharedState *_ss;
+};
+
+
+#endif //_SQFUNCSTATE_H_
+

+ 2 - 0
SquiLu/squirrel/sqmem.cpp

@@ -2,8 +2,10 @@
 	see copyright notice in squirrel.h
 	see copyright notice in squirrel.h
 */
 */
 #include "sqpcheader.h"
 #include "sqpcheader.h"
+#ifndef SQ_EXCLUDE_DEFAULT_MEMFUNCTIONS
 void *sq_vm_malloc(SQUnsignedInteger size){	return malloc(size); }
 void *sq_vm_malloc(SQUnsignedInteger size){	return malloc(size); }
 
 
 void *sq_vm_realloc(void *p, SQUnsignedInteger oldsize, SQUnsignedInteger size){ return realloc(p, size); }
 void *sq_vm_realloc(void *p, SQUnsignedInteger oldsize, SQUnsignedInteger size){ return realloc(p, size); }
 
 
 void sq_vm_free(void *p, SQUnsignedInteger size){	free(p); }
 void sq_vm_free(void *p, SQUnsignedInteger size){	free(p); }
+#endif

+ 1 - 0
SquiLu/squirrel/sqpcheader.h

@@ -6,6 +6,7 @@
 #include <crtdbg.h>
 #include <crtdbg.h>
 #endif 
 #endif 
 
 
+#include <limits.h>
 #include <stdio.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdlib.h>
 #include <string.h>
 #include <string.h>

+ 133 - 124
SquiLu/squirrel/squtils.h

@@ -1,126 +1,135 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQUTILS_H_
-#define _SQUTILS_H_
-
-void *sq_vm_malloc(SQUnsignedInteger size);
-void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size);
-void sq_vm_free(void *p,SQUnsignedInteger size);
-
-#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;}
-#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));}
-#define SQ_MALLOC(__size) sq_vm_malloc((__size));
-#define SQ_FREE(__ptr,__size) sq_vm_free((__ptr),(__size));
-#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc((__ptr),(__oldsize),(__size));
-
-#define sq_aligning(v) (((size_t)(v) + (SQ_ALIGNMENT-1)) & (~(SQ_ALIGNMENT-1)))
-
-//sqvector mini vector class, supports objects by value
-template<typename T> class sqvector
-{
-public:
-	sqvector()
-	{
-		_vals = NULL;
-		_size = 0;
-		_allocated = 0;
-	}
-	sqvector(const sqvector<T>& v)
-	{
-		copy(v);
-	}
-	void copy(const sqvector<T>& v)
-	{
-		if(_size) {
-			resize(0); //destroys all previous stuff
-		}
-		//resize(v._size);
-		if(v._size > _allocated) {
-			_realloc(v._size);
-		}
-		for(SQUnsignedInteger i = 0; i < v._size; i++) {
-			new ((void *)&_vals[i]) T(v._vals[i]);
-		}
-		_size = v._size;
-	}
-	~sqvector()
-	{
-		if(_allocated) {
-			for(SQUnsignedInteger i = 0; i < _size; i++)
-				_vals[i].~T();
-			SQ_FREE(_vals, (_allocated * sizeof(T)));
-		}
-	}
-	void reserve(SQUnsignedInteger newsize) { _realloc(newsize); }
-	void resize(SQUnsignedInteger newsize, const T& fill = T())
-	{
-		if(newsize > _allocated)
-			_realloc(newsize);
-		if(newsize > _size) {
-			while(_size < newsize) {
-				new ((void *)&_vals[_size]) T(fill);
-				_size++;
-			}
-		}
-		else{
-			for(SQUnsignedInteger i = newsize; i < _size; i++) {
-				_vals[i].~T();
-			}
-			_size = newsize;
-		}
-	}
-	void shrinktofit() { if(_size > 4) { _realloc(_size); } }
-	T& top() const { return _vals[_size - 1]; }
-	inline SQUnsignedInteger size() const { return _size; }
-	bool empty() const { return (_size <= 0); }
-	inline T &push_back(const T& val = T())
-	{
-		if(_allocated <= _size)
-			_realloc(_size * 2);
-		return *(new ((void *)&_vals[_size++]) T(val));
-	}
-	inline void pop_back()
-	{
-		_size--; _vals[_size].~T();
-	}
-	void insert(SQUnsignedInteger idx, const T& val)
-	{
-		resize(_size + 1);
-		for(SQUnsignedInteger i = _size - 1; i > idx; i--) {
-			_vals[i] = _vals[i - 1];
-		}
-    	_vals[idx] = val;
-	}
-	void remove(SQUnsignedInteger idx)
-	{
-		_vals[idx].~T();
-		if(idx < (_size - 1)) {
-			memmove(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1));
-		}
-		_size--;
-	}
-	void removeFromBegining(SQUnsignedInteger count)
+/*	see copyright notice in squirrel.h */
+#ifndef _SQUTILS_H_
+#define _SQUTILS_H_
+
+void *sq_vm_malloc(SQUnsignedInteger size);
+void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size);
+void sq_vm_free(void *p,SQUnsignedInteger size);
+
+#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;}
+#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));}
+#define SQ_MALLOC(__size) sq_vm_malloc((__size));
+#define SQ_FREE(__ptr,__size) sq_vm_free((__ptr),(__size));
+#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc((__ptr),(__oldsize),(__size));
+
+#define sq_aligning(v) (((size_t)(v) + (SQ_ALIGNMENT-1)) & (~(SQ_ALIGNMENT-1)))
+
+//sqvector mini vector class, supports objects by value
+template<typename T> class sqvector
+{
+public:
+	sqvector():_vals(NULL),_size(0),_allocated(0)
+	{
+	}
+	sqvector(const sqvector<T>& v)
+	{
+		copy(v);
+	}
+	void copy(const sqvector<T>& v)
+	{
+		if(_size) {
+			resize(0); //destroys all previous stuff
+		}
+		//resize(v._size);
+		if(v._size > _allocated) {
+			_realloc(v._size);
+		}
+		for(SQUnsignedInteger i = 0; i < v._size; i++) {
+			new ((void *)&_vals[i]) T(v._vals[i]);
+		}
+		_size = v._size;
+	}
+	~sqvector()
+	{
+		if(_allocated) {
+			for(SQUnsignedInteger i = 0; i < _size; i++)
+				_vals[i].~T();
+			SQ_FREE(_vals, (_allocated * sizeof(T)));
+		}
+	}
+	void reserve(SQUnsignedInteger newsize) { _realloc(newsize); }
+	void resize(SQUnsignedInteger newsize, const T& fill = T())
+	{
+		if(newsize > _allocated)
+			_realloc(newsize);
+		if(newsize > _size) {
+			while(_size < newsize) {
+				new ((void *)&_vals[_size]) T(fill);
+				_size++;
+			}
+		}
+		else{
+			for(SQUnsignedInteger i = newsize; i < _size; i++) {
+				_vals[i].~T();
+			}
+			_size = newsize;
+		}
+	}
+	void shrinktofit() { if(_size > 4) { _realloc(_size); } }
+	T& top() const { return _vals[_size - 1]; }
+	inline SQUnsignedInteger size() const { return _size; }
+	bool empty() const { return (_size <= 0); }
+	inline T &push_back(const T& val = T())
+	{
+		if(_allocated <= _size)
+			_realloc(_size * 2);
+		return *(new ((void *)&_vals[_size++]) T(val));
+	}
+	inline void pop_back()
+	{
+		_size--; _vals[_size].~T();
+	}
+	void insert(SQUnsignedInteger idx, const T& val)
+	{
+		resize(_size + 1);
+		for(SQUnsignedInteger i = _size - 1; i > idx; i--) {
+			_vals[i] = _vals[i - 1];
+		}
+    	_vals[idx] = val;
+	}
+	void remove(SQUnsignedInteger idx)
+	{
+		_vals[idx].~T();
+		if(idx < (_size - 1)) {
+			memmove(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1));
+		}
+		_size--;
+	}
+	void removeFromBegining(SQUnsignedInteger count)
 	{
 	{
 	    if(count <= _size){
 	    if(count <= _size){
-	        for(SQUnsignedInteger i=0; i < count; ++i) _vals[i].~T();
-            if(count < (_size - 1)) {
-                memmove(&_vals[0], &_vals[count], sizeof(T) * (_size - count));
-            }
-            _size -= count;
-	    }
-	}
-	SQUnsignedInteger capacity() { return _allocated; }
-	inline T &back() const { return _vals[_size - 1]; }
-	inline T& operator[](SQUnsignedInteger pos) const{ return _vals[pos]; }
-	T* _vals;
-private:
-	void _realloc(SQUnsignedInteger newsize)
-	{
-		newsize = (newsize > 0)?newsize:4;
-		_vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T));
-		_allocated = newsize;
-	}
-	SQUnsignedInteger _size;
-	SQUnsignedInteger _allocated;
-};
-
-#endif //_SQUTILS_H_
+	        for(SQUnsignedInteger i=0; i < count; ++i) _vals[i].~T();
+            if(count < (_size - 1)) {
+                memmove(&_vals[0], &_vals[count], sizeof(T) * (_size - count));
+            }
+            _size -= count;
+	    }
+	}
+	SQUnsignedInteger capacity() { return _allocated; }
+	inline T &back() const { return _vals[_size - 1]; }
+	inline T& operator[](SQUnsignedInteger pos) const{ return _vals[pos]; }
+	T* _vals;
+private:
+	void _realloc(SQUnsignedInteger newsize)
+	{
+		newsize = (newsize > 0)?newsize:4;
+		_vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T));
+		_allocated = newsize;
+	}
+	SQUnsignedInteger _size;
+	SQUnsignedInteger _allocated;
+};
+
+class SQCharBuf : public sqvector<char>
+{
+public:
+    void append(const char *p, size_t count)
+    {
+        size_t old_size = size();
+        resize(old_size + count);
+        memcpy(_vals+old_size, p, count);
+    }
+    const char *data(){return _vals;}
+};
+
+#endif //_SQUTILS_H_