2 see copyright notice in squirrel.h
4 #include "sqpcheader.h"
7 #include "sqfuncproto.h"
12 #include "squserdata.h"
16 SQObjectPtr _true_(true);
17 SQObjectPtr _false_(false);
19 SQObjectPtr _minusone_(-1);
21 SQSharedState::SQSharedState()
23 _compilererrorhandler = NULL;
28 #define newsysstring(s) { \
29 _systemstrings->push_back(SQString::Create(this,s)); \
32 #define newmetamethod(s) { \
33 _metamethods->push_back(SQString::Create(this,s)); \
34 _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \
37 bool CompileTypemask(SQIntVec &res,const SQChar *typemask)
42 while(typemask[i] != 0) {
45 case 'o': mask |= _RT_NULL; break;
46 case 'i': mask |= _RT_INTEGER; break;
47 case 'f': mask |= _RT_FLOAT; break;
48 case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break;
49 case 's': mask |= _RT_STRING; break;
50 case 't': mask |= _RT_TABLE; break;
51 case 'a': mask |= _RT_ARRAY; break;
52 case 'u': mask |= _RT_USERDATA; break;
53 case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break;
54 case 'b': mask |= _RT_BOOL; break;
55 case 'g': mask |= _RT_GENERATOR; break;
56 case 'p': mask |= _RT_USERPOINTER; break;
57 case 'v': mask |= _RT_THREAD; break;
58 case 'x': mask |= _RT_INSTANCE; break;
59 case 'y': mask |= _RT_CLASS; break;
60 case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue;
61 case ' ': i++; continue; //ignores spaces
66 if(typemask[i] == '|') {
79 SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)
82 SQTable *t=SQTable::Create(ss,0);
83 while(funcz[i].name!=0){
84 SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f);
85 nc->_nparamscheck = funcz[i].nparamscheck;
86 nc->_name = SQString::Create(ss,funcz[i].name);
87 if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask))
89 t->NewSlot(SQString::Create(ss,funcz[i].name),nc);
95 void SQSharedState::Init()
99 #ifndef NO_GARBAGE_COLLECTOR
102 sq_new(_stringtable,StringTable);
103 sq_new(_metamethods,SQObjectPtrVec);
104 sq_new(_systemstrings,SQObjectPtrVec);
105 sq_new(_types,SQObjectPtrVec);
106 _metamethodsmap = SQTable::Create(this,MT_LAST-1);
107 //adding type strings to avoid memory trashing
109 newsysstring(_SC("null"));
110 newsysstring(_SC("table"));
111 newsysstring(_SC("array"));
112 newsysstring(_SC("closure"));
113 newsysstring(_SC("string"));
114 newsysstring(_SC("userdata"));
115 newsysstring(_SC("integer"));
116 newsysstring(_SC("float"));
117 newsysstring(_SC("userpointer"));
118 newsysstring(_SC("function"));
119 newsysstring(_SC("generator"));
120 newsysstring(_SC("thread"));
121 newsysstring(_SC("class"));
122 newsysstring(_SC("instance"));
123 newsysstring(_SC("bool"));
125 newmetamethod(MM_ADD);
126 newmetamethod(MM_SUB);
127 newmetamethod(MM_MUL);
128 newmetamethod(MM_DIV);
129 newmetamethod(MM_UNM);
130 newmetamethod(MM_MODULO);
131 newmetamethod(MM_SET);
132 newmetamethod(MM_GET);
133 newmetamethod(MM_TYPEOF);
134 newmetamethod(MM_NEXTI);
135 newmetamethod(MM_CMP);
136 newmetamethod(MM_CALL);
137 newmetamethod(MM_CLONED);
138 newmetamethod(MM_NEWSLOT);
139 newmetamethod(MM_DELSLOT);
141 _constructoridx = SQString::Create(this,_SC("constructor"));
142 _refs_table = SQTable::Create(this,0);
143 _registry = SQTable::Create(this,0);
144 _table_default_delegate=CreateDefaultDelegate(this,_table_default_delegate_funcz);
145 _array_default_delegate=CreateDefaultDelegate(this,_array_default_delegate_funcz);
146 _string_default_delegate=CreateDefaultDelegate(this,_string_default_delegate_funcz);
147 _number_default_delegate=CreateDefaultDelegate(this,_number_default_delegate_funcz);
148 _closure_default_delegate=CreateDefaultDelegate(this,_closure_default_delegate_funcz);
149 _generator_default_delegate=CreateDefaultDelegate(this,_generator_default_delegate_funcz);
150 _thread_default_delegate=CreateDefaultDelegate(this,_thread_default_delegate_funcz);
151 _class_default_delegate=CreateDefaultDelegate(this,_class_default_delegate_funcz);
152 _instance_default_delegate=CreateDefaultDelegate(this,_instance_default_delegate_funcz);
156 SQSharedState::~SQSharedState()
158 _constructoridx = _null_;
159 _table(_refs_table)->Finalize();
160 _table(_registry)->Finalize();
161 _table(_metamethodsmap)->Finalize();
162 _refs_table = _null_;
164 _metamethodsmap = _null_;
165 while(!_systemstrings->empty()){
166 _systemstrings->back()=_null_;
167 _systemstrings->pop_back();
169 _thread(_root_vm)->Finalize();
171 _table_default_delegate=_null_;
172 _array_default_delegate=_null_;
173 _string_default_delegate=_null_;
174 _number_default_delegate=_null_;
175 _closure_default_delegate=_null_;
176 _generator_default_delegate=_null_;
177 _thread_default_delegate=_null_;
178 _class_default_delegate=_null_;
179 _instance_default_delegate=_null_;
181 #ifndef NO_GARBAGE_COLLECTOR
184 SQCollectable *t=_gc_chain;
185 SQCollectable *nx=NULL;
194 assert(_gc_chain==NULL); //just to proove a theory
197 _gc_chain->Release();
200 sq_delete(_types,SQObjectPtrVec);
201 sq_delete(_systemstrings,SQObjectPtrVec);
202 sq_delete(_metamethods,SQObjectPtrVec);
203 sq_delete(_stringtable,StringTable);
204 if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);
208 SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name)
210 if(type(name) != OT_STRING)
213 if(_table(_metamethodsmap)->Get(name,ret)) {
214 return _integer(ret);
219 #ifndef NO_GARBAGE_COLLECTOR
221 void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)
224 case OT_TABLE:_table(o)->Mark(chain);break;
225 case OT_ARRAY:_array(o)->Mark(chain);break;
226 case OT_USERDATA:_userdata(o)->Mark(chain);break;
227 case OT_CLOSURE:_closure(o)->Mark(chain);break;
228 case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break;
229 case OT_GENERATOR:_generator(o)->Mark(chain);break;
230 case OT_THREAD:_thread(o)->Mark(chain);break;
231 case OT_CLASS:_class(o)->Mark(chain);break;
232 case OT_INSTANCE:_instance(o)->Mark(chain);break;
237 int SQSharedState::CollectGarbage(SQVM *vm)
240 SQCollectable *tchain=NULL;
241 SQVM *vms=_thread(_root_vm);
244 int x = _table(_thread(_root_vm)->_roottable)->CountUsed();
245 MarkObject(_refs_table,&tchain);
246 MarkObject(_registry,&tchain);
247 MarkObject(_metamethodsmap,&tchain);
248 MarkObject(_table_default_delegate,&tchain);
249 MarkObject(_array_default_delegate,&tchain);
250 MarkObject(_string_default_delegate,&tchain);
251 MarkObject(_number_default_delegate,&tchain);
252 MarkObject(_generator_default_delegate,&tchain);
253 MarkObject(_thread_default_delegate,&tchain);
254 MarkObject(_closure_default_delegate,&tchain);
255 MarkObject(_class_default_delegate,&tchain);
256 MarkObject(_instance_default_delegate,&tchain);
258 SQCollectable *t=_gc_chain;
259 SQCollectable *nx=NULL;
276 int z = _table(_thread(_root_vm)->_roottable)->CountUsed();
282 #ifndef NO_GARBAGE_COLLECTOR
283 void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)
287 if(*chain) (*chain)->_prev=c;
291 void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)
293 if(c->_prev) c->_prev->_next=c->_next;
294 else *chain=c->_next;
296 c->_next->_prev=c->_prev;
302 SQChar* SQSharedState::GetScratchPad(int size)
306 if(_scratchpadsize<size){
307 newsize=size+(size>>1);
308 _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
309 _scratchpadsize=newsize;
311 }else if(_scratchpadsize>=(size<<5)){
312 newsize=_scratchpadsize>>1;
313 _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
314 _scratchpadsize=newsize;
320 //////////////////////////////////////////////////////////////////////////
323 * The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
324 * http://www.lua.org/copyright.html#4
325 * http://www.lua.org/source/4.0.1/src_lstring.c.html
328 int SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
330 int idx = (int)TranslateIndex(refpos);
332 outkey = (SQInteger)idx;
333 outval = SQInteger(_val[idx]);
334 //return idx for the next iteration
337 //nothing to iterate anymore
341 StringTable::StringTable()
347 StringTable::~StringTable()
349 SQ_FREE(_strings,sizeof(SQString*)*_numofslots);
353 void StringTable::AllocNodes(int size)
357 _strings=(SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
358 memset(_strings,0,sizeof(SQString*)*_numofslots);
361 SQString *StringTable::Add(const SQChar *news,int len)
365 unsigned int h=::_hashstr(news,len)&(_numofslots-1);
367 for (s = _strings[h]; s; s = s->_next){
368 if(s->_len == len && (!memcmp(news,s->_val,rsl(len))))
372 SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString));
374 memcpy(t->_val,news,rsl(len));
375 t->_val[len]=_SC('\0');
377 t->_hash=::_hashstr(news,len);
378 t->_next=_strings[h];
382 if (_slotused > _numofslots) /* too crowded? */
383 Resize(_numofslots*2);
387 void StringTable::Resize(int size)
389 int oldsize=_numofslots;
390 SQString **oldtable=_strings;
392 for (int i=0; i<oldsize; i++){
393 SQString *p = oldtable[i];
395 SQString *next = p->_next;
396 unsigned int h=p->_hash&(_numofslots-1);
397 p->_next=_strings[h];
402 SQ_FREE(oldtable,oldsize*sizeof(SQString*));
405 void StringTable::Remove(SQString *bs)
409 unsigned int h=bs->_hash&(_numofslots-1);
411 for (s = _strings[h]; s; ){
414 prev->_next = s->_next;
416 _strings[h] = s->_next;
420 SQ_FREE(s,sizeof(SQString)+rsl(slen));
426 assert(0);//if this fail something is wrong