Johan Wikman / SQUIRREL3

Dependents:   Squirrel

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sqapi.cpp Source File

sqapi.cpp

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