Update SQUIRREL to 2.2.5
[supertux.git] / external / squirrel / squirrel / sqstate.cpp
old mode 100644 (file)
new mode 100755 (executable)
index 4a25ae1..fd84b0a
-/*
-       see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include "sqopcodes.h"
-#include "sqvm.h"
-#include "sqfuncproto.h"
-#include "sqclosure.h"
-#include "sqstring.h"
-#include "sqtable.h"
-#include "sqarray.h"
-#include "squserdata.h"
-#include "sqclass.h"
-
-SQObjectPtr _null_;
-SQObjectPtr _true_(true);
-SQObjectPtr _false_(false);
-SQObjectPtr _one_((SQInteger)1);
-SQObjectPtr _minusone_((SQInteger)-1);
-
-SQSharedState::SQSharedState()
-{
-       _compilererrorhandler = NULL;
-       _printfunc = NULL;
-       _debuginfo = false;
-       _notifyallexceptions = false;
-}
-
-#define newsysstring(s) {      \
-       _systemstrings->push_back(SQString::Create(this,s));    \
-       }
-
-#define newmetamethod(s) {     \
-       _metamethods->push_back(SQString::Create(this,s));      \
-       _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \
-       }
-
-bool CompileTypemask(SQIntVec &res,const SQChar *typemask)
-{
-       SQInteger i = 0;
-       
-       SQInteger mask = 0;
-       while(typemask[i] != 0) {
-               
-               switch(typemask[i]){
-                               case 'o': mask |= _RT_NULL; break;
-                               case 'i': mask |= _RT_INTEGER; break;
-                               case 'f': mask |= _RT_FLOAT; break;
-                               case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break;
-                               case 's': mask |= _RT_STRING; break;
-                               case 't': mask |= _RT_TABLE; break;
-                               case 'a': mask |= _RT_ARRAY; break;
-                               case 'u': mask |= _RT_USERDATA; break;
-                               case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break;
-                               case 'b': mask |= _RT_BOOL; break;
-                               case 'g': mask |= _RT_GENERATOR; break;
-                               case 'p': mask |= _RT_USERPOINTER; break;
-                               case 'v': mask |= _RT_THREAD; break;
-                               case 'x': mask |= _RT_INSTANCE; break;
-                               case 'y': mask |= _RT_CLASS; break;
-                               case 'r': mask |= _RT_WEAKREF; break;
-                               case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue;
-                               case ' ': i++; continue; //ignores spaces
-                               default:
-                                       return false;
-               }
-               i++;
-               if(typemask[i] == '|') { 
-                       i++; 
-                       if(typemask[i] == 0)
-                               return false;
-                       continue; 
-               }
-               res.push_back(mask);
-               mask = 0;
-               
-       }
-       return true;
-}
-
-SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)
-{
-       SQInteger i=0;
-       SQTable *t=SQTable::Create(ss,0);
-       while(funcz[i].name!=0){
-               SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f);
-               nc->_nparamscheck = funcz[i].nparamscheck;
-               nc->_name = SQString::Create(ss,funcz[i].name);
-               if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask))
-                       return NULL;
-               t->NewSlot(SQString::Create(ss,funcz[i].name),nc);
-               i++;
-       }
-       return t;
-}
-
-void SQSharedState::Init()
-{      
-       _scratchpad=NULL;
-       _scratchpadsize=0;
-#ifndef NO_GARBAGE_COLLECTOR
-       _gc_chain=NULL;
-#endif
-       sq_new(_stringtable,StringTable);
-       sq_new(_metamethods,SQObjectPtrVec);
-       sq_new(_systemstrings,SQObjectPtrVec);
-       sq_new(_types,SQObjectPtrVec);
-       _metamethodsmap = SQTable::Create(this,MT_LAST-1);
-       //adding type strings to avoid memory trashing
-       //types names
-       newsysstring(_SC("null"));
-       newsysstring(_SC("table"));
-       newsysstring(_SC("array"));
-       newsysstring(_SC("closure"));
-       newsysstring(_SC("string"));
-       newsysstring(_SC("userdata"));
-       newsysstring(_SC("integer"));
-       newsysstring(_SC("float"));
-       newsysstring(_SC("userpointer"));
-       newsysstring(_SC("function"));
-       newsysstring(_SC("generator"));
-       newsysstring(_SC("thread"));
-       newsysstring(_SC("class"));
-       newsysstring(_SC("instance"));
-       newsysstring(_SC("bool"));
-       //meta methods
-       newmetamethod(MM_ADD);
-       newmetamethod(MM_SUB);
-       newmetamethod(MM_MUL);
-       newmetamethod(MM_DIV);
-       newmetamethod(MM_UNM);
-       newmetamethod(MM_MODULO);
-       newmetamethod(MM_SET);
-       newmetamethod(MM_GET);
-       newmetamethod(MM_TYPEOF);
-       newmetamethod(MM_NEXTI);
-       newmetamethod(MM_CMP);
-       newmetamethod(MM_CALL);
-       newmetamethod(MM_CLONED);
-       newmetamethod(MM_NEWSLOT);
-       newmetamethod(MM_DELSLOT);
-       newmetamethod(MM_TOSTRING);
-       newmetamethod(MM_NEWMEMBER);
-       newmetamethod(MM_INHERITED);
-
-       _constructoridx = SQString::Create(this,_SC("constructor"));
-       _registry = SQTable::Create(this,0);
-       _consts = SQTable::Create(this,0);
-       _table_default_delegate = CreateDefaultDelegate(this,_table_default_delegate_funcz);
-       _array_default_delegate = CreateDefaultDelegate(this,_array_default_delegate_funcz);
-       _string_default_delegate = CreateDefaultDelegate(this,_string_default_delegate_funcz);
-       _number_default_delegate = CreateDefaultDelegate(this,_number_default_delegate_funcz);
-       _closure_default_delegate = CreateDefaultDelegate(this,_closure_default_delegate_funcz);
-       _generator_default_delegate = CreateDefaultDelegate(this,_generator_default_delegate_funcz);
-       _thread_default_delegate = CreateDefaultDelegate(this,_thread_default_delegate_funcz);
-       _class_default_delegate = CreateDefaultDelegate(this,_class_default_delegate_funcz);
-       _instance_default_delegate = CreateDefaultDelegate(this,_instance_default_delegate_funcz);
-       _weakref_default_delegate = CreateDefaultDelegate(this,_weakref_default_delegate_funcz);
-
-}
-
-SQSharedState::~SQSharedState()
-{
-       _constructoridx = _null_;
-       _table(_registry)->Finalize();
-       _table(_consts)->Finalize();
-       _table(_metamethodsmap)->Finalize();
-       _registry = _null_;
-       _consts = _null_;
-       _metamethodsmap = _null_;
-       while(!_systemstrings->empty()) {
-               _systemstrings->back()=_null_;
-               _systemstrings->pop_back();
-       }
-       _thread(_root_vm)->Finalize();
-       _root_vm = _null_;
-       _table_default_delegate = _null_;
-       _array_default_delegate = _null_;
-       _string_default_delegate = _null_;
-       _number_default_delegate = _null_;
-       _closure_default_delegate = _null_;
-       _generator_default_delegate = _null_;
-       _thread_default_delegate = _null_;
-       _class_default_delegate = _null_;
-       _instance_default_delegate = _null_;
-       _weakref_default_delegate = _null_;
-       _refs_table.Finalize();
-#ifndef NO_GARBAGE_COLLECTOR
-       SQCollectable *t = _gc_chain;
-       SQCollectable *nx = NULL;
-       while(t) {
-               t->_uiRef++;
-               t->Finalize();
-               nx = t->_next;
-               if(--t->_uiRef == 0)
-                       t->Release();
-               t=nx;
-       }
-       assert(_gc_chain==NULL); //just to proove a theory
-       while(_gc_chain){
-               _gc_chain->_uiRef++;
-               _gc_chain->Release();
-       }
-#endif
-
-       sq_delete(_types,SQObjectPtrVec);
-       sq_delete(_systemstrings,SQObjectPtrVec);
-       sq_delete(_metamethods,SQObjectPtrVec);
-       sq_delete(_stringtable,StringTable);
-       if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);
-}
-
-
-SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name)
-{
-       if(type(name) != OT_STRING)
-               return -1;
-       SQObjectPtr ret;
-       if(_table(_metamethodsmap)->Get(name,ret)) {
-               return _integer(ret);
-       }
-       return -1;
-}
-
-#ifndef NO_GARBAGE_COLLECTOR
-
-void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)
-{
-       switch(type(o)){
-       case OT_TABLE:_table(o)->Mark(chain);break;
-       case OT_ARRAY:_array(o)->Mark(chain);break;
-       case OT_USERDATA:_userdata(o)->Mark(chain);break;
-       case OT_CLOSURE:_closure(o)->Mark(chain);break;
-       case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break;
-       case OT_GENERATOR:_generator(o)->Mark(chain);break;
-       case OT_THREAD:_thread(o)->Mark(chain);break;
-       case OT_CLASS:_class(o)->Mark(chain);break;
-       case OT_INSTANCE:_instance(o)->Mark(chain);break;
-       default: break; //shutup compiler
-       }
-}
-
-
-SQInteger SQSharedState::CollectGarbage(SQVM *vm)
-{
-       SQInteger n=0;
-       SQCollectable *tchain=NULL;
-       SQVM *vms = _thread(_root_vm);
-       
-       vms->Mark(&tchain);
-       SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed();
-       _refs_table.Mark(&tchain);
-       MarkObject(_registry,&tchain);
-       MarkObject(_consts,&tchain);
-       MarkObject(_metamethodsmap,&tchain);
-       MarkObject(_table_default_delegate,&tchain);
-       MarkObject(_array_default_delegate,&tchain);
-       MarkObject(_string_default_delegate,&tchain);
-       MarkObject(_number_default_delegate,&tchain);
-       MarkObject(_generator_default_delegate,&tchain);
-       MarkObject(_thread_default_delegate,&tchain);
-       MarkObject(_closure_default_delegate,&tchain);
-       MarkObject(_class_default_delegate,&tchain);
-       MarkObject(_instance_default_delegate,&tchain);
-       MarkObject(_weakref_default_delegate,&tchain);
-       
-       SQCollectable *t = _gc_chain;
-       SQCollectable *nx = NULL;
-       while(t) {
-               t->_uiRef++;
-               t->Finalize();
-               nx = t->_next;
-               if(--t->_uiRef == 0)
-                       t->Release();
-               t = nx;
-               n++;
-       }
-
-       t = tchain;
-       while(t) {
-               t->UnMark();
-               t = t->_next;
-       }
-       _gc_chain = tchain;
-       SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed();
-       assert(z == x);
-       return n;
-}
-#endif
-
-#ifndef NO_GARBAGE_COLLECTOR
-void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)
-{
-    c->_prev = NULL;
-       c->_next = *chain;
-       if(*chain) (*chain)->_prev = c;
-       *chain = c;
-}
-
-void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)
-{
-       if(c->_prev) c->_prev->_next = c->_next;
-       else *chain = c->_next;
-       if(c->_next)
-               c->_next->_prev = c->_prev;
-       c->_next = NULL;
-       c->_prev = NULL;
-}
-#endif
-
-SQChar* SQSharedState::GetScratchPad(SQInteger size)
-{
-       SQInteger newsize;
-       if(size>0) {
-               if(_scratchpadsize < size) {
-                       newsize = size + (size>>1);
-                       _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
-                       _scratchpadsize = newsize;
-
-               }else if(_scratchpadsize >= (size<<5)) {
-                       newsize = _scratchpadsize >> 1;
-                       _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
-                       _scratchpadsize = newsize;
-               }
-       }
-       return _scratchpad;
-}
-
-RefTable::RefTable()
-{
-       AllocNodes(4);
-}
-
-void RefTable::Finalize()
-{
-       RefNode *nodes = _nodes;
-       for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
-               nodes->obj = _null_;
-               nodes++;
-       }
-}
-
-RefTable::~RefTable()
-{
-       SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode)));
-}
-
-#ifndef NO_GARBAGE_COLLECTOR
-void RefTable::Mark(SQCollectable **chain)
-{
-       RefNode *nodes = (RefNode *)_nodes;
-       for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
-               if(type(nodes->obj) != OT_NULL) {
-                       SQSharedState::MarkObject(nodes->obj,chain);
-               }
-               nodes++;
-       }
-}
-#endif
-
-void RefTable::AddRef(SQObject &obj)
-{
-       SQHash mainpos;
-       RefNode *prev;
-       RefNode *ref = Get(obj,mainpos,&prev,true);
-       ref->refs++;
-}
-
-SQBool RefTable::Release(SQObject &obj)
-{
-       SQHash mainpos;
-       RefNode *prev;
-       RefNode *ref = Get(obj,mainpos,&prev,false);
-       if(ref) {
-               if(--ref->refs == 0) {
-                       SQObjectPtr o = ref->obj;
-                       if(prev) {
-                               prev->next = ref->next;
-                       }
-                       else {
-                               _buckets[mainpos] = ref->next;
-                       }
-                       ref->next = _freelist;
-                       _freelist = ref;
-                       _slotused--;
-                       ref->obj = _null_;
-                       //<<FIXME>>test for shrink?
-                       return SQTrue;
-               }
-       }
-       else {
-               assert(0);
-       }
-       return SQFalse;
-}
-
-void RefTable::Resize(SQUnsignedInteger size)
-{
-       RefNode **oldbucks = _buckets;
-       RefNode *t = _nodes;
-       SQUnsignedInteger oldnumofslots = _numofslots;
-       AllocNodes(size);
-       //rehash
-       SQUnsignedInteger nfound = 0;
-       for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {
-               if(type(t->obj) != OT_NULL) {
-                       //add back;
-                       assert(t->refs != 0);
-                       RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj);
-                       nn->refs = t->refs; 
-                       t->obj = _null_;
-                       nfound++;
-               }
-               t++;
-       }
-       assert(nfound == oldnumofslots);
-       SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode)));
-}
-
-RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj)
-{
-       RefNode *t = _buckets[mainpos];
-       RefNode *newnode = _freelist;
-       newnode->obj = obj;
-       _buckets[mainpos] = newnode;
-       _freelist = _freelist->next;
-       newnode->next = t;
-       assert(newnode->refs == 0);
-       _slotused++;
-       return newnode;
-}
-
-RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add)
-{
-       RefNode *ref;
-       mainpos = ::HashObj(obj)&(_numofslots-1);
-       *prev = NULL;
-       for (ref = _buckets[mainpos]; ref; ) {
-               if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj))
-                       break;
-               *prev = ref;
-               ref = ref->next;
-       }
-       if(ref == NULL && add) {
-               if(_numofslots == _slotused) {
-                       assert(_freelist == 0);
-                       Resize(_numofslots*2);
-                       mainpos = ::HashObj(obj)&(_numofslots-1);
-               }
-               ref = Add(mainpos,obj);
-       }
-       return ref;
-}
-
-void RefTable::AllocNodes(SQUnsignedInteger size)
-{
-       RefNode **bucks;
-       RefNode *nodes;
-       bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode)));
-       nodes = (RefNode *)&bucks[size];
-       RefNode *temp = nodes;
-       SQUnsignedInteger n;
-       for(n = 0; n < size - 1; n++) {
-               bucks[n] = NULL;
-               temp->refs = 0;
-               new (&temp->obj) SQObjectPtr;
-               temp->next = temp+1;
-               temp++;
-       }
-       bucks[n] = NULL;
-       temp->refs = 0;
-       new (&temp->obj) SQObjectPtr;
-       temp->next = NULL;
-       _freelist = nodes;
-       _nodes = nodes;
-       _buckets = bucks;
-       _slotused = 0;
-       _numofslots = size;
-}
-//////////////////////////////////////////////////////////////////////////
-//StringTable
-/*
-* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
-* http://www.lua.org/copyright.html#4
-* http://www.lua.org/source/4.0.1/src_lstring.c.html
-*/
-
-StringTable::StringTable()
-{
-       AllocNodes(4);
-       _slotused = 0;
-}
-
-StringTable::~StringTable()
-{
-       SQ_FREE(_strings,sizeof(SQString*)*_numofslots);
-       _strings = NULL;
-}
-
-void StringTable::AllocNodes(SQInteger size)
-{
-       _numofslots = size;
-       _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
-       memset(_strings,0,sizeof(SQString*)*_numofslots);
-}
-
-SQString *StringTable::Add(const SQChar *news,SQInteger len)
-{
-       if(len<0)
-               len = (SQInteger)scstrlen(news);
-       SQHash h = ::_hashstr(news,len)&(_numofslots-1);
-       SQString *s;
-       for (s = _strings[h]; s; s = s->_next){
-               if(s->_len == len && (!memcmp(news,s->_val,rsl(len))))
-                       return s; //found
-       }
-
-       SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString));
-       new (t) SQString;
-       memcpy(t->_val,news,rsl(len));
-       t->_val[len] = _SC('\0');
-       t->_len = len;
-       t->_hash = ::_hashstr(news,len);
-       t->_next = _strings[h];
-       _strings[h] = t;
-       _slotused++;
-       if (_slotused > _numofslots)  /* too crowded? */
-               Resize(_numofslots*2);
-       return t;
-}
-
-void StringTable::Resize(SQInteger size)
-{
-       SQInteger oldsize=_numofslots;
-       SQString **oldtable=_strings;
-       AllocNodes(size);
-       for (SQInteger i=0; i<oldsize; i++){
-               SQString *p = oldtable[i];
-               while(p){
-                       SQString *next = p->_next;
-                       SQHash h = p->_hash&(_numofslots-1);
-                       p->_next = _strings[h];
-                       _strings[h] = p;
-                       p = next;
-               }
-       }
-       SQ_FREE(oldtable,oldsize*sizeof(SQString*));
-}
-
-void StringTable::Remove(SQString *bs)
-{
-       SQString *s;
-       SQString *prev=NULL;
-       SQHash h = bs->_hash&(_numofslots - 1);
-       
-       for (s = _strings[h]; s; ){
-               if(s == bs){
-                       if(prev)
-                               prev->_next = s->_next;
-                       else
-                               _strings[h] = s->_next;
-                       _slotused--;
-                       SQInteger slen = s->_len;
-                       s->~SQString();
-                       SQ_FREE(s,sizeof(SQString) + rsl(slen));
-                       return;
-               }
-               prev = s;
-               s = s->_next;
-       }
-       assert(0);//if this fail something is wrong
-}
+/*\r
+       see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include "sqopcodes.h"\r
+#include "sqvm.h"\r
+#include "sqfuncproto.h"\r
+#include "sqclosure.h"\r
+#include "sqstring.h"\r
+#include "sqtable.h"\r
+#include "sqarray.h"\r
+#include "squserdata.h"\r
+#include "sqclass.h"\r
+\r
+SQObjectPtr _null_;\r
+SQObjectPtr _true_(true);\r
+SQObjectPtr _false_(false);\r
+SQObjectPtr _one_((SQInteger)1);\r
+SQObjectPtr _minusone_((SQInteger)-1);\r
+\r
+SQSharedState::SQSharedState()\r
+{\r
+       _compilererrorhandler = NULL;\r
+       _printfunc = NULL;\r
+       _debuginfo = false;\r
+       _notifyallexceptions = false;\r
+}\r
+\r
+#define newsysstring(s) {      \\r
+       _systemstrings->push_back(SQString::Create(this,s));    \\r
+       }\r
+\r
+#define newmetamethod(s) {     \\r
+       _metamethods->push_back(SQString::Create(this,s));      \\r
+       _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \\r
+       }\r
+\r
+bool CompileTypemask(SQIntVec &res,const SQChar *typemask)\r
+{\r
+       SQInteger i = 0;\r
+       \r
+       SQInteger mask = 0;\r
+       while(typemask[i] != 0) {\r
+               \r
+               switch(typemask[i]){\r
+                               case 'o': mask |= _RT_NULL; break;\r
+                               case 'i': mask |= _RT_INTEGER; break;\r
+                               case 'f': mask |= _RT_FLOAT; break;\r
+                               case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break;\r
+                               case 's': mask |= _RT_STRING; break;\r
+                               case 't': mask |= _RT_TABLE; break;\r
+                               case 'a': mask |= _RT_ARRAY; break;\r
+                               case 'u': mask |= _RT_USERDATA; break;\r
+                               case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break;\r
+                               case 'b': mask |= _RT_BOOL; break;\r
+                               case 'g': mask |= _RT_GENERATOR; break;\r
+                               case 'p': mask |= _RT_USERPOINTER; break;\r
+                               case 'v': mask |= _RT_THREAD; break;\r
+                               case 'x': mask |= _RT_INSTANCE; break;\r
+                               case 'y': mask |= _RT_CLASS; break;\r
+                               case 'r': mask |= _RT_WEAKREF; break;\r
+                               case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue;\r
+                               case ' ': i++; continue; //ignores spaces\r
+                               default:\r
+                                       return false;\r
+               }\r
+               i++;\r
+               if(typemask[i] == '|') { \r
+                       i++; \r
+                       if(typemask[i] == 0)\r
+                               return false;\r
+                       continue; \r
+               }\r
+               res.push_back(mask);\r
+               mask = 0;\r
+               \r
+       }\r
+       return true;\r
+}\r
+\r
+SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)\r
+{\r
+       SQInteger i=0;\r
+       SQTable *t=SQTable::Create(ss,0);\r
+       while(funcz[i].name!=0){\r
+               SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f);\r
+               nc->_nparamscheck = funcz[i].nparamscheck;\r
+               nc->_name = SQString::Create(ss,funcz[i].name);\r
+               if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask))\r
+                       return NULL;\r
+               t->NewSlot(SQString::Create(ss,funcz[i].name),nc);\r
+               i++;\r
+       }\r
+       return t;\r
+}\r
+\r
+void SQSharedState::Init()\r
+{      \r
+       _scratchpad=NULL;\r
+       _scratchpadsize=0;\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       _gc_chain=NULL;\r
+#endif\r
+       sq_new(_stringtable,SQStringTable);\r
+       sq_new(_metamethods,SQObjectPtrVec);\r
+       sq_new(_systemstrings,SQObjectPtrVec);\r
+       sq_new(_types,SQObjectPtrVec);\r
+       _metamethodsmap = SQTable::Create(this,MT_LAST-1);\r
+       //adding type strings to avoid memory trashing\r
+       //types names\r
+       newsysstring(_SC("null"));\r
+       newsysstring(_SC("table"));\r
+       newsysstring(_SC("array"));\r
+       newsysstring(_SC("closure"));\r
+       newsysstring(_SC("string"));\r
+       newsysstring(_SC("userdata"));\r
+       newsysstring(_SC("integer"));\r
+       newsysstring(_SC("float"));\r
+       newsysstring(_SC("userpointer"));\r
+       newsysstring(_SC("function"));\r
+       newsysstring(_SC("generator"));\r
+       newsysstring(_SC("thread"));\r
+       newsysstring(_SC("class"));\r
+       newsysstring(_SC("instance"));\r
+       newsysstring(_SC("bool"));\r
+       //meta methods\r
+       newmetamethod(MM_ADD);\r
+       newmetamethod(MM_SUB);\r
+       newmetamethod(MM_MUL);\r
+       newmetamethod(MM_DIV);\r
+       newmetamethod(MM_UNM);\r
+       newmetamethod(MM_MODULO);\r
+       newmetamethod(MM_SET);\r
+       newmetamethod(MM_GET);\r
+       newmetamethod(MM_TYPEOF);\r
+       newmetamethod(MM_NEXTI);\r
+       newmetamethod(MM_CMP);\r
+       newmetamethod(MM_CALL);\r
+       newmetamethod(MM_CLONED);\r
+       newmetamethod(MM_NEWSLOT);\r
+       newmetamethod(MM_DELSLOT);\r
+       newmetamethod(MM_TOSTRING);\r
+       newmetamethod(MM_NEWMEMBER);\r
+       newmetamethod(MM_INHERITED);\r
+\r
+       _constructoridx = SQString::Create(this,_SC("constructor"));\r
+       _registry = SQTable::Create(this,0);\r
+       _consts = SQTable::Create(this,0);\r
+       _table_default_delegate = CreateDefaultDelegate(this,_table_default_delegate_funcz);\r
+       _array_default_delegate = CreateDefaultDelegate(this,_array_default_delegate_funcz);\r
+       _string_default_delegate = CreateDefaultDelegate(this,_string_default_delegate_funcz);\r
+       _number_default_delegate = CreateDefaultDelegate(this,_number_default_delegate_funcz);\r
+       _closure_default_delegate = CreateDefaultDelegate(this,_closure_default_delegate_funcz);\r
+       _generator_default_delegate = CreateDefaultDelegate(this,_generator_default_delegate_funcz);\r
+       _thread_default_delegate = CreateDefaultDelegate(this,_thread_default_delegate_funcz);\r
+       _class_default_delegate = CreateDefaultDelegate(this,_class_default_delegate_funcz);\r
+       _instance_default_delegate = CreateDefaultDelegate(this,_instance_default_delegate_funcz);\r
+       _weakref_default_delegate = CreateDefaultDelegate(this,_weakref_default_delegate_funcz);\r
+\r
+}\r
+\r
+SQSharedState::~SQSharedState()\r
+{\r
+       _constructoridx = _null_;\r
+       _table(_registry)->Finalize();\r
+       _table(_consts)->Finalize();\r
+       _table(_metamethodsmap)->Finalize();\r
+       _registry = _null_;\r
+       _consts = _null_;\r
+       _metamethodsmap = _null_;\r
+       while(!_systemstrings->empty()) {\r
+               _systemstrings->back()=_null_;\r
+               _systemstrings->pop_back();\r
+       }\r
+       _thread(_root_vm)->Finalize();\r
+       _root_vm = _null_;\r
+       _table_default_delegate = _null_;\r
+       _array_default_delegate = _null_;\r
+       _string_default_delegate = _null_;\r
+       _number_default_delegate = _null_;\r
+       _closure_default_delegate = _null_;\r
+       _generator_default_delegate = _null_;\r
+       _thread_default_delegate = _null_;\r
+       _class_default_delegate = _null_;\r
+       _instance_default_delegate = _null_;\r
+       _weakref_default_delegate = _null_;\r
+       _refs_table.Finalize();\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+       SQCollectable *t = _gc_chain;\r
+       SQCollectable *nx = NULL;\r
+       if(t) {\r
+               t->_uiRef++;\r
+               while(t) {\r
+                       t->Finalize();\r
+                       nx = t->_next;\r
+                       if(nx) nx->_uiRef++;\r
+                       if(--t->_uiRef == 0)\r
+                               t->Release();\r
+                       t = nx;\r
+               }\r
+       }\r
+       assert(_gc_chain==NULL); //just to proove a theory\r
+       while(_gc_chain){\r
+               _gc_chain->_uiRef++;\r
+               _gc_chain->Release();\r
+       }\r
+#endif\r
+\r
+       sq_delete(_types,SQObjectPtrVec);\r
+       sq_delete(_systemstrings,SQObjectPtrVec);\r
+       sq_delete(_metamethods,SQObjectPtrVec);\r
+       sq_delete(_stringtable,SQStringTable);\r
+       if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);\r
+}\r
+\r
+\r
+SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name)\r
+{\r
+       if(type(name) != OT_STRING)\r
+               return -1;\r
+       SQObjectPtr ret;\r
+       if(_table(_metamethodsmap)->Get(name,ret)) {\r
+               return _integer(ret);\r
+       }\r
+       return -1;\r
+}\r
+\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+\r
+void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)\r
+{\r
+       switch(type(o)){\r
+       case OT_TABLE:_table(o)->Mark(chain);break;\r
+       case OT_ARRAY:_array(o)->Mark(chain);break;\r
+       case OT_USERDATA:_userdata(o)->Mark(chain);break;\r
+       case OT_CLOSURE:_closure(o)->Mark(chain);break;\r
+       case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break;\r
+       case OT_GENERATOR:_generator(o)->Mark(chain);break;\r
+       case OT_THREAD:_thread(o)->Mark(chain);break;\r
+       case OT_CLASS:_class(o)->Mark(chain);break;\r
+       case OT_INSTANCE:_instance(o)->Mark(chain);break;\r
+       default: break; //shutup compiler\r
+       }\r
+}\r
+\r
+\r
+SQInteger SQSharedState::CollectGarbage(SQVM *vm)\r
+{\r
+       SQInteger n=0;\r
+       SQCollectable *tchain=NULL;\r
+       SQVM *vms = _thread(_root_vm);\r
+       \r
+       vms->Mark(&tchain);\r
+       SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed();\r
+       _refs_table.Mark(&tchain);\r
+       MarkObject(_registry,&tchain);\r
+       MarkObject(_consts,&tchain);\r
+       MarkObject(_metamethodsmap,&tchain);\r
+       MarkObject(_table_default_delegate,&tchain);\r
+       MarkObject(_array_default_delegate,&tchain);\r
+       MarkObject(_string_default_delegate,&tchain);\r
+       MarkObject(_number_default_delegate,&tchain);\r
+       MarkObject(_generator_default_delegate,&tchain);\r
+       MarkObject(_thread_default_delegate,&tchain);\r
+       MarkObject(_closure_default_delegate,&tchain);\r
+       MarkObject(_class_default_delegate,&tchain);\r
+       MarkObject(_instance_default_delegate,&tchain);\r
+       MarkObject(_weakref_default_delegate,&tchain);\r
+       \r
+       SQCollectable *t = _gc_chain;\r
+       SQCollectable *nx = NULL;\r
+       if(t) {\r
+               t->_uiRef++;\r
+               while(t) {\r
+                       t->Finalize();\r
+                       nx = t->_next;\r
+                       if(nx) nx->_uiRef++;\r
+                       if(--t->_uiRef == 0)\r
+                               t->Release();\r
+                       t = nx;\r
+                       n++;\r
+               }\r
+       }\r
+\r
+       t = tchain;\r
+       while(t) {\r
+               t->UnMark();\r
+               t = t->_next;\r
+       }\r
+       _gc_chain = tchain;\r
+       SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed();\r
+       assert(z == x);\r
+       return n;\r
+}\r
+#endif\r
+\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)\r
+{\r
+    c->_prev = NULL;\r
+       c->_next = *chain;\r
+       if(*chain) (*chain)->_prev = c;\r
+       *chain = c;\r
+}\r
+\r
+void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)\r
+{\r
+       if(c->_prev) c->_prev->_next = c->_next;\r
+       else *chain = c->_next;\r
+       if(c->_next)\r
+               c->_next->_prev = c->_prev;\r
+       c->_next = NULL;\r
+       c->_prev = NULL;\r
+}\r
+#endif\r
+\r
+SQChar* SQSharedState::GetScratchPad(SQInteger size)\r
+{\r
+       SQInteger newsize;\r
+       if(size>0) {\r
+               if(_scratchpadsize < size) {\r
+                       newsize = size + (size>>1);\r
+                       _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);\r
+                       _scratchpadsize = newsize;\r
+\r
+               }else if(_scratchpadsize >= (size<<5)) {\r
+                       newsize = _scratchpadsize >> 1;\r
+                       _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);\r
+                       _scratchpadsize = newsize;\r
+               }\r
+       }\r
+       return _scratchpad;\r
+}\r
+\r
+RefTable::RefTable()\r
+{\r
+       AllocNodes(4);\r
+}\r
+\r
+void RefTable::Finalize()\r
+{\r
+       RefNode *nodes = _nodes;\r
+       for(SQUnsignedInteger n = 0; n < _numofslots; n++) {\r
+               nodes->obj = _null_;\r
+               nodes++;\r
+       }\r
+}\r
+\r
+RefTable::~RefTable()\r
+{\r
+       SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode)));\r
+}\r
+\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+void RefTable::Mark(SQCollectable **chain)\r
+{\r
+       RefNode *nodes = (RefNode *)_nodes;\r
+       for(SQUnsignedInteger n = 0; n < _numofslots; n++) {\r
+               if(type(nodes->obj) != OT_NULL) {\r
+                       SQSharedState::MarkObject(nodes->obj,chain);\r
+               }\r
+               nodes++;\r
+       }\r
+}\r
+#endif\r
+\r
+void RefTable::AddRef(SQObject &obj)\r
+{\r
+       SQHash mainpos;\r
+       RefNode *prev;\r
+       RefNode *ref = Get(obj,mainpos,&prev,true);\r
+       ref->refs++;\r
+}\r
+\r
+SQBool RefTable::Release(SQObject &obj)\r
+{\r
+       SQHash mainpos;\r
+       RefNode *prev;\r
+       RefNode *ref = Get(obj,mainpos,&prev,false);\r
+       if(ref) {\r
+               if(--ref->refs == 0) {\r
+                       SQObjectPtr o = ref->obj;\r
+                       if(prev) {\r
+                               prev->next = ref->next;\r
+                       }\r
+                       else {\r
+                               _buckets[mainpos] = ref->next;\r
+                       }\r
+                       ref->next = _freelist;\r
+                       _freelist = ref;\r
+                       _slotused--;\r
+                       ref->obj = _null_;\r
+                       //<<FIXME>>test for shrink?\r
+                       return SQTrue;\r
+               }\r
+       }\r
+       else {\r
+               assert(0);\r
+       }\r
+       return SQFalse;\r
+}\r
+\r
+void RefTable::Resize(SQUnsignedInteger size)\r
+{\r
+       RefNode **oldbucks = _buckets;\r
+       RefNode *t = _nodes;\r
+       SQUnsignedInteger oldnumofslots = _numofslots;\r
+       AllocNodes(size);\r
+       //rehash\r
+       SQUnsignedInteger nfound = 0;\r
+       for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {\r
+               if(type(t->obj) != OT_NULL) {\r
+                       //add back;\r
+                       assert(t->refs != 0);\r
+                       RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj);\r
+                       nn->refs = t->refs; \r
+                       t->obj = _null_;\r
+                       nfound++;\r
+               }\r
+               t++;\r
+       }\r
+       assert(nfound == oldnumofslots);\r
+       SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode)));\r
+}\r
+\r
+RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj)\r
+{\r
+       RefNode *t = _buckets[mainpos];\r
+       RefNode *newnode = _freelist;\r
+       newnode->obj = obj;\r
+       _buckets[mainpos] = newnode;\r
+       _freelist = _freelist->next;\r
+       newnode->next = t;\r
+       assert(newnode->refs == 0);\r
+       _slotused++;\r
+       return newnode;\r
+}\r
+\r
+RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add)\r
+{\r
+       RefNode *ref;\r
+       mainpos = ::HashObj(obj)&(_numofslots-1);\r
+       *prev = NULL;\r
+       for (ref = _buckets[mainpos]; ref; ) {\r
+               if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj))\r
+                       break;\r
+               *prev = ref;\r
+               ref = ref->next;\r
+       }\r
+       if(ref == NULL && add) {\r
+               if(_numofslots == _slotused) {\r
+                       assert(_freelist == 0);\r
+                       Resize(_numofslots*2);\r
+                       mainpos = ::HashObj(obj)&(_numofslots-1);\r
+               }\r
+               ref = Add(mainpos,obj);\r
+       }\r
+       return ref;\r
+}\r
+\r
+void RefTable::AllocNodes(SQUnsignedInteger size)\r
+{\r
+       RefNode **bucks;\r
+       RefNode *nodes;\r
+       bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode)));\r
+       nodes = (RefNode *)&bucks[size];\r
+       RefNode *temp = nodes;\r
+       SQUnsignedInteger n;\r
+       for(n = 0; n < size - 1; n++) {\r
+               bucks[n] = NULL;\r
+               temp->refs = 0;\r
+               new (&temp->obj) SQObjectPtr;\r
+               temp->next = temp+1;\r
+               temp++;\r
+       }\r
+       bucks[n] = NULL;\r
+       temp->refs = 0;\r
+       new (&temp->obj) SQObjectPtr;\r
+       temp->next = NULL;\r
+       _freelist = nodes;\r
+       _nodes = nodes;\r
+       _buckets = bucks;\r
+       _slotused = 0;\r
+       _numofslots = size;\r
+}\r
+//////////////////////////////////////////////////////////////////////////\r
+//SQStringTable\r
+/*\r
+* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)\r
+* http://www.lua.org/copyright.html#4\r
+* http://www.lua.org/source/4.0.1/src_lstring.c.html\r
+*/\r
+\r
+SQStringTable::SQStringTable()\r
+{\r
+       AllocNodes(4);\r
+       _slotused = 0;\r
+}\r
+\r
+SQStringTable::~SQStringTable()\r
+{\r
+       SQ_FREE(_strings,sizeof(SQString*)*_numofslots);\r
+       _strings = NULL;\r
+}\r
+\r
+void SQStringTable::AllocNodes(SQInteger size)\r
+{\r
+       _numofslots = size;\r
+       _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);\r
+       memset(_strings,0,sizeof(SQString*)*_numofslots);\r
+}\r
+\r
+SQString *SQStringTable::Add(const SQChar *news,SQInteger len)\r
+{\r
+       if(len<0)\r
+               len = (SQInteger)scstrlen(news);\r
+       SQHash h = ::_hashstr(news,len)&(_numofslots-1);\r
+       SQString *s;\r
+       for (s = _strings[h]; s; s = s->_next){\r
+               if(s->_len == len && (!memcmp(news,s->_val,rsl(len))))\r
+                       return s; //found\r
+       }\r
+\r
+       SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString));\r
+       new (t) SQString;\r
+       memcpy(t->_val,news,rsl(len));\r
+       t->_val[len] = _SC('\0');\r
+       t->_len = len;\r
+       t->_hash = ::_hashstr(news,len);\r
+       t->_next = _strings[h];\r
+       _strings[h] = t;\r
+       _slotused++;\r
+       if (_slotused > _numofslots)  /* too crowded? */\r
+               Resize(_numofslots*2);\r
+       return t;\r
+}\r
+\r
+void SQStringTable::Resize(SQInteger size)\r
+{\r
+       SQInteger oldsize=_numofslots;\r
+       SQString **oldtable=_strings;\r
+       AllocNodes(size);\r
+       for (SQInteger i=0; i<oldsize; i++){\r
+               SQString *p = oldtable[i];\r
+               while(p){\r
+                       SQString *next = p->_next;\r
+                       SQHash h = p->_hash&(_numofslots-1);\r
+                       p->_next = _strings[h];\r
+                       _strings[h] = p;\r
+                       p = next;\r
+               }\r
+       }\r
+       SQ_FREE(oldtable,oldsize*sizeof(SQString*));\r
+}\r
+\r
+void SQStringTable::Remove(SQString *bs)\r
+{\r
+       SQString *s;\r
+       SQString *prev=NULL;\r
+       SQHash h = bs->_hash&(_numofslots - 1);\r
+       \r
+       for (s = _strings[h]; s; ){\r
+               if(s == bs){\r
+                       if(prev)\r
+                               prev->_next = s->_next;\r
+                       else\r
+                               _strings[h] = s->_next;\r
+                       _slotused--;\r
+                       SQInteger slen = s->_len;\r
+                       s->~SQString();\r
+                       SQ_FREE(s,sizeof(SQString) + rsl(slen));\r
+                       return;\r
+               }\r
+               prev = s;\r
+               s = s->_next;\r
+       }\r
+       assert(0);//if this fail something is wrong\r
+}\r