SQInteger SquirrelStd::require(HSQUIRRELVM vm) { SQInteger top = sq_gettop(vm); const SQChar *filename; SQChar *real_filename; sq_getstring(vm, 2, &filename); /* Get the script-name of the current file, so we can work relative from it */ SQStackInfos si; sq_stackinfos(vm, 1, &si); if (si.source == NULL) { DEBUG(misc, 0, "[squirrel] Couldn't detect the script-name of the 'require'-caller; this should never happen!"); return SQ_ERROR; } real_filename = scstrdup(si.source); /* Keep the dir, remove the rest */ SQChar *s = scstrrchr(real_filename, PATHSEPCHAR); if (s != NULL) { /* Keep the PATHSEPCHAR there, remove the rest */ s++; *s = '\0'; } /* And now we concat, so we are relative from the current script * First, we have to make sure we have enough space for the full path */ real_filename = ReallocT(real_filename, scstrlen(real_filename) + scstrlen(filename) + 1); scstrcat(real_filename, filename); /* Tars dislike opening files with '/' on Windows.. so convert it to '\\' ;) */ char *filen = strdup(SQ2OTTD(real_filename)); #if (PATHSEPCHAR != '/') for (char *n = filen; *n != '\0'; n++) if (*n == '/') *n = PATHSEPCHAR; #endif bool ret = Squirrel::LoadScript(vm, filen); /* Reset the top, so the stack stays correct */ sq_settop(vm, top); free(real_filename); free(filen); return ret ? 0 : SQ_ERROR; }
void CSquirrelVM::Call(stScriptFunction function, CScriptArguments * pArguments) { if (function.function._type != SQObjectType::OT_CLOSURE || function.function._unVal.pClosure == 0) return; SQObjectPtr res; int iTop = sq_gettop(m_pVM); if (pArguments) { for (auto it : pArguments->m_Arguments) it->Push(this); m_pVM->Call(function.function, pArguments->m_Arguments.size() + 1, m_pVM->_top - (pArguments->m_Arguments.size() + 1), res, true); } else { m_pVM->Call(function.function, 1, m_pVM->_top - 1, res, true); } sq_settop(m_pVM, iTop); }
/* * Call Squirrel function with one float parameter * Returns SQTrue if sq_call succeeds. */ SQBool callSqFunction_Bool_Float(HSQUIRRELVM v, const SQChar* nname, const SQChar* name, SQFloat value, SQBool defaultValue) { SQBool result = SQFalse; SQInteger top = sq_gettop(v); sq_pushroottable(v); sq_pushstring(v, nname, -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { sq_pushstring(v, name, -1); if(SQ_SUCCEEDED(sq_get(v, -2))) { sq_pushroottable(v); sq_pushfloat(v, value); if (SQ_SUCCEEDED(sq_call(v, 2, SQTrue, SQTrue))) { sq_getbool(v, sq_gettop(v), &result); } } } sq_settop(v,top); return result; }
//QSORT ala Sedgewick bool _qsort_compare(HSQUIRRELVM v,SQObjectPtr &arr,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret) { if(func < 0) { if(!v->ObjCmp(a,b,ret)) return false; } else { SQInteger top = sq_gettop(v); sq_push(v, func); sq_pushroottable(v); v->Push(a); v->Push(b); if(SQ_FAILED(sq_call(v, 3, SQTrue, SQFalse))) { if(!sq_isstring( v->_lasterror)) v->Raise_Error(_SC("compare func failed")); return false; } sq_getinteger(v, -1, &ret); sq_settop(v, top); return true; } return true; }
/* * Call Squirrel function with strings parameter * Returns SQTrue if sq_call succeeds. */ SQBool callSqFunction_Bool_Strings(HSQUIRRELVM v, const SQChar* nname, const SQChar* name, const SQChar* value1, const SQChar* value2, const SQChar* value3, const SQChar* value4, SQBool defaultValue) { SQBool result = defaultValue; SQInteger top = sq_gettop(v); sq_pushroottable(v); sq_pushstring(v, nname, -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { sq_pushstring(v, name, -1); if(SQ_SUCCEEDED(sq_get(v, -2))) { sq_pushroottable(v); sq_pushstring(v, value1, -1); sq_pushstring(v, value2, -1); sq_pushstring(v, value3, -1); sq_pushstring(v, value4, -1); result = SQ_SUCCEEDED(sq_call(v, 5, SQFalse, SQTrue)); } } sq_settop(v,top); return result; }
/* * Call Squirrel function with multiple float parameters, returns boolean * Returns default value if sq_call failed. */ SQBool callSqFunction_Bool_Floats(HSQUIRRELVM v, const SQChar* nname, const SQChar* name, SQFloat param[], int count, SQBool defaultValue) { SQBool result = defaultValue; SQInteger top = sq_gettop(v); sq_pushroottable(v); sq_pushstring(v, nname, -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { sq_pushstring(v, name, -1); if(SQ_SUCCEEDED(sq_get(v, -2))) { sq_pushroottable(v); for (int i = 0; i < count; i++) { sq_pushfloat(v, param[i]); } if (SQ_SUCCEEDED(sq_call(v, count + 1, SQTrue, SQTrue))) { sq_getbool(v, sq_gettop(v), &result); } } } sq_settop(v,top); return result; }
static SQRESULT sq_slave_vm_get(HSQUIRRELVM v) { GET_sq_slave_vm_INSTANCE(v, 1); SQInteger top = sq_gettop(self); SQRESULT result = SQ_ERROR; sq_pushroottable(self); if(copy_values_between_vms(self, v, 1, 2) == SQ_OK) { if(sq_get(self, -2) == SQ_OK && copy_values_between_vms(v, self, 1, sq_gettop(self)) == SQ_OK) { result = 1; } else { if(sq_gettop(v) == 3) result = 1; //we have a default value else sq_throwerror(v, sq_getlasterror_str(self)); } } sq_settop(self, top); return result; }
void CScripts::onVehicleDamage(int vehicleId, float oldhp, float newhp) { 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, "onVehicleDamage", -1); // Get the closure for the function if(SQ_SUCCEEDED(sq_get(pVM, -2))) { // Push the root table onto the stack sq_pushroottable(pVM); // Push the vehicle id onto the stack sq_pushinteger(pVM, vehicleId); // Push the player old health onto the stack sq_pushfloat(pVM, oldhp); // Push the player new health onto the stack sq_pushfloat(pVM, newhp); // Call the function sq_call(pVM, 4, true, true); } // Restore the stack top sq_settop(pVM, iTop); } } }
void CScripts::onPlayerDeath(int playerId, int killerId, int reason) { 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, "onPlayerDeath", -1); // Get the closure for the function if(SQ_SUCCEEDED(sq_get(pVM, -2))) { // Push the root table onto the stack sq_pushroottable(pVM); // Push the player id onto the stack sq_pushinteger(pVM, playerId); // Push the killer id onto the stack sq_pushinteger(pVM, killerId); // Push the death reason onto the stack sq_pushinteger(pVM, reason); // Call the function sq_call(pVM, 4, true, true); } // Restore the stack top sq_settop(pVM, iTop); } } }
/* * invoke contact event */ static SQBool invokeContactEvent(HSQUIRRELVM v, ContactPoint cp) { SQBool result = false; SQInteger top = sq_gettop(v); sq_pushroottable(v); sq_pushstring(v, "emo", -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { sq_pushstring(v, "_onContact", -1); if(SQ_SUCCEEDED(sq_get(v, -2))) { sq_pushroottable(v); switch(cp.state) { case b2_addState: sq_pushinteger(v, PHYSICS_STATE_ADD); break; case b2_persistState: sq_pushinteger(v, PHYSICS_STATE_PERSIST); break; case b2_removeState: sq_pushinteger(v, PHYSICS_STATE_REMOVE); break; default: sq_pushinteger(v, PHYSICS_STATE_NULL); } sq_pushuserpointer(v, cp.fixtureA); sq_pushuserpointer(v, cp.fixtureB); sq_pushuserpointer(v, cp.fixtureA->GetBody()); sq_pushuserpointer(v, cp.fixtureB->GetBody()); pushVec2(v, cp.position); pushVec2(v, cp.normal); sq_pushfloat(v, cp.normalImpulse); sq_pushfloat(v, cp.tangentImpulse); result = SQ_SUCCEEDED(sq_call(v, 10, SQFalse, SQTrue)); } } sq_settop(v,top); return result; }
SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own) { SQInteger top = sq_gettop(v); sq_pushregistrytable(v); sq_pushstring(v,_SC("std_file"),-1); if(SQ_SUCCEEDED(sq_get(v,-2))) { sq_remove(v,-2); //removes the registry sq_pushroottable(v); // push the this sq_pushuserpointer(v,file); //file if(own){ sq_pushinteger(v,1); //true } else{ sq_pushnull(v); //false } if(SQ_SUCCEEDED( sq_call(v,3,SQTrue,SQFalse) )) { sq_remove(v,-2); return SQ_OK; } } sq_settop(v,top); return SQ_OK; }
static SQRESULT sq_slave_vm_dofile(HSQUIRRELVM v) { SQ_FUNC_VARS(v); GET_sq_slave_vm_INSTANCE(v, 1); SQ_GET_STRING(v, 2, file_name); SQ_OPT_BOOL(v, 3, retval, false); SQ_OPT_BOOL(v, 4, printerror, false); SQ_OPT_BOOL(v, 5, show_warnings, false); SQInteger top = sq_gettop(self); SQRESULT result = SQ_ERROR; sq_pushroottable(self); //important always push the root table, because sqstd_dofile will try to do a sq_push(v, -2) if(sqstd_dofile(self, file_name, retval, printerror, show_warnings) >= 0) { if(retval) { if(copy_values_between_vms(v, self, 1, sq_gettop(self)) == SQ_OK) result = 1; } else result = SQ_OK; } else sq_throwerror(v, sq_getlasterror_str(self)); sq_settop(self, top); return result; }
void CScripts::onPlayerCommand(int playerId, const char *command) { 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, "onPlayerCommand", -1); // Get the closure for the function if(SQ_SUCCEEDED(sq_get(pVM, -2))) { // Push the root table onto the stack sq_pushroottable(pVM); // Push the player id onto the stack sq_pushinteger(pVM, playerId); // Push the text onto the stack sq_pushstring(pVM, command, -1); // Call the function sq_call(pVM, 3, true, true); } // Restore the stack top sq_settop(pVM, iTop); } } }
void ScriptBehavior::Update( float deltaTime ) { if( !m_start ) { Start(); m_start = true; } if( !m_initialize || !m_haveUpdate ) { return; } int top = sq_gettop(m_vm); sq_pushobject(m_vm, m_instance); sq_pushobject(m_vm, m_updateFunction); sq_push( m_vm,-3 ); sq_pushfloat( m_vm,deltaTime ); sq_call( m_vm,2,SQFalse,SQTrue ); sq_settop( m_vm,top ); }
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 ); }
void Interactive(HSQUIRRELVM v) { #define MAXINPUT 1024 SQChar buffer[MAXINPUT]; SQInteger blocks =0; SQInteger string=0; SQInteger retval=0; SQInteger done=0; PrintVersionInfos(); sq_pushroottable(v); sq_pushstring(v,_SC("quit"),-1); sq_pushuserpointer(v,&done); sq_newclosure(v,quit,1); sq_setparamscheck(v,1,NULL); sq_newslot(v,-3,SQFalse); sq_pop(v,1); while (!done) { SQInteger i = 0; scprintf(_SC("\nsq>")); for(;;) { int c; if(done)return; c = getchar(); if (c == _SC('\n')) { if (i>0 && buffer[i-1] == _SC('\\')) { buffer[i-1] = _SC('\n'); } else if(blocks==0)break; buffer[i++] = _SC('\n'); } else if (c==_SC('}')) {blocks--; buffer[i++] = (SQChar)c;} else if(c==_SC('{') && !string){ blocks++; buffer[i++] = (SQChar)c; } else if(c==_SC('"') || c==_SC('\'')){ string=!string; buffer[i++] = (SQChar)c; } else if (i >= MAXINPUT-1) { scfprintf(stderr, _SC("sq : input line too long\n")); break; } else{ buffer[i++] = (SQChar)c; } } buffer[i] = _SC('\0'); if(buffer[0]==_SC('=')){ scsprintf(sq_getscratchpad(v,MAXINPUT),_SC("return (%s)"),&buffer[1]); memcpy(buffer,sq_getscratchpad(v,-1),(scstrlen(sq_getscratchpad(v,-1))+1)*sizeof(SQChar)); retval=1; } i=scstrlen(buffer); if(i>0){ SQInteger oldtop=sq_gettop(v); if(SQ_SUCCEEDED(sq_compilebuffer(v,buffer,i,_SC("interactive console"),SQTrue))){ sq_pushroottable(v); if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue)) && retval){ scprintf(_SC("\n")); sq_pushroottable(v); sq_pushstring(v,_SC("print"),-1); sq_get(v,-2); sq_pushroottable(v); sq_push(v,-4); sq_call(v,2,SQFalse,SQTrue); retval=0; scprintf(_SC("\n")); } } sq_settop(v,oldtop); } } }
StackLock::~StackLock() { sq_settop(context_.getHandle(), top_); }
int main (int argc, char** argv) { ENABLE_LEAK_CHECK(); #if defined(SHELL_PLATFORM_WINDOWS) SetConsoleTitle("Squirrel Shell " SHELL_VERSION_STR " (" SHELL_CPUARCH ")"); #else stderrIsRedirected = !isatty(2); #endif // Parse command line arguments. const char* fileName = NULL; bool interactive = argc == 1; int firstArg = 0, i; bool isDebug = false; int debuggerPort = 0; for (i = 1; argv[i]; ++i) { char* arg = argv[i]; if (!strcmp(arg, "-h") || !strcmp(arg, "--help")) { printf("Squirrel Shell %s for %s on %s (" __DATE__ ")\n" SHELL_VERSION_COPYRIGHT "\n" "\n" "This is free software, and comes WITHOUT ANY WARRANTY; without even the implied\n" "warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n" "General Public License for more details.\n" "\n" "MD5 hash calculation code (c) Colin Plumb\n" "PCRE (c) University of Cambridge\n" "Squirrel (c) Alberto Demichelis\n" "zlib (c) Jean-loup Gailly and Mark Adler\n" "\n" "Usage:\n" " squirrelsh [options] [script_file] [script_arguments]\n" "\n" "Options:\n" " -h, --help Display this text\n" " -d<PORT> Enable the debugger, in the specified port\n" " -i, --interactive Run shell in interactive mode\n" " If script file is specified, it will be executed before\n" " entering this mode\n" " -s, --silent Do not display error and warning messages\n" " -v, --version Display shell version number\n" "\n" "Examples:\n" " squirrelsh Run shell in interactive mode\n" " squirrelsh foo.nut Run foo.nut script without arguments\n" " squirrelsh -i foo.nut 1 2 3 Run foo.nut script with arguments \"1\", \"2\"\n" " and \"3\", and switch into interactive mode\n", SHELL_VERSION_STR, SHELL_PLATFORM, SHELL_CPUARCH); return EXIT_SUCCESS; } else if (!strncmp(arg, "-d", 2)) { // RVF + isDebug = true; debuggerPort = std::atoi(arg + 2); if (debuggerPort == 0) { printf("No debugger port specified\n"); return EXIT_FAILURE; } // RVF - } else if (!strcmp(arg, "-i") || !strcmp(arg, "--interactive")) interactive = true; else if (!strcmp(arg, "-v") || !strcmp(arg, "--version")) { printf("%s\n", SHELL_VERSION_STR); return EXIT_SUCCESS; } else if (!strcmp(arg, "-s") || !strcmp(arg, "--silent")) silent = true; else { // First unreserved argument will be treated as script file name. fileName = arg; firstArg = i; break; } } if (!fileName && !interactive) { PrintError("ERROR: Script file not specified.\n"); return EXIT_FAILURE; } // Initialize Squirrel. sqvm = sq_open(1024); if (!sqvm) { PrintError("ERROR: Failed to create Squirrel VM.\n"); return EXIT_FAILURE; } sqstd_seterrorhandlers(sqvm); HSQREMOTEDBG rdbg = nullptr; if (isDebug) { rdbg = sq_rdbg_init(sqvm, debuggerPort, SQTrue); sq_enabledebuginfo(sqvm, SQTrue); //!! SUSPENDS THE APP UNTIL THE DEBUGGER CLIENT CONNECTS scprintf("Waiting for the debugger to connect...\n"); if (!SQ_SUCCEEDED(sq_rdbg_waitforconnections(rdbg))) { PrintError("ERROR: Failed to connect to the debugger.\n"); return EXIT_FAILURE; } scprintf(_SC("Connected to the debugger\n")); } //sq_setcompilererrorhandler(sqvm, SquirrelCompileError); _RPT0(_CRT_WARN, "--- Squirrel initialized\n"); // Register some globals. SetSqString("SHELL_VERSION", SHELL_VERSION_STR, SQTrue); SetSqString("SQUIRREL_VERSION", SQUIRREL_VERSION_SHORT, SQTrue); SetSqString("PLATFORM", SHELL_PLATFORM, SQTrue); SetSqString("CPU_ARCH", SHELL_CPUARCH, SQTrue); // Initialize libraries. Init_Base(); Init_IO(); Init_File(); Init_Math(); Init_Util(); Init_Hash(); Init_RegExp(); _RPT0(_CRT_WARN, "--- Libraries initialized\n"); // Set up global variables... sq_pushroottable(sqvm); // RVF + // Initialize squirrel std libraries //sqstd_register_bloblib(sqvm); sqstd_register_iolib(sqvm); // We need this one because of the handy "dofile" function sqstd_register_stringfunctions(sqvm); // This registers only some string functions that are useful and don't clash with Squirrel Shell // NOTE: Not registering the other libraries, because there are name clashing between Squirrel Shell and SqStdLib //sqstd_register_systemlib(sqvm); //sqstd_register_mathlib(sqvm); //sqstd_register_stringlib(sqvm); // RVF - // ... number of command line arguments... sq_pushstring(sqvm, "__argc", -1); sq_pushinteger(sqvm, SQInteger(argc - firstArg)); if (SQ_FAILED(sq_newslot(sqvm, -3, SQFalse))) { PrintError("ERROR: Failed to create \"__argc\" integer value.\n"); Shutdown(); return EXIT_FAILURE; } // ... and arguments themselves. sq_pushstring(sqvm, "__argv", -1); sq_newarray(sqvm, 0); for (i = firstArg; argv[i]; ++i) { sq_pushstring(sqvm, argv[i], -1); sq_arrayappend(sqvm, -2); } if (SQ_FAILED(sq_newslot(sqvm, -3, SQFalse))) { PrintError("ERROR: Failed to create \"__argv\" array.\n"); Shutdown(); return EXIT_FAILURE; } sq_pop(sqvm, 1); // Load and run script. SQInteger result = EXIT_SUCCESS; if (fileName && LoadScript(fileName)) { sq_pushroottable(sqvm); if (SQ_FAILED(sq_call(sqvm, 1, SQTrue, isDebug ? SQTrue : SQFalse))) { if (!silent) { const SQChar* errMsg = "Unknown error."; sq_getlasterror(sqvm); if (sq_gettype(sqvm, -1) == OT_STRING) sq_getstring(sqvm, -1, &errMsg); PrintError("ERROR: %s\n", errMsg); } Shutdown(); return EXIT_FAILURE; } // Get script execution result. if (sq_getvmstate(sqvm) == SQ_VMSTATE_SUSPENDED) result = retCode; else { if (sq_gettype(sqvm, -1) == OT_INTEGER) sq_getinteger(sqvm, -1, &result); } // Pop everything except root table. sq_settop(sqvm, 1); } // Enter interactive mode (if necessary). if (interactive) { SQChar cmd[MAX_CMD_LENGTH + 1]; do { #if defined(SHELL_PLATFORM_WINDOWS) GetCurrentDirectory(sizeof(cmd), cmd); #else getcwd(cmd, sizeof(cmd)); #endif cmd[sizeof(cmd) - 1] = 0; printf("%s> ", ConvPath(cmd, SQFalse)); fgets(cmd, MAX_CMD_LENGTH, stdin); if (SQ_FAILED(sq_compilebuffer(sqvm, cmd, SQInteger(strlen(cmd)), "", SQTrue))) continue; sq_pushroottable(sqvm); if (SQ_FAILED(sq_call(sqvm, 1, SQFalse, SQFalse)) && !silent) { const SQChar* errMsg = "Unknown error."; sq_getlasterror(sqvm); if (sq_gettype(sqvm, -1) == OT_STRING) sq_getstring(sqvm, -1, &errMsg); PrintError("ERROR: %s\n", errMsg); } } while(sq_getvmstate(sqvm) != SQ_VMSTATE_SUSPENDED); result = retCode; } if (isDebug) { sq_rdbg_shutdown(rdbg); } Shutdown(); return int(result); }
static SQInteger squirrel_errorhandler(HSQUIRRELVM v) { /* Detect whether this error is just propagating through, or it originated * here. To do so, we store the last error we saw in the registry and compare * it to the current error. If they are the equal, we've already handled this * error. * * Without this check, we'll call the error handler for every transition * between the Squirrel and Wasm VMs. */ /* TODO(binji): It seems like there should be a better way to handle this */ SQInteger top = sq_gettop(v); WasmBool is_new_error = WASM_TRUE; /* get the last error we saw */ sq_pushregistrytable(v); sq_pushstring(v, WASM_LAST_ERROR_NAME, -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { /* STACK: error registry_table last_error */ sq_push(v, -3); HSQOBJECT last_error; HSQOBJECT error; if (SQ_SUCCEEDED(sq_getstackobj(v, -1, &error)) && SQ_SUCCEEDED(sq_getstackobj(v, -2, &last_error))) { /* we don't want to use cmp here, because it will throw if the values are * unordered, and because it performs value equality */ if (squirrel_objects_are_equal_raw(last_error, error)) is_new_error = WASM_FALSE; } /* set the last_error in the registry to the new error. */ /* STACK: registry_table last_error error */ sq_remove(v, -2); sq_pushstring(v, WASM_LAST_ERROR_NAME, -1); sq_push(v, -2); /* STACK: registry_table error WASM_LAST_ERROR_NAME error */ SQRESULT r = sq_set(v, -4); WASM_USE(r); assert(r == SQ_OK); } sq_settop(v, top); if (is_new_error) { const char* error_msg = "unknown"; if (sq_gettop(v) >= 1) sq_getstring(v, -1, &error_msg); squirrel_error(v, "error: %s\n", error_msg); squirrel_error(v, "callstack:\n"); SQStackInfos stack_info; SQInteger depth; for (depth = 1; SQ_SUCCEEDED(sq_stackinfos(v, depth, &stack_info)); depth++) { const char* source = stack_info.source ? stack_info.source : "unknown"; const char* funcname = stack_info.funcname ? stack_info.funcname : "unknown"; SQInteger line = stack_info.line; squirrel_error(v, " #"_PRINT_INT_FMT ": %s:"_PRINT_INT_FMT ": %s()\n", depth, source, line, funcname); } } return 0; }
void CScripts::Call(RakNet::BitStream * bitStream) { for(int i = 0; i < MAX_SCRIPTS; i++) { if(m_pScripts[i]) { int iArgCount = 0; int funcLen = 0; CHAR szFunc[256]; bitStream->Read(funcLen); bitStream->Read(iArgCount); bitStream->Read(szFunc, funcLen); szFunc[funcLen] = '\0'; // 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(iArgCount > 0) { for(int j = 0; i < iArgCount; i++) { int type; bitStream->Read(type); if(type == OT_INTEGER) { int val; bitStream->Read(val); sq_pushinteger(pVM, val); } else if(type == OT_FLOAT) { float val; bitStream->Read(val); sq_pushfloat(pVM, val); } else if(type == OT_BOOL) { bool val; bitStream->Read(val); sq_pushbool(pVM, val); } else if(type == OT_STRING) { int len; bitStream->Read(len); CHAR szStr[256]; bitStream->Read(szStr, len); szStr[len] = '\0'; std::string str = szStr; sq_pushstring(pVM, str.c_str(), -1); } } } sq_call(pVM, iArgCount + 1, true, true); } // Restore the stack top sq_settop(pVM, iTop); bitStream->ResetReadPointer(); } } }
int app_sqlang_run_ex(sip_msg_t *msg, char *func, char *p1, char *p2, char *p3, int emode) { int n; int ret; int top; sip_msg_t *bmsg; SQInteger rv; if(_sr_J_env.JJ==NULL) { LM_ERR("sqlang loading state not initialized (call: %s)\n", func); return -1; } /* check the script version loaded */ sqlang_kemi_reload_script(); top = sqlang_gettop(_sr_J_env.JJ); LM_DBG("sqlang top index is: %d\n", top); sq_pushroottable(_sr_J_env.JJ); /* pushes the global table */ sq_pushstring(_sr_J_env.JJ, _SC(func), -1); if(!SQ_SUCCEEDED(sq_get(_sr_J_env.JJ, -2))) { /* failed to gets the func field from the global table */ sq_settop(_sr_J_env.JJ, (top<=0)?1:top); /* restores the original stack size */ LM_ERR("sqlang failed to find symbol (call: %s)\n", func); return -1; } if(!sqlang_isfunction(_sr_J_env.JJ, -1)) { LM_ERR("no such function [%s] in sqlang scripts\n", func); LM_ERR("top stack type [%d]\n", sqlang_gettype(_sr_J_env.JJ, -1)); } /* push the 'this' (in this case is the global table) */ sq_pushroottable(_sr_J_env.JJ); n = 1; if(p1!=NULL) { sqlang_pushstring(_sr_J_env.JJ, p1); n++; if(p2!=NULL) { sqlang_pushstring(_sr_J_env.JJ, p2); n++; if(p3!=NULL) { sqlang_pushstring(_sr_J_env.JJ, p3); n++; } } } LM_DBG("executing sqlang function: [[%s]] (n: %d)\n", func, n); bmsg = _sr_J_env.msg; _sr_J_env.msg = msg; _sr_J_env.JJ_exit = 0; /* call the function */ rv = sq_call(_sr_J_env.JJ, n, SQFalse, SQTrue); if(SQ_SUCCEEDED(rv)) { ret = 1; } else { if(_sr_J_env.JJ_exit==0) { LM_ERR("failed to execute the func: %s (%d)\n", func, (int)rv); sqstd_printcallstack(_sr_J_env.JJ); ret = -1; } else { LM_DBG("script execution exit\n"); ret = 1; } } _sr_J_env.msg = bmsg; _sr_J_env.JJ_exit = 0; sq_settop(_sr_J_env.JJ, (top<=0)?1:top); /* restores the original stack size */ return ret; }
void sq_closethread(HSQUIRRELVM v) { sq_settop(v, 0); v->Finalize(); }
int Xml_eval(HSQUIRRELVM v) { SQ_FUNC_VARS_NO_TOP(v); SQChar* str = 0; size_t str_size=0; if(sq_gettype(v,2) == OT_USERPOINTER) sq_getuserpointer(v, 2, &str); else { SQ_GET_STRING(v, 2, sTmp); str = (SQChar*)sq_malloc(sTmp_size+(sizeof(SQChar))); memcpy(str, sTmp, sTmp_size); str[sTmp_size]=0; str_size = sTmp_size; } Tokenizer* tok = Tokenizer_new(str, str_size ? str_size : scstrlen(str)); sq_settop(v,0); const SQChar* token=0; int firstStatement = 1; while((token=Tokenizer_next(tok))!=0) if(token[0]==OPN) { // new tag found if(sq_gettop(v)) { int newIndex=sq_size(v,-1)+1; sq_pushinteger(v,newIndex); sq_newtable(v); sq_set(v, -3); sq_pushinteger(v,newIndex); sq_get(v,-2); } else { if (firstStatement) { sq_newtable(v); firstStatement = 0; } else return lua_gettop(L); } // set metatable: sq_newtable(v); sq_pushliteral(v, _SC("__index")); sq_getglobal(v, "xml"); lua_settable(v, -3); sq_pushliteral(v, _SC("__tostring")); // set __tostring metamethod lua_getglobal(L, "xml"); lua_pushliteral(L,"str"); lua_gettable(v, -2); sq_remove(v, -2); sq_set(v, -3); lua_setmetatable(L, -2); // parse tag and content: sq_pushinteger(v,0); // use index 0 for storing the tag sq_pushstring(v, Tokenizer_next(tok), -1); sq_set(v, -3); while(((token = Tokenizer_next(tok))!=0)&&(token[0]!=CLS)&&(token[0]!=ESC)) { // parse tag header size_t sepPos=find(token, "=", 0); if(token[sepPos]) { // regular attribute const SQChar* aVal =token+sepPos+2; sq_pushstring(v, token, sepPos); size_t lenVal = strlen(aVal)-1; if(!lenVal) Xml_pushDecode(v, _SC(""), 0); else Xml_pushDecode(v, aVal, lenVal); sq_set(v, -3); } } if(!token||(token[0]==ESC)) { if(sq_gettop(v)>1) sq_settop(v,-2); // this tag has no content, only attributes else break; } } else if(token[0]==ESC) { // previous tag is over if(sq_gettop(v)>1) sq_settop(v,-2); // pop current table else break; } else { // read elements sq_pushinteger(v,sq_size(v,-1)+1); Xml_pushDecode(v, token, 0); sq_rawset(v, -3); } Tokenizer_delete(tok); sq_free(str); return sq_gettop(v); }