mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2025-06-16 07:07:13 +02:00
Added external Sqrat library.
This commit is contained in:
20
external/Sqrat/License.txt
vendored
Normal file
20
external/Sqrat/License.txt
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
Copyright (c) 2009 Brandon Jones
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source
|
||||
distribution.
|
373
external/Sqrat/sqratThread.cpp
vendored
Normal file
373
external/Sqrat/sqratThread.cpp
vendored
Normal file
@ -0,0 +1,373 @@
|
||||
//
|
||||
// SqratThread: Sqrat threading module
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
//#include "sqratlib/sqratBase.h"
|
||||
#include "sqratThread.h"
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
static HSQAPI sq;
|
||||
|
||||
//
|
||||
// Thread lib utility functions (not visible externally)
|
||||
//
|
||||
|
||||
static SQFloat sqrat_clock() {
|
||||
return ((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC;
|
||||
}
|
||||
|
||||
static SQInteger sqrat_strlen(const SQChar* str) {
|
||||
#if defined(_UNICODE)
|
||||
return static_cast<SQInteger>(wcslen(str) * sizeof(SQChar));
|
||||
#else
|
||||
return static_cast<SQInteger>(strlen(str) * sizeof(SQChar));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void sqrat_pushtaskarray(HSQUIRRELVM v) {
|
||||
HSQOBJECT taskarray;
|
||||
|
||||
sq->pushroottable(v);
|
||||
sq->pushstring(v,_SC("__sqrat_taskarray__"),-1);
|
||||
if(SQ_FAILED(sq->get(v, -2))) {
|
||||
// Not found, create a new namespace
|
||||
sq->pushstring(v,_SC("__sqrat_taskarray__"),-1);
|
||||
sq->newarray(v, 0);
|
||||
sq->getstackobj(v,-1,&taskarray); // Save namespace for later use
|
||||
sq->newslot(v, -3, 0);
|
||||
sq->pop(v, 1); // pop root table
|
||||
|
||||
sq->pushobject(v, taskarray); // push the newly bound array
|
||||
} else {
|
||||
sq->remove(v, -2); // pop sqrat table
|
||||
}
|
||||
}
|
||||
|
||||
static SQRESULT sqrat_pushclosure(HSQUIRRELVM v, const SQChar* script) {
|
||||
if(SQ_FAILED(sq->compilebuffer(v, script, sqrat_strlen(script), _SC(""), true))) {
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
sq->pushroottable(v);
|
||||
if(SQ_FAILED(sq->call(v, 1, 0, 1))) {
|
||||
sq->remove(v, -1); // remove compiled closure
|
||||
return SQ_ERROR;
|
||||
}
|
||||
sq->remove(v, -2); // remove compiled closure
|
||||
return SQ_OK;
|
||||
}
|
||||
|
||||
static SQInteger sqrat_schedule_argcall(HSQUIRRELVM v) {
|
||||
SQInteger nparams = sq->gettop(v) - 2; // Get the number of parameters provided
|
||||
|
||||
// The task table is the last argument (free variable), so we can operate on immediately
|
||||
sq->pushstring(v, _SC("args"), -1);
|
||||
|
||||
sq->newarray(v, 0); // Create the array for the arguments
|
||||
|
||||
// Loop through all arguments and push them into the arg array
|
||||
for(SQInteger i = 0; i < nparams; ++i) {
|
||||
sq->push(v, i+2);
|
||||
sq->arrayappend(v, -2);
|
||||
}
|
||||
|
||||
sq->newslot(v, -3, 0); // Push the arg array into the task table
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is a horrid way to get this functionality in there, but I can't find any alternatives right now.
|
||||
static SQRESULT sqrat_pushsleep(HSQUIRRELVM v) {
|
||||
SQChar* sleep_script = _SC(" \
|
||||
__sqratsleep__ <- function(timeout) { \
|
||||
local begin = clock(); \
|
||||
local now; \
|
||||
do { \
|
||||
::suspend(); \
|
||||
now = clock(); \
|
||||
} while( (now - begin) < timeout ); \
|
||||
} \
|
||||
");
|
||||
|
||||
if(SQ_FAILED(sq->compilebuffer(v, sleep_script, sqrat_strlen(sleep_script), _SC(""), true))) {
|
||||
return SQ_ERROR;
|
||||
}
|
||||
|
||||
sq->pushroottable(v);
|
||||
if(SQ_FAILED(sq->call(v, 1, 0, 1))) {
|
||||
sq->remove(v, -1); // remove compiled closure
|
||||
return SQ_ERROR;
|
||||
}
|
||||
sq->remove(v, -1); // remove compiled closure
|
||||
|
||||
sq->pushroottable(v);
|
||||
sq->pushstring(v, _SC("__sqratsleep__"), -1);
|
||||
SQRESULT res = sq->get(v, -2);
|
||||
|
||||
sq->remove(v, -2); // remove root table
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
//
|
||||
// Thread lib main functions
|
||||
//
|
||||
|
||||
static SQRESULT sqrat_sleep(HSQUIRRELVM v, SQFloat timeout) {
|
||||
return sq->suspendvm(v);
|
||||
|
||||
// Get "::suspend"
|
||||
/*HSQOBJECT suspend;
|
||||
sq->pushroottable(v);
|
||||
sq->pushstring(v, _SC("suspend"), -1);
|
||||
if(SQ_FAILED(sq->get(v, -2))) {
|
||||
return SQ_ERROR;
|
||||
}
|
||||
sq->getstackobj(v, -1, &suspend);
|
||||
sq->pop(v, 2);
|
||||
|
||||
// Loop ::suspend until the appropriate time has passed
|
||||
SQFloat timeStart = sqrat_clock();
|
||||
SQFloat timeNow = 0;
|
||||
|
||||
while(timeNow - timeStart < timeout) {
|
||||
sq->pushobject(v, suspend);
|
||||
sq->pushroottable(v);
|
||||
if(SQ_FAILED(sq->call(v, 1, 0, 1))) {
|
||||
return SQ_ERROR;
|
||||
}
|
||||
timeNow = sqrat_clock();
|
||||
}
|
||||
|
||||
return SQ_OK;*/
|
||||
}
|
||||
|
||||
static void sqrat_schedule(HSQUIRRELVM v, SQInteger idx) {
|
||||
HSQOBJECT thread;
|
||||
HSQOBJECT func;
|
||||
HSQOBJECT task;
|
||||
|
||||
sq->getstackobj(v, idx, &func);
|
||||
SQInteger stksize = 256; // TODO: Allow initial stack size to be configurable
|
||||
|
||||
sqrat_pushtaskarray(v); // Push the task array
|
||||
|
||||
// Create the task
|
||||
sq->newtable(v);
|
||||
sq->getstackobj(v, -1, &task);
|
||||
|
||||
// Create the thread and add it to the task table
|
||||
sq->pushstring(v, _SC("thread"), -1);
|
||||
sq->newthread(v, stksize);
|
||||
sq->getstackobj(v, -1, &thread);
|
||||
sq->newslot(v, -3, 0);
|
||||
|
||||
// Push the function to be called onto the thread stack
|
||||
sq->pushobject(v, func);
|
||||
sq->move(thread._unVal.pThread, v, -1);
|
||||
sq->pop(v, 1);
|
||||
|
||||
// Args will be pushed later, in the closure
|
||||
|
||||
sq->arrayappend(v, -2); // Add the task to the task array
|
||||
|
||||
sq->pushobject(v, task); // Push the task object as a free variable for the temporary closure
|
||||
sq->newclosure(v, sqrat_schedule_argcall, 1); // push a temporary closure used to retrieve call args
|
||||
}
|
||||
|
||||
// Wow... this has to be one of the ugliest functions I've ever writter. Ever.
|
||||
// Building complex logic with the squirrel stack really sucks.
|
||||
static void sqrat_run(HSQUIRRELVM v) {
|
||||
|
||||
HSQOBJECT taskArray;
|
||||
HSQOBJECT thread;
|
||||
HSQUIRRELVM threadVm;
|
||||
SQInteger nparams; // Number of parameters to pass to a function
|
||||
SQInteger arrayidx; //Cached index of the task array
|
||||
|
||||
// Push the tasklist
|
||||
sqrat_pushtaskarray(v); // Push the task array to the stack
|
||||
|
||||
sq->getstackobj(v, -1, &taskArray);
|
||||
arrayidx = sq->gettop(v); // Cache the stack location of the task array
|
||||
|
||||
SQInteger tasklistSize = sq->getsize(v, arrayidx); // Query the initial size of the task array
|
||||
do {
|
||||
SQInteger i = 0;
|
||||
|
||||
// This outer while is to allow us to pick up any new tasks that are added during the loop,
|
||||
// but still give us an opportunity to sleep after running through the initial tasks
|
||||
while(i < tasklistSize) {
|
||||
|
||||
for(; i < tasklistSize; ++i) {
|
||||
sq->pushinteger(v, i);
|
||||
if(SQ_FAILED(sq->get(v, -2))) { // Get the task
|
||||
sq->arrayremove(v, -2, i);
|
||||
sq->pop(v, 1);
|
||||
--tasklistSize;
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Now that we have the task, get the thread
|
||||
sq->pushstring(v, _SC("thread"), -1);
|
||||
if(SQ_FAILED(sq->get(v, -2))) {
|
||||
sq->arrayremove(v, -3, i);
|
||||
sq->pop(v, 1);
|
||||
--tasklistSize;
|
||||
--i;
|
||||
continue;
|
||||
}
|
||||
sq->getstackobj(v, -1, &thread);
|
||||
sq->pop(v, 1);
|
||||
|
||||
threadVm = thread._unVal.pThread;
|
||||
|
||||
if(sq->getvmstate(threadVm) == SQ_VMSTATE_IDLE) { // New thread? If so we need to call it
|
||||
|
||||
// Function to be called is already pushed to the thread (happens in schedule)
|
||||
sq->pushroottable(threadVm); // Pus the threads root table
|
||||
|
||||
sq->pushstring(v, _SC("args"), -1);
|
||||
if(SQ_FAILED(sq->get(v, -2))) { // Check to see if we have arguments for this thread
|
||||
nparams = 0; // No arguments
|
||||
} else {
|
||||
nparams = sq->getsize(v, -1); // Get the number of args in the arg array
|
||||
|
||||
// Push the arguments onto the thread stack
|
||||
for(SQInteger a = 0; a < nparams; ++a) {
|
||||
sq->pushinteger(v, a);
|
||||
if(SQ_FAILED(sq->get(v, -2))) {
|
||||
sq->pushnull(threadVm); // Is this the best way to handle this?
|
||||
} else {
|
||||
sq->move(threadVm, v, -1);
|
||||
sq->pop(v, 1);
|
||||
}
|
||||
}
|
||||
|
||||
sq->pop(v, 1); // Pop the arg array
|
||||
}
|
||||
|
||||
sq->call(threadVm, nparams+1, 0, 1); // Call the thread
|
||||
|
||||
} else {
|
||||
// If the thread is suspended, wake it up.
|
||||
// This function changed in Squirrel 2.2.3,
|
||||
// removing the last parameter makes it compatible with 2.2.2 and earlier
|
||||
sq->wakeupvm(threadVm, 0, 0, 1, 0);
|
||||
}
|
||||
|
||||
if(sq->getvmstate(threadVm) == SQ_VMSTATE_IDLE) { // Check to see if the thread is finished (idle again)
|
||||
sq->arrayremove(v, -2, i); // Remove the task from the task array
|
||||
|
||||
--tasklistSize; // Adjust the for variables to account for the removal
|
||||
--i;
|
||||
}
|
||||
|
||||
sq->pop(v, 1); // Pop off the task
|
||||
}
|
||||
|
||||
// Yield to system if needed
|
||||
|
||||
tasklistSize = sq->getsize(v, arrayidx); // Get the task
|
||||
|
||||
}
|
||||
|
||||
} while(tasklistSize > 0); // Loop until we have no more pending tasks
|
||||
}
|
||||
|
||||
//
|
||||
// Script interface functions
|
||||
//
|
||||
|
||||
static SQInteger sqratbase_sleep(HSQUIRRELVM v) {
|
||||
SQFloat timeout;
|
||||
sq->getfloat(v, -1, &timeout);
|
||||
sqrat_sleep(v, timeout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static SQInteger sqratbase_schedule(HSQUIRRELVM v) {
|
||||
sqrat_schedule(v, -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static SQInteger sqratbase_run(HSQUIRRELVM v) {
|
||||
sqrat_run(v);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// This is a squirrel only function, since there's really no need to
|
||||
// expose a native api for it. Just use the VM that you would have passed
|
||||
// in anyway!
|
||||
static SQInteger sqratbase_getthread(HSQUIRRELVM v) {
|
||||
// For the record, this way of doing things really sucks.
|
||||
// I would love a better way of retrieving this object!
|
||||
HSQOBJECT threadObj;
|
||||
threadObj._type = OT_THREAD;
|
||||
threadObj._unVal.pThread = v;
|
||||
|
||||
sq->pushobject(v, threadObj);
|
||||
sq->weakref(v, -1);
|
||||
sq->remove(v, -2);
|
||||
return 1;
|
||||
}
|
||||
|
||||
//
|
||||
// Module registration
|
||||
//
|
||||
|
||||
SQRESULT sqmodule_load(HSQUIRRELVM v, HSQAPI api) {
|
||||
|
||||
sq = api;
|
||||
|
||||
sq->pushstring(v, _SC("schedule"), -1);
|
||||
sq->newclosure(v, &sqratbase_schedule, 0);
|
||||
sq->newslot(v, -3, 0);
|
||||
|
||||
sq->pushstring(v, _SC("run"), -1);
|
||||
sq->newclosure(v, &sqratbase_run, 0);
|
||||
sq->newslot(v, -3, 0);
|
||||
|
||||
sq->pushstring(v, _SC("getthread"), -1);
|
||||
sq->newclosure(v, &sqratbase_getthread, 0);
|
||||
sq->newslot(v, -3, 0);
|
||||
|
||||
// Would rather do this...
|
||||
/*sq->pushstring(v, _SC("sleep"), -1);
|
||||
sq->newclosure(v, &sqratbase_sleep, 0);
|
||||
sq->newslot(v, -3, 0);*/
|
||||
|
||||
// Than this...
|
||||
sq->pushstring(v, _SC("sleep"), -1);
|
||||
if(SQ_FAILED(sqrat_pushsleep(v))) {
|
||||
sq->pop(v, 1);
|
||||
} else {
|
||||
sq->newslot(v, -3, 0);
|
||||
}
|
||||
|
||||
return SQ_OK;
|
||||
}
|
308
external/Sqrat/sqratimport.cpp
vendored
Normal file
308
external/Sqrat/sqratimport.cpp
vendored
Normal file
@ -0,0 +1,308 @@
|
||||
//
|
||||
// SqratImport: Supports importing of squirrel modules
|
||||
//
|
||||
|
||||
//
|
||||
// Copyright (c) 2009 Brandon Jones
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
//
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
//
|
||||
// 3. This notice may not be removed or altered from any source
|
||||
// distribution.
|
||||
//
|
||||
|
||||
#include "sqratimport.h"
|
||||
#include "sqmodule.h"
|
||||
|
||||
//#include "sqratlib/sqratBase.h"
|
||||
#include <sqstdio.h>
|
||||
#include <string>
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#elif defined(__unix)
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#endif
|
||||
|
||||
typedef SQRESULT (*SQMODULELOAD)(HSQUIRRELVM v, HSQAPI sq);
|
||||
|
||||
static HSQAPI sqapi = NULL;
|
||||
|
||||
// Create and populate the HSQAPI structure with function pointers
|
||||
// If new functions are added to the Squirrel API, they should be added here too
|
||||
static HSQAPI sqrat_newapi() {
|
||||
HSQAPI sq = (HSQAPI)sq_malloc(sizeof(sq_api));
|
||||
|
||||
/*vm*/
|
||||
sq->open = sq_open;
|
||||
sq->newthread = sq_newthread;
|
||||
sq->seterrorhandler = sq_seterrorhandler;
|
||||
sq->close = sq_close;
|
||||
sq->setforeignptr = sq_setforeignptr;
|
||||
sq->getforeignptr = sq_getforeignptr;
|
||||
sq->setprintfunc = sq_setprintfunc;
|
||||
sq->getprintfunc = sq_getprintfunc;
|
||||
sq->suspendvm = sq_suspendvm;
|
||||
sq->wakeupvm = sq_wakeupvm;
|
||||
sq->getvmstate = sq_getvmstate;
|
||||
|
||||
/*compiler*/
|
||||
sq->compile = sq_compile;
|
||||
sq->compilebuffer = sq_compilebuffer;
|
||||
sq->enabledebuginfo = sq_enabledebuginfo;
|
||||
sq->notifyallexceptions = sq_notifyallexceptions;
|
||||
sq->setcompilererrorhandler = sq_setcompilererrorhandler;
|
||||
|
||||
/*stack operations*/
|
||||
sq->push = sq_push;
|
||||
sq->pop = sq_pop;
|
||||
sq->poptop = sq_poptop;
|
||||
sq->remove = sq_remove;
|
||||
sq->gettop = sq_gettop;
|
||||
sq->settop = sq_settop;
|
||||
sq->reservestack = sq_reservestack;
|
||||
sq->cmp = sq_cmp;
|
||||
sq->move = sq_move;
|
||||
|
||||
/*object creation handling*/
|
||||
sq->newuserdata = sq_newuserdata;
|
||||
sq->newtable = sq_newtable;
|
||||
sq->newarray = sq_newarray;
|
||||
sq->newclosure = sq_newclosure;
|
||||
sq->setparamscheck = sq_setparamscheck;
|
||||
sq->bindenv = sq_bindenv;
|
||||
sq->pushstring = sq_pushstring;
|
||||
sq->pushfloat = sq_pushfloat;
|
||||
sq->pushinteger = sq_pushinteger;
|
||||
sq->pushbool = sq_pushbool;
|
||||
sq->pushuserpointer = sq_pushuserpointer;
|
||||
sq->pushnull = sq_pushnull;
|
||||
sq->gettype = sq_gettype;
|
||||
sq->getsize = sq_getsize;
|
||||
sq->getbase = sq_getbase;
|
||||
sq->instanceof = sq_instanceof;
|
||||
sq->tostring = sq_tostring;
|
||||
sq->tobool = sq_tobool;
|
||||
sq->getstring = sq_getstring;
|
||||
sq->getinteger = sq_getinteger;
|
||||
sq->getthread = sq_getthread;
|
||||
sq->getbool = sq_getbool;
|
||||
sq->getuserpointer = sq_getuserpointer;
|
||||
sq->getuserdata = sq_getuserdata;
|
||||
sq->settypetag = sq_settypetag;
|
||||
sq->gettypetag = sq_gettypetag;
|
||||
sq->setreleasehook = sq_setreleasehook;
|
||||
sq->getscratchpad = sq_getscratchpad;
|
||||
sq->getclosureinfo = sq_getclosureinfo;
|
||||
sq->setnativeclosurename = sq_setnativeclosurename;
|
||||
sq->setinstanceup = sq_setinstanceup;
|
||||
sq->getinstanceup = sq_getinstanceup;
|
||||
sq->setclassudsize = sq_setclassudsize;
|
||||
sq->newclass = sq_newclass;
|
||||
sq->createinstance = sq_createinstance;
|
||||
sq->setattributes = sq_setattributes;
|
||||
sq->getattributes = sq_getattributes;
|
||||
sq->getclass = sq_getclass;
|
||||
sq->weakref = sq_weakref;
|
||||
sq->getdefaultdelegate = sq_getdefaultdelegate;
|
||||
|
||||
/*object manipulation*/
|
||||
sq->pushroottable = sq_pushroottable;
|
||||
sq->pushregistrytable = sq_pushregistrytable;
|
||||
sq->pushconsttable = sq_pushconsttable;
|
||||
sq->setroottable = sq_setroottable;
|
||||
sq->setconsttable = sq_setconsttable;
|
||||
sq->newslot = sq_newslot;
|
||||
sq->deleteslot = sq_deleteslot;
|
||||
sq->set = sq_set;
|
||||
sq->get = sq_get;
|
||||
sq->rawset = sq_rawset;
|
||||
sq->rawget = sq_rawget;
|
||||
sq->rawdeleteslot = sq_rawdeleteslot;
|
||||
sq->arrayappend = sq_arrayappend;
|
||||
sq->arraypop = sq_arraypop;
|
||||
sq->arrayresize = sq_arrayresize;
|
||||
sq->arrayreverse = sq_arrayreverse;
|
||||
sq->arrayremove = sq_arrayremove;
|
||||
sq->arrayinsert = sq_arrayinsert;
|
||||
sq->setdelegate = sq_setdelegate;
|
||||
sq->getdelegate = sq_getdelegate;
|
||||
sq->clone = sq_clone;
|
||||
sq->setfreevariable = sq_setfreevariable;
|
||||
sq->next = sq_next;
|
||||
sq->getweakrefval = sq_getweakrefval;
|
||||
sq->clear = sq_clear;
|
||||
|
||||
/*calls*/
|
||||
sq->call = sq_call;
|
||||
sq->resume = sq_resume;
|
||||
sq->getlocal = sq_getlocal;
|
||||
sq->getfreevariable = sq_getfreevariable;
|
||||
sq->throwerror = sq_throwerror;
|
||||
sq->reseterror = sq_reseterror;
|
||||
sq->getlasterror = sq_getlasterror;
|
||||
|
||||
/*raw object handling*/
|
||||
sq->getstackobj = sq_getstackobj;
|
||||
sq->pushobject = sq_pushobject;
|
||||
sq->addref = sq_addref;
|
||||
sq->release = sq_release;
|
||||
sq->resetobject = sq_resetobject;
|
||||
sq->objtostring = sq_objtostring;
|
||||
sq->objtobool = sq_objtobool;
|
||||
sq->objtointeger = sq_objtointeger;
|
||||
sq->objtofloat = sq_objtofloat;
|
||||
sq->getobjtypetag = sq_getobjtypetag;
|
||||
|
||||
/*GC*/
|
||||
sq->collectgarbage = sq_collectgarbage;
|
||||
|
||||
/*serialization*/
|
||||
sq->writeclosure = sq_writeclosure;
|
||||
sq->readclosure = sq_readclosure;
|
||||
|
||||
/*mem allocation*/
|
||||
sq->malloc = sq_malloc;
|
||||
sq->realloc = sq_realloc;
|
||||
sq->free = sq_free;
|
||||
|
||||
/*debug*/
|
||||
sq->stackinfos = sq_stackinfos;
|
||||
sq->setdebughook = sq_setdebughook;
|
||||
|
||||
return sq;
|
||||
}
|
||||
|
||||
|
||||
static SQRESULT sqrat_importscript(HSQUIRRELVM v, const SQChar* moduleName) {
|
||||
std::basic_string<SQChar> filename(moduleName);
|
||||
filename += _SC(".nut");
|
||||
if(SQ_FAILED(sqstd_loadfile(v, moduleName, true))) {
|
||||
if(SQ_FAILED(sqstd_loadfile(v, filename.c_str(), true))) {
|
||||
return SQ_ERROR;
|
||||
}
|
||||
}
|
||||
sq_push(v, -2);
|
||||
sq_call(v, 1, false, true);
|
||||
return SQ_OK;
|
||||
}
|
||||
|
||||
static SQRESULT sqrat_importbin(HSQUIRRELVM v, const SQChar* moduleName) {
|
||||
#ifdef SQUNICODE
|
||||
#warning sqrat_importbin() Not Implemented
|
||||
return SQ_ERROR;
|
||||
#else
|
||||
SQMODULELOAD modLoad = 0;
|
||||
|
||||
#if defined(_WIN32)
|
||||
HMODULE mod;
|
||||
mod = GetModuleHandle(moduleName);
|
||||
if(mod == NULL) {
|
||||
mod = LoadLibrary(moduleName);
|
||||
if(mod == NULL) {
|
||||
return SQ_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
modLoad = (SQMODULELOAD)GetProcAddress(mod, "sqmodule_load");
|
||||
if(modLoad == NULL) {
|
||||
FreeLibrary(mod);
|
||||
return SQ_ERROR;
|
||||
}
|
||||
#elif defined(__unix)
|
||||
/* adding .so to moduleName? */
|
||||
void *mod = dlopen(moduleName, RTLD_NOW | RTLD_LOCAL | RTLD_NOLOAD); //RTLD_NOLOAD flag is not specified in POSIX.1-2001..so not the best solution :(
|
||||
if (mod == NULL) {
|
||||
mod = dlopen(moduleName, RTLD_NOW | RTLD_LOCAL);
|
||||
if (mod == NULL)
|
||||
return SQ_ERROR;
|
||||
}
|
||||
modLoad = (SQMODULELOAD) dlsym(mod, "sqmodule_load");
|
||||
if (modLoad == NULL) {
|
||||
dlclose(mod);
|
||||
return SQ_ERROR;
|
||||
}
|
||||
#endif
|
||||
|
||||
if(sqapi == NULL) {
|
||||
sqapi = sqrat_newapi(); // Caching this for multiple imports is probably a very good idea
|
||||
}
|
||||
|
||||
SQRESULT res = modLoad(v, sqapi);
|
||||
|
||||
return res;
|
||||
#endif
|
||||
}
|
||||
|
||||
SQRESULT sqrat_import(HSQUIRRELVM v) {
|
||||
const SQChar* moduleName;
|
||||
HSQOBJECT table;
|
||||
SQRESULT res = SQ_OK;
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
static SQInteger sqratbase_import(HSQUIRRELVM v) {
|
||||
SQInteger args = sq_gettop(v);
|
||||
switch(args) {
|
||||
case 2:
|
||||
sq_pushroottable(v);
|
||||
break;
|
||||
case 3:
|
||||
// should already have the desired table pushed onto the stack
|
||||
break;
|
||||
default:
|
||||
// Error, unexpected number of arguments
|
||||
break;
|
||||
}
|
||||
|
||||
sqrat_import(v);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
SQRESULT sqrat_register_importlib(HSQUIRRELVM v) {
|
||||
sq_pushroottable(v);
|
||||
|
||||
sq_pushstring(v, _SC("import"), -1);
|
||||
sq_newclosure(v, &sqratbase_import, 0);
|
||||
sq_newslot(v, -3, 0);
|
||||
|
||||
sq_pop(v, 1); // pop sqrat table
|
||||
|
||||
return SQ_OK;
|
||||
}
|
Reference in New Issue
Block a user