Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

346 lines
7.7 KiB

  1. #include <stdio.h>
  2. #include <stdarg.h>
  3. #define _DEBUG_DUMP
  4. #include "sqplus.h"
  5. #include <sqstdio.h>
  6. #include <sqstdmath.h>
  7. #include <sqstdstring.h>
  8. #include <sqstdaux.h>
  9. #include <sqstdblob.h>
  10. #if defined(VSCRIPT_DLL_EXPORT) || defined(VSQUIRREL_TEST)
  11. #include "memdbgon.h"
  12. #endif
  13. #ifdef _MSC_VER
  14. #define STRLEN(n) _tcslen(n)
  15. #else
  16. #define STRLEN(n) strlen(n)
  17. #endif
  18. HSQUIRRELVM SquirrelVM::_VM = NULL;
  19. int SquirrelVM::_CallState = -1;
  20. SquirrelObject * SquirrelVM::_root = NULL;
  21. SquirrelError::SquirrelError()
  22. {
  23. const SQChar *s;
  24. sq_getlasterror(SquirrelVM::_VM);
  25. sq_getstring(SquirrelVM::_VM,-1,&s);
  26. if(s) {
  27. desc = s;
  28. }
  29. else {
  30. desc = _T("unknown error");
  31. }
  32. }
  33. void SquirrelVM::Init()
  34. {
  35. _VM = sq_open(1024);
  36. sq_setprintfunc(_VM,SquirrelVM::PrintFunc);
  37. sq_pushroottable(_VM);
  38. sqstd_register_iolib(_VM);
  39. sqstd_register_bloblib(_VM);
  40. sqstd_register_mathlib(_VM);
  41. sqstd_register_stringlib(_VM);
  42. sqstd_seterrorhandlers(_VM);
  43. _root = new SquirrelObject();
  44. _root->AttachToStackObject(-1);
  45. sq_pop(_VM,1);
  46. //TODO error handler, compiler error handler
  47. }
  48. BOOL SquirrelVM::Update()
  49. {
  50. //update remote debugger
  51. return TRUE;
  52. }
  53. void SquirrelVM::Cleanup()
  54. {
  55. //cleans the root table
  56. sq_pushnull(_VM);
  57. sq_setroottable(_VM);
  58. }
  59. void SquirrelVM::Shutdown()
  60. {
  61. if (_VM) {
  62. Cleanup();
  63. #if 0
  64. sq_release(_VM,&_root->_o);
  65. sq_resetobject(&_root->_o);
  66. #endif
  67. delete _root;
  68. _root = NULL;
  69. HSQUIRRELVM v = _VM;
  70. _VM = NULL;
  71. sq_close(v);
  72. } // if
  73. }
  74. void SquirrelVM::PrintFunc(HSQUIRRELVM v,const SQChar* s,...)
  75. {
  76. static SQChar temp[2048];
  77. va_list vl;
  78. va_start(vl, s);
  79. scvsprintf( temp,s, vl);
  80. SCPUTS(temp);
  81. va_end(vl);
  82. }
  83. SquirrelObject SquirrelVM::CompileScript(const SQChar *s)
  84. {
  85. #define MAX_EXPANDED_PATH 1023
  86. SquirrelObject ret;
  87. if(SQ_SUCCEEDED(sqstd_loadfile(_VM,s,1))) {
  88. ret.AttachToStackObject(-1);
  89. sq_pop(_VM,1);
  90. return ret;
  91. }
  92. throw SquirrelError();
  93. }
  94. SquirrelObject SquirrelVM::CompileBuffer(const SQChar *s,const SQChar * debugInfo)
  95. {
  96. SquirrelObject ret;
  97. if(SQ_SUCCEEDED(sq_compilebuffer(_VM,s,(int)STRLEN(s)*sizeof(SQChar),debugInfo,1))) {
  98. ret.AttachToStackObject(-1);
  99. sq_pop(_VM,1);
  100. return ret;
  101. }
  102. throw SquirrelError();
  103. }
  104. SquirrelObject SquirrelVM::RunScript(const SquirrelObject &o,SquirrelObject *_this)
  105. {
  106. SquirrelObject ret;
  107. sq_pushobject(_VM,o._o);
  108. if(_this) {
  109. sq_pushobject(_VM,_this->_o);
  110. }
  111. else {
  112. sq_pushroottable(_VM);
  113. }
  114. if(SQ_SUCCEEDED(sq_call(_VM,1,SQTrue,SQ_CALL_RAISE_ERROR))) {
  115. ret.AttachToStackObject(-1);
  116. sq_pop(_VM,1);
  117. return ret;
  118. }
  119. sq_pop(_VM,1);
  120. throw SquirrelError();
  121. }
  122. BOOL SquirrelVM::BeginCall(const SquirrelObject &func)
  123. {
  124. if(_CallState != -1)
  125. return FALSE;
  126. _CallState = 1;
  127. sq_pushobject(_VM,func._o);
  128. sq_pushroottable(_VM);
  129. return TRUE;
  130. }
  131. BOOL SquirrelVM::BeginCall(const SquirrelObject &func,SquirrelObject &_this)
  132. {
  133. if(_CallState != -1)
  134. throw SquirrelError(_T("call already initialized"));
  135. _CallState = 1;
  136. sq_pushobject(_VM,func._o);
  137. sq_pushobject(_VM,_this._o);
  138. return TRUE;
  139. }
  140. #define _CHECK_CALL_STATE \
  141. if(_CallState == -1) \
  142. throw SquirrelError(_T("call not initialized"));
  143. void SquirrelVM::PushParam(const SquirrelObject &o)
  144. {
  145. _CHECK_CALL_STATE
  146. sq_pushobject(_VM,o._o);
  147. _CallState++;
  148. }
  149. void SquirrelVM::PushParam(const SQChar *s)
  150. {
  151. _CHECK_CALL_STATE
  152. sq_pushstring(_VM,s,-1);
  153. _CallState++;
  154. }
  155. void SquirrelVM::PushParam(SQInteger n)
  156. {
  157. _CHECK_CALL_STATE
  158. sq_pushinteger(_VM,n);
  159. _CallState++;
  160. }
  161. void SquirrelVM::PushParam(SQFloat f)
  162. {
  163. _CHECK_CALL_STATE
  164. sq_pushfloat(_VM,f);
  165. _CallState++;
  166. }
  167. void SquirrelVM::PushParamNull()
  168. {
  169. _CHECK_CALL_STATE
  170. sq_pushnull(_VM);
  171. _CallState++;
  172. }
  173. void SquirrelVM::PushParam(SQUserPointer up)
  174. {
  175. _CHECK_CALL_STATE
  176. sq_pushuserpointer(_VM,up);
  177. _CallState++;
  178. }
  179. SquirrelObject SquirrelVM::EndCall()
  180. {
  181. SquirrelObject ret;
  182. if(_CallState >= 0) {
  183. int oldtop = sq_gettop(_VM);
  184. int nparams = _CallState;
  185. _CallState = -1;
  186. if(SQ_SUCCEEDED(sq_call(_VM,nparams,SQTrue,SQ_CALL_RAISE_ERROR))) {
  187. ret.AttachToStackObject(-1);
  188. sq_pop(_VM,2);
  189. }else {
  190. sq_settop(_VM,oldtop-(nparams+1));
  191. throw SquirrelError();
  192. }
  193. }
  194. return ret;
  195. }
  196. SquirrelObject SquirrelVM::CreateInstance(SquirrelObject &oclass)
  197. {
  198. SquirrelObject ret;
  199. int oldtop = sq_gettop(_VM);
  200. sq_pushobject(_VM,oclass._o);
  201. if(SQ_FAILED(sq_createinstance(_VM,-1))) {
  202. sq_settop(_VM,oldtop);
  203. throw SquirrelError();
  204. }
  205. ret.AttachToStackObject(-1);
  206. sq_pop(_VM,2);
  207. return ret;
  208. }
  209. SquirrelObject SquirrelVM::CreateTable()
  210. {
  211. SquirrelObject ret;
  212. sq_newtable(_VM);
  213. ret.AttachToStackObject(-1);
  214. sq_pop(_VM,1);
  215. return ret;
  216. }
  217. SquirrelObject SquirrelVM::CreateString(const SQChar *s)
  218. {
  219. SquirrelObject ret;
  220. sq_pushstring(_VM,s,-1);
  221. ret.AttachToStackObject(-1);
  222. sq_pop(_VM,1);
  223. return ret;
  224. }
  225. SquirrelObject SquirrelVM::CreateArray(int size)
  226. {
  227. SquirrelObject ret;
  228. sq_newarray(_VM,size);
  229. ret.AttachToStackObject(-1);
  230. sq_pop(_VM,1);
  231. return ret;
  232. }
  233. SquirrelObject SquirrelVM::CreateFunction(SQFUNCTION func)
  234. {
  235. SquirrelObject ret;
  236. sq_newclosure(_VM,func,0);
  237. ret.AttachToStackObject(-1);
  238. sq_pop(_VM,1);
  239. return ret;
  240. }
  241. SquirrelObject SquirrelVM::CreateUserData(int size) {
  242. SquirrelObject ret;
  243. sq_newuserdata(_VM,size);
  244. ret.AttachToStackObject(-1);
  245. sq_pop(_VM,1);
  246. return ret;
  247. }
  248. const SquirrelObject &SquirrelVM::GetRootTable()
  249. {
  250. return *_root;
  251. }
  252. void SquirrelVM::PushRootTable(void) {
  253. sq_pushroottable(_VM);
  254. } // SquirrelVM::PushRootTable
  255. // Creates a function in the table or class currently on the stack.
  256. //void CreateFunction(HSQUIRRELVM v,const SQChar * scriptFuncName,SQFUNCTION func,int numParams=0,const SQChar * typeMask=0) {
  257. SquirrelObject SquirrelVM::CreateFunction(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask) {
  258. sq_pushstring(_VM,scriptFuncName,-1);
  259. sq_newclosure(_VM,func,0);
  260. SquirrelObject ret;
  261. ret.AttachToStackObject(-1);
  262. SQChar tm[64];
  263. SQChar * ptm = tm;
  264. int numParams = SQ_MATCHTYPEMASKSTRING;
  265. if (typeMask) {
  266. if (typeMask[0] == '*') {
  267. ptm = 0; // Variable args: don't check parameters.
  268. numParams = 0; // Clear SQ_MATCHTYPEMASKSTRING (does not mean match 0 params. See sq_setparamscheck()).
  269. } else {
  270. if (SCSNPRINTF(tm,sizeof(tm),_T("t|y|x%s"),typeMask) < 0) {
  271. // sq_throwerror(_VM,_T("CreateFunction: typeMask string too long."));
  272. throw SquirrelError(_T("CreateFunction: typeMask string too long."));
  273. } // if
  274. } // if
  275. } else { // <TODO> Need to check object type on stack: table, class, instance, etc.
  276. SCSNPRINTF(tm,sizeof(tm),_T("%s"),_T("t|y|x")); // table, class, instance.
  277. // tm[0] = 't';
  278. // tm[1] = 0;
  279. } // if
  280. #if 0
  281. sq_setparamscheck(_VM,numParams+1,ptm); // Parameters are table+args (thus, the +1).
  282. #else
  283. if (ptm) {
  284. sq_setparamscheck(_VM,numParams,ptm); // Determine arg count from type string.
  285. } // if
  286. #endif
  287. #ifdef _DEBUG
  288. sq_setnativeclosurename(_VM,-1,scriptFuncName); // For debugging only.
  289. #endif
  290. sq_createslot(_VM,-3); // Create slot in table or class (assigning function to slot at scriptNameFunc).
  291. return ret;
  292. } // SquirrelVM::CreateFunction
  293. SquirrelObject SquirrelVM::CreateFunction(SquirrelObject & so,SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask) {
  294. PushObject(so);
  295. SquirrelObject ret = CreateFunction(func,scriptFuncName,typeMask);
  296. Pop(1);
  297. return ret;
  298. } // SquirrelVM::CreateFunction
  299. // Create a Global function on the root table.
  300. //void CreateFunctionGlobal(HSQUIRRELVM v,const SQChar * scriptFuncName,SQFUNCTION func,int numParams=0,const SQChar * typeMask=0) {
  301. SquirrelObject SquirrelVM::CreateFunctionGlobal(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask) {
  302. PushRootTable(); // Push root table.
  303. // CreateFunction(scriptFuncName,func,numParams,typeMask);
  304. SquirrelObject ret = CreateFunction(func,scriptFuncName,typeMask);
  305. Pop(1); // Pop root table.
  306. return ret;
  307. } // SquirrelVM::CreateFunctionGlobal