static int getInstanceVarInfo(StackHandler & sa,VarRefPtr & vr,SQUserPointer & data) { HSQOBJECT ho = sa.GetObjectHandle(1); SquirrelObject instance(ho); const SQChar * el = sa.GetString(2); ScriptStringVar256 varNameTag; getVarNameTag(varNameTag,sizeof(varNameTag),el); SQUserPointer ivrData=0; if (!instance.RawGetUserData(varNameTag,&ivrData)) { return sa.ThrowError(_SC("getInstanceVarInfo: Could not retrieve UserData")); // Results in variable not being found error. } vr = (VarRefPtr)ivrData; char * up; if (!(vr->m_access & (VAR_ACCESS_STATIC|VAR_ACCESS_CONSTANT))) { SQUserPointer typetag; instance.GetTypeTag(&typetag); #if defined(SQ_USE_CLASS_INHERITANCE) if (typetag != vr->instanceType) { SquirrelObject typeTable = instance.GetValue(SQ_CLASS_OBJECT_TABLE_NAME); up = (char *)typeTable.GetUserPointer(INT((size_t)vr->instanceType)); // <TODO> 64-bit compatible version. if (!up) { throw SquirrelError(_SC("Invalid Instance Type")); } } else { up = (char *)instance.GetInstanceUP(0); } // if #elif defined(SQ_USE_CLASS_INHERITANCE_SIMPLE) ClassTypeBase *ctb = (ClassTypeBase*)vr->instanceType; up = (char *)instance.GetInstanceUP(0); // Walk base classes until type tag match, adjust for inheritence offset while(ctb && typetag!=ctb) { up = (char*)up - ctb->m_offset; ctb = ctb->m_pbase; } if (!ctb) { throw SquirrelError(_SC("Invalid Instance Type")); } #else up = (char *)instance.GetInstanceUP(0); #endif #ifdef SQPLUS_SMARTPOINTER_OPT #define SQPLUS_SMARTPOINTER_INSTANCE_VARINFO #include "SqPlusSmartPointer.h" #endif up += (size_t)vr->offsetOrAddrOrConst; // Offset } else { up = (char *)vr->offsetOrAddrOrConst; // Address } // if data = up; return SQ_OK; } // getInstanceVarInfo
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; }
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; }
SquirrelObject SquirrelVM::CompileBuffer(const SQChar *s) { SquirrelObject ret(_VM); if(SUCCEEDED(sq_compilebuffer(_VM,s,(int)wcslen(s)*sizeof(SQChar),_SC("console buffer"),1))) { ret.AttachToStackObject(-1); sq_pop(_VM,1); return ret; } throw SquirrelError(_VM); }
SquirrelObject SquirrelVM::CompileScript(const SQChar *s) { #define MAX_EXPANDED_PATH 1023 SquirrelObject ret(_VM); if(SUCCEEDED(sqstd_loadfile(_VM,s,1))) { ret.AttachToStackObject(-1); sq_pop(_VM,1); return ret; } throw SquirrelError(_VM); }
SquirrelObject SquirrelVM::CreateInstance(SquirrelObject &oclass) { SquirrelObject ret(_VM); int oldtop = sq_gettop(_VM); sq_pushobject(_VM,oclass._o); if(SQ_FAILED(sq_createinstance(_VM,-1))) { sq_settop(_VM,oldtop); throw SquirrelError(_VM); } ret.AttachToStackObject(-1); sq_pop(_VM,2); return ret; }
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); }
SquirrelObject SquirrelVM::EndCall() { SquirrelObject ret(_VM); if(_CallState >= 0) { int oldtop = sq_gettop(_VM); int nparams = _CallState; _CallState = -1; if(SQ_SUCCEEDED(sq_call(_VM,nparams,1,1))) { ret.AttachToStackObject(-1); sq_pop(_VM,2); }else { sq_settop(_VM,oldtop-(nparams+1)); throw SquirrelError(_VM); } } return ret; }
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); }
static int getInstanceVarInfo(StackHandler & sa,VarRefPtr & vr,SQUserPointer & data) { HSQOBJECT ho = sa.GetObjectHandle(1); SquirrelObject instance(ho); #ifdef _DEBUG SQObjectType type = (SQObjectType)sa.GetType(2); #endif const SQChar * el = sa.GetString(2); ScriptStringVar256 varNameTag; getVarNameTag(varNameTag,sizeof(varNameTag),el); SQUserPointer ivrData=0; if (!instance.RawGetUserData(varNameTag,&ivrData)) { // throw SquirrelError("getInstanceVarInfo: Could not retrieve UserData"); return sa.ThrowError(_T("getInstanceVarInfo: Could not retrieve UserData")); // Results in variable not being found error. } // if vr = (VarRefPtr)ivrData; unsigned char * up; if (!(vr->access & (VAR_ACCESS_STATIC|VAR_ACCESS_CONSTANT))) { #ifdef SQ_USE_CLASS_INHERITANCE SQUserPointer typetag; instance.GetTypeTag(&typetag); if (typetag != vr->instanceType) { SquirrelObject typeTable = instance.GetValue(SQ_CLASS_OBJECT_TABLE_NAME); up = (unsigned char *)typeTable.GetUserPointer(INT((size_t)vr->instanceType)); // <TODO> 64-bit compatible version. if (!up) { #if defined( MONASQ ) return sa.ThrowError(_T("Invalid Instance Type")); #else throw SquirrelError(_T("Invalid Instance Type")); #endif } // if } else { up = (unsigned char *)instance.GetInstanceUP(0); } // if #else up = (unsigned char *)instance.GetInstanceUP(0); #endif up += (size_t)vr->offsetOrAddrOrConst; // Offset } else { up = (unsigned char *)vr->offsetOrAddrOrConst; // Address } // if data = up; return SQ_OK; } // getInstanceVarInfo
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()); }
void compile_and_run(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename) { compile_script(vm, in, sourcename); SQInteger oldtop = sq_gettop(vm); try { sq_pushroottable(vm); if(SQ_FAILED(sq_call(vm, 1, SQFalse, SQTrue))) throw SquirrelError(vm, "Couldn't start script"); } catch(...) { sq_settop(vm, oldtop); throw; } // we can remove the closure in case the script was not suspended if(sq_getvmstate(vm) != SQ_VMSTATE_SUSPENDED) { sq_settop(vm, oldtop-1); } }
static int getVar(StackHandler & sa,VarRef * vr,void * data) { switch (vr->type) { case TypeInfo<INT>::TypeID: { if (!(vr->access & VAR_ACCESS_CONSTANT)) { INT * val = (INT *)data; // Address if (val) { return sa.Return(*val); } // if } else { INT * val = (INT *)&data; // Constant value return sa.Return(*val); } // if break; } // case case TypeInfo<FLOAT>::TypeID: { if (!(vr->access & VAR_ACCESS_CONSTANT)) { FLOAT * val = (FLOAT *)data; // Address if (val) { return sa.Return(*val); } // if } else { FLOAT * val = (FLOAT *)&data; // Constant value return sa.Return(*val); } // if break; } // case case TypeInfo<bool>::TypeID: { if (!(vr->access & VAR_ACCESS_CONSTANT)) { bool * val = (bool *)data; // Address if (val) { return sa.Return(*val); } // if } else { bool * val = (bool *)&data; // Constant value return sa.Return(*val); } // if break; } // case case VAR_TYPE_INSTANCE: if (!CreateNativeClassInstance(sa.GetVMPtr(),vr->typeName,data,0)) { // data = address. Allocates memory. ScriptStringVar256 msg; SCSNPRINTF(msg.s,sizeof(msg),_T("getVar(): Could not create instance: %s"),vr->typeName); #if defined( MONASQ ) return sa.ThrowError(msg.s); #else throw SquirrelError(msg.s); #endif } // if return 1; case TypeInfo<SQUserPointer>::TypeID: { return sa.Return(data); // The address of member variable, not the variable itself. } // case case TypeInfo<ScriptStringVarBase>::TypeID: { if (!(vr->access & VAR_ACCESS_CONSTANT)) { ScriptStringVarBase * val = (ScriptStringVarBase *)data; // Address if (val) { return sa.Return(val->s); } // if } else { #if defined( MONASQ ) return sa.ThrowError(_T("getVar(): Invalid type+access: 'ScriptStringVarBase' with VAR_ACCESS_CONSTANT (use VAR_ACCESS_READ_ONLY instead)")); #else throw SquirrelError(_T("getVar(): Invalid type+access: 'ScriptStringVarBase' with VAR_ACCESS_CONSTANT (use VAR_ACCESS_READ_ONLY instead)")); #endif } // if break; } // case case TypeInfo<const SQChar *>::TypeID: { if (!(vr->access & VAR_ACCESS_CONSTANT)) { #if defined( MONASQ ) return sa.ThrowError(_T("getVar(): Invalid type+access: 'const SQChar *' without VAR_ACCESS_CONSTANT")); #else throw SquirrelError(_T("getVar(): Invalid type+access: 'const SQChar *' without VAR_ACCESS_CONSTANT")); #endif } else { return sa.Return((const SQChar *)data); // Address } // if break; } // case } // switch return SQ_ERROR; } // getVar
static int setVar(StackHandler & sa,VarRef * vr,void * data) { if (vr->m_access & (VAR_ACCESS_READ_ONLY|VAR_ACCESS_CONSTANT)) { const SQChar * el = sa.GetString(2); SCSNPRINTF(g_msg_throw.s,sizeof(g_msg_throw),_SC("setVar(): Cannot write to constant: %s"),el); throw SquirrelError(g_msg_throw.s); } // if switch (vr->m_type) { case TypeInfo<INT>::TypeID: { INT * val = (INT *)data; // Address if (val) { INT v = sa.GetInt(3); // Support for different int sizes switch( vr->m_size ) { case 1: v = (*(char*)val = (char)v); break; case 2: v = (*(short*)val = (short)v); break; #ifdef _SQ64 case 4: v = (*(int*)val = (int)v); break; #endif default: *val = v; } return sa.Return(v); } // if break; } // case case TypeInfo<unsigned>::TypeID: { unsigned * val = (unsigned *)data; // Address if (val) { *val = sa.GetInt(3); return sa.Return(static_cast<INT>(*val)); } // if break; } // case case TypeInfo<FLOAT>::TypeID: { FLOAT * val = (FLOAT *)data; // Address if (val) { *val = sa.GetFloat(3); return sa.Return(*val); } // if break; } // case case TypeInfo<bool>::TypeID: { bool * val = (bool *)data; // Address if (val) { *val = sa.GetBool(3) ? true : false; return sa.Return(*val); } // if break; } // case case VAR_TYPE_INSTANCE: { HSQUIRRELVM v = sa.GetVMPtr(); SQUserPointer src = sa.GetInstanceUp(3,(SQUserPointer)vr->varType); // Effectively performs: ClassType<>::type() == ClassType<>(). if (!src) { throw SquirrelError(_SC("INSTANCE type assignment mismatch")); } vr->varType->vgetCopyFunc()(data,src); return 0; } case TypeInfo<SQUserPointer>::TypeID: { const SQChar * el = sa.GetString(2); SCSNPRINTF(g_msg_throw.s,sizeof(g_msg_throw),_SC("setVar(): Cannot write to an SQUserPointer: %s"),el); throw SquirrelError(g_msg_throw.s); } // case case TypeInfo<ScriptStringVarBase>::TypeID: { ScriptStringVarBase * val = (ScriptStringVarBase *)data; // Address if (val) { const SQChar * strVal = sa.GetString(3); if (strVal) { *val = strVal; return sa.Return(val->s); } // if } // if break; } // case #if defined(SQPLUS_SUPPORT_STD_STRING) && !defined(SQUNICODE) case TypeInfo<std::string>::TypeID: { std::string *val = (std::string*)data; // Address if (val) { const SQChar *strVal = sa.GetString(3); if (strVal) { *val = strVal; return sa.Return(val->c_str()); } // if } // if break; } // case #endif } // switch return SQ_ERROR; } // setVar
static int getVar(StackHandler & sa,VarRef * vr,void * data) { switch (vr->m_type) { case TypeInfo<INT>::TypeID: { if (!(vr->m_access & VAR_ACCESS_CONSTANT)) { if (data) { INT v; // Support for different int sizes switch( vr->m_size ){ case 1: v = *(char*)data; break; case 2: v = *(short*)data; break; #ifdef _SQ64 case 4: v = *(int*)data; break; #endif default: v = *(INT*)data; } return sa.Return(v); } // if } else { INT * val = (INT *)&data; // Constant value return sa.Return(*val); } // if break; } // case case TypeInfo<unsigned>::TypeID: { if (!(vr->m_access & VAR_ACCESS_CONSTANT)) { unsigned * val = (unsigned *)data; // Address if (val){ return sa.Return(static_cast<INT>(*val)); } } else { unsigned * val = (unsigned *)&data; // Constant value return sa.Return(static_cast<INT>(*val)); } // if break; } // case case TypeInfo<FLOAT>::TypeID: { if (!(vr->m_access & VAR_ACCESS_CONSTANT)) { FLOAT * val = (FLOAT *)data; // Address if (val) { return sa.Return(*val); } // if } else { FLOAT * val = (FLOAT *)&data; // Constant value return sa.Return(*val); } // if break; } // case case TypeInfo<bool>::TypeID: { if (!(vr->m_access & VAR_ACCESS_CONSTANT)) { bool * val = (bool *)data; // Address if (val) { return sa.Return(*val); } // if } else { bool * val = (bool *)&data; // Constant value return sa.Return(*val); } // if break; } // case case VAR_TYPE_INSTANCE: if (!CreateNativeClassInstance(sa.GetVMPtr(),vr->varType->GetTypeName(),data,0)) { // data = address. Allocates memory. SCSNPRINTF(g_msg_throw.s,sizeof(g_msg_throw),_SC("getVar(): Could not create instance: %s"),vr->varType->GetTypeName()); throw SquirrelError(g_msg_throw.s); } // if return 1; case TypeInfo<SQUserPointer>::TypeID: return sa.Return(data); // The address of member variable, not the variable itself. case TypeInfo<ScriptStringVarBase>::TypeID: { if (!(vr->m_access & VAR_ACCESS_CONSTANT)) { ScriptStringVarBase * val = (ScriptStringVarBase *)data; // Address if (val) { return sa.Return(val->s); } // if } else { throw SquirrelError(_SC("getVar(): Invalid type+access: 'ScriptStringVarBase' with VAR_ACCESS_CONSTANT (use VAR_ACCESS_READ_ONLY instead)")); } break; } // case case TypeInfo<const SQChar *>::TypeID: { if (!(vr->m_access & VAR_ACCESS_CONSTANT)) { if( vr->m_access==VAR_ACCESS_READ_WRITE ) throw SquirrelError(_SC("getVar(): Invalid type+access: 'const SQChar *' without VAR_ACCESS_CONSTANT")); // It is OK to read from a SQChar* if requested return sa.Return(*(const SQChar **)data); // Address } else { return sa.Return((const SQChar *)data); // Address } break; } // case #ifdef SQPLUS_SUPPORT_STD_STRING case TypeInfo<std::string>::TypeID: { if (!(vr->m_access & VAR_ACCESS_CONSTANT)) { std::string *val = (std::string *)data; // Address if (val) { return sa.Return(val->c_str()); } } else { throw SquirrelError(_SC("getVar(): Invalid type+access: 'std::string' with VAR_ACCESS_CONSTANT (use VAR_ACCESS_READ_ONLY instead)")); } break; } // case #endif } // switch return SQ_ERROR; } // getVar
static int setVar(StackHandler & sa,VarRef * vr,void * data) { if (vr->access & (VAR_ACCESS_READ_ONLY|VAR_ACCESS_CONSTANT)) { ScriptStringVar256 msg; const SQChar * el = sa.GetString(2); SCSNPRINTF(msg.s,sizeof(msg),_T("setVar(): Cannot write to constant: %s"),el); #if defined( MONASQ ) return sa.ThrowError(msg.s); #else throw SquirrelError(msg.s); #endif } // if switch (vr->type) { case TypeInfo<INT>::TypeID: { INT * val = (INT *)data; // Address if (val) { *val = sa.GetInt(3); return sa.Return(*val); } // if break; } // case case TypeInfo<FLOAT>::TypeID: { FLOAT * val = (FLOAT *)data; // Address if (val) { *val = sa.GetFloat(3); return sa.Return(*val); } // if break; } // case case TypeInfo<bool>::TypeID: { bool * val = (bool *)data; // Address if (val) { *val = sa.GetBool(3) ? true : false; return sa.Return(*val); } // if break; } // case case VAR_TYPE_INSTANCE: { HSQUIRRELVM v = sa.GetVMPtr(); // vr->copyFunc is the LHS variable type: the RHS var's type is ClassType<>::type() (both point to ClassType<>::copy()). // src will be null if the LHS and RHS types don't match. SQUserPointer src = sa.GetInstanceUp(3,(SQUserPointer)vr->copyFunc); // Effectively performs: ClassType<>::type() == ClassType<>getCopyFunc(). #if defined( MONASQ ) if (!src) return sa.ThrowError(_T("INSTANCE type assignment mismatch")); #else if (!src) throw SquirrelError(_T("INSTANCE type assignment mismatch")); #endif vr->copyFunc(data,src); #if 0 // Return an instance on the stack (allocates memory) if (!CreateNativeClassInstance(sa.GetVMPtr(),vr->typeName,data,0)) { // data = address ScriptStringVar256 msg; SCSNPRINTF(msg.s,sizeof(msg),_T("getVar(): Could not create instance: %s"),vr->typeName); throw SquirrelError(msg.s); } // if return 1; #else // Don't return on stack. return 0; #endif } case TypeInfo<SQUserPointer>::TypeID: { ScriptStringVar256 msg; const SQChar * el = sa.GetString(2); SCSNPRINTF(msg.s,sizeof(msg),_T("setVar(): Cannot write to an SQUserPointer: %s"),el); #if defined( MONASQ ) return sa.ThrowError(msg.s); #else throw SquirrelError(msg.s); #endif } // case case TypeInfo<ScriptStringVarBase>::TypeID: { ScriptStringVarBase * val = (ScriptStringVarBase *)data; // Address if (val) { const SQChar * strVal = sa.GetString(3); if (strVal) { *val = strVal; return sa.Return(val->s); } // if } // if break; } // case } // switch return SQ_ERROR; } // setVar
void compile_script(HSQUIRRELVM vm, std::istream& in, const std::string& sourcename) { if(SQ_FAILED(sq_compile(vm, squirrel_read_char, &in, sourcename.c_str(), true))) throw SquirrelError(vm, "Couldn't parse script"); }