updated squirrel version
[supertux.git] / src / squirrel / squirrel / sqbaselib.cpp
1 /*
2         see copyright notice in squirrel.h
3 */
4 #include "sqpcheader.h"
5 #include "sqvm.h"
6 #include "sqstring.h"
7 #include "sqtable.h"
8 #include "sqarray.h"
9 #include "sqfuncproto.h"
10 #include "sqclosure.h"
11 #include "sqclass.h"
12 #include <stdlib.h>
13 #include <stdarg.h>
14 #include <ctype.h>
15
16 bool str2num(const SQChar *s,SQObjectPtr &res)
17 {
18         SQChar *end;
19         if(scstrstr(s,_SC("."))){
20                 SQFloat r = SQFloat(scstrtod(s,&end));
21                 if(s == end) return false;
22                 while (scisspace((*end)) ) end++;
23                 if (*end != _SC('\0')) return false;
24                 res = r;
25                 return true;
26         }
27         else{
28                 const SQChar *t = s;
29                 while(*t != _SC('\0')) if(!scisdigit(*t++)) return false;
30                 res = SQInteger(scatoi(s));
31                 return true;
32         }
33 }
34
35 #ifndef NO_GARBAGE_COLLECTOR
36 static int base_collectgarbage(HSQUIRRELVM v)
37 {
38         sq_pushinteger(v, sq_collectgarbage(v));
39         return 1;
40 }
41 #endif
42
43 static int base_getroottable(HSQUIRRELVM v)
44 {
45         v->Push(v->_roottable);
46         return 1;
47 }
48
49 static int base_setroottable(HSQUIRRELVM v)
50 {
51         SQObjectPtr &o=stack_get(v,2);
52         if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR;
53         v->Push(o);
54         return 1;
55 }
56
57 static int base_seterrorhandler(HSQUIRRELVM v)
58 {
59         sq_seterrorhandler(v);
60         return 0;
61 }
62
63 static int base_setdebughook(HSQUIRRELVM v)
64 {
65         sq_setdebughook(v);
66         return 0;
67 }
68
69 static int base_enabledebuginfo(HSQUIRRELVM v)
70 {
71         SQObjectPtr &o=stack_get(v,2);
72         sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0);
73         return 0;
74 }
75
76 static int base_getstackinfos(HSQUIRRELVM v)
77 {
78         SQInteger level;
79         SQStackInfos si;
80         int seq = 0;
81         const SQChar *name = NULL;
82         sq_getinteger(v, -1, &level);
83         if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))
84         {
85                 const SQChar *fn = _SC("unknown");
86                 const SQChar *src = _SC("unknown");
87                 if(si.funcname)fn = si.funcname;
88                 if(si.source)src = si.source;
89                 sq_newtable(v);
90                 sq_pushstring(v, _SC("func"), -1);
91                 sq_pushstring(v, fn, -1);
92                 sq_createslot(v, -3);
93                 sq_pushstring(v, _SC("src"), -1);
94                 sq_pushstring(v, src, -1);
95                 sq_createslot(v, -3);
96                 sq_pushstring(v, _SC("line"), -1);
97                 sq_pushinteger(v, si.line);
98                 sq_createslot(v, -3);
99                 sq_pushstring(v, _SC("locals"), -1);
100                 sq_newtable(v);
101                 seq=0;
102                 while (name = sq_getlocal(v, level, seq)) {
103                         sq_pushstring(v, name, -1);
104                         sq_push(v, -2);
105                         sq_createslot(v, -4);
106                         sq_pop(v, 1);
107                         seq++;
108                 }
109                 sq_createslot(v, -3);
110                 return 1;
111         }
112
113         return 0;
114 }
115
116 static int base_assert(HSQUIRRELVM v)
117 {
118         if(v->IsFalse(stack_get(v,2))){
119                 return sq_throwerror(v,_SC("assertion failed"));
120         }
121         return 0;
122 }
123
124 static int get_slice_params(HSQUIRRELVM v,int &sidx,int &eidx,SQObjectPtr &o)
125 {
126         int top = sq_gettop(v);
127         sidx=0;
128         eidx=0;
129         o=stack_get(v,1);
130         SQObjectPtr &start=stack_get(v,2);
131         if(type(start)!=OT_NULL && sq_isnumeric(start)){
132                 sidx=tointeger(start);
133         }
134         if(top>2){
135                 SQObjectPtr &end=stack_get(v,3);
136                 if(sq_isnumeric(end)){
137                         eidx=tointeger(end);
138                 }
139         }
140         else {
141                 eidx = sq_getsize(v,1);
142         }
143         return 1;
144 }
145
146 static int base_print(HSQUIRRELVM v)
147 {
148         SQObjectPtr &o=stack_get(v,2);
149         switch(type(o)){
150         case OT_STRING:
151                 if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),_stringval(o));
152                 break;
153         case OT_INTEGER:
154                 if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%d"),_integer(o));
155                 break;
156         case OT_FLOAT:
157                 if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%.14g"),_float(o));
158                 break;
159         default:{
160                 SQObjectPtr tname;
161                 v->TypeOf(o,tname);
162                 if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("(%s)"),_stringval(tname));
163                 }
164                 break;
165         }
166         return 0;
167 }
168
169 static int base_compilestring(HSQUIRRELVM v)
170 {
171         int nargs=sq_gettop(v);
172         const SQChar *src=NULL,*name=_SC("unnamedbuffer");
173         SQInteger size;
174         sq_getstring(v,2,&src);
175         size=sq_getsize(v,2);
176         if(nargs>2){
177                 sq_getstring(v,3,&name);
178         }
179         if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse)))
180                 return 1;
181         else
182                 return SQ_ERROR;
183 }
184
185 static int base_newthread(HSQUIRRELVM v)
186 {
187         SQObjectPtr &func = stack_get(v,2);
188         int stksize = (_funcproto(_closure(func)->_function)->_stacksize << 1) +2;
189         HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize);
190         sq_move(newv,v,-2);
191         return 1;
192 }
193
194 static int base_suspend(HSQUIRRELVM v)
195 {
196         return sq_suspendvm(v);
197 }
198
199 static int base_array(HSQUIRRELVM v)
200 {
201         SQArray *a;
202         SQObject &size = stack_get(v,2);
203         if(sq_gettop(v) > 2) {
204                 a = SQArray::Create(_ss(v),0);
205                 a->Resize(tointeger(size),stack_get(v,3));
206         }
207         else {
208                 a = SQArray::Create(_ss(v),tointeger(size));
209         }
210         v->Push(a);
211         return 1;
212 }
213
214 static int base_type(HSQUIRRELVM v)
215 {
216         SQObjectPtr &o = stack_get(v,2);
217         v->Push(SQString::Create(_ss(v),GetTypeName(o),-1));
218         return 1;
219 }
220
221 static SQRegFunction base_funcs[]={
222         //generic
223         {_SC("seterrorhandler"),base_seterrorhandler,2, NULL},
224         {_SC("setdebughook"),base_setdebughook,2, NULL},
225         {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL},
226         {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},
227         {_SC("getroottable"),base_getroottable,1, NULL},
228         {_SC("setroottable"),base_setroottable,2, NULL},
229         {_SC("assert"),base_assert,2, NULL},
230         {_SC("print"),base_print,2, NULL},
231         {_SC("compilestring"),base_compilestring,-2, _SC(".ss")},
232         {_SC("newthread"),base_newthread,2, _SC(".c")},
233         {_SC("suspend"),base_suspend,-1, NULL},
234         {_SC("array"),base_array,-2, _SC(".n")},
235         {_SC("type"),base_type,2, NULL},
236 #ifndef NO_GARBAGE_COLLECTOR
237         {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")},
238 #endif
239         {0,0}
240 };
241
242 void sq_base_register(HSQUIRRELVM v)
243 {
244         int i=0;
245         sq_pushroottable(v);
246         while(base_funcs[i].name!=0) {
247                 sq_pushstring(v,base_funcs[i].name,-1);
248                 sq_newclosure(v,base_funcs[i].f,0);
249                 sq_setnativeclosurename(v,-1,base_funcs[i].name);
250                 sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);
251                 sq_createslot(v,-3);
252                 i++;
253         }
254         sq_pushstring(v,_SC("_charsize_"),-1);
255         sq_pushinteger(v,sizeof(SQChar));
256         sq_createslot(v,-3);
257         sq_pop(v,1);
258 }
259
260 static int default_delegate_len(HSQUIRRELVM v)
261 {
262         v->Push(SQInteger(sq_getsize(v,1)));
263         return 1;
264 }
265
266 static int default_delegate_tofloat(HSQUIRRELVM v)
267 {
268         SQObjectPtr &o=stack_get(v,1);
269         switch(type(o)){
270         case OT_STRING:{
271                 SQObjectPtr res;
272                 if(str2num(_stringval(o),res)){
273                         v->Push(SQObjectPtr(tofloat(res)));
274                         break;
275                 }}
276         case OT_INTEGER:case OT_FLOAT:
277                 v->Push(SQObjectPtr(tofloat(o)));
278                 break;
279         case OT_BOOL:
280                 v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0)));
281                 break;
282         default:
283                 v->Push(_null_);
284                 break;
285         }
286         return 1;
287 }
288
289 static int default_delegate_tointeger(HSQUIRRELVM v)
290 {
291         SQObjectPtr &o=stack_get(v,1);
292         switch(type(o)){
293         case OT_STRING:{
294                 SQObjectPtr res;
295                 if(str2num(_stringval(o),res)){
296                         v->Push(SQObjectPtr(tointeger(res)));
297                         break;
298                 }}
299         case OT_INTEGER:case OT_FLOAT:
300                 v->Push(SQObjectPtr(tointeger(o)));
301                 break;
302         case OT_BOOL:
303                 v->Push(SQObjectPtr(_integer(o)?1:0));
304                 break;
305         default:
306                 v->Push(_null_);
307                 break;
308         }
309         return 1;
310 }
311
312 static int default_delegate_tostring(HSQUIRRELVM v)
313 {
314         SQObjectPtr &o=stack_get(v,1);
315         switch(type(o)){
316         case OT_STRING:
317                 v->Push(o);
318                 break;
319         case OT_INTEGER:
320                 scsprintf(_ss(v)->GetScratchPad(rsl(NUMBER_MAX_CHAR+1)),_SC("%d"),_integer(o));
321                 v->Push(SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1)));
322                 break;
323         case OT_FLOAT:
324                 scsprintf(_ss(v)->GetScratchPad(rsl(NUMBER_MAX_CHAR+1)),_SC("%.14g"),_float(o));
325                 v->Push(SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1)));
326                 break;
327         case OT_BOOL:
328                 v->Push(SQObjectPtr(SQString::Create(_ss(v),_integer(o)?_SC("true"):_SC("false"))));
329                 break;
330         default:
331                 v->Push(_null_);
332                 break;
333         }
334         return 1;
335 }
336
337 static int number_delegate_tochar(HSQUIRRELVM v)
338 {
339         SQObject &o=stack_get(v,1);
340         SQChar c=tointeger(o);
341         v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1));
342         return 1;
343 }
344
345
346 /////////////////////////////////////////////////////////////////
347 //TABLE DEFAULT DELEGATE
348
349 static int table_rawdelete(HSQUIRRELVM v)
350 {
351         if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue)))
352                 return SQ_ERROR;
353         return 1;
354 }
355
356
357 static int container_rawexists(HSQUIRRELVM v)
358 {
359         if(SQ_SUCCEEDED(sq_rawget(v,-2))) {
360                 sq_pushbool(v,SQTrue);
361                 return 1;
362         }
363         sq_pushbool(v,SQFalse);
364         return 1;
365 }
366
367 static int table_rawset(HSQUIRRELVM v)
368 {
369         return sq_rawset(v,-3);
370 }
371
372
373 static int table_rawget(HSQUIRRELVM v)
374 {
375         return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;
376 }
377
378 SQRegFunction SQSharedState::_table_default_delegate_funcz[]={
379         {_SC("len"),default_delegate_len,1, _SC("t")},
380         {_SC("rawget"),table_rawget,2, _SC("t")},
381         {_SC("rawset"),table_rawset,3, _SC("t")},
382         {_SC("rawdelete"),table_rawdelete,2, _SC("t")},
383         {_SC("rawin"),container_rawexists,2, _SC("t")},
384         {0,0}
385 };
386
387 //ARRAY DEFAULT DELEGATE///////////////////////////////////////
388
389 static int array_append(HSQUIRRELVM v)
390 {
391         return sq_arrayappend(v,-2);
392 }
393
394 static int array_extend(HSQUIRRELVM v)
395 {
396         _array(stack_get(v,1))->Extend(_array(stack_get(v,2)));
397         return 0;
398 }
399
400 static int array_reverse(HSQUIRRELVM v)
401 {
402         return sq_arrayreverse(v,-1);
403 }
404
405 static int array_pop(HSQUIRRELVM v)
406 {
407         return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR;
408 }
409
410 static int array_top(HSQUIRRELVM v)
411 {
412         SQObject &o=stack_get(v,1);
413         if(_array(o)->Size()>0){
414                 v->Push(_array(o)->Top());
415                 return 1;
416         }
417         else return sq_throwerror(v,_SC("top() on a empty array"));
418 }
419
420 static int array_insert(HSQUIRRELVM v)
421 {
422         SQObject &o=stack_get(v,1);
423         SQObject &idx=stack_get(v,2);
424         SQObject &val=stack_get(v,3);
425         _array(o)->Insert(idx,val);
426         return 0;
427 }
428
429 static int array_remove(HSQUIRRELVM v)
430 {
431         SQObject &o = stack_get(v, 1);
432         SQObject &idx = stack_get(v, 2);
433         if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type"));
434         SQObjectPtr val;
435         if(_array(o)->Get(tointeger(idx), val)) {
436                 _array(o)->Remove(tointeger(idx));
437                 v->Push(val);
438                 return 1;
439         }
440         return sq_throwerror(v, _SC("idx out of range"));
441 }
442
443 static int array_resize(HSQUIRRELVM v)
444 {
445         SQObject &o = stack_get(v, 1);
446         SQObject &nsize = stack_get(v, 2);
447         SQObjectPtr fill;
448         if(sq_isnumeric(nsize)) {
449                 if(sq_gettop(v) > 2)
450                         fill = stack_get(v, 3);
451                 _array(o)->Resize(tointeger(nsize),fill);
452                 return 0;
453         }
454         return sq_throwerror(v, _SC("size must be a number"));
455 }
456
457
458 //QSORT ala Sedgewick
459 bool _qsort_compare(HSQUIRRELVM v,SQObjectPtr &arr,SQObjectPtr &a,SQObjectPtr &b,int func,int &ret)
460 {
461         if(func < 0) {
462                 if(!v->ObjCmp(a,b,ret)) return false;
463         }
464         else {
465                 int top = sq_gettop(v);
466                 sq_push(v, func);
467                 sq_pushroottable(v);
468                 v->Push(a);
469                 v->Push(b);
470                 if(SQ_FAILED(sq_call(v, 3, SQTrue))) {
471                         v->Raise_Error(_SC("compare func failed"));
472                         return false;
473                 }
474                 sq_getinteger(v, -1, &ret);
475                 sq_settop(v, top);
476                 return true;
477         }
478         return true;
479 }
480 //QSORT ala Sedgewick
481 bool _qsort(HSQUIRRELVM v,SQObjectPtr &arr, int l, int r,int func)
482 {
483         int i, j;
484         SQArray *a=_array(arr);
485         SQObjectPtr pivot,t;
486         if( l < r ){
487                 pivot = a->_values[l];
488                 i = l; j = r+1;
489                 while(1){
490                         int ret;
491                         do { 
492                                 ++i; 
493                                 if(i > r) break;
494                                 if(!_qsort_compare(v,arr,a->_values[i],pivot,func,ret))
495                                         return false;
496                         } while( ret <= 0);
497                         do {
498                                 --j; 
499                                 if(!_qsort_compare(v,arr,a->_values[j],pivot,func,ret))
500                                         return false;
501                         }
502                         while( ret > 0 );
503                         if( i >= j ) break;
504                         t = a->_values[i]; a->_values[i] = a->_values[j]; a->_values[j] = t;
505                 }
506                 t = a->_values[l]; a->_values[l] = a->_values[j]; a->_values[j] = t;
507                 if(!_qsort( v, arr, l, j-1,func)) return false;
508                 if(!_qsort( v, arr, j+1, r,func)) return false;
509         }
510         return true;
511 }
512
513 static int array_sort(HSQUIRRELVM v)
514 {
515         //SQ_TRY {
516         int func = -1;
517         SQObjectPtr &o = stack_get(v,1);
518         SQObject &funcobj = stack_get(v,2);
519         if(_array(o)->Size() > 1) {
520                 if(type(funcobj) == OT_CLOSURE || type(funcobj) == OT_NATIVECLOSURE) func = 2;
521                 if(!_qsort(v, o, 0, _array(o)->Size()-1, func))
522                         return SQ_ERROR;
523
524         }
525         return 0;
526 }
527 static int array_slice(HSQUIRRELVM v)
528 {
529         int sidx,eidx;
530         SQObjectPtr o;
531         if(get_slice_params(v,sidx,eidx,o)==-1)return -1;
532         if(sidx<0)sidx=_array(o)->Size()+sidx;
533         if(eidx<0)eidx=_array(o)->Size()+eidx;
534         if(eidx <= sidx)return sq_throwerror(v,_SC("wrong indexes"));
535         SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);
536         SQObjectPtr t;
537         int count=0;
538         for(int i=sidx;i<eidx;i++){
539                 _array(o)->Get(i,t);
540                 arr->Set(count++,t);
541         }
542         v->Push(arr);
543         return 1;
544         
545 }
546
547 SQRegFunction SQSharedState::_array_default_delegate_funcz[]={
548         {_SC("len"),default_delegate_len,1, _SC("a")},
549         {_SC("append"),array_append,2, _SC("a")},
550         {_SC("extend"),array_extend,2, _SC("aa")},
551         {_SC("push"),array_append,2, _SC("a")},
552         {_SC("pop"),array_pop,1, _SC("a")},
553         {_SC("top"),array_top,1, _SC("a")},
554         {_SC("insert"),array_insert,3, _SC("an")},
555         {_SC("remove"),array_remove,2, _SC("an")},
556         {_SC("resize"),array_resize,-2, _SC("an")},
557         {_SC("reverse"),array_reverse,1, _SC("a")},
558         {_SC("sort"),array_sort,-1, _SC("ac")},
559         {_SC("slice"),array_slice,-1, _SC("ann")},
560         {0,0}
561 };
562
563 //STRING DEFAULT DELEGATE//////////////////////////
564 static int string_slice(HSQUIRRELVM v)
565 {
566         int sidx,eidx;
567         SQObjectPtr o;
568         if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;
569         if(sidx<0)sidx=_string(o)->_len+sidx;
570         if(eidx<0)eidx=_string(o)->_len+eidx;
571         if(eidx<sidx)
572                 return sq_throwerror(v,_SC("wrong indexes"));
573         v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));
574         return 1;
575 }
576
577 static int string_find(HSQUIRRELVM v)
578 {
579         int top,start_idx=0;
580         const SQChar *str,*substr,*ret;
581         if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){
582                 if(top>2)sq_getinteger(v,3,&start_idx);
583                 if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){
584                         ret=scstrstr(&str[start_idx],substr);
585                         if(ret){
586                                 sq_pushinteger(v,(int)(ret-str));
587                                 return 1;
588                         }
589                 }
590                 return 0;
591         }
592         return sq_throwerror(v,_SC("invalid param"));
593 }
594
595 #define STRING_TOFUNCZ(func) static int string_##func(HSQUIRRELVM v) \
596 { \
597         SQObject str=stack_get(v,1); \
598         int len=_string(str)->_len; \
599         const SQChar *sThis=_stringval(str); \
600         SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \
601         for(int i=0;i<len;i++) sNew[i]=func(sThis[i]); \
602         v->Push(SQString::Create(_ss(v),sNew,len)); \
603         return 1; \
604 }
605
606
607 STRING_TOFUNCZ(tolower)
608 STRING_TOFUNCZ(toupper)
609
610 SQRegFunction SQSharedState::_string_default_delegate_funcz[]={
611         {_SC("len"),default_delegate_len,1, _SC("s")},
612         {_SC("tointeger"),default_delegate_tointeger,1, _SC("s")},
613         {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")},
614         {_SC("tostring"),default_delegate_tostring,1, _SC("s")},
615         {_SC("slice"),string_slice,-1, _SC(" s n  n")},
616         {_SC("find"),string_find,-2, _SC("s s n ")},
617         {_SC("tolower"),string_tolower,1, _SC("s")},
618         {_SC("toupper"),string_toupper,1, _SC("s")},
619         {0,0}
620 };
621
622 //INTEGER DEFAULT DELEGATE//////////////////////////
623 SQRegFunction SQSharedState::_number_default_delegate_funcz[]={
624         {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")},
625         {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")},
626         {_SC("tostring"),default_delegate_tostring,1, _SC("n|b")},
627         {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},
628         {0,0}
629 };
630
631 //CLOSURE DEFAULT DELEGATE//////////////////////////
632 static int closure_call(HSQUIRRELVM v)
633 {
634         return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue))?1:SQ_ERROR;
635 }
636
637 static int closure_acall(HSQUIRRELVM v)
638 {
639         SQArray *aparams=_array(stack_get(v,2));
640         int nparams=aparams->Size();
641         v->Push(stack_get(v,1));
642         for(int i=0;i<nparams;i++)v->Push(aparams->_values[i]);
643         return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue))?1:SQ_ERROR;
644 }
645
646 SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={
647         {_SC("call"),closure_call,-1, _SC("c")},
648         {_SC("acall"),closure_acall,2, _SC("ca")},
649         {0,0}
650 };
651
652 //GENERATOR DEFAULT DELEGATE
653 static int generator_getstatus(HSQUIRRELVM v)
654 {
655         SQObject &o=stack_get(v,1);
656         switch(_generator(o)->_state){
657                 case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break;
658                 case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break;
659                 case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break;
660         }
661         return 1;
662 }
663
664 SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={
665         {_SC("getstatus"),generator_getstatus,1, _SC("g")},
666         {0,0}
667 };
668
669 //THREAD DEFAULT DELEGATE
670
671 static int thread_call(HSQUIRRELVM v)
672 {
673         SQObjectPtr o = stack_get(v,1);
674         if(type(o) == OT_THREAD) {
675                 int nparams = sq_gettop(v);
676                 _thread(o)->Push(_thread(o)->_roottable);
677                 for(int i = 2; i<(nparams+1); i++)
678                         sq_move(_thread(o),v,i);
679                 if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue))) {
680                         sq_move(v,_thread(o),-1);
681                         return 1;
682                 }
683                 return SQ_ERROR;
684         }
685         return sq_throwerror(v,_SC("wrong parameter"));
686 }
687
688 static int thread_wakeup(HSQUIRRELVM v)
689 {
690         SQObjectPtr o = stack_get(v,1);
691         if(type(o) == OT_THREAD) {
692                 SQVM *thread = _thread(o);
693                 int state = sq_getvmstate(thread);
694                 if(state != SQ_VMSTATE_SUSPENDED) {
695                         switch(state) {
696                                 case SQ_VMSTATE_IDLE:
697                                         return sq_throwerror(v,_SC("cannot wakeup a idle thread"));
698                                 break;
699                                 case SQ_VMSTATE_RUNNING:
700                                         return sq_throwerror(v,_SC("cannot wakeup a running thread"));
701                                 break;
702                         }
703                 }
704                         
705                 int wakeupret = sq_gettop(v)>1?1:0;
706                 if(wakeupret) {
707                         sq_move(thread,v,2);
708                 }
709                 if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,1))) {
710                         sq_move(v,thread,-1);
711                         sq_pop(thread,1);
712                         if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {
713                                 sq_pop(thread,1);
714                         }
715                         return 1;
716                 }
717                 return SQ_ERROR;
718         }
719         return sq_throwerror(v,_SC("wrong parameter"));
720 }
721
722 static int thread_getstatus(HSQUIRRELVM v)
723 {
724         SQObjectPtr &o = stack_get(v,1);
725         switch(sq_getvmstate(_thread(o))) {
726                 case SQ_VMSTATE_IDLE:
727                         sq_pushstring(v,_SC("idle"),-1);
728                 break;
729                 case SQ_VMSTATE_RUNNING:
730                         sq_pushstring(v,_SC("running"),-1);
731                 break;
732                 case SQ_VMSTATE_SUSPENDED:
733                         sq_pushstring(v,_SC("suspended"),-1);
734                 break;
735                 default:
736                         return sq_throwerror(v,_SC("internal VM error"));
737         }
738         return 1;
739 }
740
741 SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {
742         {_SC("call"), thread_call, -1, _SC("v")},
743         {_SC("wakeup"), thread_wakeup, -1, _SC("v")},
744         {_SC("getstatus"), thread_getstatus, 1, _SC("v")},
745         {0,0},
746 };
747
748 static int class_getattributes(HSQUIRRELVM v)
749 {
750         if(SQ_SUCCEEDED(sq_getattributes(v,-2)))
751                 return 1;
752         return SQ_ERROR;
753 }
754
755 static int class_setattributes(HSQUIRRELVM v)
756 {
757         if(SQ_SUCCEEDED(sq_setattributes(v,-3)))
758                 return 1;
759         return SQ_ERROR;
760 }
761
762 SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {
763         {_SC("getattributes"), class_getattributes, 2, _SC("y.")},
764         {_SC("setattributes"), class_setattributes, 3, _SC("y..")},
765         {_SC("rawin"),container_rawexists,2, _SC("y")},
766         {0,0}
767 };
768
769 static int instance_getclass(HSQUIRRELVM v)
770 {
771         if(SQ_SUCCEEDED(sq_getclass(v,1)))
772                 return 1;
773         return SQ_ERROR;
774 }
775
776 SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {
777         {_SC("getclass"), instance_getclass, 1, _SC("x")},
778         {_SC("rawin"),container_rawexists,2, _SC("x")},
779         {0,0}
780 };
781