sqratimport.cpp 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314
  1. //
  2. // SqratImport: Supports importing of squirrel modules
  3. //
  4. //
  5. // Copyright (c) 2009 Brandon Jones
  6. //
  7. // This software is provided 'as-is', without any express or implied
  8. // warranty. In no event will the authors be held liable for any damages
  9. // arising from the use of this software.
  10. //
  11. // Permission is granted to anyone to use this software for any purpose,
  12. // including commercial applications, and to alter it and redistribute it
  13. // freely, subject to the following restrictions:
  14. //
  15. // 1. The origin of this software must not be misrepresented; you must not
  16. // claim that you wrote the original software. If you use this software
  17. // in a product, an acknowledgment in the product documentation would be
  18. // appreciated but is not required.
  19. //
  20. // 2. Altered source versions must be plainly marked as such, and must not be
  21. // misrepresented as being the original software.
  22. //
  23. // 3. This notice may not be removed or altered from any source
  24. // distribution.
  25. //
  26. #include "sqratimport.h"
  27. #include "sqmodule.h"
  28. //#include "sqratlib/sqratBase.h"
  29. #include <sqstdio.h>
  30. #include <string>
  31. #if defined(_WIN32)
  32. #include <windows.h>
  33. #elif defined(__unix)
  34. #include <dlfcn.h>
  35. #endif
  36. typedef SQRESULT (*SQMODULELOAD)(HSQUIRRELVM v, HSQAPI sq);
  37. static HSQAPI sqapi = NULL;
  38. // Create and populate the HSQAPI structure with function pointers
  39. // If new functions are added to the Squirrel API, they should be added here too
  40. static HSQAPI sqrat_newapi() {
  41. HSQAPI sq = (HSQAPI)sq_malloc(sizeof(sq_api));
  42. /*vm*/
  43. sq->open = sq_open;
  44. sq->newthread = sq_newthread;
  45. sq->seterrorhandler = sq_seterrorhandler;
  46. sq->close = sq_close;
  47. sq->setforeignptr = sq_setforeignptr;
  48. sq->getforeignptr = sq_getforeignptr;
  49. sq->setprintfunc = sq_setprintfunc;
  50. sq->getprintfunc = sq_getprintfunc;
  51. sq->suspendvm = sq_suspendvm;
  52. sq->wakeupvm = sq_wakeupvm;
  53. sq->getvmstate = sq_getvmstate;
  54. /*compiler*/
  55. sq->compile = sq_compile;
  56. sq->compilebuffer = sq_compilebuffer;
  57. sq->enabledebuginfo = sq_enabledebuginfo;
  58. sq->notifyallexceptions = sq_notifyallexceptions;
  59. sq->setcompilererrorhandler = sq_setcompilererrorhandler;
  60. /*stack operations*/
  61. sq->push = sq_push;
  62. sq->pop = sq_pop;
  63. sq->poptop = sq_poptop;
  64. sq->remove = sq_remove;
  65. sq->gettop = sq_gettop;
  66. sq->settop = sq_settop;
  67. sq->reservestack = sq_reservestack;
  68. sq->cmp = sq_cmp;
  69. sq->move = sq_move;
  70. /*object creation handling*/
  71. sq->newuserdata = sq_newuserdata;
  72. sq->newtable = sq_newtable;
  73. sq->newarray = sq_newarray;
  74. sq->newclosure = sq_newclosure;
  75. sq->setparamscheck = sq_setparamscheck;
  76. sq->bindenv = sq_bindenv;
  77. sq->pushstring = sq_pushstring;
  78. sq->pushfloat = sq_pushfloat;
  79. sq->pushinteger = sq_pushinteger;
  80. sq->pushbool = sq_pushbool;
  81. sq->pushuserpointer = sq_pushuserpointer;
  82. sq->pushnull = sq_pushnull;
  83. sq->gettype = sq_gettype;
  84. sq->getsize = sq_getsize;
  85. sq->getbase = sq_getbase;
  86. sq->instanceof = sq_instanceof;
  87. sq->tostring = sq_tostring;
  88. sq->tobool = sq_tobool;
  89. sq->tointeger = sq_tointeger;
  90. sq->tofloat = sq_tofloat;
  91. sq->getstring = sq_getstring;
  92. sq->getinteger = sq_getinteger;
  93. sq->getthread = sq_getthread;
  94. sq->getbool = sq_getbool;
  95. sq->getuserpointer = sq_getuserpointer;
  96. sq->getuserdata = sq_getuserdata;
  97. sq->settypetag = sq_settypetag;
  98. sq->gettypetag = sq_gettypetag;
  99. sq->setreleasehook = sq_setreleasehook;
  100. sq->getscratchpad = sq_getscratchpad;
  101. sq->getclosureinfo = sq_getclosureinfo;
  102. sq->setnativeclosurename = sq_setnativeclosurename;
  103. sq->setinstanceup = sq_setinstanceup;
  104. sq->getinstanceup = sq_getinstanceup;
  105. sq->setclassudsize = sq_setclassudsize;
  106. sq->newclass = sq_newclass;
  107. sq->createinstance = sq_createinstance;
  108. sq->setattributes = sq_setattributes;
  109. sq->getattributes = sq_getattributes;
  110. sq->getclass = sq_getclass;
  111. sq->weakref = sq_weakref;
  112. sq->getdefaultdelegate = sq_getdefaultdelegate;
  113. /*object manipulation*/
  114. sq->pushroottable = sq_pushroottable;
  115. sq->pushregistrytable = sq_pushregistrytable;
  116. sq->pushconsttable = sq_pushconsttable;
  117. sq->setroottable = sq_setroottable;
  118. sq->setconsttable = sq_setconsttable;
  119. sq->newslot = sq_newslot;
  120. sq->deleteslot = sq_deleteslot;
  121. sq->set = sq_set;
  122. sq->get = sq_get;
  123. sq->rawset = sq_rawset;
  124. sq->rawget = sq_rawget;
  125. sq->rawdeleteslot = sq_rawdeleteslot;
  126. sq->arrayappend = sq_arrayappend;
  127. sq->arraypop = sq_arraypop;
  128. sq->arrayresize = sq_arrayresize;
  129. sq->arrayreverse = sq_arrayreverse;
  130. sq->arrayremove = sq_arrayremove;
  131. sq->arrayinsert = sq_arrayinsert;
  132. sq->setdelegate = sq_setdelegate;
  133. sq->getdelegate = sq_getdelegate;
  134. sq->clone = sq_clone;
  135. sq->setfreevariable = sq_setfreevariable;
  136. sq->next = sq_next;
  137. sq->getweakrefval = sq_getweakrefval;
  138. sq->clear = sq_clear;
  139. /*calls*/
  140. sq->call = sq_call;
  141. sq->resume = sq_resume;
  142. sq->getlocal = sq_getlocal;
  143. sq->getfreevariable = sq_getfreevariable;
  144. sq->throwerror = sq_throwerror;
  145. sq->reseterror = sq_reseterror;
  146. sq->getlasterror = sq_getlasterror;
  147. /*raw object handling*/
  148. sq->getstackobj = sq_getstackobj;
  149. sq->pushobject = sq_pushobject;
  150. sq->addref = sq_addref;
  151. sq->release = sq_release;
  152. sq->resetobject = sq_resetobject;
  153. sq->objtostring = sq_objtostring;
  154. sq->objtobool = sq_objtobool;
  155. sq->objtointeger = sq_objtointeger;
  156. sq->objtofloat = sq_objtofloat;
  157. sq->getobjtypetag = sq_getobjtypetag;
  158. /*GC*/
  159. sq->collectgarbage = sq_collectgarbage;
  160. /*serialization*/
  161. sq->writeclosure = sq_writeclosure;
  162. sq->readclosure = sq_readclosure;
  163. /*mem allocation*/
  164. sq->malloc = sq_malloc;
  165. sq->realloc = sq_realloc;
  166. sq->free = sq_free;
  167. /*debug*/
  168. sq->stackinfos = sq_stackinfos;
  169. sq->setdebughook = sq_setdebughook;
  170. return sq;
  171. }
  172. static void sqrat_deleteapi(HSQAPI sq) {
  173. sq_free(sq, sizeof(sq_api));
  174. }
  175. static SQRESULT sqrat_importscript(HSQUIRRELVM v, const SQChar* moduleName) {
  176. if(SQ_FAILED(sqstd_loadfile(v, moduleName, true, true))) {
  177. std::basic_string<SQChar> filename(moduleName);
  178. filename += _SC(".nut");
  179. if(SQ_FAILED(sqstd_loadfile(v, filename.c_str(), true, true))) {
  180. return SQ_ERROR;
  181. }
  182. }
  183. sq_push(v, -2);
  184. sq_call(v, 1, false, true);
  185. return SQ_OK;
  186. }
  187. static SQRESULT sqrat_importbin(HSQUIRRELVM v, const SQChar* moduleName) {
  188. SQMODULELOAD modLoad = 0;
  189. #if defined(_WIN32)
  190. HMODULE mod;
  191. mod = GetModuleHandleA(moduleName);
  192. if(mod == NULL) {
  193. mod = LoadLibraryA(moduleName);
  194. if(mod == NULL) {
  195. return SQ_ERROR;
  196. }
  197. }
  198. modLoad = (SQMODULELOAD)GetProcAddressA(mod, "sqmodule_load");
  199. if(modLoad == NULL) {
  200. FreeLibrary(mod);
  201. return SQ_ERROR;
  202. }
  203. #elif defined(__unix)
  204. /* adding .so to moduleName? */
  205. void *mod = dlopen(moduleName, RTLD_NOW | RTLD_LOCAL
  206. #ifndef ANDROID_BUILD
  207. | RTLD_NOLOAD //RTLD_NOLOAD flag is not specified in POSIX.1-2001..so not the best solution :(
  208. #endif
  209. );
  210. if (mod == NULL) {
  211. mod = dlopen(moduleName, RTLD_NOW | RTLD_LOCAL);
  212. if (mod == NULL)
  213. return SQ_ERROR;
  214. }
  215. modLoad = (SQMODULELOAD) dlsym(mod, "sqmodule_load");
  216. if (modLoad == NULL) {
  217. dlclose(mod);
  218. return SQ_ERROR;
  219. }
  220. #endif
  221. if(sqapi == NULL) {
  222. sqapi = sqrat_newapi(); // Caching this for multiple imports is probably a very good idea
  223. }
  224. SQRESULT res = modLoad(v, sqapi);
  225. return res;
  226. }
  227. SQRESULT sqrat_import(HSQUIRRELVM v) {
  228. const SQChar* moduleName;
  229. HSQOBJECT table;
  230. SQRESULT res = SQ_OK;
  231. //SQInteger top = sq_gettop(v);
  232. sq_getstring(v, -2, &moduleName);
  233. sq_getstackobj(v, -1, &table);
  234. sq_addref(v, &table);
  235. sq_settop(v, 0); // Clear Stack
  236. sq_pushobject(v, table); // Push the target table onto the stack
  237. if(SQ_FAILED(sqrat_importscript(v, moduleName))) {
  238. res = sqrat_importbin(v, moduleName);
  239. }
  240. sq_settop(v, 0); // Clean up the stack (just in case the module load leaves it messy)
  241. sq_pushobject(v, table); // return the target table
  242. sq_release(v, &table);
  243. return res;
  244. }
  245. static SQRESULT sqratbase_import(HSQUIRRELVM v) {
  246. SQInteger args = sq_gettop(v);
  247. switch(args) {
  248. case 2:
  249. sq_pushroottable(v);
  250. break;
  251. case 3:
  252. // should already have the desired table pushed onto the stack
  253. if(sq_gettype(v, 3) != OT_TABLE) return sq_throwerror(v, _SC("table expected as second parameter"));
  254. break;
  255. default:
  256. // Error, unexpected number of arguments
  257. return sq_throwerror(v, _SC("unexpected number of arguments"));
  258. break;
  259. }
  260. sqrat_import(v);
  261. return 1;
  262. }
  263. SQRESULT sqrat_register_importlib(HSQUIRRELVM v) {
  264. sq_pushroottable(v);
  265. sq_pushstring(v, _SC("import"), -1);
  266. sq_newclosure(v, &sqratbase_import, 0);
  267. sq_newslot(v, -3, 0);
  268. sq_pop(v, 1); // pop root table
  269. return SQ_OK;
  270. }