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 bool sq_resumeerror(HSQUIRRELVM v)
01014 {
01015   SQObjectPtr ret;
01016   v->_can_suspend = true;
01017   v->_ops_till_suspend = 1;
01018   return v->Execute(_null_, v->_top, -1, -1, ret, SQTrue, SQVM::ET_RESUME_THROW_VM);
01019 }
01020 
01021 void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook)
01022 {
01023   if(sq_gettop(v) >= 1){
01024     SQObjectPtr &ud=stack_get(v,idx);
01025     switch( type(ud) ) {
01026     case OT_USERDATA: _userdata(ud)->_hook = hook;  break;
01027     case OT_INSTANCE: _instance(ud)->_hook = hook;  break;
01028     case OT_CLASS:    _class(ud)->_hook = hook;   break;
01029     default: break; //shutup compiler
01030     }
01031   }
01032 }
01033 
01034 void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f)
01035 {
01036   _ss(v)->_compilererrorhandler = f;
01037 }
01038 
01039 SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)
01040 {
01041   SQObjectPtr *o = NULL;
01042   _GETSAFE_OBJ(v, -1, OT_CLOSURE,o);
01043   unsigned short tag = SQ_BYTECODE_STREAM_TAG;
01044   if(w(up,&tag,2) != 2)
01045     return sq_throwerror(v,_SC("io error"));
01046   if(!_closure(*o)->Save(v,up,w))
01047     return SQ_ERROR;
01048   return SQ_OK;
01049 }
01050 
01051 SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)
01052 {
01053   SQObjectPtr closure;
01054 
01055   unsigned short tag;
01056   if(r(up,&tag,2) != 2)
01057     return sq_throwerror(v,_SC("io error"));
01058   if(tag != SQ_BYTECODE_STREAM_TAG)
01059     return sq_throwerror(v,_SC("invalid stream"));
01060   if(!SQClosure::Load(v,up,r,closure))
01061     return SQ_ERROR;
01062   v->Push(closure);
01063   return SQ_OK;
01064 }
01065 
01066 SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)
01067 {
01068   return _ss(v)->GetScratchPad(minsize);
01069 }
01070 
01071 SQInteger sq_collectgarbage(HSQUIRRELVM v)
01072 {
01073 #ifndef NO_GARBAGE_COLLECTOR
01074   return _ss(v)->CollectGarbage(v);
01075 #else
01076   return -1;
01077 #endif
01078 }
01079 
01080 const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
01081 {
01082   SQObjectPtr &self = stack_get(v,idx);
01083   const SQChar *name = NULL;
01084   if(type(self) == OT_CLOSURE) {
01085     if(_closure(self)->_outervalues.size()>nval) {
01086       v->Push(_closure(self)->_outervalues[nval]);
01087       SQFunctionProto *fp = _funcproto(_closure(self)->_function);
01088       SQOuterVar &ov = fp->_outervalues[nval];
01089       name = _stringval(ov._name);
01090     }
01091   }
01092   return name;
01093 }
01094 
01095 SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
01096 {
01097   SQObjectPtr &self=stack_get(v,idx);
01098   switch(type(self))
01099   {
01100   case OT_CLOSURE:
01101     if(_closure(self)->_outervalues.size()>nval){
01102       _closure(self)->_outervalues[nval]=stack_get(v,-1);
01103     }
01104     else return sq_throwerror(v,_SC("invalid free var index"));
01105     break;
01106   case OT_NATIVECLOSURE:
01107     if(_nativeclosure(self)->_outervalues.size()>nval){
01108       _nativeclosure(self)->_outervalues[nval]=stack_get(v,-1);
01109     }
01110     else return sq_throwerror(v,_SC("invalid free var index"));
01111     break;
01112   default:
01113     return sq_aux_invalidtype(v,type(self));
01114   }
01115   v->Pop(1);
01116   return SQ_OK;
01117 }
01118 
01119 SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx)
01120 {
01121   SQObjectPtr *o = NULL;
01122   _GETSAFE_OBJ(v, idx, OT_CLASS,o);
01123   SQObjectPtr &key = stack_get(v,-2);
01124   SQObjectPtr &val = stack_get(v,-1);
01125   SQObjectPtr attrs;
01126   if(type(key) == OT_NULL) {
01127     attrs = _class(*o)->_attributes;
01128     _class(*o)->_attributes = val;
01129     v->Pop(2);
01130     v->Push(attrs);
01131     return SQ_OK;
01132   }else if(_class(*o)->GetAttributes(key,attrs)) {
01133     _class(*o)->SetAttributes(key,val);
01134     v->Pop(2);
01135     v->Push(attrs);
01136     return SQ_OK;
01137   }
01138   return sq_throwerror(v,_SC("wrong index"));
01139 }
01140 
01141 SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx)
01142 {
01143   SQObjectPtr *o = NULL;
01144   _GETSAFE_OBJ(v, idx, OT_CLASS,o);
01145   SQObjectPtr &key = stack_get(v,-1);
01146   SQObjectPtr attrs;
01147   if(type(key) == OT_NULL) {
01148     attrs = _class(*o)->_attributes;
01149     v->Pop();
01150     v->Push(attrs);
01151     return SQ_OK;
01152   }
01153   else if(_class(*o)->GetAttributes(key,attrs)) {
01154     v->Pop();
01155     v->Push(attrs);
01156     return SQ_OK;
01157   }
01158   return sq_throwerror(v,_SC("wrong index"));
01159 }
01160 
01161 SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx)
01162 {
01163   SQObjectPtr *o = NULL;
01164   _GETSAFE_OBJ(v, idx, OT_CLASS,o);
01165   if(_class(*o)->_base)
01166     v->Push(SQObjectPtr(_class(*o)->_base));
01167   else
01168     v->Push(_null_);
01169   return SQ_OK;
01170 }
01171 
01172 SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx)
01173 {
01174   SQObjectPtr *o = NULL;
01175   _GETSAFE_OBJ(v, idx, OT_INSTANCE,o);
01176   v->Push(SQObjectPtr(_instance(*o)->_class));
01177   return SQ_OK;
01178 }
01179 
01180 SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx)
01181 {
01182   SQObjectPtr *o = NULL;
01183   _GETSAFE_OBJ(v, idx, OT_CLASS,o);
01184   v->Push(_class(*o)->CreateInstance());
01185   return SQ_OK;
01186 }
01187 
01188 void sq_weakref(HSQUIRRELVM v,SQInteger idx)
01189 {
01190   SQObject &o=stack_get(v,idx);
01191   if(ISREFCOUNTED(type(o))) {
01192     v->Push(_refcounted(o)->GetWeakRef(type(o)));
01193     return;
01194   }
01195   v->Push(o);
01196 }
01197 
01198 SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx)
01199 {
01200   SQObjectPtr &o = stack_get(v,idx);
01201   if(type(o) != OT_WEAKREF) {
01202     return sq_throwerror(v,_SC("the object must be a weakref"));
01203   }
01204   v->Push(_weakref(o)->_obj);
01205   return SQ_OK;
01206 }
01207 
01208 SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t)
01209 {
01210   SQSharedState *ss = _ss(v);
01211   switch(t) {
01212   case OT_TABLE: v->Push(ss->_table_default_delegate); break;
01213   case OT_ARRAY: v->Push(ss->_array_default_delegate); break;
01214   case OT_STRING: v->Push(ss->_string_default_delegate); break;
01215   case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break;
01216   case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break;
01217   case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break;
01218   case OT_THREAD: v->Push(ss->_thread_default_delegate); break;
01219   case OT_CLASS: v->Push(ss->_class_default_delegate); break;
01220   case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break;
01221   case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break;
01222   default: return sq_throwerror(v,_SC("the type doesn't have a default delegate"));
01223   }
01224   return SQ_OK;
01225 }
01226 
01227 SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx)
01228 {
01229   SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val;
01230   if(type(o) == OT_GENERATOR) {
01231     return sq_throwerror(v,_SC("cannot iterate a generator"));
01232   }
01233   int faketojump;
01234   if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump))
01235     return SQ_ERROR;
01236   if(faketojump != 666) {
01237     v->Push(realkey);
01238     v->Push(val);
01239     return SQ_OK;
01240   }
01241   return SQ_ERROR;
01242 }
01243 
01244 struct BufState{
01245   const SQChar *buf;
01246   SQInteger ptr;
01247   SQInteger size;
01248 };
01249 
01250 SQInteger buf_lexfeed(SQUserPointer file)
01251 {
01252   BufState *buf=(BufState*)file;
01253   if(buf->size<(buf->ptr+1))
01254     return 0;
01255   return buf->buf[buf->ptr++];
01256 }
01257 
01258 SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror) {
01259   BufState buf;
01260   buf.buf = s;
01261   buf.size = size;
01262   buf.ptr = 0;
01263   return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror);
01264 }
01265 
01266 void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx)
01267 {
01268   dest->Push(stack_get(src,idx));
01269 }
01270 
01271 void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc)
01272 {
01273   _ss(v)->_printfunc = printfunc;
01274 }
01275 
01276 SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)
01277 {
01278   return _ss(v)->_printfunc;
01279 }
01280 
01281 void *sq_malloc(SQUnsignedInteger size)
01282 {
01283   return SQ_MALLOC(size);
01284 }
01285 
01286 void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize)
01287 {
01288   return SQ_REALLOC(p,oldsize,newsize);
01289 }
01290 
01291 void sq_free(void *p,SQUnsignedInteger size)
01292 {
01293   SQ_FREE(p,size);
01294 }
01295 

Generated on Thu Oct 1 11:03:10 2009 for OpenTTD by  doxygen 1.5.6