sq_slave_vm.cpp 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299
  1. /*
  2. ** Rings: Multiple Lua States
  3. ** $Id: rings.c,v 1.24 2008/06/30 17:52:31 carregal Exp $
  4. ** See Copyright Notice in license.html
  5. */
  6. #include <string.h>
  7. #include <stdio.h>
  8. #include "squirrel.h"
  9. #include <sqstdblob.h>
  10. #include <sqstdsystem.h>
  11. #include <sqstdio.h>
  12. #include <sqstdmath.h>
  13. #include <sqstdstring.h>
  14. /*
  15. ** Copies values from State src to State dst.
  16. */
  17. static SQRESULT copy_values_between_vms (HSQUIRRELVM dst, HSQUIRRELVM src, int argc, int argIdx) {
  18. SQRESULT _rc_;
  19. sq_reservestack(dst, argc + 20);
  20. argc += argIdx; //we will work with argc args starting at argIdx
  21. for (; argIdx < argc; argIdx++) {
  22. switch (sq_gettype(src, argIdx)) {
  23. case OT_INTEGER:
  24. SQ_GET_INTEGER(src, argIdx, vint);
  25. sq_pushinteger(dst, vint);
  26. break;
  27. case OT_FLOAT:
  28. SQ_GET_FLOAT(src, argIdx, vfloat);
  29. sq_pushfloat (dst, vfloat);
  30. break;
  31. case OT_BOOL:
  32. SQ_GET_BOOL(src, argIdx, vbool);
  33. sq_pushbool (dst, vbool);
  34. break;
  35. case OT_STRING: {
  36. SQ_GET_STRING(src, argIdx, vstr)
  37. sq_pushstring (dst, vstr, vstr_size);
  38. break;
  39. }
  40. case OT_ARRAY:{
  41. SQInteger size = sq_getsize(src, argIdx);
  42. sq_newarray(dst, size);
  43. for(SQInteger i=0; i<size; ++i){
  44. sq_pushinteger(src, i);
  45. sq_get(src, -2);
  46. sq_pushinteger(dst, i);
  47. if(copy_values_between_vms(dst, src, 1, sq_gettop(src)) != SQ_OK) return SQ_ERROR;
  48. sq_poptop(src);
  49. sq_set(dst, -3);
  50. }
  51. }
  52. break;
  53. case OT_TABLE:{
  54. sq_newtable(dst);
  55. sq_pushnull(src);
  56. while(sq_next(src, -2) == SQ_OK){
  57. SQInteger src_top = sq_gettop(src);
  58. if(copy_values_between_vms(dst, src, 1, src_top-1) != SQ_OK
  59. || copy_values_between_vms(dst, src, 1, src_top) != SQ_OK) return SQ_ERROR;
  60. sq_newslot(dst, -3, SQFalse);
  61. sq_pop(src, 2);
  62. }
  63. }
  64. break;
  65. case OT_USERPOINTER: {
  66. SQUserPointer ptr;
  67. sq_getuserpointer(src, argIdx, &ptr);
  68. sq_pushuserpointer(dst, ptr);
  69. break;
  70. }
  71. case OT_NULL:
  72. sq_pushnull(dst);
  73. break;
  74. default:
  75. return SQ_ERROR;
  76. }
  77. }
  78. return SQ_OK;
  79. }
  80. static const SQChar sq_slave_vm_TAG[] = _SC("SlaveVM");
  81. static SQRESULT get_slave_vm_instance(HSQUIRRELVM v, SQInteger idx, HSQUIRRELVM *vm) {
  82. if(sq_getinstanceup(v, idx, (SQUserPointer*)vm, (void*)sq_slave_vm_TAG) != SQ_OK) return SQ_ERROR;
  83. if(!vm) return sq_throwerror(v, _SC("slave vm already closed"));
  84. return SQ_OK;
  85. }
  86. #define GET_sq_slave_vm_INSTANCE(v, idx) \
  87. HSQUIRRELVM self=NULL; if(get_slave_vm_instance(v, idx, &self) != SQ_OK) return SQ_ERROR;
  88. static SQRESULT sq_slave_vm__tostring (HSQUIRRELVM v) {
  89. GET_sq_slave_vm_INSTANCE(v, 1);
  90. sq_pushfstring (v, _SC("Squirrel vm (%p)"), self);
  91. return 1;
  92. }
  93. static SQRESULT sq_slave_vm_release_hook(SQUserPointer p, SQInteger size, HSQUIRRELVM v) {
  94. HSQUIRRELVM self = (HSQUIRRELVM)p;
  95. if(self) sq_close(self);
  96. return 0;
  97. }
  98. /*
  99. ** Creates a new SQuirrel vm.
  100. */
  101. static SQRESULT sq_slave_vm_constructor (HSQUIRRELVM v) {
  102. SQ_FUNC_VARS(v);
  103. SQ_OPT_INTEGER(v, 2, stack_size, 1024);
  104. HSQUIRRELVM self = sq_open(stack_size);
  105. /* Initialize environment */
  106. sq_setprintfunc(self,sq_getprintfunc(v),sq_geterrorfunc(v));
  107. /* load base libraries */
  108. sq_pushroottable(self);
  109. sqstd_register_bloblib(self);
  110. sqstd_register_iolib(self);
  111. sqstd_register_systemlib(self);
  112. sqstd_register_mathlib(self);
  113. sqstd_register_stringlib(self);
  114. sq_poptop(self); //remove root table
  115. sq_setinstanceup(v, 1, self);
  116. sq_setreleasehook(v, 1, sq_slave_vm_release_hook);
  117. return 1;
  118. }
  119. static SQRESULT sq_slave_vm_close(HSQUIRRELVM v){
  120. GET_sq_slave_vm_INSTANCE(v, 1);
  121. sq_close(self);
  122. sq_setinstanceup(v, 1, 0); //next calls will fail with "vm is closed"
  123. return 0;
  124. }
  125. static SQRESULT sq_slave_vm_call(HSQUIRRELVM v){
  126. SQ_FUNC_VARS_NO_TOP(v);
  127. GET_sq_slave_vm_INSTANCE(v, 1);
  128. SQ_GET_BOOL(v, 2, has_ret_val);
  129. SQ_GET_STRING(v, 3, func_name);
  130. SQInteger top = sq_gettop(self);
  131. SQRESULT result = SQ_ERROR;
  132. sq_pushroottable(self);
  133. sq_pushstring(self, func_name, func_name_size);
  134. if(sq_get(self, -2) == SQ_OK){
  135. switch(sq_gettype(self, -1)){
  136. case OT_CLOSURE:
  137. case OT_NATIVECLOSURE:
  138. case OT_CLASS:{
  139. sq_pushroottable(self);
  140. int argc = sq_gettop(v) - 3;
  141. if(argc && copy_values_between_vms(self, v, argc, 4) != SQ_OK) {
  142. sq_throwerror(v, sq_getlasterror_str(self));
  143. goto cleanup;
  144. }
  145. if(sq_call(self, argc+1, has_ret_val, SQFalse) != SQ_OK){
  146. sq_throwerror(v, sq_getlasterror_str(self));
  147. goto cleanup;
  148. }
  149. if(has_ret_val){
  150. if(copy_values_between_vms(v, self, 1, sq_gettop(self)) == SQ_OK) result = 1;
  151. }
  152. else result = SQ_OK;
  153. }
  154. }
  155. }
  156. else
  157. {
  158. sq_throwerror(v, sq_getlasterror_str(self));
  159. }
  160. cleanup:
  161. sq_settop(self, top);
  162. return result;
  163. }
  164. static SQRESULT sq_slave_vm_set(HSQUIRRELVM v){
  165. GET_sq_slave_vm_INSTANCE(v, 1);
  166. SQInteger top = sq_gettop(self);
  167. SQRESULT result;
  168. sq_pushroottable(self);
  169. if(copy_values_between_vms(self, v, 1, 2) == SQ_OK
  170. && copy_values_between_vms(self, v, 1, 3) == SQ_OK) {
  171. result = sq_newslot(self, -3, SQFalse);
  172. if(result == SQ_ERROR) sq_throwerror(v, sq_getlasterror_str(self));
  173. }
  174. else result = SQ_ERROR;
  175. sq_settop(self, top);
  176. return result;
  177. }
  178. static SQRESULT sq_slave_vm_get(HSQUIRRELVM v){
  179. GET_sq_slave_vm_INSTANCE(v, 1);
  180. SQInteger top = sq_gettop(self);
  181. SQRESULT result = SQ_ERROR;
  182. sq_pushroottable(self);
  183. if(copy_values_between_vms(self, v, 1, 2) == SQ_OK) {
  184. if(sq_get(self, -2) == SQ_OK
  185. && copy_values_between_vms(v, self, 1, sq_gettop(self)) == SQ_OK){
  186. result = 1;
  187. }
  188. else
  189. {
  190. if(sq_gettop(v) == 3) result = 1; //we have a default value
  191. else sq_throwerror(v, sq_getlasterror_str(self));
  192. }
  193. }
  194. sq_settop(self, top);
  195. return result;
  196. }
  197. static SQRESULT sq_slave_vm_dofile(HSQUIRRELVM v){
  198. SQ_FUNC_VARS(v);
  199. GET_sq_slave_vm_INSTANCE(v, 1);
  200. SQ_GET_STRING(v, 2, file_name);
  201. SQ_OPT_BOOL(v, 3, retval, false);
  202. SQ_OPT_BOOL(v, 4, printerror, false);
  203. SQInteger top = sq_gettop(self);
  204. SQRESULT result = SQ_ERROR;
  205. sq_pushroottable(self); //important always push the root table, because sqstd_dofile will try to do a sq_push(v, -2)
  206. if(sqstd_dofile(self, file_name, retval, printerror) >= 0){
  207. if(retval){
  208. if(copy_values_between_vms(v, self, 1, sq_gettop(self)) == SQ_OK) result = 1;
  209. }
  210. else result = SQ_OK;
  211. }
  212. else sq_throwerror(v, sq_getlasterror_str(self));
  213. sq_settop(self, top);
  214. return result;
  215. }
  216. static SQRESULT sq_slave_vm_loadfile(HSQUIRRELVM v){
  217. SQ_FUNC_VARS(v);
  218. GET_sq_slave_vm_INSTANCE(v, 1);
  219. SQ_GET_STRING(v, 2, func_name);
  220. SQ_GET_STRING(v, 3, file_name);
  221. SQ_OPT_BOOL(v, 4, printerror, false);
  222. SQInteger top = sq_gettop(self);
  223. SQRESULT result = SQ_ERROR;
  224. sq_pushroottable(self);
  225. sq_pushstring(self, func_name, func_name_size);
  226. if(sqstd_loadfile(self, file_name, printerror) >= 0){
  227. result = sq_newslot(self, -3, SQFalse);
  228. }
  229. sq_settop(self, top);
  230. return result;
  231. }
  232. static SQRESULT sq_slave_vm_compilestring(HSQUIRRELVM v){
  233. SQ_FUNC_VARS(v);
  234. GET_sq_slave_vm_INSTANCE(v, 1);
  235. SQ_GET_STRING(v, 2, func_name);
  236. SQ_GET_STRING(v, 3, str_script);
  237. SQ_OPT_BOOL(v, 4, printerror, false);
  238. SQInteger top = sq_gettop(self);
  239. SQRESULT result = SQ_ERROR;
  240. sq_pushroottable(self);
  241. sq_pushstring(self, func_name, func_name_size);
  242. if(sq_compilebuffer(self, str_script, str_script_size, func_name, printerror) >= 0){
  243. result = sq_newslot(self, -3, SQFalse);
  244. }
  245. sq_settop(self, top);
  246. return result;
  247. }
  248. #ifdef __cplusplus
  249. extern "C" {
  250. #endif
  251. SQRESULT sqext_register_sq_slave_vm(HSQUIRRELVM v)
  252. {
  253. const SQChar get_set_validation_mask[] = _SC("x s|n|p s|n|b|a|t|p|o");
  254. sq_pushstring(v,sq_slave_vm_TAG, -1);
  255. sq_newclass(v, SQFalse);
  256. sq_settypetag(v,-1,(void*)sq_slave_vm_TAG);
  257. sq_insertfunc(v, _SC("constructor"), sq_slave_vm_constructor, -1, _SC("xi"), SQFalse);
  258. sq_insertfunc(v, _SC("_tostring"), sq_slave_vm__tostring, 1, _SC("x"), SQFalse);
  259. sq_insertfunc(v, _SC("close"), sq_slave_vm_close, 1, _SC("x"), SQFalse);
  260. sq_insertfunc(v, _SC("set"), sq_slave_vm_set, 3, get_set_validation_mask, SQFalse);
  261. sq_insertfunc(v, _SC("_set"), sq_slave_vm_set, 3, get_set_validation_mask, SQFalse);
  262. sq_insertfunc(v, _SC("get"), sq_slave_vm_get, -2, get_set_validation_mask, SQFalse);
  263. sq_insertfunc(v, _SC("_get"), sq_slave_vm_get, -2, get_set_validation_mask, SQFalse);
  264. sq_insertfunc(v, _SC("dofile"), sq_slave_vm_dofile, -2, _SC("xsbb"), SQFalse);
  265. sq_insertfunc(v, _SC("loadfile"), sq_slave_vm_loadfile, -3, _SC("xssb"), SQFalse);
  266. sq_insertfunc(v, _SC("compilestring"), sq_slave_vm_compilestring, -3, _SC("xssb"), SQFalse);
  267. sq_insertfunc(v, _SC("call"), sq_slave_vm_call, -3, _SC("xbs"), SQFalse);
  268. sq_newslot(v,-3,SQTrue); //push sq_slave_vm class
  269. return 0;
  270. }
  271. #ifdef __cplusplus
  272. }
  273. #endif