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