~ubuntu-branches/ubuntu/oneiric/codeblocks/oneiric

« back to all changes in this revision

Viewing changes to src/sdk/scripting/sqplus/SquirrelVM.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Michael Casadevall
  • Date: 2008-07-17 04:39:23 UTC
  • Revision ID: james.westby@ubuntu.com-20080717043923-gmsy5cwkdjswghkm
Tags: upstream-8.02
ImportĀ upstreamĀ versionĀ 8.02

Show diffs side-by-side

added added

removed removed

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