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