# sqapi.cpp

    00001 /*
    00002   see copyright notice in squirrel.h
    00003 */
    00004 #include <squirrel.h>
    00005 #include "sqpcheader.h"
    00006 #include "sqvm.h"
    00007 #include "sqstring.h"
    00008 #include "sqtable.h"
    00009 #include "sqarray.h"
    00010 #include "sqfuncproto.h"
    00011 #include "sqclosure.h"
    00012 #include "squserdata.h"
    00013 #include "sqcompiler.h"
    00014 #include "sqfuncstate.h"
    00015 #include "sqclass.h"
    00016
    00017 bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPtr **o)
    00018 {
    00019   *o = &stack_get(v,idx);
    00020   if(type(**o) != type){
    00021     SQObjectPtr oval = v->PrintObjVal(**o);
    00022     v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval));
    00023     return false;
    00024   }
    00025   return true;
    00026 }
    00027
    00028 #define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; }
    00029
    00030 #define sq_aux_paramscheck(v,count) \
    00031 { \
    00032   if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\
    00033 }
    00034
    00035 SQInteger sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e)
    00036 {
    00037   v->_lasterror = e;
    00038   return SQ_ERROR;
    00039 }
    00040
    00041 SQInteger sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type)
    00042 {
    00043   scsprintf(_ss(v)->GetScratchPad(100), _SC("unexpected type %s"), IdType2Name(type));
    00044   return sq_throwerror(v, _ss(v)->GetScratchPad(-1));
    00045 }
    00046
    00047 HSQUIRRELVM sq_open(SQInteger initialstacksize)
    00048 {
    00049   SQSharedState *ss;
    00050   SQVM *v;
    00051   sq_new(ss, SQSharedState);
    00052   ss->Init();
    00053   v = (SQVM *)SQ_MALLOC(sizeof(SQVM));
    00054   new (v) SQVM(ss);
    00055   ss->_root_vm = v;
    00056   if(v->Init(NULL, initialstacksize)) {
    00057     return v;
    00058   } else {
    00059     sq_delete(v, SQVM);
    00060     return NULL;
    00061   }
    00062   return v;
    00063 }
    00064
    00065 HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize)
    00066 {
    00067   SQSharedState *ss;
    00068   SQVM *v;
    00069   ss=_ss(friendvm);
    00070
    00071   v= (SQVM *)SQ_MALLOC(sizeof(SQVM));
    00072   new (v) SQVM(ss);
    00073
    00074   if(v->Init(friendvm, initialstacksize)) {
    00075     friendvm->Push(v);
    00076     return v;
    00077   } else {
    00078     sq_delete(v, SQVM);
    00079     return NULL;
    00080   }
    00081 }
    00082
    00083 SQInteger sq_getvmstate(HSQUIRRELVM v)
    00084 {
    00085   if(v->_suspended)
    00086     return SQ_VMSTATE_SUSPENDED;
    00087   else {
    00088     if(v->_callsstacksize != 0) return SQ_VMSTATE_RUNNING;
    00089     else return SQ_VMSTATE_IDLE;
    00090   }
    00091 }
    00092
    00093 void sq_seterrorhandler(HSQUIRRELVM v)
    00094 {
    00095   SQObject o = stack_get(v, -1);
    00096   if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
    00097     v->_errorhandler = o;
    00098     v->Pop();
    00099   }
    00100 }
    00101
    00102 void sq_setdebughook(HSQUIRRELVM v)
    00103 {
    00104   SQObject o = stack_get(v,-1);
    00105   if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
    00106     v->_debughook = o;
    00107     v->Pop();
    00108   }
    00109 }
    00110
    00111 void sq_close(HSQUIRRELVM v)
    00112 {
    00113   SQSharedState *ss = _ss(v);
    00114   _thread(ss->_root_vm)->Finalize();
    00115   sq_delete(ss, SQSharedState);
    00116 }
    00117
    00118 SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror)
    00119 {
    00120   SQObjectPtr o;
    00121   if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) {
    00122     v->Push(SQClosure::Create(_ss(v), _funcproto(o)));
    00123     return SQ_OK;
    00124   }
    00125   return SQ_ERROR;
    00126 }
    00127
    00128 void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable)
    00129 {
    00130   _ss(v)->_debuginfo = enable?true:false;
    00131 }
    00132
    00133 void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable)
    00134 {
    00135   _ss(v)->_notifyallexceptions = enable?true:false;
    00136 }
    00137
    00138 void sq_addref(HSQUIRRELVM v,HSQOBJECT *po)
    00139 {
    00140   if(!ISREFCOUNTED(type(*po))) return;
    00141 #ifdef NO_GARBAGE_COLLECTOR
    00142   __AddRef(po->_type,po->_unVal);
    00143 #else
    00144   _ss(v)->_refs_table.AddRef(*po);
    00145 #endif
    00146 }
    00147
    00148 SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)
    00149 {
    00150   if(!ISREFCOUNTED(type(*po))) return SQTrue;
    00151 #ifdef NO_GARBAGE_COLLECTOR
    00152   __Release(po->_type,po->_unVal);
    00153   return SQFalse; //the ret val doesn't work(and cannot be fixed)
    00154 #else
    00155   return _ss(v)->_refs_table.Release(*po);
    00156 #endif
    00157 }
    00158
    00159 const SQChar *sq_objtostring(HSQOBJECT *o)
    00160 {
    00161   if(sq_type(*o) == OT_STRING) {
    00162     return _stringval(*o);
    00163   }
    00164   return NULL;
    00165 }
    00166
    00167 SQInteger sq_objtointeger(HSQOBJECT *o)
    00168 {
    00169   if(sq_isnumeric(*o)) {
    00170     return tointeger(*o);
    00171   }
    00172   return 0;
    00173 }
    00174
    00175 SQFloat sq_objtofloat(HSQOBJECT *o)
    00176 {
    00177   if(sq_isnumeric(*o)) {
    00178     return tofloat(*o);
    00179   }
    00180   return 0;
    00181 }
    00182
    00183 SQBool sq_objtobool(HSQOBJECT *o)
    00184 {
    00185   if(sq_isbool(*o)) {
    00186     return _integer(*o);
    00187   }
    00188   return SQFalse;
    00189 }
    00190
    00191 void sq_pushnull(HSQUIRRELVM v)
    00192 {
    00193   v->Push(_null_);
    00194 }
    00195
    00196 void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len)
    00197 {
    00198   if(s)
    00199     v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len)));
    00200   else v->Push(_null_);
    00201 }
    00202
    00203 void sq_pushinteger(HSQUIRRELVM v,SQInteger n)
    00204 {
    00205   v->Push(n);
    00206 }
    00207
    00208 void sq_pushbool(HSQUIRRELVM v,SQBool b)
    00209 {
    00210   v->Push(b?true:false);
    00211 }
    00212
    00213 void sq_pushfloat(HSQUIRRELVM v,SQFloat n)
    00214 {
    00215   v->Push(n);
    00216 }
    00217
    00218 void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p)
    00219 {
    00220   v->Push(p);
    00221 }
    00222
    00223 SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size)
    00224 {
    00225   SQUserData *ud = SQUserData::Create(_ss(v), size);
    00226   v->Push(ud);
    00227   return ud->_val;
    00228 }
    00229
    00230 void sq_newtable(HSQUIRRELVM v)
    00231 {
    00232   v->Push(SQTable::Create(_ss(v), 0));
    00233 }
    00234
    00235 void sq_newarray(HSQUIRRELVM v,SQInteger size)
    00236 {
    00237   v->Push(SQArray::Create(_ss(v), size));
    00238 }
    00239
    00240 SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase)
    00241 {
    00242   SQClass *baseclass = NULL;
    00243   if(hasbase) {
    00244     SQObjectPtr &base = stack_get(v,-1);
    00245     if(type(base) != OT_CLASS)
    00246       return sq_throwerror(v,_SC("invalid base type"));
    00247     baseclass = _class(base);
    00248   }
    00249   SQClass *newclass = SQClass::Create(_ss(v), baseclass);
    00250   if(baseclass) v->Pop();
    00251   v->Push(newclass);
    00252   return SQ_OK;
    00253 }
    00254
    00255 SQBool sq_instanceof(HSQUIRRELVM v)
    00256 {
    00257   SQObjectPtr &inst = stack_get(v,-1);
    00258   SQObjectPtr &cl = stack_get(v,-2);
    00259   if(type(inst) != OT_INSTANCE || type(cl) != OT_CLASS)
    00260     return sq_throwerror(v,_SC("invalid param type"));
    00261   return _instance(inst)->InstanceOf(_class(cl))?SQTrue:SQFalse;
    00262 }
    00263
    00264 SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx)
    00265 {
    00266   sq_aux_paramscheck(v,2);
    00267   SQObjectPtr *arr;
    00268   _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
    00269   _array(*arr)->Append(v->GetUp(-1));
    00270   v->Pop(1);
    00271   return SQ_OK;
    00272 }
    00273
    00274 SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
    00275 {
    00276   sq_aux_paramscheck(v, 1);
    00277   SQObjectPtr *arr;
    00278   _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
    00279   if(_array(*arr)->Size() > 0) {
    00280         if(pushval != 0){ v->Push(_array(*arr)->Top()); }
    00281     _array(*arr)->Pop();
    00282     return SQ_OK;
    00283   }
    00284   return sq_throwerror(v, _SC("empty array"));
    00285 }
    00286
    00287 SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize)
    00288 {
    00289   sq_aux_paramscheck(v,1);
    00290   SQObjectPtr *arr;
    00291   _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
    00292   if(newsize >= 0) {
    00293     _array(*arr)->Resize(newsize);
    00294     return SQ_OK;
    00295   }
    00296   return sq_throwerror(v,_SC("negative size"));
    00297 }
    00298
    00299
    00300 SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx)
    00301 {
    00302   sq_aux_paramscheck(v, 1);
    00303   SQObjectPtr *o;
    00304   _GETSAFE_OBJ(v, idx, OT_ARRAY,o);
    00305   SQArray *arr = _array(*o);
    00306   if(arr->Size() > 0) {
    00307     SQObjectPtr t;
    00308     SQInteger size = arr->Size();
    00309     SQInteger n = size >> 1; size -= 1;
    00310     for(SQInteger i = 0; i < n; i++) {
    00311       t = arr->_values[i];
    00312       arr->_values[i] = arr->_values[size-i];
    00313       arr->_values[size-i] = t;
    00314     }
    00315     return SQ_OK;
    00316   }
    00317   return SQ_OK;
    00318 }
    00319
    00320 SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx)
    00321 {
    00322   sq_aux_paramscheck(v, 1);
    00323   SQObjectPtr *arr;
    00324   _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
    00325   return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));
    00326 }
    00327
    00328 SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos)
    00329 {
    00330   sq_aux_paramscheck(v, 1);
    00331   SQObjectPtr *arr;
    00332   _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
    00333   SQRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));
    00334   v->Pop();
    00335   return ret;
    00336 }
    00337
    00338
    00339 void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars)
    00340 {
    00341   SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func);
    00342   nc->_nparamscheck = 0;
    00343   for(SQUnsignedInteger i = 0; i < nfreevars; i++) {
    00344     nc->_outervalues.push_back(v->Top());
    00345     v->Pop();
    00346   }
    00347   v->Push(SQObjectPtr(nc));
    00348 }
    00349
    00350 SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars)
    00351 {
    00352   SQObject o = stack_get(v, idx);
    00353   if(sq_isclosure(o)) {
    00354     SQClosure *c = _closure(o);
    00355     SQFunctionProto *proto = _funcproto(c->_function);
    00356     *nparams = (SQUnsignedInteger)proto->_nparameters;
    00357         *nfreevars = (SQUnsignedInteger)c->_outervalues.size();
    00358     return SQ_OK;
    00359   }
    00360   return sq_throwerror(v,_SC("the object is not a closure"));
    00361 }
    00362
    00363 SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name)
    00364 {
    00365   SQObject o = stack_get(v, idx);
    00366   if(sq_isnativeclosure(o)) {
    00367     SQNativeClosure *nc = _nativeclosure(o);
    00368     nc->_name = SQString::Create(_ss(v),name);
    00369     return SQ_OK;
    00370   }
    00371   return sq_throwerror(v,_SC("the object is not a nativeclosure"));
    00372 }
    00373
    00374 SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask)
    00375 {
    00376   SQObject o = stack_get(v, -1);
    00377   if(!sq_isnativeclosure(o))
    00378     return sq_throwerror(v, _SC("native closure expected"));
    00379   SQNativeClosure *nc = _nativeclosure(o);
    00380   nc->_nparamscheck = nparamscheck;
    00381   if(typemask) {
    00382     SQIntVec res;
    00383     if(!CompileTypemask(res, typemask))
    00384       return sq_throwerror(v, _SC("invalid typemask"));
    00385     nc->_typecheck.copy(res);
    00386   }
    00387   else {
    00388     nc->_typecheck.resize(0);
    00389   }
    00390   if(nparamscheck == SQ_MATCHTYPEMASKSTRING) {
    00391     nc->_nparamscheck = nc->_typecheck.size();
    00392   }
    00393   return SQ_OK;
    00394 }
    00395
    00396 SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)
    00397 {
    00398   SQObjectPtr &o = stack_get(v,idx);
    00399   if(!sq_isnativeclosure(o) &&
    00400     !sq_isclosure(o))
    00401     return sq_throwerror(v,_SC("the target is not a closure"));
    00402     SQObjectPtr &env = stack_get(v,-1);
    00403   if(!sq_istable(env) &&
    00404     !sq_isclass(env) &&
    00405     !sq_isinstance(env))
    00406     return sq_throwerror(v,_SC("invalid environment"));
    00407   SQObjectPtr w = _refcounted(env)->GetWeakRef(type(env));
    00408   SQObjectPtr ret;
    00409   if(sq_isclosure(o)) {
    00410     SQClosure *c = _closure(o)->Clone();
    00411     c->_env = w;
    00412     ret = c;
    00413   }
    00414   else { //then must be a native closure
    00415     SQNativeClosure *c = _nativeclosure(o)->Clone();
    00416     c->_env = w;
    00417     ret = c;
    00418   }
    00419   v->Pop();
    00420   v->Push(ret);
    00421   return SQ_OK;
    00422 }
    00423
    00424 SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx)
    00425 {
    00426   SQObject &o=stack_get(v,idx);
    00427   switch(type(o)) {
    00428     case OT_TABLE: _table(o)->Clear();  break;
    00429     case OT_ARRAY: _array(o)->Resize(0); break;
    00430     default:
    00431       return sq_throwerror(v, _SC("clear only works on table and array"));
    00432     break;
    00433
    00434   }
    00435   return SQ_OK;
    00436 }
    00437
    00438 void sq_pushroottable(HSQUIRRELVM v)
    00439 {
    00440   v->Push(v->_roottable);
    00441 }
    00442
    00443 void sq_pushregistrytable(HSQUIRRELVM v)
    00444 {
    00445   v->Push(_ss(v)->_registry);
    00446 }
    00447
    00448 void sq_pushconsttable(HSQUIRRELVM v)
    00449 {
    00450   v->Push(_ss(v)->_consts);
    00451 }
    00452
    00453 SQRESULT sq_setroottable(HSQUIRRELVM v)
    00454 {
    00455   SQObject o = stack_get(v, -1);
    00456   if(sq_istable(o) || sq_isnull(o)) {
    00457     v->_roottable = o;
    00458     v->Pop();
    00459     return SQ_OK;
    00460   }
    00461   return sq_throwerror(v, _SC("ivalid type"));
    00462 }
    00463
    00464 SQRESULT sq_setconsttable(HSQUIRRELVM v)
    00465 {
    00466   SQObject o = stack_get(v, -1);
    00467   if(sq_istable(o)) {
    00468     _ss(v)->_consts = o;
    00469     v->Pop();
    00470     return SQ_OK;
    00471   }
    00472   return sq_throwerror(v, _SC("ivalid type, expected table"));
    00473 }
    00474
    00475 void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p)
    00476 {
    00477   v->_foreignptr = p;
    00478 }
    00479
    00480 SQUserPointer sq_getforeignptr(HSQUIRRELVM v)
    00481 {
    00482   return v->_foreignptr;
    00483 }
    00484
    00485 void sq_push(HSQUIRRELVM v,SQInteger idx)
    00486 {
    00487   v->Push(stack_get(v, idx));
    00488 }
    00489
    00490 SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx)
    00491 {
    00492   return type(stack_get(v, idx));
    00493 }
    00494
    00495
    00496 void sq_tostring(HSQUIRRELVM v,SQInteger idx)
    00497 {
    00498   SQObjectPtr &o = stack_get(v, idx);
    00499   SQObjectPtr res;
    00500   v->ToString(o,res);
    00501   v->Push(res);
    00502 }
    00503
    00504 void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b)
    00505 {
    00506   SQObjectPtr &o = stack_get(v, idx);
    00507   *b = v->IsFalse(o)?SQFalse:SQTrue;
    00508 }
    00509
    00510 SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i)
    00511 {
    00512   SQObjectPtr &o = stack_get(v, idx);
    00513   if(sq_isnumeric(o)) {
    00514     *i = tointeger(o);
    00515     return SQ_OK;
    00516   }
    00517   return SQ_ERROR;
    00518 }
    00519
    00520 SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f)
    00521 {
    00522   SQObjectPtr &o = stack_get(v, idx);
    00523   if(sq_isnumeric(o)) {
    00524     *f = tofloat(o);
    00525     return SQ_OK;
    00526   }
    00527   return SQ_ERROR;
    00528 }
    00529
    00530 SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b)
    00531 {
    00532   SQObjectPtr &o = stack_get(v, idx);
    00533   if(sq_isbool(o)) {
    00534     *b = _integer(o);
    00535     return SQ_OK;
    00536   }
    00537   return SQ_ERROR;
    00538 }
    00539
    00540 SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c)
    00541 {
    00542   SQObjectPtr *o = NULL;
    00543   _GETSAFE_OBJ(v, idx, OT_STRING,o);
    00544   *c = _stringval(*o);
    00545   return SQ_OK;
    00546 }
    00547
    00548 SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread)
    00549 {
    00550   SQObjectPtr *o = NULL;
    00551   _GETSAFE_OBJ(v, idx, OT_THREAD,o);
    00552   *thread = _thread(*o);
    00553   return SQ_OK;
    00554 }
    00555
    00556 SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx)
    00557 {
    00558   SQObjectPtr &o = stack_get(v,idx);
    00559   v->Push(_null_);
    00560   if(!v->Clone(o, stack_get(v, -1))){
    00561     v->Pop();
    00562     return sq_aux_invalidtype(v, type(o));
    00563   }
    00564   return SQ_OK;
    00565 }
    00566
    00567 SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx)
    00568 {
    00569   SQObjectPtr &o = stack_get(v, idx);
    00570   SQObjectType type = type(o);
    00571   switch(type) {
    00572   case OT_STRING:   return _string(o)->_len;
    00573   case OT_TABLE:    return _table(o)->CountUsed();
    00574   case OT_ARRAY:    return _array(o)->Size();
    00575   case OT_USERDATA: return _userdata(o)->_size;
    00576   default:
    00577     return sq_aux_invalidtype(v, type);
    00578   }
    00579 }
    00580
    00581 SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag)
    00582 {
    00583   SQObjectPtr *o = NULL;
    00584   _GETSAFE_OBJ(v, idx, OT_USERDATA,o);
    00585   (*p) = _userdataval(*o);
    00586   if(typetag) *typetag = _userdata(*o)->_typetag;
    00587   return SQ_OK;
    00588 }
    00589
    00590 SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag)
    00591 {
    00592   SQObjectPtr &o = stack_get(v,idx);
    00593   switch(type(o)) {
    00594     case OT_USERDATA: _userdata(o)->_typetag = typetag; break;
    00595     case OT_CLASS:    _class(o)->_typetag = typetag;    break;
    00596     default:      return sq_throwerror(v,_SC("invalid object type"));
    00597   }
    00598   return SQ_OK;
    00599 }
    00600
    00601 SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag)
    00602 {
    00603   switch(type(*o)) {
    00604     case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break;
    00605     case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break;
    00606     case OT_CLASS:    *typetag = _class(*o)->_typetag; break;
    00607     default: return SQ_ERROR;
    00608   }
    00609   return SQ_OK;
    00610 }
    00611
    00612 SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag)
    00613 {
    00614   SQObjectPtr &o = stack_get(v,idx);
    00615   if(SQ_FAILED(sq_getobjtypetag(&o,typetag)))
    00616     return sq_throwerror(v,_SC("invalid object type"));
    00617   return SQ_OK;
    00618 }
    00619
    00620 SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p)
    00621 {
    00622   SQObjectPtr *o = NULL;
    00623   _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o);
    00624   (*p) = _userpointer(*o);
    00625   return SQ_OK;
    00626 }
    00627
    00628 SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p)
    00629 {
    00630   SQObjectPtr &o = stack_get(v,idx);
    00631   if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));
    00632   _instance(o)->_userpointer = p;
    00633   return SQ_OK;
    00634 }
    00635
    00636 SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize)
    00637 {
    00638   SQObjectPtr &o = stack_get(v,idx);
    00639   if(type(o) != OT_CLASS) return sq_throwerror(v,_SC("the object is not a class"));
    00640   if(_class(o)->_locked) return sq_throwerror(v,_SC("the class is locked"));
    00641   _class(o)->_udsize = udsize;
    00642   return SQ_OK;
    00643 }
    00644
    00645
    00646 SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag)
    00647 {
    00648   SQObjectPtr &o = stack_get(v,idx);
    00649   if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));
    00650   (*p) = _instance(o)->_userpointer;
    00651   if(typetag != 0) {
    00652     SQClass *cl = _instance(o)->_class;
    00653     do{
    00654       if(cl->_typetag == typetag)
    00655         return SQ_OK;
    00656       cl = cl->_base;
    00657     }while(cl != NULL);
    00658     return sq_throwerror(v,_SC("invalid type tag"));
    00659   }
    00660   return SQ_OK;
    00661 }
    00662
    00663 SQInteger sq_gettop(HSQUIRRELVM v)
    00664 {
    00665   return (v->_top) - v->_stackbase;
    00666 }
    00667
    00668 void sq_settop(HSQUIRRELVM v, SQInteger newtop)
    00669 {
    00670   SQInteger top = sq_gettop(v);
    00671   if(top > newtop)
    00672     sq_pop(v, top - newtop);
    00673   else
    00674     while(top++ < newtop) sq_pushnull(v);
    00675 }
    00676
    00677 void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop)
    00678 {
    00679   assert(v->_top >= nelemstopop);
    00680   v->Pop(nelemstopop);
    00681 }
    00682
    00683 void sq_poptop(HSQUIRRELVM v)
    00684 {
    00685   assert(v->_top >= 1);
    00686     v->Pop();
    00687 }
    00688
    00689
    00690 void sq_remove(HSQUIRRELVM v, SQInteger idx)
    00691 {
    00692   v->Remove(idx);
    00693 }
    00694
    00695 SQInteger sq_cmp(HSQUIRRELVM v)
    00696 {
    00697   SQInteger res;
    00698   v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res);
    00699   return res;
    00700 }
    00701
    00702 SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic)
    00703 {
    00704   sq_aux_paramscheck(v, 3);
    00705   SQObjectPtr &self = stack_get(v, idx);
    00706   if(type(self) == OT_TABLE || type(self) == OT_CLASS) {
    00707     SQObjectPtr &key = v->GetUp(-2);
    00708     if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));
    00709     v->NewSlot(self, key, v->GetUp(-1),bstatic?true:false);
    00710     v->Pop(2);
    00711   }
    00712   return SQ_OK;
    00713 }
    00714
    00715 SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
    00716 {
    00717   sq_aux_paramscheck(v, 2);
    00718   SQObjectPtr *self;
    00719   _GETSAFE_OBJ(v, idx, OT_TABLE,self);
    00720   SQObjectPtr &key = v->GetUp(-1);
    00721   if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));
    00722   SQObjectPtr res;
    00723   if(!v->DeleteSlot(*self, key, res)){
    00724     return SQ_ERROR;
    00725   }
    00726   if(pushval) v->GetUp(-1) = res;
    00727   else v->Pop(1);
    00728   return SQ_OK;
    00729 }
    00730
    00731 SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx)
    00732 {
    00733   SQObjectPtr &self = stack_get(v, idx);
    00734   if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) {
    00735     v->Pop(2);
    00736     return SQ_OK;
    00737   }
    00738   v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;
    00739 }
    00740
    00741 SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx)
    00742 {
    00743   SQObjectPtr &self = stack_get(v, idx);
    00744   if(type(v->GetUp(-2)) == OT_NULL) return sq_throwerror(v, _SC("null key"));
    00745   switch(type(self)) {
    00746   case OT_TABLE:
    00747     _table(self)->NewSlot(v->GetUp(-2), v->GetUp(-1));
    00748     v->Pop(2);
    00749     return SQ_OK;
    00750   break;
    00751   case OT_CLASS:
    00752     _class(self)->NewSlot(_ss(v), v->GetUp(-2), v->GetUp(-1),false);
    00753     v->Pop(2);
    00754     return SQ_OK;
    00755   break;
    00756   case OT_INSTANCE:
    00757     if(_instance(self)->Set(v->GetUp(-2), v->GetUp(-1))) {
    00758       v->Pop(2);
    00759       return SQ_OK;
    00760     }
    00761   break;
    00762   case OT_ARRAY:
    00763     if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) {
    00764       v->Pop(2);
    00765       return SQ_OK;
    00766     }
    00767   break;
    00768   default:
    00769     v->Pop(2);
    00770     return sq_throwerror(v, _SC("rawset works only on array/table/class and instance"));
    00771   }
    00772   v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;
    00773 }
    00774
    00775 SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx)
    00776 {
    00777   SQObjectPtr &self = stack_get(v, idx);
    00778   SQObjectPtr &mt = v->GetUp(-1);
    00779   SQObjectType type = type(self);
    00780   switch(type) {
    00781   case OT_TABLE:
    00782     if(type(mt) == OT_TABLE) {
    00783       if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, _SC("delagate cycle")); v->Pop();}
    00784     else if(type(mt)==OT_NULL) {
    00785       _table(self)->SetDelegate(NULL); v->Pop(); }
    00786     else return sq_aux_invalidtype(v,type);
    00787     break;
    00788   case OT_USERDATA:
    00789     if(type(mt)==OT_TABLE) {
    00790       _userdata(self)->SetDelegate(_table(mt)); v->Pop(); }
    00791     else if(type(mt)==OT_NULL) {
    00792       _userdata(self)->SetDelegate(NULL); v->Pop(); }
    00793     else return sq_aux_invalidtype(v, type);
    00794     break;
    00795   default:
    00796       return sq_aux_invalidtype(v, type);
    00797     break;
    00798   }
    00799   return SQ_OK;
    00800 }
    00801
    00802 SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
    00803 {
    00804   sq_aux_paramscheck(v, 2);
    00805   SQObjectPtr *self;
    00806   _GETSAFE_OBJ(v, idx, OT_TABLE,self);
    00807   SQObjectPtr &key = v->GetUp(-1);
    00808   SQObjectPtr t;
    00809   if(_table(*self)->Get(key,t)) {
    00810     _table(*self)->Remove(key);
    00811   }
    00812   if(pushval != 0) {
    00813     if(pushval) v->GetUp(-1) = t;
    00814   } else {
    00815     v->Pop(1);
    00816   }
    00817   return SQ_OK;
    00818 }
    00819
    00820 SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx)
    00821 {
    00822   SQObjectPtr &self=stack_get(v,idx);
    00823   switch(type(self)){
    00824   case OT_TABLE:
    00825   case OT_USERDATA:
    00826     if(!_delegable(self)->_delegate){
    00827       v->Push(_null_);
    00828       break;
    00829     }
    00830     v->Push(SQObjectPtr(_delegable(self)->_delegate));
    00831     break;
    00832   default: return sq_throwerror(v,_SC("wrong type")); break;
    00833   }
    00834   return SQ_OK;
    00835
    00836 }
    00837
    00838 SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx)
    00839 {
    00840   SQObjectPtr &self=stack_get(v,idx);
    00841   if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false))
    00842     return SQ_OK;
    00843   v->Pop(1);
    00844   return sq_throwerror(v,_SC("the index doesn't exist"));
    00845 }
    00846
    00847 SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx)
    00848 {
    00849   SQObjectPtr &self=stack_get(v,idx);
    00850   switch(type(self)) {
    00851   case OT_TABLE:
    00852     if(_table(self)->Get(v->GetUp(-1),v->GetUp(-1)))
    00853       return SQ_OK;
    00854     break;
    00855   case OT_CLASS:
    00856     if(_class(self)->Get(v->GetUp(-1),v->GetUp(-1)))
    00857       return SQ_OK;
    00858     break;
    00859   case OT_INSTANCE:
    00860     if(_instance(self)->Get(v->GetUp(-1),v->GetUp(-1)))
    00861       return SQ_OK;
    00862     break;
    00863   case OT_ARRAY:
    00864     if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false))
    00865       return SQ_OK;
    00866     break;
    00867   default:
    00868     v->Pop(1);
    00869     return sq_throwerror(v,_SC("rawget works only on array/table/instance and class"));
    00870   }
    00871   v->Pop(1);
    00872   return sq_throwerror(v,_SC("the index doesn't exist"));
    00873 }
    00874
    00875 SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po)
    00876 {
    00877   *po=stack_get(v,idx);
    00878   return SQ_OK;
    00879 }
    00880
    00881 const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx)
    00882 {
    00883   SQUnsignedInteger cstksize=v->_callsstacksize;
    00884   SQUnsignedInteger lvl=(cstksize-level)-1;
    00885   SQInteger stackbase=v->_stackbase;
    00886   if(lvl<cstksize){
    00887     for(SQUnsignedInteger i=0;i<level;i++){
    00888       SQVM::CallInfo &ci=v->_callsstack[(cstksize-i)-1];
    00889       stackbase-=ci._prevstkbase;
    00890     }
    00891     SQVM::CallInfo &ci=v->_callsstack[lvl];
    00892     if(type(ci._closure)!=OT_CLOSURE)
    00893       return NULL;
    00894     SQClosure *c=_closure(ci._closure);
    00895     SQFunctionProto *func=_funcproto(c->_function);
    00896     if(func->_noutervalues > (SQInteger)idx) {
    00897       v->Push(c->_outervalues[idx]);
    00898       return _stringval(func->_outervalues[idx]._name);
    00899     }
    00900     idx -= func->_noutervalues;
    00901     return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-1);
    00902   }
    00903   return NULL;
    00904 }
    00905
    00906 void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj)
    00907 {
    00908   v->Push(SQObjectPtr(obj));
    00909 }
    00910
    00911 void sq_resetobject(HSQOBJECT *po)
    00912 {
    00913   po->_unVal.pUserPointer=NULL;po->_type=OT_NULL;
    00914 }
    00915
    00916 SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err)
    00917 {
    00918   v->_lasterror=SQString::Create(_ss(v),err);
    00919   return -1;
    00920 }
    00921
    00922 void sq_reseterror(HSQUIRRELVM v)
    00923 {
    00924   v->_lasterror = _null_;
    00925 }
    00926
    00927 void sq_getlasterror(HSQUIRRELVM v)
    00928 {
    00929   v->Push(v->_lasterror);
    00930 }
    00931
    00932 void sq_reservestack(HSQUIRRELVM v,SQInteger nsize)
    00933 {
    00934   if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) {
    00935     v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size()));
    00936   }
    00937 }
    00938
    00939 SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror)
    00940 {
    00941   if(type(v->GetUp(-1))==OT_GENERATOR){
    00942     v->Push(_null_); //retval
    00943     v->_can_suspend = false;
    00944     if(!v->Execute(v->GetUp(-2),v->_top,0,v->_top,v->GetUp(-1),raiseerror,SQVM::ET_RESUME_GENERATOR))
    00945     {v->Raise_Error(v->_lasterror); return SQ_ERROR;}
    00946     if(!retval)
    00947       v->Pop();
    00948     return SQ_OK;
    00949   }
    00950   return sq_throwerror(v,_SC("only generators can be resumed"));
    00951 }
    00952
    00953 SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror, int suspend)
    00954 {
    00955   SQObjectPtr res;
    00956   v->_can_suspend = suspend >= 0;
    00957   if (v->_can_suspend) v->_ops_till_suspend = suspend;
    00958
    00959   if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false,v->_can_suspend)){
    00960     if(!v->_suspended) {
    00961       v->Pop(params);//pop closure and args
    00962     }
    00963     if(retval){
    00964       v->Push(res); return SQ_OK;
    00965     }
    00966     return SQ_OK;
    00967   }
    00968   else {
    00969     v->Pop(params);
    00970     return SQ_ERROR;
    00971   }
    00972   if(!v->_suspended)
    00973     v->Pop(params);
    00974   return sq_throwerror(v,_SC("call failed"));
    00975 }
    00976
    00977 SQRESULT sq_suspendvm(HSQUIRRELVM v)
    00978 {
    00979   return v->Suspend();
    00980 }
    00981
    00982 SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval,SQBool raiseerror)
    00983 {
    00984   SQObjectPtr ret;
    00985   if(!v->_suspended)
    00986     return sq_throwerror(v,_SC("cannot resume a vm that is not running any code"));
    00987   if(wakeupret) {
    00988     v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval
    00989     v->Pop();
    00990   } else v->GetAt(v->_stackbase+v->_suspended_target)=_null_;
    00991   v->_can_suspend = false;
    00992   if(!v->Execute(_null_,v->_top,-1,-1,ret,raiseerror,SQVM::ET_RESUME_VM)) {
    00993     return SQ_ERROR;
    00994   }
    00995   if(retval)
    00996     v->Push(ret);
    00997   return SQ_OK;
    00998 }
    00999
    01000 bool sq_resumecatch(HSQUIRRELVM v, int suspend)
    01001 {
    01002   SQObjectPtr ret;
    01003   v->_can_suspend = suspend >= 0;
    01004   if (v->_can_suspend) v->_ops_till_suspend = suspend;
    01005   return v->Execute(_null_, v->_top, -1, -1, ret, SQTrue, SQVM::ET_RESUME_OPENTTD);
    01006 }
    01007
    01008 void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook)
    01009 {
    01010   if(sq_gettop(v) >= 1){
    01011     SQObjectPtr &ud=stack_get(v,idx);
    01012     switch( type(ud) ) {
    01013     case OT_USERDATA: _userdata(ud)->_hook = hook;  break;
    01014     case OT_INSTANCE: _instance(ud)->_hook = hook;  break;
    01015     case OT_CLASS:    _class(ud)->_hook = hook;   break;
    01016     default: break; //shutup compiler
    01017     }
    01018   }
    01019 }
    01020
    01021 void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f)
    01022 {
    01023   _ss(v)->_compilererrorhandler = f;
    01024 }
    01025
    01026 SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)
    01027 {
    01028   SQObjectPtr *o = NULL;
    01029   _GETSAFE_OBJ(v, -1, OT_CLOSURE,o);
    01030   unsigned short tag = SQ_BYTECODE_STREAM_TAG;
    01031   if(w(up,&tag,2) != 2)
    01032     return sq_throwerror(v,_SC("io error"));
    01033   if(!_closure(*o)->Save(v,up,w))
    01034     return SQ_ERROR;
    01035   return SQ_OK;
    01036 }
    01037
    01038 SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)
    01039 {
    01040   SQObjectPtr closure;
    01041
    01042   unsigned short tag;
    01043   if(r(up,&tag,2) != 2)
    01044     return sq_throwerror(v,_SC("io error"));
    01045   if(tag != SQ_BYTECODE_STREAM_TAG)
    01046     return sq_throwerror(v,_SC("invalid stream"));
    01047   if(!SQClosure::Load(v,up,r,closure))
    01048     return SQ_ERROR;
    01049   v->Push(closure);
    01050   return SQ_OK;
    01051 }
    01052
    01053 SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)
    01054 {
    01055   return _ss(v)->GetScratchPad(minsize);
    01056 }
    01057
    01058 SQInteger sq_collectgarbage(HSQUIRRELVM v)
    01059 {
    01060 #ifndef NO_GARBAGE_COLLECTOR
    01061   return _ss(v)->CollectGarbage(v);
    01062 #else
    01063   return -1;
    01064 #endif
    01065 }
    01066
    01067 const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
    01068 {
    01069   SQObjectPtr &self = stack_get(v,idx);
    01070   const SQChar *name = NULL;
    01071   if(type(self) == OT_CLOSURE) {
    01072     if(_closure(self)->_outervalues.size()>nval) {
    01073       v->Push(_closure(self)->_outervalues[nval]);
    01074       SQFunctionProto *fp = _funcproto(_closure(self)->_function);
    01075       SQOuterVar &ov = fp->_outervalues[nval];
    01076       name = _stringval(ov._name);
    01077     }
    01078   }
    01079   return name;
    01080 }
    01081
    01082 SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
    01083 {
    01084   SQObjectPtr &self=stack_get(v,idx);
    01085   switch(type(self))
    01086   {
    01087   case OT_CLOSURE:
    01088     if(_closure(self)->_outervalues.size()>nval){
    01089       _closure(self)->_outervalues[nval]=stack_get(v,-1);
    01090     }
    01091     else return sq_throwerror(v,_SC("invalid free var index"));
    01092     break;
    01093   case OT_NATIVECLOSURE:
    01094     if(_nativeclosure(self)->_outervalues.size()>nval){
    01095       _nativeclosure(self)->_outervalues[nval]=stack_get(v,-1);
    01096     }
    01097     else return sq_throwerror(v,_SC("invalid free var index"));
    01098     break;
    01099   default:
    01100     return sq_aux_invalidtype(v,type(self));
    01101   }
    01102   v->Pop(1);
    01103   return SQ_OK;
    01104 }
    01105
    01106 SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx)
    01107 {
    01108   SQObjectPtr *o = NULL;
    01109   _GETSAFE_OBJ(v, idx, OT_CLASS,o);
    01110   SQObjectPtr &key = stack_get(v,-2);
    01111   SQObjectPtr &val = stack_get(v,-1);
    01112   SQObjectPtr attrs;
    01113   if(type(key) == OT_NULL) {
    01114     attrs = _class(*o)->_attributes;
    01115     _class(*o)->_attributes = val;
    01116     v->Pop(2);
    01117     v->Push(attrs);
    01118     return SQ_OK;
    01119   }else if(_class(*o)->GetAttributes(key,attrs)) {
    01120     _class(*o)->SetAttributes(key,val);
    01121     v->Pop(2);
    01122     v->Push(attrs);
    01123     return SQ_OK;
    01124   }
    01125   return sq_throwerror(v,_SC("wrong index"));
    01126 }
    01127
    01128 SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx)
    01129 {
    01130   SQObjectPtr *o = NULL;
    01131   _GETSAFE_OBJ(v, idx, OT_CLASS,o);
    01132   SQObjectPtr &key = stack_get(v,-1);
    01133   SQObjectPtr attrs;
    01134   if(type(key) == OT_NULL) {
    01135     attrs = _class(*o)->_attributes;
    01136     v->Pop();
    01137     v->Push(attrs);
    01138     return SQ_OK;
    01139   }
    01140   else if(_class(*o)->GetAttributes(key,attrs)) {
    01141     v->Pop();
    01142     v->Push(attrs);
    01143     return SQ_OK;
    01144   }
    01145   return sq_throwerror(v,_SC("wrong index"));
    01146 }
    01147
    01148 SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx)
    01149 {
    01150   SQObjectPtr *o = NULL;
    01151   _GETSAFE_OBJ(v, idx, OT_CLASS,o);
    01152   if(_class(*o)->_base)
    01153     v->Push(SQObjectPtr(_class(*o)->_base));
    01154   else
    01155     v->Push(_null_);
    01156   return SQ_OK;
    01157 }
    01158
    01159 SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx)
    01160 {
    01161   SQObjectPtr *o = NULL;
    01162   _GETSAFE_OBJ(v, idx, OT_INSTANCE,o);
    01163   v->Push(SQObjectPtr(_instance(*o)->_class));
    01164   return SQ_OK;
    01165 }
    01166
    01167 SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx)
    01168 {
    01169   SQObjectPtr *o = NULL;
    01170   _GETSAFE_OBJ(v, idx, OT_CLASS,o);
    01171   v->Push(_class(*o)->CreateInstance());
    01172   return SQ_OK;
    01173 }
    01174
    01175 void sq_weakref(HSQUIRRELVM v,SQInteger idx)
    01176 {
    01177   SQObject &o=stack_get(v,idx);
    01178   if(ISREFCOUNTED(type(o))) {
    01179     v->Push(_refcounted(o)->GetWeakRef(type(o)));
    01180     return;
    01181   }
    01182   v->Push(o);
    01183 }
    01184
    01185 SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx)
    01186 {
    01187   SQObjectPtr &o = stack_get(v,idx);
    01188   if(type(o) != OT_WEAKREF) {
    01189     return sq_throwerror(v,_SC("the object must be a weakref"));
    01190   }
    01191   v->Push(_weakref(o)->_obj);
    01192   return SQ_OK;
    01193 }
    01194
    01195 SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t)
    01196 {
    01197   SQSharedState *ss = _ss(v);
    01198   switch(t) {
    01199   case OT_TABLE: v->Push(ss->_table_default_delegate); break;
    01200   case OT_ARRAY: v->Push(ss->_array_default_delegate); break;
    01201   case OT_STRING: v->Push(ss->_string_default_delegate); break;
    01202   case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break;
    01203   case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break;
    01204   case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break;
    01205   case OT_THREAD: v->Push(ss->_thread_default_delegate); break;
    01206   case OT_CLASS: v->Push(ss->_class_default_delegate); break;
    01207   case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break;
    01208   case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break;
    01209   default: return sq_throwerror(v,_SC("the type doesn't have a default delegate"));
    01210   }
    01211   return SQ_OK;
    01212 }
    01213
    01214 SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx)
    01215 {
    01216   SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val;
    01217   if(type(o) == OT_GENERATOR) {
    01218     return sq_throwerror(v,_SC("cannot iterate a generator"));
    01219   }
    01220   int faketojump;
    01221   if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump))
    01222     return SQ_ERROR;
    01223   if(faketojump != 666) {
    01224     v->Push(realkey);
    01225     v->Push(val);
    01226     return SQ_OK;
    01227   }
    01228   return SQ_ERROR;
    01229 }
    01230
    01231 struct BufState{
    01232   const SQChar *buf;
    01233   SQInteger ptr;
    01234   SQInteger size;
    01235 };
    01236
    01237 SQInteger buf_lexfeed(SQUserPointer file)
    01238 {
    01239   BufState *buf=(BufState*)file;
    01240   if(buf->size<(buf->ptr+1))
    01241     return 0;
    01242   return buf->buf[buf->ptr++];
    01243 }
    01244
    01245 SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror) {
    01246   BufState buf;
    01247   buf.buf = s;
    01248   buf.size = size;
    01249   buf.ptr = 0;
    01250   return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror);
    01251 }
    01252
    01253 void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx)
    01254 {
    01255   dest->Push(stack_get(src,idx));
    01256 }
    01257
    01258 void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc)
    01259 {
    01260   _ss(v)->_printfunc = printfunc;
    01261 }
    01262
    01263 SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)
    01264 {
    01265   return _ss(v)->_printfunc;
    01266 }
    01267
    01268 void *sq_malloc(SQUnsignedInteger size)
    01269 {
    01270   return SQ_MALLOC(size);
    01271 }
    01272
    01273 void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize)
    01274 {
    01275   return SQ_REALLOC(p,oldsize,newsize);
    01276 }
    01277
    01278 void sq_free(void *p,SQUnsignedInteger size)
    01279 {
    01280   SQ_FREE(p,size);
    01281 }
    01282