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