1 /*
2  see copyright notice in squirrel.h
3 */
4 #include "sqpcheader.h"
5 #include "sqvm.h"
6 #include "sqstring.h"
7 #include "sqtable.h"
8 #include "sqarray.h"
9 #include "sqfuncproto.h"
10 #include "sqclosure.h"
11 #include "squserdata.h"
12 #include "sqcompiler.h"
13 #include "sqfuncstate.h"
14 #include "sqclass.h"
15 
sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPtr ** o)16 bool sq_aux_gettypedarg( HSQUIRRELVM v, SQInteger idx, SQObjectType type, SQObjectPtr **o ) {
17 	*o = &stack_get( v, idx );
18 	if ( squirrel_type( **o ) != type ) {
19 		SQObjectPtr oval = v->PrintObjVal( **o );
20 		v->Raise_Error( _SC( "wrong argument type, expected '%s' got '%.50s'" ), IdType2Name( type ), _stringval( oval ) );
21 		return false;
22 	}
23 	return true;
24 }
25 
26 #define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; }
27 
28 #define sq_aux_paramscheck(v,count) \
29 	{ \
30 		if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\
31 	}
32 
sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr & e)33 SQInteger sq_aux_throwobject( HSQUIRRELVM v, SQObjectPtr &e ) {
34 	v->_lasterror = e;
35 	return SQ_ERROR;
36 }
37 
sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type)38 SQInteger sq_aux_invalidtype( HSQUIRRELVM v, SQObjectType type ) {
39 	scsprintf( _ss( v )->GetScratchPad( 100 ), _SC( "unexpected type %s" ), IdType2Name( type ) );
40 	return sq_throwerror( v, _ss( v )->GetScratchPad( -1 ) );
41 }
42 
sq_open(SQInteger initialstacksize)43 HSQUIRRELVM sq_open( SQInteger initialstacksize ) {
44 	SQSharedState *ss;
45 	SQVM *v;
46 	sq_new( ss, SQSharedState );
47 	ss->Init();
48 	v = ( SQVM * )SQ_MALLOC( sizeof( SQVM ) );
49 	new ( v ) SQVM( ss );
50 	ss->_root_vm = v;
51 	if ( v->Init( NULL, initialstacksize ) ) {
52 		return v;
53 	} else {
54 		sq_delete( v, SQVM );
55 		return NULL;
56 	}
57 	return v;
58 }
59 
sq_newthread(HSQUIRRELVM friendvm,SQInteger initialstacksize)60 HSQUIRRELVM sq_newthread( HSQUIRRELVM friendvm, SQInteger initialstacksize ) {
61 	SQSharedState *ss;
62 	SQVM *v;
63 	ss = _ss( friendvm );
64 
65 	v = ( SQVM * )SQ_MALLOC( sizeof( SQVM ) );
66 	new ( v ) SQVM( ss );
67 
68 	if ( v->Init( friendvm, initialstacksize ) ) {
69 		friendvm->Push( v );
70 		return v;
71 	} else {
72 		sq_delete( v, SQVM );
73 		return NULL;
74 	}
75 }
76 
sq_getvmstate(HSQUIRRELVM v)77 SQInteger sq_getvmstate( HSQUIRRELVM v ) {
78 	if ( v->_suspended )
79 		return SQ_VMSTATE_SUSPENDED;
80 	else {
81 		if ( !v->_callsstack.empty() ) return SQ_VMSTATE_RUNNING;
82 		else return SQ_VMSTATE_IDLE;
83 	}
84 }
85 
sq_seterrorhandler(HSQUIRRELVM v)86 void sq_seterrorhandler( HSQUIRRELVM v ) {
87 	SQObject o = stack_get( v, -1 );
88 	if ( sq_isclosure( o ) || sq_isnativeclosure( o ) || sq_isnull( o ) ) {
89 		v->_errorhandler = o;
90 		v->Pop();
91 	}
92 }
93 
sq_setdebughook(HSQUIRRELVM v)94 void sq_setdebughook( HSQUIRRELVM v ) {
95 	SQObject o = stack_get( v, -1 );
96 	if ( sq_isclosure( o ) || sq_isnativeclosure( o ) || sq_isnull( o ) ) {
97 		v->_debughook = o;
98 		v->Pop();
99 	}
100 }
101 
sq_close(HSQUIRRELVM v)102 void sq_close( HSQUIRRELVM v ) {
103 	SQSharedState *ss = _ss( v );
104 	_thread( ss->_root_vm )->Finalize();
105 	sq_delete( ss, SQSharedState );
106 }
107 
sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar * sourcename,SQBool raiseerror)108 SQRESULT sq_compile( HSQUIRRELVM v, SQLEXREADFUNC read, SQUserPointer p, const SQChar *sourcename, SQBool raiseerror ) {
109 	SQObjectPtr o;
110 	if ( Compile( v, read, p, sourcename, o, raiseerror ? true : false, _ss( v )->_debuginfo ) ) {
111 		v->Push( SQClosure::Create( _ss( v ), _funcproto( o ) ) );
112 		return SQ_OK;
113 	}
114 	return SQ_ERROR;
115 }
116 
sq_enabledebuginfo(HSQUIRRELVM v,SQBool debuginfo)117 void sq_enabledebuginfo( HSQUIRRELVM v, SQBool debuginfo ) {
118 	_ss( v )->_debuginfo = debuginfo ? true : false;
119 }
120 
sq_addref(HSQUIRRELVM v,HSQOBJECT * po)121 void sq_addref( HSQUIRRELVM v, HSQOBJECT *po ) {
122 	SQObjectPtr refs;
123 	if ( !ISREFCOUNTED( squirrel_type( *po ) ) ) return;
124 	if ( _table( _ss( v )->_refs_table )->Get( *po, refs ) ) {
125 		refs = _integer( refs ) + 1;
126 	} else {
127 		refs = 1;
128 	}
129 	_table( _ss( v )->_refs_table )->NewSlot( *po, refs );
130 }
131 
sq_release(HSQUIRRELVM v,HSQOBJECT * po)132 SQBool sq_release( HSQUIRRELVM v, HSQOBJECT *po ) {
133 	SQObjectPtr refs;
134 	if ( !ISREFCOUNTED( squirrel_type( *po ) ) ) return SQTrue;
135 	if ( _table( _ss( v )->_refs_table )->Get( *po, refs ) ) {
136 		SQInteger n = _integer( refs ) - 1;
137 		if ( n <= 0 ) {
138 			_table( _ss( v )->_refs_table )->Remove( *po );
139 			sq_resetobject( po );
140 		} else {
141 			refs = n;_table( _ss( v )->_refs_table )->Set( *po, refs );
142 			return SQFalse;
143 		}
144 	}
145 	return SQTrue;
146 }
147 
sq_objtostring(HSQOBJECT * o)148 const SQChar *sq_objtostring( HSQOBJECT *o ) {
149 	if ( sq_type( *o ) == OT_STRING ) {
150 		return _stringval( *o );
151 	}
152 	return NULL;
153 }
154 
sq_objtointeger(HSQOBJECT * o)155 SQInteger sq_objtointeger( HSQOBJECT *o ) {
156 	if ( sq_isnumeric( *o ) ) {
157 		return tointeger( *o );
158 	}
159 	return 0;
160 }
161 
sq_objtofloat(HSQOBJECT * o)162 SQFloat sq_objtofloat( HSQOBJECT *o ) {
163 	if ( sq_isnumeric( *o ) ) {
164 		return tofloat( *o );
165 	}
166 	return 0;
167 }
168 
sq_objtobool(HSQOBJECT * o)169 SQBool sq_objtobool( HSQOBJECT *o ) {
170 	if ( sq_isbool( *o ) ) {
171 		return _integer( *o );
172 	}
173 	return SQFalse;
174 }
175 
sq_pushnull(HSQUIRRELVM v)176 void sq_pushnull( HSQUIRRELVM v ) {
177 	v->Push( _null_ );
178 }
179 
sq_pushstring(HSQUIRRELVM v,const SQChar * s,SQInteger len)180 void sq_pushstring( HSQUIRRELVM v, const SQChar *s, SQInteger len ) {
181 	if ( s )
182 		v->Push( SQObjectPtr( SQString::Create( _ss( v ), s, len ) ) );
183 	else v->Push( _null_ );
184 }
185 
sq_pushinteger(HSQUIRRELVM v,SQInteger n)186 void sq_pushinteger( HSQUIRRELVM v, SQInteger n ) {
187 	v->Push( n );
188 }
189 
sq_pushbool(HSQUIRRELVM v,SQBool b)190 void sq_pushbool( HSQUIRRELVM v, SQBool b ) {
191 	v->Push( b ? true : false );
192 }
193 
sq_pushfloat(HSQUIRRELVM v,SQFloat n)194 void sq_pushfloat( HSQUIRRELVM v, SQFloat n ) {
195 	v->Push( n );
196 }
197 
sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p)198 void sq_pushuserpointer( HSQUIRRELVM v, SQUserPointer p ) {
199 	v->Push( p );
200 }
201 
sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size)202 SQUserPointer sq_newuserdata( HSQUIRRELVM v, SQUnsignedInteger size ) {
203 	SQUserData *ud = SQUserData::Create( _ss( v ), size );
204 	v->Push( ud );
205 	return ud->_val;
206 }
207 
sq_newtable(HSQUIRRELVM v)208 void sq_newtable( HSQUIRRELVM v ) {
209 	v->Push( SQTable::Create( _ss( v ), 0 ) );
210 }
211 
sq_newarray(HSQUIRRELVM v,SQInteger size)212 void sq_newarray( HSQUIRRELVM v, SQInteger size ) {
213 	v->Push( SQArray::Create( _ss( v ), size ) );
214 }
215 
sq_newclass(HSQUIRRELVM v,SQBool hasbase)216 SQRESULT sq_newclass( HSQUIRRELVM v, SQBool hasbase ) {
217 	SQClass *baseclass = NULL;
218 	if ( hasbase ) {
219 		SQObjectPtr &base = stack_get( v, -1 );
220 		if ( squirrel_type( base ) != OT_CLASS )
221 			return sq_throwerror( v, _SC( "invalid base type" ) );
222 		baseclass = _class( base );
223 	}
224 	SQClass *newclass = SQClass::Create( _ss( v ), baseclass );
225 	if ( baseclass ) v->Pop();
226 	v->Push( newclass );
227 	return SQ_OK;
228 }
229 
sq_instanceof(HSQUIRRELVM v)230 SQInteger sq_instanceof( HSQUIRRELVM v ) {
231 	SQObjectPtr &inst = stack_get( v, -1 );
232 	SQObjectPtr &cl = stack_get( v, -2 );
233 	if ( squirrel_type( inst ) != OT_INSTANCE || squirrel_type( cl ) != OT_CLASS )
234 		return sq_throwerror( v, _SC( "invalid param type" ) );
235 	return _instance( inst )->InstanceOf( _class( cl ) ) ? 1 : 0;
236 }
237 
sq_arrayappend(HSQUIRRELVM v,SQInteger idx)238 SQRESULT sq_arrayappend( HSQUIRRELVM v, SQInteger idx ) {
239 	sq_aux_paramscheck( v, 2 );
240 	SQObjectPtr *arr;
241 	_GETSAFE_OBJ( v, idx, OT_ARRAY, arr );
242 	_array( *arr )->Append( v->GetUp( -1 ) );
243 	v->Pop( 1 );
244 	return SQ_OK;
245 }
246 
sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval)247 SQRESULT sq_arraypop( HSQUIRRELVM v, SQInteger idx, SQBool pushval ) {
248 	sq_aux_paramscheck( v, 1 );
249 	SQObjectPtr *arr;
250 	_GETSAFE_OBJ( v, idx, OT_ARRAY, arr );
251 	if ( _array( *arr )->Size() > 0 ) {
252 		if ( pushval != 0 ) {
253 			v->Push( _array( *arr )->Top() );
254 		}
255 		_array( *arr )->Pop();
256 		return SQ_OK;
257 	}
258 	return sq_throwerror( v, _SC( "empty array" ) );
259 }
260 
sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize)261 SQRESULT sq_arrayresize( HSQUIRRELVM v, SQInteger idx, SQInteger newsize ) {
262 	sq_aux_paramscheck( v, 1 );
263 	SQObjectPtr *arr;
264 	_GETSAFE_OBJ( v, idx, OT_ARRAY, arr );
265 	if ( _array( *arr )->Size() > 0 ) {
266 		_array( *arr )->Resize( newsize );
267 		return SQ_OK;
268 	}
269 	return SQ_OK;
270 }
271 
sq_arrayreverse(HSQUIRRELVM v,SQInteger idx)272 SQRESULT sq_arrayreverse( HSQUIRRELVM v, SQInteger idx ) {
273 	sq_aux_paramscheck( v, 1 );
274 	SQObjectPtr *o;
275 	_GETSAFE_OBJ( v, idx, OT_ARRAY, o );
276 	SQArray *arr = _array( *o );
277 	if ( arr->Size() > 0 ) {
278 		SQObjectPtr t;
279 		SQInteger size = arr->Size();
280 		SQInteger n = size >> 1; size -= 1;
281 		for ( SQInteger i = 0; i < n; i++ ) {
282 			t = arr->_values[i];
283 			arr->_values[i] = arr->_values[size-i];
284 			arr->_values[size-i] = t;
285 		}
286 		return SQ_OK;
287 	}
288 	return SQ_OK;
289 }
290 
sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars)291 void sq_newclosure( HSQUIRRELVM v, SQFUNCTION func, SQUnsignedInteger nfreevars ) {
292 	SQNativeClosure *nc = SQNativeClosure::Create( _ss( v ), func );
293 	nc->_nparamscheck = 0;
294 	for ( SQUnsignedInteger i = 0; i < nfreevars; i++ ) {
295 		nc->_outervalues.push_back( v->Top() );
296 		v->Pop();
297 	}
298 	v->Push( SQObjectPtr( nc ) );
299 }
300 
sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger * nparams,SQUnsignedInteger * nfreevars)301 SQRESULT sq_getclosureinfo( HSQUIRRELVM v, SQInteger idx, SQUnsignedInteger *nparams, SQUnsignedInteger *nfreevars ) {
302 	SQObject o = stack_get( v, idx );
303 	if ( sq_isclosure( o ) ) {
304 		SQClosure *c = _closure( o );
305 		SQFunctionProto *proto = _funcproto( c->_function );
306 		*nparams = ( SQUnsignedInteger )proto->_parameters.size();
307 		*nfreevars = ( SQUnsignedInteger )c->_outervalues.size();
308 		return SQ_OK;
309 	}
310 	return sq_throwerror( v, _SC( "the object is not a closure" ) );
311 }
312 
sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar * name)313 SQRESULT sq_setnativeclosurename( HSQUIRRELVM v, SQInteger idx, const SQChar *name ) {
314 	SQObject o = stack_get( v, idx );
315 	if ( sq_isnativeclosure( o ) ) {
316 		SQNativeClosure *nc = _nativeclosure( o );
317 		nc->_name = SQString::Create( _ss( v ), name );
318 		return SQ_OK;
319 	}
320 	return sq_throwerror( v, _SC( "the object is not a nativeclosure" ) );
321 }
322 
sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar * typemask)323 SQRESULT sq_setparamscheck( HSQUIRRELVM v, SQInteger nparamscheck, const SQChar *typemask ) {
324 	SQObject o = stack_get( v, -1 );
325 	if ( !sq_isnativeclosure( o ) )
326 		return sq_throwerror( v, _SC( "native closure expected" ) );
327 	SQNativeClosure *nc = _nativeclosure( o );
328 	nc->_nparamscheck = nparamscheck;
329 	if ( typemask ) {
330 		SQIntVec res;
331 		if ( !CompileTypemask( res, typemask ) )
332 			return sq_throwerror( v, _SC( "invalid typemask" ) );
333 		nc->_typecheck.copy( res );
334 	} else {
335 		nc->_typecheck.resize( 0 );
336 	}
337 	if ( nparamscheck == SQ_MATCHTYPEMASKSTRING ) {
338 		nc->_nparamscheck = nc->_typecheck.size();
339 	}
340 	return SQ_OK;
341 }
342 
sq_pushroottable(HSQUIRRELVM v)343 void sq_pushroottable( HSQUIRRELVM v ) {
344 	v->Push( v->_roottable );
345 }
346 
sq_pushregistrytable(HSQUIRRELVM v)347 void sq_pushregistrytable( HSQUIRRELVM v ) {
348 	v->Push( _ss( v )->_registry );
349 }
350 
sq_setroottable(HSQUIRRELVM v)351 SQRESULT sq_setroottable( HSQUIRRELVM v ) {
352 	SQObject o = stack_get( v, -1 );
353 	if ( sq_istable( o ) || sq_isnull( o ) ) {
354 		v->_roottable = o;
355 		v->Pop();
356 		return SQ_OK;
357 	}
358 	return sq_throwerror( v, _SC( "ivalid type" ) );
359 }
360 
sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p)361 void sq_setforeignptr( HSQUIRRELVM v, SQUserPointer p ) {
362 	v->_foreignptr = p;
363 }
364 
sq_getforeignptr(HSQUIRRELVM v)365 SQUserPointer sq_getforeignptr( HSQUIRRELVM v ) {
366 	return v->_foreignptr;
367 }
368 
sq_push(HSQUIRRELVM v,SQInteger idx)369 void sq_push( HSQUIRRELVM v, SQInteger idx ) {
370 	v->Push( stack_get( v, idx ) );
371 }
372 
sq_gettype(HSQUIRRELVM v,SQInteger idx)373 SQObjectType sq_gettype( HSQUIRRELVM v, SQInteger idx ) {
374 	return squirrel_type( stack_get( v, idx ) );
375 }
376 
sq_tostring(HSQUIRRELVM v,SQInteger idx)377 void sq_tostring( HSQUIRRELVM v, SQInteger idx ) {
378 	SQObjectPtr &o = stack_get( v, idx );
379 	SQObjectPtr res;
380 	v->ToString( o, res );
381 	v->Push( res );
382 }
383 
sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger * i)384 SQRESULT sq_getinteger( HSQUIRRELVM v, SQInteger idx, SQInteger *i ) {
385 	SQObjectPtr &o = stack_get( v, idx );
386 	if ( sq_isnumeric( o ) ) {
387 		*i = tointeger( o );
388 		return SQ_OK;
389 	}
390 	return SQ_ERROR;
391 }
392 
sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat * f)393 SQRESULT sq_getfloat( HSQUIRRELVM v, SQInteger idx, SQFloat *f ) {
394 	SQObjectPtr &o = stack_get( v, idx );
395 	if ( sq_isnumeric( o ) ) {
396 		*f = tofloat( o );
397 		return SQ_OK;
398 	}
399 	return SQ_ERROR;
400 }
401 
sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool * b)402 SQRESULT sq_getbool( HSQUIRRELVM v, SQInteger idx, SQBool *b ) {
403 	SQObjectPtr &o = stack_get( v, idx );
404 	if ( sq_isbool( o ) ) {
405 		*b = _integer( o );
406 		return SQ_OK;
407 	}
408 	return SQ_ERROR;
409 }
410 
sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar ** c)411 SQRESULT sq_getstring( HSQUIRRELVM v, SQInteger idx, const SQChar **c ) {
412 	SQObjectPtr *o = NULL;
413 	_GETSAFE_OBJ( v, idx, OT_STRING, o );
414 	*c = _stringval( *o );
415 	return SQ_OK;
416 }
417 
sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM * thread)418 SQRESULT sq_getthread( HSQUIRRELVM v, SQInteger idx, HSQUIRRELVM *thread ) {
419 	SQObjectPtr *o = NULL;
420 	_GETSAFE_OBJ( v, idx, OT_THREAD, o );
421 	*thread = _thread( *o );
422 	return SQ_OK;
423 }
424 
sq_clone(HSQUIRRELVM v,SQInteger idx)425 SQRESULT sq_clone( HSQUIRRELVM v, SQInteger idx ) {
426 	SQObjectPtr &o = stack_get( v, idx );
427 	v->Push( _null_ );
428 	if ( !v->Clone( o, stack_get( v, -1 ) ) ) {
429 		v->Pop();
430 		return sq_aux_invalidtype( v, squirrel_type( o ) );
431 	}
432 	return SQ_OK;
433 }
434 
sq_getsize(HSQUIRRELVM v,SQInteger idx)435 SQInteger sq_getsize( HSQUIRRELVM v, SQInteger idx ) {
436 	SQObjectPtr &o = stack_get( v, idx );
437 	SQObjectType type = squirrel_type( o );
438 	switch ( type ) {
439 	case OT_STRING:  return _string( o )->_len;
440 	case OT_TABLE:  return _table( o )->CountUsed();
441 	case OT_ARRAY:  return _array( o )->Size();
442 	case OT_USERDATA: return _userdata( o )->_size;
443 	default:
444 		return sq_aux_invalidtype( v, type );
445 	}
446 }
447 
sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer * p,SQUserPointer * typetag)448 SQRESULT sq_getuserdata( HSQUIRRELVM v, SQInteger idx, SQUserPointer *p, SQUserPointer *typetag ) {
449 	SQObjectPtr *o = NULL;
450 	_GETSAFE_OBJ( v, idx, OT_USERDATA, o );
451 	( *p ) = _userdataval( *o );
452 	if ( typetag ) *typetag = _userdata( *o )->_typetag;
453 	return SQ_OK;
454 }
455 
sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag)456 SQRESULT sq_settypetag( HSQUIRRELVM v, SQInteger idx, SQUserPointer typetag ) {
457 	SQObjectPtr &o = stack_get( v, idx );
458 	switch ( squirrel_type( o ) ) {
459 	case OT_USERDATA: _userdata( o )->_typetag = typetag; break;
460 	case OT_CLASS:  _class( o )->_typetag = typetag;  break;
461 	default:   return sq_throwerror( v, _SC( "invalid object type" ) );
462 	}
463 	return SQ_OK;
464 }
465 
sq_getobjtypetag(HSQOBJECT * o,SQUserPointer * typetag)466 SQRESULT sq_getobjtypetag( HSQOBJECT *o, SQUserPointer * typetag ) {
467 	switch ( squirrel_type( *o ) ) {
468 	case OT_INSTANCE: *typetag = _instance( *o )->_class->_typetag; break;
469 	case OT_USERDATA: *typetag = _userdata( *o )->_typetag; break;
470 	case OT_CLASS:    *typetag = _class( *o )->_typetag; break;
471 	default: return SQ_ERROR;
472 	}
473 	return SQ_OK;
474 }
475 
sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer * typetag)476 SQRESULT sq_gettypetag( HSQUIRRELVM v, SQInteger idx, SQUserPointer *typetag ) {
477 	SQObjectPtr &o = stack_get( v, idx );
478 	if ( SQ_FAILED( sq_getobjtypetag( &o, typetag ) ) )
479 		return sq_throwerror( v, _SC( "invalid object type" ) );
480 	return SQ_OK;
481 }
482 
sq_getuserpointer(HSQUIRRELVM v,SQInteger idx,SQUserPointer * p)483 SQRESULT sq_getuserpointer( HSQUIRRELVM v, SQInteger idx, SQUserPointer *p ) {
484 	SQObjectPtr *o = NULL;
485 	_GETSAFE_OBJ( v, idx, OT_USERPOINTER, o );
486 	( *p ) = _userpointer( *o );
487 	return SQ_OK;
488 }
489 
sq_setinstanceup(HSQUIRRELVM v,SQInteger idx,SQUserPointer p)490 SQRESULT sq_setinstanceup( HSQUIRRELVM v, SQInteger idx, SQUserPointer p ) {
491 	SQObjectPtr &o = stack_get( v, idx );
492 	if ( squirrel_type( o ) != OT_INSTANCE ) return sq_throwerror( v, _SC( "the object is not a class instance" ) );
493 	_instance( o )->_userpointer = p;
494 	return SQ_OK;
495 }
496 
sq_getinstanceup(HSQUIRRELVM v,SQInteger idx,SQUserPointer * p,SQUserPointer typetag)497 SQRESULT sq_getinstanceup( HSQUIRRELVM v, SQInteger idx, SQUserPointer *p, SQUserPointer typetag ) {
498 	SQObjectPtr &o = stack_get( v, idx );
499 	if ( squirrel_type( o ) != OT_INSTANCE ) return sq_throwerror( v, _SC( "the object is not a class instance" ) );
500 	( *p ) = _instance( o )->_userpointer;
501 	if ( typetag != 0 ) {
502 		SQClass *cl = _instance( o )->_class;
503 		do {
504 			if ( cl->_typetag == typetag )
505 				return SQ_OK;
506 			cl = cl->_base;
507 		} while ( cl != NULL );
508 		return sq_throwerror( v, _SC( "invalid type tag" ) );
509 	}
510 	return SQ_OK;
511 }
512 
sq_gettop(HSQUIRRELVM v)513 SQInteger sq_gettop( HSQUIRRELVM v ) {
514 	return ( v->_top ) - v->_stackbase;
515 }
516 
sq_settop(HSQUIRRELVM v,SQInteger newtop)517 void sq_settop( HSQUIRRELVM v, SQInteger newtop ) {
518 	SQInteger top = sq_gettop( v );
519 	if ( top > newtop )
520 		sq_pop( v, top - newtop );
521 	else
522 		while ( top < newtop ) sq_pushnull( v );
523 }
524 
sq_pop(HSQUIRRELVM v,SQInteger nelemstopop)525 void sq_pop( HSQUIRRELVM v, SQInteger nelemstopop ) {
526 	assert( v->_top >= nelemstopop );
527 	v->Pop( nelemstopop );
528 }
529 
sq_poptop(HSQUIRRELVM v)530 void sq_poptop( HSQUIRRELVM v ) {
531 	assert( v->_top >= 1 );
532 	v->Pop();
533 }
534 
535 
sq_remove(HSQUIRRELVM v,SQInteger idx)536 void sq_remove( HSQUIRRELVM v, SQInteger idx ) {
537 	v->Remove( idx );
538 }
539 
sq_cmp(HSQUIRRELVM v)540 SQInteger sq_cmp( HSQUIRRELVM v ) {
541 	SQInteger res;
542 	v->ObjCmp( stack_get( v, -1 ), stack_get( v, -2 ), res );
543 	return res;
544 }
545 
sq_createslot(HSQUIRRELVM v,SQInteger idx)546 SQRESULT sq_createslot( HSQUIRRELVM v, SQInteger idx ) {
547 	sq_aux_paramscheck( v, 3 );
548 	SQObjectPtr &self = stack_get( v, idx );
549 	if ( squirrel_type( self ) == OT_TABLE || squirrel_type( self ) == OT_CLASS ) {
550 		SQObjectPtr &key = v->GetUp( -2 );
551 		if ( squirrel_type( key ) == OT_NULL ) return sq_throwerror( v, _SC( "null is not a valid key" ) );
552 		v->NewSlot( self, key, v->GetUp( -1 ) );
553 		v->Pop( 2 );
554 	}
555 	return SQ_OK;
556 }
557 
sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)558 SQRESULT sq_deleteslot( HSQUIRRELVM v, SQInteger idx, SQBool pushval ) {
559 	sq_aux_paramscheck( v, 2 );
560 	SQObjectPtr *self;
561 	_GETSAFE_OBJ( v, idx, OT_TABLE, self );
562 	SQObjectPtr &key = v->GetUp( -1 );
563 	if ( squirrel_type( key ) == OT_NULL ) return sq_throwerror( v, _SC( "null is not a valid key" ) );
564 	SQObjectPtr res;
565 	if ( !v->DeleteSlot( *self, key, res ) ) {
566 		return SQ_ERROR;
567 	}
568 	if ( pushval ) v->GetUp( -1 ) = res;
569 	else v->Pop( 1 );
570 	return SQ_OK;
571 }
572 
sq_set(HSQUIRRELVM v,SQInteger idx)573 SQRESULT sq_set( HSQUIRRELVM v, SQInteger idx ) {
574 	SQObjectPtr &self = stack_get( v, idx );
575 	if ( v->Set( self, v->GetUp( -2 ), v->GetUp( -1 ), false ) ) {
576 		v->Pop( 2 );
577 		return SQ_OK;
578 	}
579 	v->Raise_IdxError( v->GetUp( -2 ) );return SQ_ERROR;
580 }
581 
sq_rawset(HSQUIRRELVM v,SQInteger idx)582 SQRESULT sq_rawset( HSQUIRRELVM v, SQInteger idx ) {
583 	SQObjectPtr &self = stack_get( v, idx );
584 	if ( squirrel_type( v->GetUp( -2 ) ) == OT_NULL ) return sq_throwerror( v, _SC( "null key" ) );
585 	switch ( squirrel_type( self ) ) {
586 	case OT_TABLE:
587 		_table( self )->NewSlot( v->GetUp( -2 ), v->GetUp( -1 ) );
588 		v->Pop( 2 );
589 		return SQ_OK;
590 		break;
591 	case OT_CLASS:
592 		_class( self )->NewSlot( v->GetUp( -2 ), v->GetUp( -1 ) );
593 		v->Pop( 2 );
594 		return SQ_OK;
595 		break;
596 	case OT_INSTANCE:
597 		if ( _instance( self )->Set( v->GetUp( -2 ), v->GetUp( -1 ) ) ) {
598 			v->Pop( 2 );
599 			return SQ_OK;
600 		}
601 		break;
602 	case OT_ARRAY:
603 		if ( v->Set( self, v->GetUp( -2 ), v->GetUp( -1 ), false ) ) {
604 			v->Pop( 2 );
605 			return SQ_OK;
606 		}
607 		break;
608 	default:
609 		v->Pop( 2 );
610 		return sq_throwerror( v, _SC( "rawset works only on array/table/calsse and instance" ) );
611 	}
612 	v->Raise_IdxError( v->GetUp( -2 ) );return SQ_ERROR;
613 }
614 
sq_setdelegate(HSQUIRRELVM v,SQInteger idx)615 SQRESULT sq_setdelegate( HSQUIRRELVM v, SQInteger idx ) {
616 	SQObjectPtr &self = stack_get( v, idx );
617 	SQObjectPtr &mt = v->GetUp( -1 );
618 	SQObjectType type = squirrel_type( self );
619 	switch ( type ) {
620 	case OT_TABLE:
621 		if ( squirrel_type( mt ) == OT_TABLE ) {
622 			if ( !_table( self )->SetDelegate( _table( mt ) ) ) return sq_throwerror( v, _SC( "delagate cycle" ) ); v->Pop();
623 		} else if ( squirrel_type( mt ) == OT_NULL ) {
624 			_table( self )->SetDelegate( NULL ); v->Pop();
625 		} else return sq_aux_invalidtype( v, type );
626 		break;
627 	case OT_USERDATA:
628 		if ( squirrel_type( mt ) == OT_TABLE ) {
629 			_userdata( self )->SetDelegate( _table( mt ) ); v->Pop();
630 		} else if ( squirrel_type( mt ) == OT_NULL ) {
631 			_userdata( self )->SetDelegate( NULL ); v->Pop();
632 		} else return sq_aux_invalidtype( v, type );
633 		break;
634 	default:
635 		return sq_aux_invalidtype( v, type );
636 		break;
637 	}
638 	return SQ_OK;
639 }
640 
sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)641 SQRESULT sq_rawdeleteslot( HSQUIRRELVM v, SQInteger idx, SQBool pushval ) {
642 	sq_aux_paramscheck( v, 2 );
643 	SQObjectPtr *self;
644 	_GETSAFE_OBJ( v, idx, OT_TABLE, self );
645 	SQObjectPtr &key = v->GetUp( -1 );
646 	SQObjectPtr t;
647 	if ( _table( *self )->Get( key, t ) ) {
648 		_table( *self )->Remove( key );
649 	}
650 	if ( pushval != 0 )
651 		if ( pushval ) v->GetUp( -1 ) = t;
652 		else
653 			v->Pop( 1 );
654 	return SQ_OK;
655 }
656 
sq_getdelegate(HSQUIRRELVM v,SQInteger idx)657 SQRESULT sq_getdelegate( HSQUIRRELVM v, SQInteger idx ) {
658 	SQObjectPtr &self = stack_get( v, idx );
659 	switch ( squirrel_type( self ) ) {
660 	case OT_TABLE:
661 		if ( !_table( self )->_delegate )break;
662 		v->Push( SQObjectPtr( _table( self )->_delegate ) );
663 		return SQ_OK;
664 		break;
665 	case OT_USERDATA:
666 		if ( !_userdata( self )->_delegate )break;
667 		v->Push( SQObjectPtr( _userdata( self )->_delegate ) );
668 		return SQ_OK;
669 		break;
670 	}
671 	return sq_throwerror( v, _SC( "wrong type" ) );
672 }
673 
sq_get(HSQUIRRELVM v,SQInteger idx)674 SQRESULT sq_get( HSQUIRRELVM v, SQInteger idx ) {
675 	SQObjectPtr &self = stack_get( v, idx );
676 	if ( v->Get( self, v->GetUp( -1 ), v->GetUp( -1 ), false, false ) )
677 		return SQ_OK;
678 	v->Pop( 1 );
679 	return sq_throwerror( v, _SC( "the index doesn't exist" ) );
680 }
681 
sq_rawget(HSQUIRRELVM v,SQInteger idx)682 SQRESULT sq_rawget( HSQUIRRELVM v, SQInteger idx ) {
683 	SQObjectPtr &self = stack_get( v, idx );
684 	switch ( squirrel_type( self ) ) {
685 	case OT_TABLE:
686 		if ( _table( self )->Get( v->GetUp( -1 ), v->GetUp( -1 ) ) )
687 			return SQ_OK;
688 		break;
689 	case OT_CLASS:
690 		if ( _class( self )->Get( v->GetUp( -1 ), v->GetUp( -1 ) ) )
691 			return SQ_OK;
692 		break;
693 	case OT_INSTANCE:
694 		if ( _instance( self )->Get( v->GetUp( -1 ), v->GetUp( -1 ) ) )
695 			return SQ_OK;
696 		break;
697 	case OT_ARRAY:
698 		if ( v->Get( self, v->GetUp( -1 ), v->GetUp( -1 ), false, false ) )
699 			return SQ_OK;
700 		break;
701 	default:
702 		v->Pop( 1 );
703 		return sq_throwerror( v, _SC( "rawget works only on array/table/instance and class" ) );
704 	}
705 	v->Pop( 1 );
706 	return sq_throwerror( v, _SC( "the index doesn't exist" ) );
707 }
708 
sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT * po)709 SQRESULT sq_getstackobj( HSQUIRRELVM v, SQInteger idx, HSQOBJECT *po ) {
710 	*po = stack_get( v, idx );
711 	return SQ_OK;
712 }
713 
sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx)714 const SQChar *sq_getlocal( HSQUIRRELVM v, SQUnsignedInteger level, SQUnsignedInteger idx ) {
715 	SQUnsignedInteger cstksize = v->_callsstack.size();
716 	SQUnsignedInteger lvl = ( cstksize - level ) - 1;
717 	SQInteger stackbase = v->_stackbase;
718 	if ( lvl < cstksize ) {
719 		for ( SQUnsignedInteger i = 0;i < level;i++ ) {
720 			SQVM::CallInfo &ci = v->_callsstack[( cstksize-i )-1];
721 			stackbase -= ci._prevstkbase;
722 		}
723 		SQVM::CallInfo &ci = v->_callsstack[lvl];
724 		if ( squirrel_type( ci._closure ) != OT_CLOSURE )
725 			return NULL;
726 		SQClosure *c = _closure( ci._closure );
727 		SQFunctionProto *func = _funcproto( c->_function );
728 		return func->GetLocal( v, stackbase, idx, ( ci._ip - func->_instructions._vals ) - 1 );
729 	}
730 	return NULL;
731 }
732 
sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj)733 void sq_pushobject( HSQUIRRELVM v, HSQOBJECT obj ) {
734 	v->Push( SQObjectPtr( obj ) );
735 }
736 
sq_resetobject(HSQOBJECT * po)737 void sq_resetobject( HSQOBJECT *po ) {
738 	po->_unVal.pUserPointer = NULL;po->_type = OT_NULL;
739 }
740 
sq_throwerror(HSQUIRRELVM v,const SQChar * err)741 SQRESULT sq_throwerror( HSQUIRRELVM v, const SQChar *err ) {
742 	v->_lasterror = SQString::Create( _ss( v ), err );
743 	return -1;
744 }
745 
sq_reseterror(HSQUIRRELVM v)746 void sq_reseterror( HSQUIRRELVM v ) {
747 	v->_lasterror = _null_;
748 }
749 
sq_getlasterror(HSQUIRRELVM v)750 void sq_getlasterror( HSQUIRRELVM v ) {
751 	v->Push( v->_lasterror );
752 }
753 
sq_reservestack(HSQUIRRELVM v,SQInteger nsize)754 void sq_reservestack( HSQUIRRELVM v, SQInteger nsize ) {
755 	if ( ( ( SQUnsignedInteger )v->_top + nsize ) > v->_stack.size() ) {
756 		v->_stack.resize( v->_stack.size() + ( ( v->_top + nsize ) - v->_stack.size() ) );
757 	}
758 }
759 
sq_resume(HSQUIRRELVM v,SQBool retval)760 SQRESULT sq_resume( HSQUIRRELVM v, SQBool retval ) {
761 	if ( squirrel_type( v->GetUp( -1 ) ) == OT_GENERATOR ) {
762 		v->Push( _null_ ); //retval
763 		if ( !v->Execute( v->GetUp( -2 ), v->_top, 0, v->_top, v->GetUp( -1 ), SQVM::ET_RESUME_GENERATOR ) ) {
764 			v->Raise_Error( v->_lasterror ); return SQ_ERROR;
765 		}
766 		if ( !retval )
767 			v->Pop();
768 		return SQ_OK;
769 	}
770 	return sq_throwerror( v, _SC( "only generators can be resumed" ) );
771 }
772 
sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval)773 SQRESULT sq_call( HSQUIRRELVM v, SQInteger params, SQBool retval ) {
774 	SQObjectPtr res;
775 	if ( v->Call( v->GetUp( -( params + 1 ) ), params, v->_top - params, res ) ) {
776 		v->Pop( params );//pop closure and args
777 		if ( retval ) {
778 			v->Push( res ); return SQ_OK;
779 		}
780 		return SQ_OK;
781 	} else {
782 		v->Pop( params );
783 		return SQ_ERROR;
784 	}
785 	if ( !v->_suspended )
786 		v->Pop( params );
787 	return sq_throwerror( v, _SC( "call failed" ) );
788 }
789 
sq_suspendvm(HSQUIRRELVM v)790 SQRESULT sq_suspendvm( HSQUIRRELVM v ) {
791 	return v->Suspend();
792 }
793 
sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval)794 SQRESULT sq_wakeupvm( HSQUIRRELVM v, SQBool wakeupret, SQBool retval ) {
795 	SQObjectPtr ret;
796 	if ( !v->_suspended )
797 		return sq_throwerror( v, _SC( "cannot resume a vm that is not running any code" ) );
798 	if ( wakeupret ) {
799 		v->GetAt( v->_stackbase + v->_suspended_target ) = v->GetUp( -1 ); //retval
800 		v->Pop();
801 	} else v->GetAt( v->_stackbase + v->_suspended_target ) = _null_;
802 	if ( !v->Execute( _null_, v->_top, -1, -1, ret, SQVM::ET_RESUME_VM ) )
803 		return SQ_ERROR;
804 	if ( sq_getvmstate( v ) == SQ_VMSTATE_IDLE ) {
805 		while ( v->_top > 1 ) v->_stack[--v->_top] = _null_;
806 	}
807 	if ( retval )
808 		v->Push( ret );
809 	return SQ_OK;
810 }
811 
sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook)812 void sq_setreleasehook( HSQUIRRELVM v, SQInteger idx, SQRELEASEHOOK hook ) {
813 	if ( sq_gettop( v ) >= 1 ) {
814 		SQObjectPtr &ud = stack_get( v, idx );
815 		switch ( squirrel_type( ud ) ) {
816 		case OT_USERDATA:
817 			_userdata( ud )->_hook = hook;
818 			break;
819 		case OT_INSTANCE:
820 			_instance( ud )->_hook = hook;
821 			break;
822 		}
823 	}
824 }
825 
sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f)826 void sq_setcompilererrorhandler( HSQUIRRELVM v, SQCOMPILERERROR f ) {
827 	_ss( v )->_compilererrorhandler = f;
828 }
829 
sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)830 SQRESULT sq_writeclosure( HSQUIRRELVM v, SQWRITEFUNC w, SQUserPointer up ) {
831 	SQObjectPtr *o = NULL;
832 	_GETSAFE_OBJ( v, -1, OT_CLOSURE, o );
833 	SQClosure *c = _closure( *o );
834 	unsigned short tag = SQ_BYTECODE_STREAM_TAG;
835 	if ( w( up, &tag, 2 ) != 2 )
836 		return sq_throwerror( v, _SC( "io error" ) );
837 	if ( !_closure( *o )->Save( v, up, w ) )
838 		return SQ_ERROR;
839 	return SQ_OK;
840 }
841 
sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)842 SQRESULT sq_readclosure( HSQUIRRELVM v, SQREADFUNC r, SQUserPointer up ) {
843 	SQObjectPtr func = SQFunctionProto::Create();
844 	SQObjectPtr closure = SQClosure::Create( _ss( v ), _funcproto( func ) );
845 	unsigned short tag;
846 	if ( r( up, &tag, 2 ) != 2 )
847 		return sq_throwerror( v, _SC( "io error" ) );
848 	if ( tag != SQ_BYTECODE_STREAM_TAG )
849 		return sq_throwerror( v, _SC( "invalid stream" ) );
850 	if ( !_closure( closure )->Load( v, up, r ) )
851 		return SQ_ERROR;
852 	v->Push( closure );
853 	return SQ_OK;
854 }
855 
sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)856 SQChar *sq_getscratchpad( HSQUIRRELVM v, SQInteger minsize ) {
857 	return _ss( v )->GetScratchPad( minsize );
858 }
859 
sq_collectgarbage(HSQUIRRELVM v)860 SQInteger sq_collectgarbage( HSQUIRRELVM v ) {
861 #ifndef NO_GARBAGE_COLLECTOR
862 	return _ss( v )->CollectGarbage( v );
863 #else
864 	return -1;
865 #endif
866 }
867 
sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)868 const SQChar *sq_getfreevariable( HSQUIRRELVM v, SQInteger idx, SQUnsignedInteger nval ) {
869 	SQObjectPtr &self = stack_get( v, idx );
870 	const SQChar *name = NULL;
871 	if ( squirrel_type( self ) == OT_CLOSURE ) {
872 		if ( _closure( self )->_outervalues.size() > nval ) {
873 			v->Push( _closure( self )->_outervalues[nval] );
874 			SQFunctionProto *fp = _funcproto( _closure( self )->_function );
875 			SQOuterVar &ov = fp->_outervalues[nval];
876 			name = _stringval( ov._name );
877 		}
878 	}
879 	return name;
880 }
881 
sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)882 SQRESULT sq_setfreevariable( HSQUIRRELVM v, SQInteger idx, SQUnsignedInteger nval ) {
883 	SQObjectPtr &self = stack_get( v, idx );
884 	switch ( squirrel_type( self ) ) {
885 	case OT_CLOSURE:
886 		if ( _closure( self )->_outervalues.size() > nval ) {
887 			_closure( self )->_outervalues[nval] = stack_get( v, -1 );
888 		} else return sq_throwerror( v, _SC( "invalid free var index" ) );
889 		break;
890 	case OT_NATIVECLOSURE:
891 		if ( _nativeclosure( self )->_outervalues.size() > nval ) {
892 			_nativeclosure( self )->_outervalues[nval] = stack_get( v, -1 );
893 		} else return sq_throwerror( v, _SC( "invalid free var index" ) );
894 		break;
895 	default:
896 		return sq_aux_invalidtype( v, squirrel_type( self ) );
897 	}
898 	v->Pop( 1 );
899 	return SQ_OK;
900 }
901 
sq_setattributes(HSQUIRRELVM v,SQInteger idx)902 SQRESULT sq_setattributes( HSQUIRRELVM v, SQInteger idx ) {
903 	SQObjectPtr *o = NULL;
904 	_GETSAFE_OBJ( v, idx, OT_CLASS, o );
905 	SQObjectPtr &key = stack_get( v, -2 );
906 	SQObjectPtr &val = stack_get( v, -1 );
907 	SQObjectPtr attrs;
908 	if ( squirrel_type( key ) == OT_NULL ) {
909 		attrs = _class( *o )->_attributes;
910 		_class( *o )->_attributes = val;
911 		v->Pop( 2 );
912 		v->Push( attrs );
913 		return SQ_OK;
914 	} else if ( _class( *o )->GetAttributes( key, attrs ) ) {
915 		_class( *o )->SetAttributes( key, val );
916 		v->Pop( 2 );
917 		v->Push( attrs );
918 		return SQ_OK;
919 	}
920 	return sq_throwerror( v, _SC( "wrong index" ) );
921 }
922 
sq_getattributes(HSQUIRRELVM v,SQInteger idx)923 SQRESULT sq_getattributes( HSQUIRRELVM v, SQInteger idx ) {
924 	SQObjectPtr *o = NULL;
925 	_GETSAFE_OBJ( v, idx, OT_CLASS, o );
926 	SQObjectPtr &key = stack_get( v, -1 );
927 	SQObjectPtr attrs;
928 	if ( squirrel_type( key ) == OT_NULL ) {
929 		attrs = _class( *o )->_attributes;
930 		v->Pop();
931 		v->Push( attrs );
932 		return SQ_OK;
933 	} else if ( _class( *o )->GetAttributes( key, attrs ) ) {
934 		v->Pop();
935 		v->Push( attrs );
936 		return SQ_OK;
937 	}
938 	return sq_throwerror( v, _SC( "wrong index" ) );
939 }
940 
sq_getclass(HSQUIRRELVM v,SQInteger idx)941 SQRESULT sq_getclass( HSQUIRRELVM v, SQInteger idx ) {
942 	SQObjectPtr *o = NULL;
943 	_GETSAFE_OBJ( v, idx, OT_INSTANCE, o );
944 	v->Push( SQObjectPtr( _instance( *o )->_class ) );
945 	return SQ_OK;
946 }
947 
sq_createinstance(HSQUIRRELVM v,SQInteger idx)948 SQRESULT sq_createinstance( HSQUIRRELVM v, SQInteger idx ) {
949 	SQObjectPtr *o = NULL;
950 	_GETSAFE_OBJ( v, idx, OT_CLASS, o );
951 	v->Push( _class( *o )->CreateInstance() );
952 	return SQ_OK;
953 }
954 
sq_weakref(HSQUIRRELVM v,SQInteger idx)955 void sq_weakref( HSQUIRRELVM v, SQInteger idx ) {
956 	SQObject &o = stack_get( v, idx );
957 	if ( ISREFCOUNTED( squirrel_type( o ) ) ) {
958 		v->Push( _refcounted( o )->GetWeakRef( squirrel_type( o ) ) );
959 		return;
960 	}
961 	v->Push( o );
962 }
963 
sq_getweakrefval(HSQUIRRELVM v,SQInteger idx)964 SQRESULT sq_getweakrefval( HSQUIRRELVM v, SQInteger idx ) {
965 	SQObjectPtr &o = stack_get( v, idx );
966 	if ( squirrel_type( o ) != OT_WEAKREF ) {
967 		return sq_throwerror( v, _SC( "the object must be a weakref" ) );
968 	}
969 	v->Push( _weakref( o )->_obj );
970 	return SQ_OK;
971 }
972 
sq_next(HSQUIRRELVM v,SQInteger idx)973 SQRESULT sq_next( HSQUIRRELVM v, SQInteger idx ) {
974 	SQObjectPtr o = stack_get( v, idx ), &refpos = stack_get( v, -1 ), realkey, val;
975 	if ( squirrel_type( o ) == OT_GENERATOR ) {
976 		return sq_throwerror( v, _SC( "cannot iterate a generator" ) );
977 	}
978 	bool finished;
979 	if ( !v->FOREACH_OP( o, realkey, val, refpos, 0, finished ) )
980 		return SQ_ERROR;
981 	if ( !finished ) {
982 		v->Push( realkey );
983 		v->Push( val );
984 		return SQ_OK;
985 	}
986 	return SQ_ERROR;
987 }
988 
989 struct BufState {
990 	const SQChar *buf;
991 	SQInteger ptr;
992 	SQInteger size;
993 };
994 
buf_lexfeed(SQUserPointer file)995 SQInteger buf_lexfeed( SQUserPointer file ) {
996 	BufState *buf = ( BufState* )file;
997 	if ( buf->size < ( buf->ptr + 1 ) )
998 		return 0;
999 	return buf->buf[buf->ptr++];
1000 }
1001 
sq_compilebuffer(HSQUIRRELVM v,const SQChar * s,SQInteger size,const SQChar * sourcename,SQBool raiseerror)1002 SQRESULT sq_compilebuffer( HSQUIRRELVM v, const SQChar *s, SQInteger size, const SQChar *sourcename, SQBool raiseerror ) {
1003 	BufState buf;
1004 	buf.buf = s;
1005 	buf.size = size;
1006 	buf.ptr = 0;
1007 	return sq_compile( v, buf_lexfeed, &buf, sourcename, raiseerror );
1008 }
1009 
sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx)1010 void sq_move( HSQUIRRELVM dest, HSQUIRRELVM src, SQInteger idx ) {
1011 	dest->Push( stack_get( src, idx ) );
1012 }
1013 
sq_setprintfunc(HSQUIRRELVM v,SQPRINTFUNCTION printfunc)1014 void sq_setprintfunc( HSQUIRRELVM v, SQPRINTFUNCTION printfunc ) {
1015 	_ss( v )->_printfunc = printfunc;
1016 }
1017 
sq_getprintfunc(HSQUIRRELVM v)1018 SQPRINTFUNCTION sq_getprintfunc( HSQUIRRELVM v ) {
1019 	return _ss( v )->_printfunc;
1020 }
1021 
sq_malloc(SQUnsignedInteger size)1022 void *sq_malloc( SQUnsignedInteger size ) {
1023 	return SQ_MALLOC( size );
1024 }
1025 
sq_realloc(void * p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize)1026 void *sq_realloc( void* p, SQUnsignedInteger oldsize, SQUnsignedInteger newsize ) {
1027 	return SQ_REALLOC( p, oldsize, newsize );
1028 }
sq_free(void * p,SQUnsignedInteger size)1029 void sq_free( void *p, SQUnsignedInteger size ) {
1030 	SQ_FREE( p, size );
1031 }
1032