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); }
static inline void sq_create_delegate_table(HSQUIRRELVM vm, SQRegFunction *methods, HSQOBJECT *handle) { sq_newtable(vm); sq_insert_reg_funcs(vm, methods); sq_resetobject(handle); sq_getstackobj(vm, -1, handle); sq_addref(vm, handle); }
void SquirrelObject::AttachToStackObject(int idx) { HSQOBJECT t; sq_getstackobj(m_Vm.GetVMPtr(),idx,&t); sq_addref(m_Vm.GetVMPtr(),&t); sq_release(m_Vm.GetVMPtr(),&_o); _o = t; }
SquirrelObject & SquirrelObject::operator =(const SquirrelObject &o) { HSQOBJECT t; t = o._o; sq_addref(m_Vm.GetVMPtr(),&t); sq_release(m_Vm.GetVMPtr(),&_o); _o = t; return *this; }
void CSquirrelVM::SetClassInstance(const char* szClassName, void * pInstance) { sq_setinstanceup(m_pVM, 1, (SQUserPointer *) pInstance); sq_setreleasehook(m_pVM, 1, deleteClassInstance); HSQOBJECT instance; sq_resetobject(&instance); sq_getstackobj(m_pVM, 1, &instance); sq_addref(m_pVM, &instance); m_Instances.insert(std::pair<void*, HSQOBJECT>(pInstance, instance)); }
bool SQDbgServer::Init() { //creates an environment table for the debugger sq_newtable(_v); sq_getstackobj(_v,-1,&_debugroot); sq_addref(_v,&_debugroot); //creates a emptyslot to store the watches sq_pushstring(_v,_SC("watches"),-1); sq_pushnull(_v); sq_createslot(_v,-3); sq_pushstring(_v,_SC("beginelement"),-1); sq_pushuserpointer(_v,this); sq_newclosure(_v,beginelement,1); sq_setparamscheck(_v,2,_SC(".s")); sq_createslot(_v,-3); sq_pushstring(_v,_SC("endelement"),-1); sq_pushuserpointer(_v,this); sq_newclosure(_v,endelement,1); sq_setparamscheck(_v,2,_SC(".s")); sq_createslot(_v,-3); sq_pushstring(_v,_SC("attribute"),-1); sq_pushuserpointer(_v,this); sq_newclosure(_v,attribute,1); sq_setparamscheck(_v,3,_SC(".ss")); sq_createslot(_v,-3); sq_pop(_v,1); //stores debug hook and error handler in the registry sq_pushregistrytable(_v); sq_pushstring(_v,SQDBG_DEBUG_HOOK,-1); sq_pushuserpointer(_v,this); sq_newclosure(_v,debug_hook,1); sq_createslot(_v,-3); sq_pushstring(_v,SQDBG_ERROR_HANDLER,-1); sq_pushuserpointer(_v,this); sq_newclosure(_v,error_handler,1); sq_createslot(_v,-3); sq_pop(_v,1); //sets the error handlers SetErrorHandlers(); return true; }
HSQOBJECT create_thread(HSQUIRRELVM vm) { HSQUIRRELVM new_vm = sq_newthread(vm, 64); if(new_vm == NULL) throw SquirrelError(vm, "Couldn't create new VM"); HSQOBJECT vm_object; sq_resetobject(&vm_object); if(SQ_FAILED(sq_getstackobj(vm, -1, &vm_object))) throw SquirrelError(vm, "Couldn't get squirrel thread from stack"); sq_addref(vm, &vm_object); sq_pop(vm, 1); return vm_object; }
void ThreadQueue::add(HSQUIRRELVM vm) { // create a weakref to the VM HSQOBJECT vm_obj = vm_to_object(vm); sq_pushobject(global_vm, vm_obj); sq_weakref(global_vm, -1); HSQOBJECT object; if(SQ_FAILED(sq_getstackobj(global_vm, -1, &object))) { sq_pop(global_vm, 2); throw SquirrelError(global_vm, "Couldn't get thread weakref from vm"); } sq_addref(global_vm, &object); threads.push_back(object); sq_pop(global_vm, 2); }
/* static */ SQInteger ScriptFileInfo::Constructor(HSQUIRRELVM vm, ScriptFileInfo *info) { /* Set some basic info from the parent */ info->SQ_instance = MallocT<SQObject>(1); Squirrel::GetInstance(vm, info->SQ_instance, 2); /* Make sure the instance stays alive over time */ sq_addref(vm, info->SQ_instance); ScriptScanner *scanner = (ScriptScanner *)Squirrel::GetGlobalPointer(vm); info->engine = scanner->GetEngine(); static const char * const required_functions[] = { "GetAuthor", "GetName", "GetShortName", "GetDescription", "GetVersion", "GetDate", "CreateInstance", }; for (size_t i = 0; i < lengthof(required_functions); i++) { if (!info->CheckMethod(required_functions[i])) return SQ_ERROR; } info->main_script = strdup(scanner->GetMainScript()); /* Cache the data the info file gives us. */ if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetAuthor", &info->author, MAX_GET_OPS)) return SQ_ERROR; if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetName", &info->name, MAX_GET_OPS)) return SQ_ERROR; if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetShortName", &info->short_name, MAX_GET_OPS)) return SQ_ERROR; if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetDescription", &info->description, MAX_GET_OPS)) return SQ_ERROR; if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetDate", &info->date, MAX_GET_OPS)) return SQ_ERROR; if (!info->engine->CallIntegerMethod(*info->SQ_instance, "GetVersion", &info->version, MAX_GET_OPS)) return SQ_ERROR; if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "CreateInstance", &info->instance_name, MAX_CREATEINSTANCE_OPS)) return SQ_ERROR; /* The GetURL function is optional. */ if (info->engine->MethodExists(*info->SQ_instance, "GetURL")) { if (!info->engine->CallStringMethodStrdup(*info->SQ_instance, "GetURL", &info->url, MAX_GET_OPS)) return SQ_ERROR; } return 0; }
void CSquirrelVM::PushInstance(const char* szClassName, void * pInstance) { // TODO:: remove instances when they are destoryed if (m_Instances.find(pInstance) != m_Instances.end()) { sq_pushobject(m_pVM, m_Instances.find(pInstance)->second); } else { CreateConstructNativeClassInstance(m_pVM, szClassName); sq_setinstanceup(m_pVM, -1, (SQUserPointer *) pInstance); sq_setreleasehook(m_pVM, -1, deleteClassInstance); HSQOBJECT instance; sq_resetobject(&instance); sq_getstackobj(m_pVM, -1, &instance); sq_addref(m_pVM, &instance); m_Instances.insert(std::pair<void*, HSQOBJECT>(pInstance, instance)); } }
void TimeScheduler::schedule_thread(HSQUIRRELVM scheduled_vm, float time) { // create a weakref to the VM SQObject vm_obj = vm_to_object(scheduled_vm); sq_pushobject(global_vm, vm_obj); sq_weakref(global_vm, -1); ScheduleEntry entry; if(SQ_FAILED(sq_getstackobj(global_vm, -1, & entry.thread_ref))) { sq_pop(global_vm, 2); throw SquirrelError(global_vm, "Couldn't get thread weakref from vm"); } entry.wakeup_time = time; sq_addref(global_vm, & entry.thread_ref); sq_pop(global_vm, 2); schedule.push_back(entry); std::push_heap(schedule.begin(), schedule.end()); }
//------------------------------------------------------------------------------ bool Script::compileString( const std::string & sourceCode, const std::string & scriptName) { releaseObject(); if(SQ_FAILED(sq_compilebuffer(m_vm, sourceCode.c_str(), static_cast<SQInteger>(sourceCode.size()), scriptName.c_str(), true // raise error ))) { return false; } sq_getstackobj(m_vm, -1, &m_object); sq_addref(m_vm, &m_object); sq_pop(m_vm, 1); return true; }
SQInteger Sq_RegisterMenu(HSQUIRRELVM v) { const SQChar *What; HSQOBJECT Handler; sq_resetobject(&Handler); sq_getstackobj(v, 2, &Handler); sq_getstring(v, 3, &What); sq_addref(v, &Handler); SquirrelHook *NewHook = (SquirrelHook*)malloc(sizeof(SquirrelHook)); if(!NewHook) exit(0); // add new menu command strlcpy(NewHook->Name, What, sizeof(NewHook->Name)); NewHook->Script = v; NewHook->Function = Handler; NewHook->Prev = NULL; NewHook->Next = AllMenuCommands; if(AllMenuCommands) AllMenuCommands->Prev = NewHook; AllMenuCommands = NewHook; return 0; }
SQRESULT sqrat_import(HSQUIRRELVM v) { const SQChar* moduleName; HSQOBJECT table; SQRESULT res = SQ_OK; SQInteger top = sq_gettop(v); sq_getstring(v, -2, &moduleName); sq_getstackobj(v, -1, &table); sq_addref(v, &table); sq_settop(v, 0); // Clear Stack sq_pushobject(v, table); // Push the target table onto the stack if(SQ_FAILED(sqrat_importscript(v, moduleName))) { res = sqrat_importbin(v, moduleName); } sq_settop(v, 0); // Clean up the stack (just in case the module load leaves it messy) sq_pushobject(v, table); // return the target table sq_release(v, &table); return res; }
void SquirrelThread::createThread() { //assert(!m_thread); m_thread = sq_newthread(m_parentVm, 1024); // create m_thread and store it on the stack if (0 == m_thread) { ASSERT_NOT_REACHED(); return; } // Create a HSQOBJECT to hold a reference to the m_thread sq_resetobject(&m_threadObj); // init the object // store m_thread created by sq_newthread into thread_obj if (sq_getstackobj(m_parentVm, -1, &m_threadObj) < 0) { ASSERT_NOT_REACHED(); return; } sq_addref(m_parentVm, &m_threadObj); // add reference sq_pop(m_parentVm, 1); // remove the m_thread from the stack }
/* static */ bool Squirrel::CreateClassInstanceVM(HSQUIRRELVM vm, const char *class_name, void *real_instance, HSQOBJECT *instance, SQRELEASEHOOK release_hook) { int oldtop = sq_gettop(vm); /* First, find the class */ sq_pushroottable(vm); sq_pushstring(vm, OTTD2SQ(class_name), -1); if (SQ_FAILED(sq_get(vm, -2))) { DEBUG(misc, 0, "[squirrel] Failed to find class by the name '%s'", class_name); sq_settop(vm, oldtop); return false; } /* Create the instance */ if (SQ_FAILED(sq_createinstance(vm, -1))) { DEBUG(misc, 0, "[squirrel] Failed to create instance for class '%s'", class_name); sq_settop(vm, oldtop); return false; } if (instance != NULL) { /* Find our instance */ sq_getstackobj(vm, -1, instance); /* Add a reference to it, so it survives for ever */ sq_addref(vm, instance); } sq_remove(vm, -2); // Class-name sq_remove(vm, -2); // Root-table /* Store it in the class */ sq_setinstanceup(vm, -1, real_instance); if (release_hook != NULL) sq_setreleasehook(vm, -1, release_hook); if (instance != NULL) sq_settop(vm, oldtop); return true; }
static SQRESULT sq_libclang_parseTranslationUnit(HSQUIRRELVM v){ SQ_FUNC_VARS(v); GET_libclang_INSTANCE(); if(sq_gettype(v, 2) != OT_CLOSURE) return sq_throwerror(v, _SC("invalid fisrt parameter expected closure")); SQ_GET_STRING(v, 3, fname); release_visitor_cb(self); sq_getstackobj(v, 2, &self->visitor_cb); sq_addref(v, &self->visitor_cb); const char *cl_argsDefault[] = {"-I."}; const char **cl_args = cl_argsDefault; int cl_argNum = 1; int rc = 0; const int cl_arg_start = 4; bool has_extra_params = _top_ >= cl_arg_start; if(has_extra_params) { //create cl_args with extra parameters cl_argNum = _top_ - (cl_arg_start -1); cl_args = (const char **)sq_malloc(sizeof(char*) * cl_argNum); for(int i=cl_arg_start; i <= _top_; ++i) { const SQChar *p; if(sq_gettype(v, i) == OT_STRING) { rc = sq_getstring(v, i, &p); } else { rc = sq_throwerror(v, _SC("not a string parameter at %d"), i); goto cleanup; } cl_args[i-cl_arg_start] = p; } } CXTranslationUnit TU; CXCursor rootCursor; TU = dlclang_parseTranslationUnit(self->index, fname, cl_args, cl_argNum, 0, 0, CXTranslationUnit_Incomplete); if (TU == NULL) { rc = sq_throwerror(v, _SC("clang_parseTranslationUnit for %s failed\n"), fname); goto cleanup; } rootCursor = dlclang_getTranslationUnitCursor(TU); dlclang_visitChildren(rootCursor, cursorVisitor, self); dlclang_disposeTranslationUnit(TU); cleanup: if(has_extra_params) { sq_free(cl_args, sizeof(char*) * cl_argNum); } return rc; }
// // Transport schedule // SQInteger Transportschedule(HSQUIRRELVM vm) { SQInteger numargs = sq_gettop(vm); // check parameter count if(numargs > 5) { return sq_throwerror(vm, "too many parameters, expected at most 4"); } if(numargs < 3) { return sq_throwerror(vm, "insufficient parameters, expected at least 2"); } // get parameter 1 "function" as function HSQOBJECT functionObj; if (SQ_FAILED(sq_getstackobj(vm, 2, &functionObj))) { return sq_throwerror(vm, "argument 1 \"function\" is not of type function"); } if (sq_gettype(vm, 2) != OT_CLOSURE) { return sq_throwerror(vm, "argument 1 \"function\" is not of type function"); } SQUnsignedInteger nparams, nfreevars; sq_getclosureinfo(vm, 2, &nparams, &nfreevars); sq_addref(vm, &functionObj); ScriptFunction function(vm, functionObj, nparams); // get parameter 2 "bar" as integer SQInteger bar; if (SQ_FAILED(sq_getinteger(vm, 3, &bar))){ return sq_throwerror(vm, "argument 2 \"bar\" is not of type integer"); } // 3 parameters passed in if(numargs == 4) { // get parameter 3 "position" as integer SQInteger position; if (SQ_FAILED(sq_getinteger(vm, 4, &position))){ return sq_throwerror(vm, "argument 3 \"position\" is not of type integer"); } // call the implementation try { Transport::instance().schedule(function, bar, position); } catch(std::exception const& e) { return sq_throwerror(vm, e.what()); } } // 4 parameters passed in else if(numargs == 5) { // get parameter 3 "position" as integer SQInteger position; if (SQ_FAILED(sq_getinteger(vm, 4, &position))){ return sq_throwerror(vm, "argument 3 \"position\" is not of type integer"); } // get parameter 4 "division" as integer SQInteger division; if (SQ_FAILED(sq_getinteger(vm, 5, &division))){ return sq_throwerror(vm, "argument 4 \"division\" is not of type integer"); } // call the implementation try { Transport::instance().schedule(function, bar, position, division); } catch(std::exception const& e) { return sq_throwerror(vm, e.what()); } } else { // call the implementation try { Transport::instance().schedule(function, bar); } catch(std::exception const& e) { return sq_throwerror(vm, e.what()); } } // void method, returns no value return 0; }
// ------------------------------------------------------------------------------------------------ SQInteger Routine::Create(HSQUIRRELVM vm) { // Locate the identifier of a free slot const SQInteger slot = FindUnused(); // See if we have where to store this routine if (slot < 0) { return sq_throwerror(vm, "Reached the maximum number of active routines"); } // Grab the top of the stack const SQInteger top = sq_gettop(vm); // See if too many arguments were specified if (top >= 20) /* 5 base + 14 parameters = 19 */ { return sq_throwerror(vm, "Too many parameters specified"); } // Was there was an environment specified? else if (top <= 1) { return sq_throwerror(vm, "Missing routine environment"); } // Was there was a callback specified? else if (top <= 2) { return sq_throwerror(vm, "Missing routine callback"); } // Validate the callback type else if (sq_gettype(vm, 3) != OT_CLOSURE && sq_gettype(vm, 3) != OT_NATIVECLOSURE) { return sq_throwerror(vm, "Invalid callback type"); } SQRESULT res = SQ_OK; // Prepare an object for the environment HSQOBJECT env; // Is the specified environment a null value? if (sq_gettype(vm, 2) == OT_NULL) { // Preserve the stack state const StackGuard sg(vm); // Push the root table on the stack sq_pushroottable(vm); // Attempt to retrieve the table object res = sq_getstackobj(vm, -1, &env); } else { sq_getstackobj(vm, 2, &env); // Just retrieve the specified environment } // Validate the result if (SQ_FAILED(res)) { return res; // Propagate the error } // Prepare an object for the function HSQOBJECT func; // Fetch the specified callback object res = sq_getstackobj(vm, 3, &func); // Validate the result if (SQ_FAILED(res)) { return res; // Propagate the error } // The number of iterations and interval to execute the routine SQInteger intrv = 0, itr = 0; // Was there an interval specified? if (top > 3) { // Grab the interval from the stack res = sq_getinteger(vm, 4, &intrv); // Validate the result if (SQ_FAILED(res)) { return res; // Propagate the error } } // Was there a number of iterations specified? if (top > 4) { // Grab the iterations from the stack res = sq_getinteger(vm, 5, &itr); // Validate the result if (SQ_FAILED(res)) { return res; // Propagate the error } } // Attempt to create a routine instance try { ClassType< Routine >::PushInstance(vm, new Routine()); } catch (const Sqrat::Exception & e) { return sq_throwerror(vm, "Unable to create the routine instance"); } // Prepare an object for the routine HSQOBJECT obj; // Fetch the created routine object res = sq_getstackobj(vm, -1, &obj); // Validate the result if (SQ_FAILED(res)) { return res; // Propagate the error } // At this point we can grab a reference to our slot Instance & inst = s_Instances[slot]; // Were there any arguments specified? if (top > 5) { // Grab a pointer to the arguments array Argument * args = inst.mArgv; // Reset the argument counter inst.mArgc = 0; // Grab the specified arguments from the stack for (SQInteger i = 6; i <= top; ++i) { res = sq_getstackobj(vm, i, &(args[inst.mArgc].mObj)); // Validate the result if (SQ_FAILED(res)) { // Clear previous arguments inst.Clear(); // Propagate the error return res; } // Keep a strong reference to the argument sq_addref(vm, &(args[inst.mArgc].mObj)); // Increase the argument counter ++inst.mArgc; } } // Attempt to retrieve the routine from the stack and associate it with the slot try { Var< Routine * >(vm, -1).value->m_Slot = ConvTo< Uint32 >::From(slot); } catch (const Sqrat::Exception & e) { // Clear extracted arguments inst.Clear(); // Now it's safe to throw the error return sq_throwerror(vm, "Unable to create the routine instance"); } // Alright, at this point we can initialize the slot inst.Init(env, func, obj, intrv, itr); // Now initialize the timer s_Intervals[slot] = intrv; // We have the created routine on the stack, so let's return it return 1; }
SquirrelObject::SquirrelObject(const SquirrelObject &o) { _o = o._o; sq_addref(m_Vm.GetVMPtr(),&_o); }
SquirrelObject::SquirrelObject(HSQOBJECT &o) { _o = o; sq_addref(m_Vm.GetVMPtr(),&_o); }
ScriptBehavior::ScriptBehavior( HSQUIRRELVM vm,HSQOBJECT classObject,const std::map< tstring_symbol,ScriptParameterInterfacePtr >& scriptParameters ) : m_vm(vm) , m_start(false) { int top = sq_gettop(m_vm); sq_pushobject(m_vm, classObject); sq_pushroottable( m_vm ); m_initialize = false; m_haveAwake = false; m_haveStart = false; m_haveUpdate = false; if( SQ_SUCCEEDED( sq_call( m_vm,1,SQTrue,SQTrue) ) ) { if( SQ_SUCCEEDED( sq_getstackobj(m_vm, -1, &m_instance) ) ) { sq_addref( m_vm,&m_instance ); m_initialize = true; sq_pushstring( m_vm,_SC("Awake"),-1 ); if( SQ_SUCCEEDED( sq_get(m_vm,-2 ) ) ) { if( SQ_SUCCEEDED( sq_getstackobj(m_vm, -1, &m_awakeFunction) ) ) { sq_addref( m_vm,&m_awakeFunction ); m_haveAwake = true; } } sq_pop(m_vm,1); sq_pushstring( m_vm,_SC("Start"),-1 ); if( SQ_SUCCEEDED( sq_get(m_vm,-2 ) ) ) { if( SQ_SUCCEEDED( sq_getstackobj(m_vm, -1, &m_startFunction) ) ) { sq_addref( m_vm,&m_startFunction ); m_haveStart = true; } } sq_pop(m_vm,1); sq_pushstring( m_vm,_SC("Update"),-1 ); if( SQ_SUCCEEDED( sq_get(m_vm,-2 ) ) ) { if( SQ_SUCCEEDED( sq_getstackobj(m_vm, -1, &m_updateFunction) ) ) { sq_addref( m_vm,&m_updateFunction ); m_haveUpdate = true; } } sq_pop(m_vm,1); std::map< tstring_symbol,ScriptParameterInterfacePtr >::const_iterator it = scriptParameters.begin(); while( it!=scriptParameters.end() ) { it->second->SetParameter( m_vm ); it++; } } } sq_settop( m_vm,top ); }
/* static */ bool Squirrel::CreateClassInstanceVM(HSQUIRRELVM vm, const char *class_name, void *real_instance, HSQOBJECT *instance, SQRELEASEHOOK release_hook, bool prepend_API_name) { Squirrel *engine = (Squirrel *)sq_getforeignptr(vm); int oldtop = sq_gettop(vm); /* First, find the class */ sq_pushroottable(vm); if (prepend_API_name) { size_t len = strlen(class_name) + strlen(engine->GetAPIName()) + 1; char *class_name2 = (char *)alloca(len); seprintf(class_name2, class_name2 + len - 1, "%s%s", engine->GetAPIName(), class_name); sq_pushstring(vm, class_name2, -1); } else { sq_pushstring(vm, class_name, -1); } if (SQ_FAILED(sq_get(vm, -2))) { DEBUG(misc, 0, "[squirrel] Failed to find class by the name '%s%s'", prepend_API_name ? engine->GetAPIName() : "", class_name); sq_settop(vm, oldtop); return false; } /* Create the instance */ if (SQ_FAILED(sq_createinstance(vm, -1))) { DEBUG(misc, 0, "[squirrel] Failed to create instance for class '%s%s'", prepend_API_name ? engine->GetAPIName() : "", class_name); sq_settop(vm, oldtop); return false; } if (instance != NULL) { /* Find our instance */ sq_getstackobj(vm, -1, instance); /* Add a reference to it, so it survives for ever */ sq_addref(vm, instance); } sq_remove(vm, -2); // Class-name sq_remove(vm, -2); // Root-table /* Store it in the class */ sq_setinstanceup(vm, -1, real_instance); if (release_hook != NULL) sq_setreleasehook(vm, -1, release_hook); if (instance != NULL) sq_settop(vm, oldtop); return true; }