bool Squirrel::CallMethod(HSQOBJECT instance, const char *method_name, HSQOBJECT *ret, int suspend) { assert(!this->crashed); /* Store the stack-location for the return value. We need to * restore this after saving or the stack will be corrupted * if we're in the middle of a DoCommand. */ SQInteger last_target = this->vm->_suspended_target; /* Store the current top */ int top = sq_gettop(this->vm); /* Go to the instance-root */ sq_pushobject(this->vm, instance); /* Find the function-name inside the script */ sq_pushstring(this->vm, OTTD2SQ(method_name), -1); if (SQ_FAILED(sq_get(this->vm, -2))) { DEBUG(misc, 0, "[squirrel] Could not find '%s' in the class", method_name); sq_settop(this->vm, top); return false; } /* Call the method */ sq_pushobject(this->vm, instance); if (SQ_FAILED(sq_call(this->vm, 1, ret == NULL ? SQFalse : SQTrue, SQTrue, suspend))) return false; if (ret != NULL) sq_getstackobj(vm, -1, ret); /* Reset the top, but don't do so for the AI main function, as we need * a correct stack when resuming. */ if (suspend == -1 || !this->IsSuspended()) sq_settop(this->vm, top); /* Restore the return-value location. */ this->vm->_suspended_target = last_target; return true; }
void SQDbgServer::SerializeState() { sq_pushnull(_v); sq_setdebughook(_v); sq_pushnull(_v); sq_seterrorhandler(_v); const SQChar *sz; sq_pushobject(_v,_serializefunc); sq_pushobject(_v,_debugroot); sq_pushstring(_v,_SC("watches"),-1); sq_newtable(_v); for(WatchSetItor i=_watches.begin(); i!=_watches.end(); ++i) { sq_pushinteger(_v,i->_id); sq_pushstring(_v,i->_exp.c_str(),(int)i->_exp.length()); sq_createslot(_v,-3); } sq_rawset(_v,-3); if(SQ_SUCCEEDED(sq_call(_v,1,SQTrue,SQTrue))){ if(SQ_SUCCEEDED(sqstd_getblob(_v,-1,(SQUserPointer*)&sz))) SendChunk(sz); } sq_pop(_v,2); SetErrorHandlers(); }
void SquirrelThread::initThread(HSQUIRRELVM parentVm) { m_oldTop = -1; m_parentVm = parentVm; createThread(); // create a local environment for the m_thread HSQOBJECT env; sq_resetobject(&env); sq_newtable(m_thread); // store the object in env if(sq_getstackobj(m_thread, -1, &env) < 0) { return; } sq_addref(m_thread, &env); sq_pop(m_thread, 1); // remove env from stack // set old roottable as delegate on env sq_pushobject(m_thread, env); // push env sq_pushroottable(m_thread); // [env, root] sq_setdelegate(m_thread, -2); // env.set_delegate(root) sq_pop(m_thread, 1); // pop env // set env as new roottable sq_pushobject(m_thread, env); sq_setroottable(m_thread); sq_release(m_thread, &env); }
BOOL SquirrelVM::BeginCall(const SquirrelObject &func,SquirrelObject &_this) { if(_CallState != -1) throw SquirrelError(_VM,_SC("call already initialized")); _CallState = 1; sq_pushobject(_VM,func._o); sq_pushobject(_VM,_this._o); return TRUE; }
void SquirrelObject::Append(const SquirrelObject &o) { if(sq_isarray(_o)) { sq_pushobject(m_Vm.GetVMPtr(),_o); sq_pushobject(m_Vm.GetVMPtr(),o._o); sq_arrayappend(m_Vm.GetVMPtr(),-2); sq_pop(m_Vm.GetVMPtr(),1); } }
// ------------------------------------------------------------------------------------------------ SQInteger Signal::SqEmit(HSQUIRRELVM vm) { const Int32 top = sq_gettop(vm); // The signal instance Signal * signal = nullptr; // Attempt to extract the signal instance try { signal = Var< Signal * >(vm, 1).value; } catch (const Sqrat::Exception & e) { return sq_throwerror(vm, e.what()); } // Do we have a valid signal instance? if (!signal) { return sq_throwerror(vm, "Invalid signal instance"); } // Walk down the chain and trigger slots for (Slot * node = signal->m_Head, * next = nullptr; node != nullptr; node = next) { // Grab the next node upfront next = node->mNext; // Remember the current stack size const StackGuard sg(vm); // Push the callback object sq_pushobject(vm, node->mFuncRef); // Is there an explicit environment? if (sq_isnull(node->mEnvRef)) { sq_pushroottable(vm); } else { sq_pushobject(vm, node->mEnvRef); } // Are there any parameters to forward? if (top > 1) { for (SQInteger i = 2; i <= top; ++i) { sq_push(vm, i); } } // Make the function call and store the result const SQRESULT res = sq_call(vm, top, false, ErrorHandling::IsEnabled()); // Validate the result if (SQ_FAILED(res)) { return res; // Propagate the error } } // Specify that we don't return anything return 0; }
BOOL SquirrelObject::SetValue(const SquirrelObject &key,const SquirrelObject &val) { BOOL ret = FALSE; int top = sq_gettop(m_Vm.GetVMPtr()); sq_pushobject(m_Vm.GetVMPtr(),_o); sq_pushobject(m_Vm.GetVMPtr(),key._o); sq_pushobject(m_Vm.GetVMPtr(),val._o); if(SQ_SUCCEEDED(sq_rawset(m_Vm.GetVMPtr(),-3))) { ret = TRUE; } sq_settop(m_Vm.GetVMPtr(),top); return ret; }
inline SQInteger DefSQNonStaticCallback(HSQUIRRELVM vm) { /* Find the amount of params we got */ int nparam = sq_gettop(vm); SQUserPointer ptr = NULL; SQUserPointer real_instance = NULL; HSQOBJECT instance; /* Get the 'SQ' instance of this class */ Squirrel::GetInstance(vm, &instance); /* Protect against calls to a non-static method in a static way */ sq_pushroottable(vm); sq_pushstring(vm, OTTD2SQ(Tcls::GetClassName()), -1); sq_get(vm, -2); sq_pushobject(vm, instance); if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, _SC("class method is non-static")); sq_pop(vm, 3); /* Get the 'real' instance of this class */ sq_getinstanceup(vm, 1, &real_instance, 0); /* Get the real function pointer */ sq_getuserdata(vm, nparam, &ptr, 0); if (real_instance == NULL) return sq_throwerror(vm, _SC("couldn't detect real instance of class for non-static call")); /* Remove the userdata from the stack */ sq_pop(vm, 1); try { /* Delegate it to a template that can handle this specific function */ return HelperT<Tmethod>::SQCall((Tcls *)real_instance, *(Tmethod *)ptr, vm); } catch (SQInteger e) { sq_pop(vm, nparam); return e; } }
template <> inline Array *GetParam(ForceType<Array *>, HSQUIRRELVM vm, int index, SQAutoFreePointers *ptr) { SQObject obj; sq_getstackobj(vm, index, &obj); sq_pushobject(vm, obj); sq_pushnull(vm); SmallVector<int32, 2> data; while (SQ_SUCCEEDED(sq_next(vm, -2))) { SQInteger tmp; if (SQ_SUCCEEDED(sq_getinteger(vm, -1, &tmp))) { *data.Append() = (int32)tmp; } else { sq_pop(vm, 4); throw sq_throwerror(vm, _SC("a member of an array used as parameter to a function is not numeric")); } sq_pop(vm, 2); } sq_pop(vm, 2); Array *arr = (Array*)MallocT<byte>(sizeof(Array) + sizeof(int32) * data.Length()); arr->size = data.Length(); memcpy(arr->array, data.Begin(), sizeof(int32) * data.Length()); *ptr->Append() = arr; return arr; }
void ThreadQueue::wakeup() { // we traverse the list in reverse orders and use indices. This should be // robust for scripts that add new entries to the list while we're traversing // it size_t i = threads.size() - 1; size_t end = static_cast<size_t>(0 - 1); size_t size_begin = threads.size(); while(i != end) { HSQOBJECT object = threads[i]; sq_pushobject(global_vm, object); sq_getweakrefval(global_vm, -1); HSQUIRRELVM scheduled_vm; if(sq_gettype(global_vm, -1) == OT_THREAD && SQ_SUCCEEDED(sq_getthread(global_vm, -1, &scheduled_vm))) { if(SQ_FAILED(sq_wakeupvm(scheduled_vm, SQFalse, SQFalse, SQTrue, SQFalse))) { log_warning << "Couldn't wakeup scheduled squirrel VM" << std::endl; } } sq_release(global_vm, &object); sq_pop(global_vm, 1); i--; } threads.erase(threads.begin(), threads.begin() + size_begin); }
BOOL SquirrelObject::SetDelegate(SquirrelObject &obj) { if(obj.GetType() == OT_TABLE || obj.GetType() == OT_NULL) { switch(_o._type) { case OT_USERDATA: case OT_TABLE: sq_pushobject(m_Vm.GetVMPtr(),_o); sq_pushobject(m_Vm.GetVMPtr(),obj._o); if(SQ_SUCCEEDED(sq_setdelegate(m_Vm.GetVMPtr(),-2))) return TRUE; break; } } return FALSE; }
inline SQInteger DefSQAdvancedNonStaticCallback(HSQUIRRELVM vm) { /* Find the amount of params we got */ int nparam = sq_gettop(vm); SQUserPointer ptr = NULL; SQUserPointer real_instance = NULL; HSQOBJECT instance; /* Get the 'SQ' instance of this class */ Squirrel::GetInstance(vm, &instance); /* Protect against calls to a non-static method in a static way */ sq_pushroottable(vm); sq_pushstring(vm, OTTD2SQ(Tcls::GetClassName()), -1); sq_get(vm, -2); sq_pushobject(vm, instance); if (sq_instanceof(vm) != SQTrue) return sq_throwerror(vm, _SC("class method is non-static")); sq_pop(vm, 3); /* Get the 'real' instance of this class */ sq_getinstanceup(vm, 1, &real_instance, 0); /* Get the real function pointer */ sq_getuserdata(vm, nparam, &ptr, 0); if (real_instance == NULL) return sq_throwerror(vm, _SC("couldn't detect real instance of class for non-static call")); /* Remove the userdata from the stack */ sq_pop(vm, 1); /* Call the function, which its only param is always the VM */ return (SQInteger)(((Tcls *)real_instance)->*(*(Tmethod *)ptr))(vm); }
void TimeScheduler::update(float time) { while(!schedule.empty() && schedule.front().wakeup_time < time) { HSQOBJECT thread_ref = schedule.front().thread_ref; sq_pushobject(global_vm, thread_ref); sq_getweakrefval(global_vm, -1); HSQUIRRELVM scheduled_vm; if(sq_gettype(global_vm, -1) == OT_THREAD && SQ_SUCCEEDED(sq_getthread(global_vm, -1, &scheduled_vm))) { if(SQ_FAILED(sq_wakeupvm(scheduled_vm, SQFalse, SQFalse, SQTrue, SQFalse))) { std::ostringstream msg; msg << "Error waking VM: "; sq_getlasterror(scheduled_vm); if(sq_gettype(scheduled_vm, -1) != OT_STRING) { msg << "(no info)"; } else { const char* lasterr; sq_getstring(scheduled_vm, -1, &lasterr); msg << lasterr; } log_warning << msg.str() << std::endl; sq_pop(scheduled_vm, 1); } } sq_release(global_vm, &thread_ref); sq_pop(global_vm, 2); std::pop_heap(schedule.begin(), schedule.end()); schedule.pop_back(); } }
void CScripts::Call(const char * szFunc, int iArgCount, SQObjectPtr * pArguments) { for(int i = 0; i < MAX_SCRIPTS; i++) { if(m_pScripts[i]) { // get the script vm pointer SQVM * pVM = m_pScripts[i]->GetVM(); // Get the stack top int iTop = sq_gettop(pVM); // Push the root table onto the stack sq_pushroottable(pVM); // Push the function name onto the stack sq_pushstring(pVM, szFunc, -1); if(SQ_SUCCEEDED(sq_get(pVM, -2))) { // Push the root table onto the stack sq_pushroottable(pVM); if(pArguments != NULL) { for(int j = 0; j < iArgCount; ++j) sq_pushobject(pVM, pArguments[j]); //pVM->Push(pArguments[j]); } sq_call(pVM, iArgCount + 1, true, true); } // Restore the stack top sq_settop(pVM, iTop); } } }
bool ScriptObject::setInstanceUp(SQUserPointer up) { MCD_ASSERT(sq_isinstance(mObj)); sq_pushobject(mSqvm, mObj); sq_setinstanceup(mSqvm, -1, up); sq_poptop(mSqvm); return true; }
SQUserPointer SquirrelObject::GetInstanceUP(unsigned int tag) //const { SQUserPointer up = NULL; sq_pushobject(m_Vm.GetVMPtr(),_o); sq_getinstanceup(m_Vm.GetVMPtr(),-1,(SQUserPointer*)&up,(SQUserPointer)tag); sq_pop(m_Vm.GetVMPtr(),1); return up; }
BOOL SquirrelObject::SetInstanceUP(SQUserPointer up) { if(!sq_isinstance(_o)) return FALSE; sq_pushobject(m_Vm.GetVMPtr(),_o); sq_setinstanceup(m_Vm.GetVMPtr(),-1,up); sq_pop(m_Vm.GetVMPtr(),1); return TRUE; }
// // Transport.Position class // SQInteger TransportPositionPush(HSQUIRRELVM vm, TimePosition *obj) { sq_pushobject(vm, TransportPositionObject); sq_createinstance(vm, -1); sq_remove(vm, -2); sq_setinstanceup(vm, -1, new TimePosition(*obj)); sq_setreleasehook(vm, -1, &TransportPositionRelease); }
void ScriptBehavior::Start() { if( !m_initialize || !m_haveStart ) { return; } int top = sq_gettop(m_vm); sq_pushobject(m_vm, m_instance); sq_pushobject(m_vm, m_startFunction); sq_push( m_vm,-2 ); sq_call( m_vm,1,SQFalse,SQTrue ); sq_settop( m_vm,top ); }
SQUserPointer ScriptObject::getInstanceUp(SQUserPointer tag) const { SQUserPointer up = 0; sq_pushobject(mSqvm, mObj); sq_getinstanceup(mSqvm, -1, (SQUserPointer*)&up, tag); sq_poptop(mSqvm); return up; }
BOOL SquirrelObject::BeginIteration() { if(!sq_istable(_o) && !sq_isarray(_o) && !sq_isclass(_o)) return FALSE; sq_pushobject(m_Vm.GetVMPtr(),_o); sq_pushnull(m_Vm.GetVMPtr()); return TRUE; }
SQInteger register_member_func(HSQUIRRELVM& v,SQFUNCTION f,const char *fname,HSQOBJECT id) { sq_pushobject(v,id); sq_pushstring(v,fname,-1); sq_newclosure(v,f,0); sq_newslot(v,-3,SQFalse); sq_pop(v,1); }
SQInteger ScriptText::_SetParam(int parameter, HSQUIRRELVM vm) { if (parameter >= SCRIPT_TEXT_MAX_PARAMETERS) return SQ_ERROR; free(this->params[parameter]); if (this->paramt[parameter] != NULL) this->paramt[parameter]->Release(); this->parami[parameter] = 0; this->params[parameter] = NULL; this->paramt[parameter] = NULL; switch (sq_gettype(vm, -1)) { case OT_STRING: { const SQChar *value; sq_getstring(vm, -1, &value); this->params[parameter] = strdup(SQ2OTTD(value)); break; } case OT_INTEGER: { SQInteger value; sq_getinteger(vm, -1, &value); this->parami[parameter] = value; break; } case OT_INSTANCE: { SQUserPointer real_instance = NULL; HSQOBJECT instance; sq_getstackobj(vm, -1, &instance); /* Validate if it is a GSText instance */ sq_pushroottable(vm); sq_pushstring(vm, _SC("GSText"), -1); sq_get(vm, -2); sq_pushobject(vm, instance); if (sq_instanceof(vm) != SQTrue) return SQ_ERROR; sq_pop(vm, 3); /* Get the 'real' instance of this class */ sq_getinstanceup(vm, -1, &real_instance, 0); if (real_instance == NULL) return SQ_ERROR; ScriptText *value = static_cast<ScriptText *>(real_instance); value->AddRef(); this->paramt[parameter] = value; break; } default: return SQ_ERROR; } if (this->paramc <= parameter) this->paramc = parameter + 1; return 0; }
BOOL SquirrelVM::BeginCall(const SquirrelObject &func) { if(_CallState != -1) return FALSE; _CallState = 1; sq_pushobject(_VM,func._o); sq_pushroottable(_VM); return TRUE; }
int SquirrelObject::Len() /*const*/ { int ret = 0; if(sq_isarray(_o) || sq_istable(_o) || sq_isstring(_o)) { sq_pushobject(m_Vm.GetVMPtr(),_o); ret = sq_getsize(m_Vm.GetVMPtr(),-1); sq_pop(m_Vm.GetVMPtr(),1); } return ret; }
BOOL SquirrelObject::GetSlot(int key) /*const*/ { sq_pushobject(m_Vm.GetVMPtr(),_o); sq_pushinteger(m_Vm.GetVMPtr(),key); if(SQ_SUCCEEDED(sq_get(m_Vm.GetVMPtr(),-2))) { return TRUE; } return FALSE; }
BOOL SquirrelObject::GetSlot(const SQChar *name) /*const*/ { sq_pushobject(m_Vm.GetVMPtr(),_o); sq_pushstring(m_Vm.GetVMPtr(),name,-1); if(SQ_SUCCEEDED(sq_get(m_Vm.GetVMPtr(),-2))) { return TRUE; } return FALSE; }
SquirrelObject SquirrelVM::RunScript(const SquirrelObject &o,SquirrelObject *_this) { SquirrelObject ret(_VM); sq_pushobject(_VM,o._o); if(_this) { sq_pushobject(_VM,_this->_o); } else { sq_pushroottable(_VM); } if(SQ_SUCCEEDED(sq_call(_VM,1,1,1))) { ret.AttachToStackObject(-1); sq_pop(_VM,1); return ret; } sq_pop(_VM,1); throw SquirrelError(_VM); }
void loadVariablePath(HSQUIRRELVM vm, const std::vector<std::string>& path) { for (const std::string& i : path) { sq_pushstring(vm, i.c_str(), i.size()); CSQ(sq_get(vm, -2)); } HSQOBJECT h; CSQ(sq_getstackobj(vm, -1, &h)); sq_pop(vm, path.size() - 1); sq_pushobject(vm, h); }
SquirrelObject SquirrelObject::GetDelegate() { SquirrelObject ret; if(_o._type == OT_TABLE || _o._type == OT_USERDATA) { sq_pushobject(m_Vm.GetVMPtr(),_o); sq_getdelegate(m_Vm.GetVMPtr(),-1); ret.AttachToStackObject(-1); sq_pop(m_Vm.GetVMPtr(),2); } return ret; }