// // 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 #include #if defined(_WIN32) #include #elif defined(__unix) #include #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)); #define SQUIRREL_API_FUNC(fret, fname, fargs) sq->sq_##fname = sq_##fname; #include "sqapi.h" #undef SQUIRREL_API_FUNC return sq; } static void sqrat_deleteapi(HSQAPI sq) { sq_free(sq, sizeof(sq_api)); } static SQRESULT sqrat_importscript(HSQUIRRELVM v, const SQChar* moduleName) { if(SQ_FAILED(sqstd_loadfile(v, moduleName, true, true))) { char filename[1024]; scsprintf(filename, sizeof(filename), "%s.nut", moduleName); if(SQ_FAILED(sqstd_loadfile(v, filename, true, 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) { SQMODULELOAD modLoad = 0; #if defined(_WIN32) HMODULE mod; mod = GetModuleHandleA(moduleName); if(mod == NULL) { mod = LoadLibraryA(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 #ifndef ANDROID_BUILD | RTLD_NOLOAD //RTLD_NOLOAD flag is not specified in POSIX.1-2001..so not the best solution :( #endif ); 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; } 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; } static SQRESULT 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 if(sq_gettype(v, 3) != OT_TABLE) return sq_throwerror(v, _SC("table expected as second parameter")); break; default: // Error, unexpected number of arguments return sq_throwerror(v, _SC("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 root table return SQ_OK; }