Updated addon repository URL and improved debug output on download
[supertux.git] / external / squirrel / squirrel / sqapi.cpp
1 /*\r
2         see copyright notice in squirrel.h\r
3 */\r
4 #include "sqpcheader.h"\r
5 #include "sqvm.h"\r
6 #include "sqstring.h"\r
7 #include "sqtable.h"\r
8 #include "sqarray.h"\r
9 #include "sqfuncproto.h"\r
10 #include "sqclosure.h"\r
11 #include "squserdata.h"\r
12 #include "sqcompiler.h"\r
13 #include "sqfuncstate.h"\r
14 #include "sqclass.h"\r
15 \r
16 bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPtr **o)\r
17 {\r
18         *o = &stack_get(v,idx);\r
19         if(type(**o) != type){\r
20                 SQObjectPtr oval = v->PrintObjVal(**o);\r
21                 v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval));\r
22                 return false;\r
23         }\r
24         return true;\r
25 }\r
26 \r
27 #define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; }\r
28 \r
29 #define sq_aux_paramscheck(v,count) \\r
30 { \\r
31         if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\\r
32 }               \r
33 \r
34 \r
35 SQInteger sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type)\r
36 {\r
37         scsprintf(_ss(v)->GetScratchPad(100), _SC("unexpected type %s"), IdType2Name(type));\r
38         return sq_throwerror(v, _ss(v)->GetScratchPad(-1));\r
39 }\r
40 \r
41 HSQUIRRELVM sq_open(SQInteger initialstacksize)\r
42 {\r
43         SQSharedState *ss;\r
44         SQVM *v;\r
45         sq_new(ss, SQSharedState);\r
46         ss->Init();\r
47         v = (SQVM *)SQ_MALLOC(sizeof(SQVM));\r
48         new (v) SQVM(ss);\r
49         ss->_root_vm = v;\r
50         if(v->Init(NULL, initialstacksize)) {\r
51                 return v;\r
52         } else {\r
53                 sq_delete(v, SQVM);\r
54                 return NULL;\r
55         }\r
56         return v;\r
57 }\r
58 \r
59 HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize)\r
60 {\r
61         SQSharedState *ss;\r
62         SQVM *v;\r
63         ss=_ss(friendvm);\r
64         \r
65         v= (SQVM *)SQ_MALLOC(sizeof(SQVM));\r
66         new (v) SQVM(ss);\r
67         \r
68         if(v->Init(friendvm, initialstacksize)) {\r
69                 friendvm->Push(v);\r
70                 return v;\r
71         } else {\r
72                 sq_delete(v, SQVM);\r
73                 return NULL;\r
74         }\r
75 }\r
76 \r
77 SQInteger sq_getvmstate(HSQUIRRELVM v)\r
78 {\r
79         if(v->_suspended)\r
80                 return SQ_VMSTATE_SUSPENDED;\r
81         else { \r
82                 if(v->_callsstacksize != 0) return SQ_VMSTATE_RUNNING;\r
83                 else return SQ_VMSTATE_IDLE;\r
84         }\r
85 }\r
86 \r
87 void sq_seterrorhandler(HSQUIRRELVM v)\r
88 {\r
89         SQObject o = stack_get(v, -1);\r
90         if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {\r
91                 v->_errorhandler = o;\r
92                 v->Pop();\r
93         }\r
94 }\r
95 \r
96 void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook)\r
97 {\r
98         v->_debughook_native = hook;\r
99         v->_debughook_closure.Null();\r
100         v->_debughook = hook?true:false;\r
101 }\r
102 \r
103 void sq_setdebughook(HSQUIRRELVM v)\r
104 {\r
105         SQObject o = stack_get(v,-1);\r
106         if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {\r
107                 v->_debughook_closure = o;\r
108                 v->_debughook_native = NULL;\r
109                 v->_debughook = !sq_isnull(o);\r
110                 v->Pop();\r
111         }\r
112 }\r
113 \r
114 void sq_close(HSQUIRRELVM v)\r
115 {\r
116         SQSharedState *ss = _ss(v);\r
117         _thread(ss->_root_vm)->Finalize();\r
118         sq_delete(ss, SQSharedState);\r
119 }\r
120 \r
121 SQInteger sq_getversion()\r
122 {\r
123         return SQUIRREL_VERSION_NUMBER;\r
124 }\r
125 \r
126 SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror)\r
127 {\r
128         SQObjectPtr o;\r
129 #ifndef NO_COMPILER\r
130         if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) {\r
131                 v->Push(SQClosure::Create(_ss(v), _funcproto(o)));\r
132                 return SQ_OK;\r
133         }\r
134         return SQ_ERROR;\r
135 #else\r
136         return sq_throwerror(v,_SC("this is a no compiler build"));\r
137 #endif\r
138 }\r
139 \r
140 void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable)\r
141 {\r
142         _ss(v)->_debuginfo = enable?true:false;\r
143 }\r
144 \r
145 void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable)\r
146 {\r
147         _ss(v)->_notifyallexceptions = enable?true:false;\r
148 }\r
149 \r
150 void sq_addref(HSQUIRRELVM v,HSQOBJECT *po)\r
151 {\r
152         if(!ISREFCOUNTED(type(*po))) return;\r
153 #ifdef NO_GARBAGE_COLLECTOR\r
154         __AddRef(po->_type,po->_unVal);\r
155 #else\r
156         _ss(v)->_refs_table.AddRef(*po);\r
157 #endif\r
158 }\r
159 \r
160 SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po)\r
161 {\r
162         if(!ISREFCOUNTED(type(*po))) return 0;\r
163 #ifdef NO_GARBAGE_COLLECTOR\r
164    return po->_unVal.pRefCounted->_uiRef; \r
165 #else\r
166    return _ss(v)->_refs_table.GetRefCount(*po); \r
167 #endif \r
168 }\r
169 \r
170 SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)\r
171 {\r
172         if(!ISREFCOUNTED(type(*po))) return SQTrue;\r
173 #ifdef NO_GARBAGE_COLLECTOR\r
174         bool ret = (po->_unVal.pRefCounted->_uiRef <= 1) ? SQTrue : SQFalse;\r
175         __Release(po->_type,po->_unVal);\r
176         return ret; //the ret val doesn't work(and cannot be fixed)\r
177 #else\r
178         return _ss(v)->_refs_table.Release(*po);\r
179 #endif\r
180 }\r
181 \r
182 const SQChar *sq_objtostring(const HSQOBJECT *o) \r
183 {\r
184         if(sq_type(*o) == OT_STRING) {\r
185                 return _stringval(*o);\r
186         }\r
187         return NULL;\r
188 }\r
189 \r
190 SQInteger sq_objtointeger(const HSQOBJECT *o) \r
191 {\r
192         if(sq_isnumeric(*o)) {\r
193                 return tointeger(*o);\r
194         }\r
195         return 0;\r
196 }\r
197 \r
198 SQFloat sq_objtofloat(const HSQOBJECT *o) \r
199 {\r
200         if(sq_isnumeric(*o)) {\r
201                 return tofloat(*o);\r
202         }\r
203         return 0;\r
204 }\r
205 \r
206 SQBool sq_objtobool(const HSQOBJECT *o) \r
207 {\r
208         if(sq_isbool(*o)) {\r
209                 return _integer(*o);\r
210         }\r
211         return SQFalse;\r
212 }\r
213 \r
214 SQUserPointer sq_objtouserpointer(const HSQOBJECT *o)\r
215 {\r
216         if(sq_isuserpointer(*o)) {\r
217                 return _userpointer(*o);\r
218         }\r
219         return 0;\r
220 }\r
221 \r
222 void sq_pushnull(HSQUIRRELVM v)\r
223 {\r
224         v->PushNull();\r
225 }\r
226 \r
227 void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len)\r
228 {\r
229         if(s)\r
230                 v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len)));\r
231         else v->PushNull();\r
232 }\r
233 \r
234 void sq_pushinteger(HSQUIRRELVM v,SQInteger n)\r
235 {\r
236         v->Push(n);\r
237 }\r
238 \r
239 void sq_pushbool(HSQUIRRELVM v,SQBool b)\r
240 {\r
241         v->Push(b?true:false);\r
242 }\r
243 \r
244 void sq_pushfloat(HSQUIRRELVM v,SQFloat n)\r
245 {\r
246         v->Push(n);\r
247 }\r
248 \r
249 void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p)\r
250 {\r
251         v->Push(p);\r
252 }\r
253 \r
254 SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size)\r
255 {\r
256         SQUserData *ud = SQUserData::Create(_ss(v), size);\r
257         v->Push(ud);\r
258         return (SQUserPointer)sq_aligning(ud + 1);\r
259 }\r
260 \r
261 void sq_newtable(HSQUIRRELVM v)\r
262 {\r
263         v->Push(SQTable::Create(_ss(v), 0));    \r
264 }\r
265 \r
266 void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity)\r
267 {\r
268         v->Push(SQTable::Create(_ss(v), initialcapacity));      \r
269 }\r
270 \r
271 void sq_newarray(HSQUIRRELVM v,SQInteger size)\r
272 {\r
273         v->Push(SQArray::Create(_ss(v), size)); \r
274 }\r
275 \r
276 SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase)\r
277 {\r
278         SQClass *baseclass = NULL;\r
279         if(hasbase) {\r
280                 SQObjectPtr &base = stack_get(v,-1);\r
281                 if(type(base) != OT_CLASS)\r
282                         return sq_throwerror(v,_SC("invalid base type"));\r
283                 baseclass = _class(base);\r
284         }\r
285         SQClass *newclass = SQClass::Create(_ss(v), baseclass);\r
286         if(baseclass) v->Pop();\r
287         v->Push(newclass);      \r
288         return SQ_OK;\r
289 }\r
290 \r
291 SQBool sq_instanceof(HSQUIRRELVM v)\r
292 {\r
293         SQObjectPtr &inst = stack_get(v,-1);\r
294         SQObjectPtr &cl = stack_get(v,-2);\r
295         if(type(inst) != OT_INSTANCE || type(cl) != OT_CLASS)\r
296                 return sq_throwerror(v,_SC("invalid param type"));\r
297         return _instance(inst)->InstanceOf(_class(cl))?SQTrue:SQFalse;\r
298 }\r
299 \r
300 SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx)\r
301 {\r
302         sq_aux_paramscheck(v,2);\r
303         SQObjectPtr *arr;\r
304         _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
305         _array(*arr)->Append(v->GetUp(-1));\r
306         v->Pop();\r
307         return SQ_OK;\r
308 }\r
309 \r
310 SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval)\r
311 {\r
312         sq_aux_paramscheck(v, 1);\r
313         SQObjectPtr *arr;\r
314         _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
315         if(_array(*arr)->Size() > 0) {\r
316         if(pushval != 0){ v->Push(_array(*arr)->Top()); }\r
317                 _array(*arr)->Pop();\r
318                 return SQ_OK;\r
319         }\r
320         return sq_throwerror(v, _SC("empty array"));\r
321 }\r
322 \r
323 SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize)\r
324 {\r
325         sq_aux_paramscheck(v,1);\r
326         SQObjectPtr *arr;\r
327         _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
328         if(newsize >= 0) {\r
329                 _array(*arr)->Resize(newsize);\r
330                 return SQ_OK;\r
331         }\r
332         return sq_throwerror(v,_SC("negative size"));\r
333 }\r
334 \r
335 \r
336 SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx)\r
337 {\r
338         sq_aux_paramscheck(v, 1);\r
339         SQObjectPtr *o;\r
340         _GETSAFE_OBJ(v, idx, OT_ARRAY,o);\r
341         SQArray *arr = _array(*o);\r
342         if(arr->Size() > 0) {\r
343                 SQObjectPtr t;\r
344                 SQInteger size = arr->Size();\r
345                 SQInteger n = size >> 1; size -= 1;\r
346                 for(SQInteger i = 0; i < n; i++) {\r
347                         t = arr->_values[i];\r
348                         arr->_values[i] = arr->_values[size-i];\r
349                         arr->_values[size-i] = t;\r
350                 }\r
351                 return SQ_OK;\r
352         }\r
353         return SQ_OK;\r
354 }\r
355 \r
356 SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx)\r
357 {\r
358         sq_aux_paramscheck(v, 1); \r
359         SQObjectPtr *arr;\r
360         _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); \r
361         return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range")); \r
362 }\r
363 \r
364 SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos)\r
365 {\r
366         sq_aux_paramscheck(v, 1); \r
367         SQObjectPtr *arr;\r
368         _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
369         SQRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));\r
370         v->Pop();\r
371         return ret;\r
372 }\r
373 \r
374 void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars)\r
375 {\r
376         SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func,nfreevars);\r
377         nc->_nparamscheck = 0;\r
378         for(SQUnsignedInteger i = 0; i < nfreevars; i++) {\r
379                 nc->_outervalues[i] = v->Top();\r
380                 v->Pop();\r
381         }\r
382         v->Push(SQObjectPtr(nc));       \r
383 }\r
384 \r
385 SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars)\r
386 {\r
387         SQObject o = stack_get(v, idx);\r
388         if(type(o) == OT_CLOSURE) {\r
389                 SQClosure *c = _closure(o);\r
390                 SQFunctionProto *proto = c->_function;\r
391                 *nparams = (SQUnsignedInteger)proto->_nparameters;\r
392                 *nfreevars = (SQUnsignedInteger)proto->_noutervalues;\r
393                 return SQ_OK;\r
394         }\r
395         else if(type(o) == OT_NATIVECLOSURE)\r
396         {\r
397                 SQNativeClosure *c = _nativeclosure(o);\r
398                 *nparams = (SQUnsignedInteger)c->_nparamscheck;\r
399                 *nfreevars = c->_noutervalues;\r
400                 return SQ_OK;\r
401         }\r
402         return sq_throwerror(v,_SC("the object is not a closure"));\r
403 }\r
404 \r
405 SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name)\r
406 {\r
407         SQObject o = stack_get(v, idx);\r
408         if(sq_isnativeclosure(o)) {\r
409                 SQNativeClosure *nc = _nativeclosure(o);\r
410                 nc->_name = SQString::Create(_ss(v),name);\r
411                 return SQ_OK;\r
412         }\r
413         return sq_throwerror(v,_SC("the object is not a nativeclosure"));\r
414 }\r
415 \r
416 SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask)\r
417 {\r
418         SQObject o = stack_get(v, -1);\r
419         if(!sq_isnativeclosure(o))\r
420                 return sq_throwerror(v, _SC("native closure expected"));\r
421         SQNativeClosure *nc = _nativeclosure(o);\r
422         nc->_nparamscheck = nparamscheck;\r
423         if(typemask) {\r
424                 SQIntVec res;\r
425                 if(!CompileTypemask(res, typemask))\r
426                         return sq_throwerror(v, _SC("invalid typemask"));\r
427                 nc->_typecheck.copy(res);\r
428         }\r
429         else {\r
430                 nc->_typecheck.resize(0);\r
431         }\r
432         if(nparamscheck == SQ_MATCHTYPEMASKSTRING) {\r
433                 nc->_nparamscheck = nc->_typecheck.size();\r
434         }\r
435         return SQ_OK;\r
436 }\r
437 \r
438 SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)\r
439 {\r
440         SQObjectPtr &o = stack_get(v,idx);\r
441         if(!sq_isnativeclosure(o) &&\r
442                 !sq_isclosure(o))\r
443                 return sq_throwerror(v,_SC("the target is not a closure"));\r
444     SQObjectPtr &env = stack_get(v,-1);\r
445         if(!sq_istable(env) &&\r
446                 !sq_isclass(env) &&\r
447                 !sq_isinstance(env))\r
448                 return sq_throwerror(v,_SC("invalid environment"));\r
449         SQWeakRef *w = _refcounted(env)->GetWeakRef(type(env));\r
450         SQObjectPtr ret;\r
451         if(sq_isclosure(o)) {\r
452                 SQClosure *c = _closure(o)->Clone();\r
453                 __ObjRelease(c->_env);\r
454                 c->_env = w;\r
455                 __ObjAddRef(c->_env);\r
456                 if(_closure(o)->_base) {\r
457                         c->_base = _closure(o)->_base;\r
458                         __ObjAddRef(c->_base);\r
459                 }\r
460                 ret = c;\r
461         }\r
462         else { //then must be a native closure\r
463                 SQNativeClosure *c = _nativeclosure(o)->Clone();\r
464                 __ObjRelease(c->_env);\r
465                 c->_env = w;\r
466                 __ObjAddRef(c->_env);\r
467                 ret = c;\r
468         }\r
469         v->Pop();\r
470         v->Push(ret);\r
471         return SQ_OK;\r
472 }\r
473 \r
474 SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx)\r
475 {\r
476         SQObjectPtr &o = stack_get(v,idx);\r
477         if(!sq_isnativeclosure(o) &&\r
478                 !sq_isclosure(o))\r
479                 return sq_throwerror(v,_SC("the target is not a closure"));\r
480         if(sq_isnativeclosure(o))\r
481         {\r
482                 v->Push(_nativeclosure(o)->_name);\r
483         }\r
484         else { //closure\r
485                 v->Push(_closure(o)->_function->_name);\r
486         }\r
487         return SQ_OK;\r
488 }\r
489 \r
490 SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx)\r
491 {\r
492         SQObject &o=stack_get(v,idx);\r
493         switch(type(o)) {\r
494                 case OT_TABLE: _table(o)->Clear();      break;\r
495                 case OT_ARRAY: _array(o)->Resize(0); break;\r
496                 default:\r
497                         return sq_throwerror(v, _SC("clear only works on table and array"));\r
498                 break;\r
499 \r
500         }\r
501         return SQ_OK;\r
502 }\r
503 \r
504 void sq_pushroottable(HSQUIRRELVM v)\r
505 {\r
506         v->Push(v->_roottable);\r
507 }\r
508 \r
509 void sq_pushregistrytable(HSQUIRRELVM v)\r
510 {\r
511         v->Push(_ss(v)->_registry);\r
512 }\r
513 \r
514 void sq_pushconsttable(HSQUIRRELVM v)\r
515 {\r
516         v->Push(_ss(v)->_consts);\r
517 }\r
518 \r
519 SQRESULT sq_setroottable(HSQUIRRELVM v)\r
520 {\r
521         SQObject o = stack_get(v, -1);\r
522         if(sq_istable(o) || sq_isnull(o)) {\r
523                 v->_roottable = o;\r
524                 v->Pop();\r
525                 return SQ_OK;\r
526         }\r
527         return sq_throwerror(v, _SC("ivalid type"));\r
528 }\r
529 \r
530 SQRESULT sq_setconsttable(HSQUIRRELVM v)\r
531 {\r
532         SQObject o = stack_get(v, -1);\r
533         if(sq_istable(o)) {\r
534                 _ss(v)->_consts = o;\r
535                 v->Pop();\r
536                 return SQ_OK;\r
537         }\r
538         return sq_throwerror(v, _SC("ivalid type, expected table"));\r
539 }\r
540 \r
541 void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p)\r
542 {\r
543         v->_foreignptr = p;\r
544 }\r
545 \r
546 SQUserPointer sq_getforeignptr(HSQUIRRELVM v)\r
547 {\r
548         return v->_foreignptr;\r
549 }\r
550 \r
551 void sq_push(HSQUIRRELVM v,SQInteger idx)\r
552 {\r
553         v->Push(stack_get(v, idx));\r
554 }\r
555 \r
556 SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx)\r
557 {\r
558         return type(stack_get(v, idx));\r
559 }\r
560 \r
561 SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx)\r
562 {\r
563         SQObjectPtr &o = stack_get(v, idx);\r
564         SQObjectPtr res;\r
565         if(!v->TypeOf(o,res)) {\r
566                 return SQ_ERROR;\r
567         }\r
568         v->Push(res);\r
569         return SQ_OK;\r
570 }\r
571 \r
572 SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx)\r
573 {\r
574         SQObjectPtr &o = stack_get(v, idx);\r
575         SQObjectPtr res;\r
576         if(!v->ToString(o,res)) {\r
577                 return SQ_ERROR;\r
578         }\r
579         v->Push(res);\r
580         return SQ_OK;\r
581 }\r
582 \r
583 void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b)\r
584 {\r
585         SQObjectPtr &o = stack_get(v, idx);\r
586         *b = SQVM::IsFalse(o)?SQFalse:SQTrue;\r
587 }\r
588 \r
589 SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i)\r
590 {\r
591         SQObjectPtr &o = stack_get(v, idx);\r
592         if(sq_isnumeric(o)) {\r
593                 *i = tointeger(o);\r
594                 return SQ_OK;\r
595         }\r
596         return SQ_ERROR;\r
597 }\r
598 \r
599 SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f)\r
600 {\r
601         SQObjectPtr &o = stack_get(v, idx);\r
602         if(sq_isnumeric(o)) {\r
603                 *f = tofloat(o);\r
604                 return SQ_OK;\r
605         }\r
606         return SQ_ERROR;\r
607 }\r
608 \r
609 SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b)\r
610 {\r
611         SQObjectPtr &o = stack_get(v, idx);\r
612         if(sq_isbool(o)) {\r
613                 *b = _integer(o);\r
614                 return SQ_OK;\r
615         }\r
616         return SQ_ERROR;\r
617 }\r
618 \r
619 SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c)\r
620 {\r
621         SQObjectPtr *o = NULL;\r
622         _GETSAFE_OBJ(v, idx, OT_STRING,o);\r
623         *c = _stringval(*o);\r
624         return SQ_OK;\r
625 }\r
626 \r
627 SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread)\r
628 {\r
629         SQObjectPtr *o = NULL;\r
630         _GETSAFE_OBJ(v, idx, OT_THREAD,o);\r
631         *thread = _thread(*o);\r
632         return SQ_OK;\r
633 }\r
634 \r
635 SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx)\r
636 {\r
637         SQObjectPtr &o = stack_get(v,idx);\r
638         v->PushNull();\r
639         if(!v->Clone(o, stack_get(v, -1))){\r
640                 v->Pop();\r
641                 return SQ_ERROR;\r
642         }\r
643         return SQ_OK;\r
644 }\r
645 \r
646 SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx)\r
647 {\r
648         SQObjectPtr &o = stack_get(v, idx);\r
649         SQObjectType type = type(o);\r
650         switch(type) {\r
651         case OT_STRING:         return _string(o)->_len;\r
652         case OT_TABLE:          return _table(o)->CountUsed();\r
653         case OT_ARRAY:          return _array(o)->Size();\r
654         case OT_USERDATA:       return _userdata(o)->_size;\r
655         case OT_INSTANCE:       return _instance(o)->_class->_udsize;\r
656         case OT_CLASS:          return _class(o)->_udsize;\r
657         default:\r
658                 return sq_aux_invalidtype(v, type);\r
659         }\r
660 }\r
661 \r
662 SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx)\r
663 {\r
664         SQObjectPtr &o = stack_get(v, idx);\r
665         return HashObj(o);\r
666 }\r
667 \r
668 SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag)\r
669 {\r
670         SQObjectPtr *o = NULL;\r
671         _GETSAFE_OBJ(v, idx, OT_USERDATA,o);\r
672         (*p) = _userdataval(*o);\r
673         if(typetag) *typetag = _userdata(*o)->_typetag;\r
674         return SQ_OK;\r
675 }\r
676 \r
677 SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag)\r
678 {\r
679         SQObjectPtr &o = stack_get(v,idx);\r
680         switch(type(o)) {\r
681                 case OT_USERDATA:       _userdata(o)->_typetag = typetag;       break;\r
682                 case OT_CLASS:          _class(o)->_typetag = typetag;          break;\r
683                 default:                        return sq_throwerror(v,_SC("invalid object type"));\r
684         }\r
685         return SQ_OK;\r
686 }\r
687 \r
688 SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag)\r
689 {\r
690   switch(type(*o)) {\r
691     case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break;\r
692     case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break;\r
693     case OT_CLASS:    *typetag = _class(*o)->_typetag; break;\r
694     default: return SQ_ERROR;\r
695   }\r
696   return SQ_OK;\r
697 }\r
698 \r
699 SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag)\r
700 {\r
701         SQObjectPtr &o = stack_get(v,idx);\r
702         if(SQ_FAILED(sq_getobjtypetag(&o,typetag)))\r
703                 return sq_throwerror(v,_SC("invalid object type"));\r
704         return SQ_OK;\r
705 }\r
706 \r
707 SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p)\r
708 {\r
709         SQObjectPtr *o = NULL;\r
710         _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o);\r
711         (*p) = _userpointer(*o);\r
712         return SQ_OK;\r
713 }\r
714 \r
715 SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p)\r
716 {\r
717         SQObjectPtr &o = stack_get(v,idx);\r
718         if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));\r
719         _instance(o)->_userpointer = p;\r
720         return SQ_OK;\r
721 }\r
722 \r
723 SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize)\r
724 {\r
725         SQObjectPtr &o = stack_get(v,idx);\r
726         if(type(o) != OT_CLASS) return sq_throwerror(v,_SC("the object is not a class"));\r
727         if(_class(o)->_locked) return sq_throwerror(v,_SC("the class is locked"));\r
728         _class(o)->_udsize = udsize;\r
729         return SQ_OK;\r
730 }\r
731 \r
732 \r
733 SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag)\r
734 {\r
735         SQObjectPtr &o = stack_get(v,idx);\r
736         if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));\r
737         (*p) = _instance(o)->_userpointer;\r
738         if(typetag != 0) {\r
739                 SQClass *cl = _instance(o)->_class;\r
740                 do{\r
741                         if(cl->_typetag == typetag)\r
742                                 return SQ_OK;\r
743                         cl = cl->_base;\r
744                 }while(cl != NULL);\r
745                 return sq_throwerror(v,_SC("invalid type tag"));\r
746         }\r
747         return SQ_OK;\r
748 }\r
749 \r
750 SQInteger sq_gettop(HSQUIRRELVM v)\r
751 {\r
752         return (v->_top) - v->_stackbase;\r
753 }\r
754 \r
755 void sq_settop(HSQUIRRELVM v, SQInteger newtop)\r
756 {\r
757         SQInteger top = sq_gettop(v);\r
758         if(top > newtop)\r
759                 sq_pop(v, top - newtop);\r
760         else\r
761                 while(top++ < newtop) sq_pushnull(v);\r
762 }\r
763 \r
764 void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop)\r
765 {\r
766         assert(v->_top >= nelemstopop);\r
767         v->Pop(nelemstopop);\r
768 }\r
769 \r
770 void sq_poptop(HSQUIRRELVM v)\r
771 {\r
772         assert(v->_top >= 1);\r
773     v->Pop();\r
774 }\r
775 \r
776 \r
777 void sq_remove(HSQUIRRELVM v, SQInteger idx)\r
778 {\r
779         v->Remove(idx);\r
780 }\r
781 \r
782 SQInteger sq_cmp(HSQUIRRELVM v)\r
783 {\r
784         SQInteger res;\r
785         v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res);\r
786         return res;\r
787 }\r
788 \r
789 SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic)\r
790 {\r
791         sq_aux_paramscheck(v, 3);\r
792         SQObjectPtr &self = stack_get(v, idx);\r
793         if(type(self) == OT_TABLE || type(self) == OT_CLASS) {\r
794                 SQObjectPtr &key = v->GetUp(-2);\r
795                 if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));\r
796                 v->NewSlot(self, key, v->GetUp(-1),bstatic?true:false);\r
797                 v->Pop(2);\r
798         }\r
799         return SQ_OK;\r
800 }\r
801 \r
802 SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)\r
803 {\r
804         sq_aux_paramscheck(v, 2);\r
805         SQObjectPtr *self;\r
806         _GETSAFE_OBJ(v, idx, OT_TABLE,self);\r
807         SQObjectPtr &key = v->GetUp(-1);\r
808         if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));\r
809         SQObjectPtr res;\r
810         if(!v->DeleteSlot(*self, key, res)){\r
811                 v->Pop();\r
812                 return SQ_ERROR;\r
813         }\r
814         if(pushval)     v->GetUp(-1) = res;\r
815         else v->Pop();\r
816         return SQ_OK;\r
817 }\r
818 \r
819 SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx)\r
820 {\r
821         SQObjectPtr &self = stack_get(v, idx);\r
822         if(v->Set(self, v->GetUp(-2), v->GetUp(-1),DONT_FALL_BACK)) {\r
823                 v->Pop(2);\r
824                 return SQ_OK;\r
825         }\r
826         return SQ_ERROR;\r
827 }\r
828 \r
829 SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx)\r
830 {\r
831         SQObjectPtr &self = stack_get(v, idx);\r
832         if(type(v->GetUp(-2)) == OT_NULL) {\r
833                 v->Pop(2);\r
834                 return sq_throwerror(v, _SC("null key"));\r
835         }\r
836         switch(type(self)) {\r
837         case OT_TABLE:\r
838                 _table(self)->NewSlot(v->GetUp(-2), v->GetUp(-1));\r
839                 v->Pop(2);\r
840                 return SQ_OK;\r
841         break;\r
842         case OT_CLASS:\r
843                 _class(self)->NewSlot(_ss(v), v->GetUp(-2), v->GetUp(-1),false);\r
844                 v->Pop(2);\r
845                 return SQ_OK;\r
846         break;\r
847         case OT_INSTANCE:\r
848                 if(_instance(self)->Set(v->GetUp(-2), v->GetUp(-1))) {\r
849                         v->Pop(2);\r
850                         return SQ_OK;\r
851                 }\r
852         break;\r
853         case OT_ARRAY:\r
854                 if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) {\r
855                         v->Pop(2);\r
856                         return SQ_OK;\r
857                 }\r
858         break;\r
859         default:\r
860                 v->Pop(2);\r
861                 return sq_throwerror(v, _SC("rawset works only on array/table/class and instance"));\r
862         }\r
863         v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;\r
864 }\r
865 \r
866 SQRESULT sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)\r
867 {\r
868         SQObjectPtr &self = stack_get(v, idx);\r
869         if(type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));\r
870         if(type(v->GetUp(-3)) == OT_NULL) return sq_throwerror(v, _SC("null key"));\r
871         if(!v->NewSlotA(self,v->GetUp(-3),v->GetUp(-2),v->GetUp(-1),bstatic?true:false,false))\r
872                 return SQ_ERROR;\r
873         return SQ_OK; \r
874 }\r
875 \r
876 SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)\r
877 {\r
878         SQObjectPtr &self = stack_get(v, idx);\r
879         if(type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));\r
880         if(type(v->GetUp(-3)) == OT_NULL) return sq_throwerror(v, _SC("null key"));\r
881         if(!v->NewSlotA(self,v->GetUp(-3),v->GetUp(-2),v->GetUp(-1),bstatic?true:false,true))\r
882                 return SQ_ERROR;\r
883         return SQ_OK; \r
884 }\r
885 \r
886 SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx)\r
887 {\r
888         SQObjectPtr &self = stack_get(v, idx);\r
889         SQObjectPtr &mt = v->GetUp(-1);\r
890         SQObjectType type = type(self);\r
891         switch(type) {\r
892         case OT_TABLE:\r
893                 if(type(mt) == OT_TABLE) {\r
894                         if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, _SC("delagate cycle")); v->Pop();}\r
895                 else if(type(mt)==OT_NULL) {\r
896                         _table(self)->SetDelegate(NULL); v->Pop(); }\r
897                 else return sq_aux_invalidtype(v,type);\r
898                 break;\r
899         case OT_USERDATA:\r
900                 if(type(mt)==OT_TABLE) {\r
901                         _userdata(self)->SetDelegate(_table(mt)); v->Pop(); }\r
902                 else if(type(mt)==OT_NULL) {\r
903                         _userdata(self)->SetDelegate(NULL); v->Pop(); }\r
904                 else return sq_aux_invalidtype(v, type);\r
905                 break;\r
906         default:\r
907                         return sq_aux_invalidtype(v, type);\r
908                 break;\r
909         }\r
910         return SQ_OK;\r
911 }\r
912 \r
913 SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)\r
914 {\r
915         sq_aux_paramscheck(v, 2);\r
916         SQObjectPtr *self;\r
917         _GETSAFE_OBJ(v, idx, OT_TABLE,self);\r
918         SQObjectPtr &key = v->GetUp(-1);\r
919         SQObjectPtr t;\r
920         if(_table(*self)->Get(key,t)) {\r
921                 _table(*self)->Remove(key);\r
922         }\r
923         if(pushval != 0)\r
924                 v->GetUp(-1) = t;\r
925         else\r
926                 v->Pop();\r
927         return SQ_OK;\r
928 }\r
929 \r
930 SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx)\r
931 {\r
932         SQObjectPtr &self=stack_get(v,idx);\r
933         switch(type(self)){\r
934         case OT_TABLE:\r
935         case OT_USERDATA:\r
936                 if(!_delegable(self)->_delegate){\r
937                         v->PushNull();\r
938                         break;\r
939                 }\r
940                 v->Push(SQObjectPtr(_delegable(self)->_delegate));\r
941                 break;\r
942         default: return sq_throwerror(v,_SC("wrong type")); break;\r
943         }\r
944         return SQ_OK;\r
945         \r
946 }\r
947 \r
948 SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx)\r
949 {\r
950         SQObjectPtr &self=stack_get(v,idx);\r
951         if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,DONT_FALL_BACK))\r
952                 return SQ_OK;\r
953         v->Pop();\r
954         return SQ_ERROR;\r
955 }\r
956 \r
957 SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx)\r
958 {\r
959         SQObjectPtr &self=stack_get(v,idx);\r
960         switch(type(self)) {\r
961         case OT_TABLE:\r
962                 if(_table(self)->Get(v->GetUp(-1),v->GetUp(-1)))\r
963                         return SQ_OK;\r
964                 break;\r
965         case OT_CLASS:\r
966                 if(_class(self)->Get(v->GetUp(-1),v->GetUp(-1)))\r
967                         return SQ_OK;\r
968                 break;\r
969         case OT_INSTANCE:\r
970                 if(_instance(self)->Get(v->GetUp(-1),v->GetUp(-1)))\r
971                         return SQ_OK;\r
972                 break;\r
973         case OT_ARRAY:{\r
974                 SQObjectPtr& key = v->GetUp(-1);\r
975                 if(sq_isnumeric(key)){\r
976                         if(_array(self)->Get(tointeger(key),v->GetUp(-1))) {\r
977                                 return SQ_OK;\r
978                         }\r
979                 }\r
980                 else {\r
981                         v->Pop();\r
982                         return sq_throwerror(v,_SC("invalid index type for an array"));\r
983                 }\r
984                                   }\r
985                 break;\r
986         default:\r
987                 v->Pop();\r
988                 return sq_throwerror(v,_SC("rawget works only on array/table/instance and class"));\r
989         }       \r
990         v->Pop();\r
991         return sq_throwerror(v,_SC("the index doesn't exist"));\r
992 }\r
993 \r
994 SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po)\r
995 {\r
996         *po=stack_get(v,idx);\r
997         return SQ_OK;\r
998 }\r
999 \r
1000 const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx)\r
1001 {\r
1002         SQUnsignedInteger cstksize=v->_callsstacksize;\r
1003         SQUnsignedInteger lvl=(cstksize-level)-1;\r
1004         SQInteger stackbase=v->_stackbase;\r
1005         if(lvl<cstksize){\r
1006                 for(SQUnsignedInteger i=0;i<level;i++){\r
1007                         SQVM::CallInfo &ci=v->_callsstack[(cstksize-i)-1];\r
1008                         stackbase-=ci._prevstkbase;\r
1009                 }\r
1010                 SQVM::CallInfo &ci=v->_callsstack[lvl];\r
1011                 if(type(ci._closure)!=OT_CLOSURE)\r
1012                         return NULL;\r
1013                 SQClosure *c=_closure(ci._closure);\r
1014                 SQFunctionProto *func=c->_function;\r
1015                 if(func->_noutervalues > (SQInteger)idx) {\r
1016                         v->Push(*_outer(c->_outervalues[idx])->_valptr);\r
1017                         return _stringval(func->_outervalues[idx]._name);\r
1018                 }\r
1019                 idx -= func->_noutervalues;\r
1020                 return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-1);\r
1021         }\r
1022         return NULL;\r
1023 }\r
1024 \r
1025 void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj)\r
1026 {\r
1027         v->Push(SQObjectPtr(obj));\r
1028 }\r
1029 \r
1030 void sq_resetobject(HSQOBJECT *po)\r
1031 {\r
1032         po->_unVal.pUserPointer=NULL;po->_type=OT_NULL;\r
1033 }\r
1034 \r
1035 SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err)\r
1036 {\r
1037         v->_lasterror=SQString::Create(_ss(v),err);\r
1038         return SQ_ERROR;\r
1039 }\r
1040 \r
1041 SQRESULT sq_throwobject(HSQUIRRELVM v)\r
1042 {\r
1043         v->_lasterror = v->GetUp(-1);\r
1044         v->Pop();\r
1045         return SQ_ERROR;\r
1046 }\r
1047 \r
1048 \r
1049 void sq_reseterror(HSQUIRRELVM v)\r
1050 {\r
1051         v->_lasterror.Null();\r
1052 }\r
1053 \r
1054 void sq_getlasterror(HSQUIRRELVM v)\r
1055 {\r
1056         v->Push(v->_lasterror);\r
1057 }\r
1058 \r
1059 SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize)\r
1060 {\r
1061         if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) {\r
1062                 if(v->_nmetamethodscall) {\r
1063                         return sq_throwerror(v,_SC("cannot resize stack while in  a metamethod"));\r
1064                 }\r
1065                 v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size()));\r
1066         }\r
1067         return SQ_OK;\r
1068 }\r
1069 \r
1070 SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror)\r
1071 {\r
1072         if(type(v->GetUp(-1))==OT_GENERATOR){\r
1073                 v->PushNull(); //retval\r
1074                 if(!v->Execute(v->GetUp(-2),0,v->_top,v->GetUp(-1),raiseerror,SQVM::ET_RESUME_GENERATOR))\r
1075                 {v->Raise_Error(v->_lasterror); return SQ_ERROR;}\r
1076                 if(!retval)\r
1077                         v->Pop();\r
1078                 return SQ_OK;\r
1079         }\r
1080         return sq_throwerror(v,_SC("only generators can be resumed"));\r
1081 }\r
1082 \r
1083 SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror)\r
1084 {\r
1085         SQObjectPtr res;\r
1086         if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){\r
1087 \r
1088                 if(!v->_suspended) {\r
1089                         v->Pop(params);//pop closure and args\r
1090                 }\r
1091                 if(retval){\r
1092                         v->Push(res); return SQ_OK;\r
1093                 }\r
1094                 return SQ_OK;\r
1095         }\r
1096         else {\r
1097                 v->Pop(params);\r
1098                 return SQ_ERROR;\r
1099         }\r
1100         if(!v->_suspended)\r
1101                 v->Pop(params);\r
1102         return sq_throwerror(v,_SC("call failed"));\r
1103 }\r
1104 \r
1105 SQRESULT sq_suspendvm(HSQUIRRELVM v)\r
1106 {\r
1107         return v->Suspend();\r
1108 }\r
1109 \r
1110 SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval,SQBool raiseerror,SQBool throwerror)\r
1111 {\r
1112         SQObjectPtr ret;\r
1113         if(!v->_suspended)\r
1114                 return sq_throwerror(v,_SC("cannot resume a vm that is not running any code"));\r
1115         SQInteger target = v->_suspended_target;\r
1116         if(wakeupret) {\r
1117                 if(target != -1) {\r
1118                         v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval\r
1119                 }\r
1120                 v->Pop();\r
1121         } else if(target != -1) { v->GetAt(v->_stackbase+v->_suspended_target).Null(); }\r
1122         SQObjectPtr dummy;\r
1123         if(!v->Execute(dummy,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM)) {\r
1124                 return SQ_ERROR;\r
1125         }\r
1126         if(retval)\r
1127                 v->Push(ret);\r
1128         return SQ_OK;\r
1129 }\r
1130 \r
1131 void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook)\r
1132 {\r
1133         if(sq_gettop(v) >= 1){\r
1134                 SQObjectPtr &ud=stack_get(v,idx);\r
1135                 switch( type(ud) ) {\r
1136                 case OT_USERDATA:       _userdata(ud)->_hook = hook;    break;\r
1137                 case OT_INSTANCE:       _instance(ud)->_hook = hook;    break;\r
1138                 case OT_CLASS:          _class(ud)->_hook = hook;               break;\r
1139                 default: break; //shutup compiler\r
1140                 }\r
1141         }\r
1142 }\r
1143 \r
1144 void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f)\r
1145 {\r
1146         _ss(v)->_compilererrorhandler = f;\r
1147 }\r
1148 \r
1149 SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)\r
1150 {\r
1151         SQObjectPtr *o = NULL;\r
1152         _GETSAFE_OBJ(v, -1, OT_CLOSURE,o);\r
1153         unsigned short tag = SQ_BYTECODE_STREAM_TAG;\r
1154         if(_closure(*o)->_function->_noutervalues) \r
1155                 return sq_throwerror(v,_SC("a closure with free valiables bound it cannot be serialized"));\r
1156         if(w(up,&tag,2) != 2)\r
1157                 return sq_throwerror(v,_SC("io error"));\r
1158         if(!_closure(*o)->Save(v,up,w))\r
1159                 return SQ_ERROR;\r
1160         return SQ_OK;\r
1161 }\r
1162 \r
1163 SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)\r
1164 {\r
1165         SQObjectPtr closure;\r
1166         \r
1167         unsigned short tag;\r
1168         if(r(up,&tag,2) != 2)\r
1169                 return sq_throwerror(v,_SC("io error"));\r
1170         if(tag != SQ_BYTECODE_STREAM_TAG)\r
1171                 return sq_throwerror(v,_SC("invalid stream"));\r
1172         if(!SQClosure::Load(v,up,r,closure))\r
1173                 return SQ_ERROR;\r
1174         v->Push(closure);\r
1175         return SQ_OK;\r
1176 }\r
1177 \r
1178 SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)\r
1179 {\r
1180         return _ss(v)->GetScratchPad(minsize);\r
1181 }\r
1182 \r
1183 SQRESULT sq_resurrectunreachable(HSQUIRRELVM v)\r
1184 {\r
1185 #ifndef NO_GARBAGE_COLLECTOR\r
1186         _ss(v)->ResurrectUnreachable(v);\r
1187         return SQ_OK;\r
1188 #else\r
1189         return sq_throwerror(v,_SC("sq_resurrectunreachable requires a garbage collector build"));\r
1190 #endif\r
1191 }\r
1192 \r
1193 SQInteger sq_collectgarbage(HSQUIRRELVM v)\r
1194 {\r
1195 #ifndef NO_GARBAGE_COLLECTOR\r
1196         return _ss(v)->CollectGarbage(v);\r
1197 #else\r
1198         return -1;\r
1199 #endif\r
1200 }\r
1201 \r
1202 SQRESULT sq_getcallee(HSQUIRRELVM v)\r
1203 {\r
1204         if(v->_callsstacksize > 1)\r
1205         {\r
1206                 v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);\r
1207                 return SQ_OK;\r
1208         }\r
1209         return sq_throwerror(v,_SC("no closure in the calls stack"));\r
1210 }\r
1211 \r
1212 const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)\r
1213 {\r
1214         SQObjectPtr &self=stack_get(v,idx);\r
1215         const SQChar *name = NULL;\r
1216         switch(type(self))\r
1217         {\r
1218         case OT_CLOSURE:{\r
1219                 SQClosure *clo = _closure(self);\r
1220                 SQFunctionProto *fp = clo->_function;\r
1221                 if(((SQUnsignedInteger)fp->_noutervalues) > nval) {\r
1222                         v->Push(*(_outer(clo->_outervalues[nval])->_valptr));\r
1223                         SQOuterVar &ov = fp->_outervalues[nval];\r
1224                         name = _stringval(ov._name);\r
1225                 }\r
1226                                         }\r
1227                 break;\r
1228         case OT_NATIVECLOSURE:{\r
1229                 SQNativeClosure *clo = _nativeclosure(self);\r
1230                 if(clo->_noutervalues > nval) {\r
1231                         v->Push(clo->_outervalues[nval]);\r
1232                         name = _SC("@NATIVE");\r
1233                 }\r
1234                                                   }\r
1235                 break;\r
1236         default: break; //shutup compiler\r
1237         }\r
1238         return name;\r
1239 }\r
1240 \r
1241 SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)\r
1242 {\r
1243         SQObjectPtr &self=stack_get(v,idx);\r
1244         switch(type(self))\r
1245         {\r
1246         case OT_CLOSURE:{\r
1247                 SQFunctionProto *fp = _closure(self)->_function;\r
1248                 if(((SQUnsignedInteger)fp->_noutervalues) > nval){\r
1249                         *(_outer(_closure(self)->_outervalues[nval])->_valptr) = stack_get(v,-1);\r
1250                 }\r
1251                 else return sq_throwerror(v,_SC("invalid free var index"));\r
1252                                         }\r
1253                 break;\r
1254         case OT_NATIVECLOSURE:\r
1255                 if(_nativeclosure(self)->_noutervalues > nval){\r
1256                         _nativeclosure(self)->_outervalues[nval] = stack_get(v,-1);\r
1257                 }\r
1258                 else return sq_throwerror(v,_SC("invalid free var index"));\r
1259                 break;\r
1260         default:\r
1261                 return sq_aux_invalidtype(v,type(self));\r
1262         }\r
1263         v->Pop();\r
1264         return SQ_OK;\r
1265 }\r
1266 \r
1267 SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx)\r
1268 {\r
1269         SQObjectPtr *o = NULL;\r
1270         _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
1271         SQObjectPtr &key = stack_get(v,-2);\r
1272         SQObjectPtr &val = stack_get(v,-1);\r
1273         SQObjectPtr attrs;\r
1274         if(type(key) == OT_NULL) {\r
1275                 attrs = _class(*o)->_attributes;\r
1276                 _class(*o)->_attributes = val;\r
1277                 v->Pop(2);\r
1278                 v->Push(attrs);\r
1279                 return SQ_OK;\r
1280         }else if(_class(*o)->GetAttributes(key,attrs)) {\r
1281                 _class(*o)->SetAttributes(key,val);\r
1282                 v->Pop(2);\r
1283                 v->Push(attrs);\r
1284                 return SQ_OK;\r
1285         }\r
1286         return sq_throwerror(v,_SC("wrong index"));\r
1287 }\r
1288 \r
1289 SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx)\r
1290 {\r
1291         SQObjectPtr *o = NULL;\r
1292         _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
1293         SQObjectPtr &key = stack_get(v,-1);\r
1294         SQObjectPtr attrs;\r
1295         if(type(key) == OT_NULL) {\r
1296                 attrs = _class(*o)->_attributes;\r
1297                 v->Pop();\r
1298                 v->Push(attrs); \r
1299                 return SQ_OK;\r
1300         }\r
1301         else if(_class(*o)->GetAttributes(key,attrs)) {\r
1302                 v->Pop();\r
1303                 v->Push(attrs);\r
1304                 return SQ_OK;\r
1305         }\r
1306         return sq_throwerror(v,_SC("wrong index"));\r
1307 }\r
1308 \r
1309 SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle)\r
1310 {\r
1311         SQObjectPtr *o = NULL;\r
1312         _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
1313         SQObjectPtr &key = stack_get(v,-1);\r
1314         SQTable *m = _class(*o)->_members;\r
1315         SQObjectPtr val;\r
1316         if(m->Get(key,val)) {\r
1317                 handle->_static = _isfield(val) ? SQFalse : SQTrue;\r
1318                 handle->_index = _member_idx(val);\r
1319                 v->Pop();\r
1320                 return SQ_OK;\r
1321         }\r
1322         return sq_throwerror(v,_SC("wrong index"));\r
1323 }\r
1324 \r
1325 SQRESULT _getmemberbyhandle(HSQUIRRELVM v,SQObjectPtr &self,const HSQMEMBERHANDLE *handle,SQObjectPtr *&val)\r
1326 {\r
1327         switch(type(self)) {\r
1328                 case OT_INSTANCE: {\r
1329                                 SQInstance *i = _instance(self);\r
1330                                 if(handle->_static) {\r
1331                                         SQClass *c = i->_class;\r
1332                                         val = &c->_methods[handle->_index].val;\r
1333                                 }\r
1334                                 else {\r
1335                                         val = &i->_values[handle->_index];\r
1336                                         \r
1337                                 }\r
1338                         }\r
1339                         break;\r
1340                 case OT_CLASS: {\r
1341                                 SQClass *c = _class(self);\r
1342                                 if(handle->_static) {\r
1343                                         val = &c->_methods[handle->_index].val;\r
1344                                 }\r
1345                                 else {\r
1346                                         val = &c->_defaultvalues[handle->_index].val;\r
1347                                 }\r
1348                         }\r
1349                         break;\r
1350                 default:\r
1351                         return sq_throwerror(v,_SC("wrong type(expected class or instance)"));\r
1352         }\r
1353         return SQ_OK;\r
1354 }\r
1355 \r
1356 SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle)\r
1357 {\r
1358         SQObjectPtr &self = stack_get(v,idx);\r
1359         SQObjectPtr *val = NULL;\r
1360         if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) {\r
1361                 return SQ_ERROR;\r
1362         }\r
1363         v->Push(_realval(*val));\r
1364         return SQ_OK;\r
1365 }\r
1366 \r
1367 SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle)\r
1368 {\r
1369         SQObjectPtr &self = stack_get(v,idx);\r
1370         SQObjectPtr &newval = stack_get(v,-1);\r
1371         SQObjectPtr *val = NULL;\r
1372         if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) {\r
1373                 return SQ_ERROR;\r
1374         }\r
1375         *val = newval;\r
1376         v->Pop();\r
1377         return SQ_OK;\r
1378 }\r
1379 \r
1380 SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx)\r
1381 {\r
1382         SQObjectPtr *o = NULL;\r
1383         _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
1384         if(_class(*o)->_base)\r
1385                 v->Push(SQObjectPtr(_class(*o)->_base));\r
1386         else\r
1387                 v->PushNull();\r
1388         return SQ_OK;\r
1389 }\r
1390 \r
1391 SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx)\r
1392 {\r
1393         SQObjectPtr *o = NULL;\r
1394         _GETSAFE_OBJ(v, idx, OT_INSTANCE,o);\r
1395         v->Push(SQObjectPtr(_instance(*o)->_class));\r
1396         return SQ_OK;\r
1397 }\r
1398 \r
1399 SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx)\r
1400 {\r
1401         SQObjectPtr *o = NULL;\r
1402         _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
1403         v->Push(_class(*o)->CreateInstance());\r
1404         return SQ_OK;\r
1405 }\r
1406 \r
1407 void sq_weakref(HSQUIRRELVM v,SQInteger idx)\r
1408 {\r
1409         SQObject &o=stack_get(v,idx);\r
1410         if(ISREFCOUNTED(type(o))) {\r
1411                 v->Push(_refcounted(o)->GetWeakRef(type(o)));\r
1412                 return;\r
1413         }\r
1414         v->Push(o);\r
1415 }\r
1416 \r
1417 SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx)\r
1418 {\r
1419         SQObjectPtr &o = stack_get(v,idx);\r
1420         if(type(o) != OT_WEAKREF) {\r
1421                 return sq_throwerror(v,_SC("the object must be a weakref"));\r
1422         }\r
1423         v->Push(_weakref(o)->_obj);\r
1424         return SQ_OK;\r
1425 }\r
1426 \r
1427 SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t)\r
1428 {\r
1429         SQSharedState *ss = _ss(v);\r
1430         switch(t) {\r
1431         case OT_TABLE: v->Push(ss->_table_default_delegate); break;\r
1432         case OT_ARRAY: v->Push(ss->_array_default_delegate); break;\r
1433         case OT_STRING: v->Push(ss->_string_default_delegate); break;\r
1434         case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break;\r
1435         case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break;\r
1436         case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break;\r
1437         case OT_THREAD: v->Push(ss->_thread_default_delegate); break;\r
1438         case OT_CLASS: v->Push(ss->_class_default_delegate); break;\r
1439         case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break;\r
1440         case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break;\r
1441         default: return sq_throwerror(v,_SC("the type doesn't have a default delegate"));\r
1442         }\r
1443         return SQ_OK;\r
1444 }\r
1445 \r
1446 SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx)\r
1447 {\r
1448         SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val;\r
1449         if(type(o) == OT_GENERATOR) {\r
1450                 return sq_throwerror(v,_SC("cannot iterate a generator"));\r
1451         }\r
1452         int faketojump;\r
1453         if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump))\r
1454                 return SQ_ERROR;\r
1455         if(faketojump != 666) {\r
1456                 v->Push(realkey);\r
1457                 v->Push(val);\r
1458                 return SQ_OK;\r
1459         }\r
1460         return SQ_ERROR;\r
1461 }\r
1462 \r
1463 struct BufState{\r
1464         const SQChar *buf;\r
1465         SQInteger ptr;\r
1466         SQInteger size;\r
1467 };\r
1468 \r
1469 SQInteger buf_lexfeed(SQUserPointer file)\r
1470 {\r
1471         BufState *buf=(BufState*)file;\r
1472         if(buf->size<(buf->ptr+1))\r
1473                 return 0;\r
1474         return buf->buf[buf->ptr++];\r
1475 }\r
1476 \r
1477 SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror) {\r
1478         BufState buf;\r
1479         buf.buf = s;\r
1480         buf.size = size;\r
1481         buf.ptr = 0;\r
1482         return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror);\r
1483 }\r
1484 \r
1485 void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx)\r
1486 {\r
1487         dest->Push(stack_get(src,idx));\r
1488 }\r
1489 \r
1490 void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc)\r
1491 {\r
1492         _ss(v)->_printfunc = printfunc;\r
1493         _ss(v)->_errorfunc = errfunc;\r
1494 }\r
1495 \r
1496 SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)\r
1497 {\r
1498         return _ss(v)->_printfunc;\r
1499 }\r
1500 \r
1501 SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v)\r
1502 {\r
1503         return _ss(v)->_errorfunc;\r
1504 }\r
1505 \r
1506 void *sq_malloc(SQUnsignedInteger size)\r
1507 {\r
1508         return SQ_MALLOC(size);\r
1509 }\r
1510 \r
1511 void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize)\r
1512 {\r
1513         return SQ_REALLOC(p,oldsize,newsize);\r
1514 }\r
1515 \r
1516 void sq_free(void *p,SQUnsignedInteger size)\r
1517 {\r
1518         SQ_FREE(p,size);\r
1519 }\r