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