// GetNodeHeader(Node:nodeid,&nodes,&vehicle_nodes,&ped_nodes,&navi_nodes); int n_GetNodeHeader(HSQUIRRELVM pVM) { int nodeid; sq_getinteger(pVM,-1,&nodeid); if(pNodes[nodeid]) { int d1 = 0, d2 = 0, d3 = 0; pNodes[nodeid]->GetInfo(&d1,&d2,&d3); sq_newarray(pVM, 0); sq_pushinteger(pVM,d1); sq_arrayappend(pVM, -2); sq_pushinteger(pVM,d2); sq_arrayappend(pVM, -2); sq_pushinteger(pVM,d3); sq_arrayappend(pVM, -2); sq_push(pVM, -1); return 1; } return 0; }
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 ); }
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); } } }
SQInteger ScriptList::Valuate(HSQUIRRELVM vm) { this->modifications++; /* The first parameter is the instance of ScriptList. */ int nparam = sq_gettop(vm) - 1; if (nparam < 1) { return sq_throwerror(vm, _SC("You need to give a least a Valuator as parameter to ScriptList::Valuate")); } /* Make sure the valuator function is really a function, and not any * other type. It's parameter 2 for us, but for the user it's the * first parameter they give. */ SQObjectType valuator_type = sq_gettype(vm, 2); if (valuator_type != OT_CLOSURE && valuator_type != OT_NATIVECLOSURE) { return sq_throwerror(vm, _SC("parameter 1 has an invalid type (expected function)")); } /* Don't allow docommand from a Valuator, as we can't resume in * mid C++-code. */ bool backup_allow = ScriptObject::GetAllowDoCommand(); ScriptObject::SetAllowDoCommand(false); /* Push the function to call */ sq_push(vm, 2); for (ScriptListMap::iterator iter = this->items.begin(); iter != this->items.end(); iter++) { /* Check for changing of items. */ int previous_modification_count = this->modifications; /* Push the root table as instance object, this is what squirrel does for meta-functions. */ sq_pushroottable(vm); /* Push all arguments for the valuator function. */ sq_pushinteger(vm, (*iter).first); for (int i = 0; i < nparam - 1; i++) { sq_push(vm, i + 3); } /* Call the function. Squirrel pops all parameters and pushes the return value. */ if (SQ_FAILED(sq_call(vm, nparam + 1, SQTrue, SQTrue))) { ScriptObject::SetAllowDoCommand(backup_allow); return SQ_ERROR; } /* Retreive the return value */ SQInteger value; switch (sq_gettype(vm, -1)) { case OT_INTEGER: { sq_getinteger(vm, -1, &value); break; } case OT_BOOL: { SQBool v; sq_getbool(vm, -1, &v); value = v ? 1 : 0; break; } default: { /* See below for explanation. The extra pop is the return value. */ sq_pop(vm, nparam + 4); ScriptObject::SetAllowDoCommand(backup_allow); return sq_throwerror(vm, _SC("return value of valuator is not valid (not integer/bool)")); } } /* Was something changed? */ if (previous_modification_count != this->modifications) { /* See below for explanation. The extra pop is the return value. */ sq_pop(vm, nparam + 4); ScriptObject::SetAllowDoCommand(backup_allow); return sq_throwerror(vm, _SC("modifying valuated list outside of valuator function")); } this->SetValue((*iter).first, value); /* Pop the return value. */ sq_poptop(vm); Squirrel::DecreaseOps(vm, 5); } /* Pop from the squirrel stack: * 1. The root stable (as instance object). * 2. The valuator function. * 3. The parameters given to this function. * 4. The ScriptList instance object. */ sq_pop(vm, nparam + 3); ScriptObject::SetAllowDoCommand(backup_allow); return 0; }
bool CSquirrelArgument::pushFromStack(SQVM * pVM, int idx) { reset(); SQObjectPtr obj = stack_get(pVM, idx); switch(obj._type) { case OT_NULL: // Nothing needed break; case OT_INTEGER: data.i = obj._unVal.nInteger; break; case OT_BOOL: data.b = (obj._unVal.nInteger != 0); break; case OT_FLOAT: data.f = obj._unVal.fFloat; break; case OT_STRING: data.str = new String(obj._unVal.pString->_val); break; case OT_TABLE: { CSquirrelArguments * pArguments = new CSquirrelArguments(); sq_push(pVM, idx); sq_pushnull(pVM); while(SQ_SUCCEEDED(sq_next(pVM, -2))) { if(!pArguments->pushFromStack(pVM, -2) || !pArguments->pushFromStack(pVM, -1)) { sq_pop(pVM, 4); delete pArguments; return false; } sq_pop(pVM, 2); } sq_pop(pVM, 2); data.pArray = pArguments; } break; case OT_ARRAY: { CSquirrelArguments * pArguments = new CSquirrelArguments(); sq_push(pVM, idx); sq_pushnull(pVM); while(SQ_SUCCEEDED(sq_next(pVM, -2))) { if(!pArguments->pushFromStack(pVM, -1)) { sq_pop(pVM, 4); delete pArguments; return false; } sq_pop(pVM, 2); } sq_pop(pVM, 2); data.pArray = pArguments; } break; case OT_CLOSURE: case OT_NATIVECLOSURE: data.sqObject = SQObject(obj); break; case OT_INSTANCE: data.pInstance = obj._unVal.pInstance; break; default: return false; break; } type = obj._type; return true; }
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; }
// ------------------------------------------------------------------------------------------------ SQInteger Signal::SqRequest(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, true, ErrorHandling::IsEnabled()); // Validate the result if (SQ_FAILED(res)) { return res; // Propagate the error } // Is the returned value not null? else if (sq_gettype(vm, -1) != OT_NULL) { // Push back the returned value sq_push(vm, -1); // Specify that we returned something return 1; } } // Specify that we returned nothing return 0; }
// ------------------------------------------------------------------------------------------------ SQInteger Signal::SqQuery(HSQUIRRELVM vm) { const Int32 top = sq_gettop(vm); // Do we have the collector environment? if (top <= 1) { return sq_throwerror(vm, "Missing collector environment"); } // Do we have the collector function? else if (top <= 2) { return sq_throwerror(vm, "Missing collector callback"); } // The signal instance Signal * signal = nullptr; // Attempt to extract the signal instance and collector 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"); } // The collector HSQOBJECT cenv, cfunc; // Grab the collector environment SQRESULT res = sq_getstackobj(vm, 2, &cenv); // Validate the result if (SQ_FAILED(res)) { return res; // Propagate the error } // Was there a valid environment? else if (sq_isnull(cenv)) { // Remember the current stack size const StackGuard sg(vm); // Default to the root table sq_pushroottable(vm); // Try to grab the collector environment again SQRESULT res = sq_getstackobj(vm, -1, &cenv); // Validate the result if (SQ_FAILED(res)) { return res; // Propagate the error } } // Grab the collector function res = sq_getstackobj(vm, 3, &cfunc); // Validate the result if (SQ_FAILED(res)) { return res; // Propagate the error } // Some dummy checks to make sure the collector is a callable object else if (!sq_isfunction(cfunc) && !sq_isclosure(cfunc) && !sq_isnativeclosure(cfunc)) { return sq_throwerror(vm, "Invalid collector"); } // 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 > 3) { for (SQInteger i = 4; i <= top; ++i) { sq_push(vm, i); } } // Make the function call and store the result res = sq_call(vm, top - 2, true, ErrorHandling::IsEnabled()); // Validate the result if (SQ_FAILED(res)) { return res; // Propagate the error } // Push the collector onto the stack sq_pushobject(vm, cfunc); sq_pushobject(vm, cenv); // Push the returned value sq_push(vm, -3); // Make the function call and store the result res = sq_call(vm, 2, 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 CSquirrelArguments::pushFromStack(SQVM* pVM, int idx) { switch(sq_gettype(pVM,idx)) { case OT_NULL: push(); break; case OT_INTEGER: { int i; sq_getinteger(pVM, idx, &i); push(i); } break; case OT_BOOL: { SQBool b; sq_getbool(pVM, idx, &b); push(b!=0); } break; case OT_FLOAT: { float f; sq_getfloat(pVM, idx, &f); push(f); } break; case OT_STRING: { const char* szTemp; sq_getstring(pVM, idx, &szTemp); push(szTemp); } break; case OT_TABLE: { CSquirrelArguments* pArguments = new CSquirrelArguments(); sq_push(pVM, idx); sq_pushnull(pVM); while(SQ_SUCCEEDED(sq_next(pVM,-2))) { if(!pArguments->pushFromStack(pVM, -2) || !pArguments->pushFromStack(pVM,-1)) { sq_pop(pVM,4); delete pArguments; return false; } sq_pop(pVM,2); } sq_pop(pVM,2); push(pArguments, false); break; } case OT_ARRAY: { CSquirrelArguments* pArguments = new CSquirrelArguments(); sq_push(pVM, idx); sq_pushnull(pVM); while(SQ_SUCCEEDED(sq_next(pVM,-2))) { if(!pArguments->pushFromStack(pVM,-1)) { sq_pop(pVM,4); delete pArguments; return false; } sq_pop(pVM,2); } sq_pop(pVM,2); push(pArguments, true); break; } default: return false; } return true; }
static SQInteger _string_escape(HSQUIRRELVM v) { const SQChar *str; SQChar *dest,*resstr; SQInteger size; sq_getstring(v,2,&str); size = sq_getsize(v,2); if(size == 0) { sq_push(v,2); return 1; } #ifdef SQUNICODE #if WCHAR_SIZE == 2 const SQChar *escpat = _SC("\\x%04x"); const SQInteger maxescsize = 6; #else //WCHAR_SIZE == 4 const SQChar *escpat = _SC("\\x%08x"); const SQInteger maxescsize = 10; #endif #else const SQChar *escpat = _SC("\\x%02x"); const SQInteger maxescsize = 4; #endif SQInteger destcharsize = (size * maxescsize); //assumes every char could be escaped resstr = dest = (SQChar *)sq_getscratchpad(v,destcharsize * sizeof(SQChar)); SQChar c; SQChar escch; SQInteger escaped = 0; for(int n = 0; n < size; n++){ c = *str++; escch = 0; if(scisprint(c) || c == 0) { switch(c) { case '\a': escch = 'a'; break; case '\b': escch = 'b'; break; case '\t': escch = 't'; break; case '\n': escch = 'n'; break; case '\v': escch = 'v'; break; case '\f': escch = 'f'; break; case '\r': escch = 'r'; break; case '\\': escch = '\\'; break; case '\"': escch = '\"'; break; case '\'': escch = '\''; break; case 0: escch = '0'; break; } if(escch) { *dest++ = '\\'; *dest++ = escch; escaped++; } else { *dest++ = c; } } else { dest += scsprintf(dest, destcharsize, escpat, c); escaped++; } } if(escaped) { sq_pushstring(v,resstr,dest - resstr); } else { sq_push(v,2); //nothing escaped } return 1; }