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 "sqclass.h"
12 #include <stdlib.h>
13 #include <stdarg.h>
14 #include <ctype.h>
15 
str2num(const SQChar * s,SQObjectPtr & res)16 bool str2num( const SQChar *s, SQObjectPtr &res ) {
17 	SQChar *end;
18 	if ( scstrstr( s, _SC( "." ) ) ) {
19 		SQFloat r = SQFloat( scstrtod( s, &end ) );
20 		if ( s == end ) return false;
21 		res = r;
22 		return true;
23 	} else {
24 		SQInteger r = SQInteger( scstrtol( s, &end, 10 ) );
25 		if ( s == end ) return false;
26 		res = r;
27 		return true;
28 	}
29 }
30 
31 #ifndef NO_GARBAGE_COLLECTOR
base_collectgarbage(HSQUIRRELVM v)32 static SQInteger base_collectgarbage( HSQUIRRELVM v ) {
33 	sq_pushinteger( v, sq_collectgarbage( v ) );
34 	return 1;
35 }
36 #endif
37 
base_getroottable(HSQUIRRELVM v)38 static SQInteger base_getroottable( HSQUIRRELVM v ) {
39 	v->Push( v->_roottable );
40 	return 1;
41 }
42 
base_setroottable(HSQUIRRELVM v)43 static SQInteger base_setroottable( HSQUIRRELVM v ) {
44 	SQObjectPtr &o = stack_get( v, 2 );
45 	if ( SQ_FAILED( sq_setroottable( v ) ) ) return SQ_ERROR;
46 	v->Push( o );
47 	return 1;
48 }
49 
base_seterrorhandler(HSQUIRRELVM v)50 static SQInteger base_seterrorhandler( HSQUIRRELVM v ) {
51 	sq_seterrorhandler( v );
52 	return 0;
53 }
54 
base_setdebughook(HSQUIRRELVM v)55 static SQInteger base_setdebughook( HSQUIRRELVM v ) {
56 	sq_setdebughook( v );
57 	return 0;
58 }
59 
base_enabledebuginfo(HSQUIRRELVM v)60 static SQInteger base_enabledebuginfo( HSQUIRRELVM v ) {
61 	SQObjectPtr &o = stack_get( v, 2 );
62 	sq_enabledebuginfo( v, ( squirrel_type( o ) != OT_NULL ) ? 1 : 0 );
63 	return 0;
64 }
65 
base_getstackinfos(HSQUIRRELVM v)66 static SQInteger base_getstackinfos( HSQUIRRELVM v ) {
67 	SQInteger level;
68 	SQStackInfos si;
69 	SQInteger seq = 0;
70 	const SQChar *name = NULL;
71 	sq_getinteger( v, -1, &level );
72 	if ( SQ_SUCCEEDED( sq_stackinfos( v, level, &si ) ) ) {
73 		const SQChar *fn = _SC( "unknown" );
74 		const SQChar *src = _SC( "unknown" );
75 		if ( si.funcname )fn = si.funcname;
76 		if ( si.source )src = si.source;
77 		sq_newtable( v );
78 		sq_pushstring( v, _SC( "func" ), -1 );
79 		sq_pushstring( v, fn, -1 );
80 		sq_createslot( v, -3 );
81 		sq_pushstring( v, _SC( "src" ), -1 );
82 		sq_pushstring( v, src, -1 );
83 		sq_createslot( v, -3 );
84 		sq_pushstring( v, _SC( "line" ), -1 );
85 		sq_pushinteger( v, si.line );
86 		sq_createslot( v, -3 );
87 		sq_pushstring( v, _SC( "locals" ), -1 );
88 		sq_newtable( v );
89 		seq = 0;
90 		while ( name = sq_getlocal( v, level, seq ) ) {
91 			sq_pushstring( v, name, -1 );
92 			sq_push( v, -2 );
93 			sq_createslot( v, -4 );
94 			sq_pop( v, 1 );
95 			seq++;
96 		}
97 		sq_createslot( v, -3 );
98 		return 1;
99 	}
100 
101 	return 0;
102 }
103 
base_assert(HSQUIRRELVM v)104 static SQInteger base_assert( HSQUIRRELVM v ) {
105 	if ( v->IsFalse( stack_get( v, 2 ) ) ) {
106 		return sq_throwerror( v, _SC( "assertion failed" ) );
107 	}
108 	return 0;
109 }
110 
get_slice_params(HSQUIRRELVM v,SQInteger & sidx,SQInteger & eidx,SQObjectPtr & o)111 static SQInteger get_slice_params( HSQUIRRELVM v, SQInteger &sidx, SQInteger &eidx, SQObjectPtr &o ) {
112 	SQInteger top = sq_gettop( v );
113 	sidx = 0;
114 	eidx = 0;
115 	o = stack_get( v, 1 );
116 	SQObjectPtr &start = stack_get( v, 2 );
117 	if ( squirrel_type( start ) != OT_NULL && sq_isnumeric( start ) ) {
118 		sidx = tointeger( start );
119 	}
120 	if ( top > 2 ) {
121 		SQObjectPtr &end = stack_get( v, 3 );
122 		if ( sq_isnumeric( end ) ) {
123 			eidx = tointeger( end );
124 		}
125 	} else {
126 		eidx = sq_getsize( v, 1 );
127 	}
128 	return 1;
129 }
130 
base_print(HSQUIRRELVM v)131 static SQInteger base_print( HSQUIRRELVM v ) {
132 	const SQChar *str;
133 	sq_tostring( v, 2 );
134 	sq_getstring( v, -1, &str );
135 	if ( _ss( v )->_printfunc ) _ss( v )->_printfunc( v, _SC( "%s" ), str );
136 	return 0;
137 }
138 
base_compilestring(HSQUIRRELVM v)139 static SQInteger base_compilestring( HSQUIRRELVM v ) {
140 	SQInteger nargs = sq_gettop( v );
141 	const SQChar *src = NULL, *name = _SC( "unnamedbuffer" );
142 	SQInteger size;
143 	sq_getstring( v, 2, &src );
144 	size = sq_getsize( v, 2 );
145 	if ( nargs > 2 ) {
146 		sq_getstring( v, 3, &name );
147 	}
148 	if ( SQ_SUCCEEDED( sq_compilebuffer( v, src, size, name, SQFalse ) ) )
149 		return 1;
150 	else
151 		return SQ_ERROR;
152 }
153 
base_newthread(HSQUIRRELVM v)154 static SQInteger base_newthread( HSQUIRRELVM v ) {
155 	SQObjectPtr &func = stack_get( v, 2 );
156 	SQInteger stksize = ( _funcproto( _closure( func )->_function )->_stacksize << 1 ) + 2;
157 	HSQUIRRELVM newv = sq_newthread( v, ( stksize < MIN_STACK_OVERHEAD + 2 ) ? MIN_STACK_OVERHEAD + 2 : stksize );
158 	sq_move( newv, v, -2 );
159 	return 1;
160 }
161 
base_suspend(HSQUIRRELVM v)162 static SQInteger base_suspend( HSQUIRRELVM v ) {
163 	return sq_suspendvm( v );
164 }
165 
base_array(HSQUIRRELVM v)166 static SQInteger base_array( HSQUIRRELVM v ) {
167 	SQArray *a;
168 	SQObject &size = stack_get( v, 2 );
169 	if ( sq_gettop( v ) > 2 ) {
170 		a = SQArray::Create( _ss( v ), 0 );
171 		a->Resize( tointeger( size ), stack_get( v, 3 ) );
172 	} else {
173 		a = SQArray::Create( _ss( v ), tointeger( size ) );
174 	}
175 	v->Push( a );
176 	return 1;
177 }
178 
base_type(HSQUIRRELVM v)179 static SQInteger base_type( HSQUIRRELVM v ) {
180 	SQObjectPtr &o = stack_get( v, 2 );
181 	v->Push( SQString::Create( _ss( v ), GetTypeName( o ), -1 ) );
182 	return 1;
183 }
184 
185 static SQRegFunction base_funcs[] = {
186 	//generic
187 	{_SC( "seterrorhandler" ), base_seterrorhandler, 2, NULL},
188 	{_SC( "setdebughook" ), base_setdebughook, 2, NULL},
189 	{_SC( "enabledebuginfo" ), base_enabledebuginfo, 2, NULL},
190 	{_SC( "getstackinfos" ), base_getstackinfos, 2, _SC( ".n" )},
191 	{_SC( "getroottable" ), base_getroottable, 1, NULL},
192 	{_SC( "setroottable" ), base_setroottable, 2, NULL},
193 	{_SC( "assert" ), base_assert, 2, NULL},
194 	{_SC( "print" ), base_print, 2, NULL},
195 	{_SC( "compilestring" ), base_compilestring, -2, _SC( ".ss" )},
196 	{_SC( "newthread" ), base_newthread, 2, _SC( ".c" )},
197 	{_SC( "suspend" ), base_suspend, -1, NULL},
198 	{_SC( "array" ), base_array, -2, _SC( ".n" )},
199 	{_SC( "type" ), base_type, 2, NULL},
200 #ifndef NO_GARBAGE_COLLECTOR
201 	{_SC( "collectgarbage" ), base_collectgarbage, 1, _SC( "t" )},
202 #endif
203 	{0, 0}
204 };
205 
sq_base_register(HSQUIRRELVM v)206 void sq_base_register( HSQUIRRELVM v ) {
207 	SQInteger i = 0;
208 	sq_pushroottable( v );
209 	while ( base_funcs[i].name != 0 ) {
210 		sq_pushstring( v, base_funcs[i].name, -1 );
211 		sq_newclosure( v, base_funcs[i].f, 0 );
212 		sq_setnativeclosurename( v, -1, base_funcs[i].name );
213 		sq_setparamscheck( v, base_funcs[i].nparamscheck, base_funcs[i].typemask );
214 		sq_createslot( v, -3 );
215 		i++;
216 	}
217 	sq_pushstring( v, _SC( "_charsize_" ), -1 );
218 	sq_pushinteger( v, sizeof( SQChar ) );
219 	sq_createslot( v, -3 );
220 	sq_pop( v, 1 );
221 }
222 
default_delegate_len(HSQUIRRELVM v)223 static SQInteger default_delegate_len( HSQUIRRELVM v ) {
224 	v->Push( SQInteger( sq_getsize( v, 1 ) ) );
225 	return 1;
226 }
227 
default_delegate_tofloat(HSQUIRRELVM v)228 static SQInteger default_delegate_tofloat( HSQUIRRELVM v ) {
229 	SQObjectPtr &o = stack_get( v, 1 );
230 	switch ( squirrel_type( o ) ) {
231 	case OT_STRING: {
232 			SQObjectPtr res;
233 			if ( str2num( _stringval( o ), res ) ) {
234 				v->Push( SQObjectPtr( tofloat( res ) ) );
235 				break;
236 			}
237 		}
238 		return sq_throwerror( v, _SC( "cannot convert the string" ) );
239 		break;
240 case OT_INTEGER: case OT_FLOAT:
241 		v->Push( SQObjectPtr( tofloat( o ) ) );
242 		break;
243 	case OT_BOOL:
244 		v->Push( SQObjectPtr( ( SQFloat )( _integer( o ) ? 1 : 0 ) ) );
245 		break;
246 	default:
247 		v->Push( _null_ );
248 		break;
249 	}
250 	return 1;
251 }
252 
default_delegate_tointeger(HSQUIRRELVM v)253 static SQInteger default_delegate_tointeger( HSQUIRRELVM v ) {
254 	SQObjectPtr &o = stack_get( v, 1 );
255 	switch ( squirrel_type( o ) ) {
256 	case OT_STRING: {
257 			SQObjectPtr res;
258 			if ( str2num( _stringval( o ), res ) ) {
259 				v->Push( SQObjectPtr( tointeger( res ) ) );
260 				break;
261 			}
262 		}
263 		return sq_throwerror( v, _SC( "cannot convert the string" ) );
264 		break;
265 case OT_INTEGER: case OT_FLOAT:
266 		v->Push( SQObjectPtr( tointeger( o ) ) );
267 		break;
268 	case OT_BOOL:
269 		v->Push( SQObjectPtr( _integer( o ) ? 1 : 0 ) );
270 		break;
271 	default:
272 		v->Push( _null_ );
273 		break;
274 	}
275 	return 1;
276 }
277 
default_delegate_tostring(HSQUIRRELVM v)278 static SQInteger default_delegate_tostring( HSQUIRRELVM v ) {
279 	sq_tostring( v, 1 );
280 	return 1;
281 }
282 
obj_delegate_weakref(HSQUIRRELVM v)283 static SQInteger obj_delegate_weakref( HSQUIRRELVM v ) {
284 	sq_weakref( v, 1 );
285 	return 1;
286 }
287 
number_delegate_tochar(HSQUIRRELVM v)288 static SQInteger number_delegate_tochar( HSQUIRRELVM v ) {
289 	SQObject &o = stack_get( v, 1 );
290 	SQChar c = tointeger( o );
291 	v->Push( SQString::Create( _ss( v ), ( const SQChar * )&c, 1 ) );
292 	return 1;
293 }
294 
295 
296 /////////////////////////////////////////////////////////////////
297 //TABLE DEFAULT DELEGATE
298 
table_rawdelete(HSQUIRRELVM v)299 static SQInteger table_rawdelete( HSQUIRRELVM v ) {
300 	if ( SQ_FAILED( sq_rawdeleteslot( v, 1, SQTrue ) ) )
301 		return SQ_ERROR;
302 	return 1;
303 }
304 
305 
container_rawexists(HSQUIRRELVM v)306 static SQInteger container_rawexists( HSQUIRRELVM v ) {
307 	if ( SQ_SUCCEEDED( sq_rawget( v, -2 ) ) ) {
308 		sq_pushbool( v, SQTrue );
309 		return 1;
310 	}
311 	sq_pushbool( v, SQFalse );
312 	return 1;
313 }
314 
table_rawset(HSQUIRRELVM v)315 static SQInteger table_rawset( HSQUIRRELVM v ) {
316 	return sq_rawset( v, -3 );
317 }
318 
319 
table_rawget(HSQUIRRELVM v)320 static SQInteger table_rawget( HSQUIRRELVM v ) {
321 	return SQ_SUCCEEDED( sq_rawget( v, -2 ) ) ? 1 : SQ_ERROR;
322 }
323 
324 SQRegFunction SQSharedState::_table_default_delegate_funcz[] = {
325 	{_SC( "len" ), default_delegate_len, 1, _SC( "t" )},
326 	{_SC( "rawget" ), table_rawget, 2, _SC( "t" )},
327 	{_SC( "rawset" ), table_rawset, 3, _SC( "t" )},
328 	{_SC( "rawdelete" ), table_rawdelete, 2, _SC( "t" )},
329 	{_SC( "rawin" ), container_rawexists, 2, _SC( "t" )},
330 	{_SC( "weakref" ), obj_delegate_weakref, 1, NULL },
331 	{0, 0}
332 };
333 
334 //ARRAY DEFAULT DELEGATE///////////////////////////////////////
335 
array_append(HSQUIRRELVM v)336 static SQInteger array_append( HSQUIRRELVM v ) {
337 	return sq_arrayappend( v, -2 );
338 }
339 
array_extend(HSQUIRRELVM v)340 static SQInteger array_extend( HSQUIRRELVM v ) {
341 	_array( stack_get( v, 1 ) )->Extend( _array( stack_get( v, 2 ) ) );
342 	return 0;
343 }
344 
array_reverse(HSQUIRRELVM v)345 static SQInteger array_reverse( HSQUIRRELVM v ) {
346 	return sq_arrayreverse( v, -1 );
347 }
348 
array_pop(HSQUIRRELVM v)349 static SQInteger array_pop( HSQUIRRELVM v ) {
350 	return SQ_SUCCEEDED( sq_arraypop( v, 1, SQTrue ) ) ? 1 : SQ_ERROR;
351 }
352 
array_top(HSQUIRRELVM v)353 static SQInteger array_top( HSQUIRRELVM v ) {
354 	SQObject &o = stack_get( v, 1 );
355 	if ( _array( o )->Size() > 0 ) {
356 		v->Push( _array( o )->Top() );
357 		return 1;
358 	} else return sq_throwerror( v, _SC( "top() on a empty array" ) );
359 }
360 
array_insert(HSQUIRRELVM v)361 static SQInteger array_insert( HSQUIRRELVM v ) {
362 	SQObject &o = stack_get( v, 1 );
363 	SQObject &idx = stack_get( v, 2 );
364 	SQObject &val = stack_get( v, 3 );
365 	_array( o )->Insert( idx, val );
366 	return 0;
367 }
368 
array_remove(HSQUIRRELVM v)369 static SQInteger array_remove( HSQUIRRELVM v ) {
370 	SQObject &o = stack_get( v, 1 );
371 	SQObject &idx = stack_get( v, 2 );
372 	if ( !sq_isnumeric( idx ) ) return sq_throwerror( v, _SC( "wrong type" ) );
373 	SQObjectPtr val;
374 	if ( _array( o )->Get( tointeger( idx ), val ) ) {
375 		_array( o )->Remove( tointeger( idx ) );
376 		v->Push( val );
377 		return 1;
378 	}
379 	return sq_throwerror( v, _SC( "idx out of range" ) );
380 }
381 
array_resize(HSQUIRRELVM v)382 static SQInteger array_resize( HSQUIRRELVM v ) {
383 	SQObject &o = stack_get( v, 1 );
384 	SQObject &nsize = stack_get( v, 2 );
385 	SQObjectPtr fill;
386 	if ( sq_isnumeric( nsize ) ) {
387 		if ( sq_gettop( v ) > 2 )
388 			fill = stack_get( v, 3 );
389 		_array( o )->Resize( tointeger( nsize ), fill );
390 		return 0;
391 	}
392 	return sq_throwerror( v, _SC( "size must be a number" ) );
393 }
394 
395 
396 //QSORT ala Sedgewick
_qsort_compare(HSQUIRRELVM v,SQObjectPtr & arr,SQObjectPtr & a,SQObjectPtr & b,SQInteger func,SQInteger & ret)397 bool _qsort_compare( HSQUIRRELVM v, SQObjectPtr &arr, SQObjectPtr &a, SQObjectPtr &b, SQInteger func, SQInteger &ret ) {
398 	if ( func < 0 ) {
399 		if ( !v->ObjCmp( a, b, ret ) ) return false;
400 	} else {
401 		SQInteger top = sq_gettop( v );
402 		sq_push( v, func );
403 		sq_pushroottable( v );
404 		v->Push( a );
405 		v->Push( b );
406 		if ( SQ_FAILED( sq_call( v, 3, SQTrue ) ) ) {
407 			v->Raise_Error( _SC( "compare func failed" ) );
408 			return false;
409 		}
410 		sq_getinteger( v, -1, &ret );
411 		sq_settop( v, top );
412 		return true;
413 	}
414 	return true;
415 }
416 //QSORT ala Sedgewick
_qsort(HSQUIRRELVM v,SQObjectPtr & arr,SQInteger l,SQInteger r,SQInteger func)417 bool _qsort( HSQUIRRELVM v, SQObjectPtr &arr, SQInteger l, SQInteger r, SQInteger func ) {
418 	SQInteger i, j;
419 	SQArray *a = _array( arr );
420 	SQObjectPtr pivot, t;
421 	if ( l < r ) {
422 		pivot = a->_values[l];
423 		i = l; j = r + 1;
424 		while ( 1 ) {
425 			SQInteger ret;
426 			do {
427 				++i;
428 				if ( i > r ) break;
429 				if ( !_qsort_compare( v, arr, a->_values[i], pivot, func, ret ) )
430 					return false;
431 			} while ( ret <= 0 );
432 			do {
433 				--j;
434 				if ( !_qsort_compare( v, arr, a->_values[j], pivot, func, ret ) )
435 					return false;
436 			} while ( ret > 0 );
437 			if ( i >= j ) break;
438 			t = a->_values[i]; a->_values[i] = a->_values[j]; a->_values[j] = t;
439 		}
440 		t = a->_values[l]; a->_values[l] = a->_values[j]; a->_values[j] = t;
441 		if ( !_qsort( v, arr, l, j - 1, func ) ) return false;
442 		if ( !_qsort( v, arr, j + 1, r, func ) ) return false;
443 	}
444 	return true;
445 }
446 
array_sort(HSQUIRRELVM v)447 static SQInteger array_sort( HSQUIRRELVM v ) {
448 	//SQ_TRY {
449 	SQInteger func = -1;
450 	SQObjectPtr &o = stack_get( v, 1 );
451 	SQObject &funcobj = stack_get( v, 2 );
452 	if ( _array( o )->Size() > 1 ) {
453 		if ( squirrel_type( funcobj ) == OT_CLOSURE || squirrel_type( funcobj ) == OT_NATIVECLOSURE ) func = 2;
454 		if ( !_qsort( v, o, 0, _array( o )->Size() - 1, func ) )
455 			return SQ_ERROR;
456 
457 	}
458 	return 0;
459 }
array_slice(HSQUIRRELVM v)460 static SQInteger array_slice( HSQUIRRELVM v ) {
461 	SQInteger sidx, eidx;
462 	SQObjectPtr o;
463 	if ( get_slice_params( v, sidx, eidx, o ) == -1 )return -1;
464 	if ( sidx < 0 )sidx = _array( o )->Size() + sidx;
465 	if ( eidx < 0 )eidx = _array( o )->Size() + eidx;
466 	if ( eidx <= sidx )return sq_throwerror( v, _SC( "wrong indexes" ) );
467 	SQArray *arr = SQArray::Create( _ss( v ), eidx - sidx );
468 	SQObjectPtr t;
469 	SQInteger count = 0;
470 	for ( SQInteger i = sidx;i < eidx;i++ ) {
471 		_array( o )->Get( i, t );
472 		arr->Set( count++, t );
473 	}
474 	v->Push( arr );
475 	return 1;
476 
477 }
478 
479 SQRegFunction SQSharedState::_array_default_delegate_funcz[] = {
480 	{_SC( "len" ), default_delegate_len, 1, _SC( "a" )},
481 	{_SC( "append" ), array_append, 2, _SC( "a" )},
482 	{_SC( "extend" ), array_extend, 2, _SC( "aa" )},
483 	{_SC( "push" ), array_append, 2, _SC( "a" )},
484 	{_SC( "pop" ), array_pop, 1, _SC( "a" )},
485 	{_SC( "top" ), array_top, 1, _SC( "a" )},
486 	{_SC( "insert" ), array_insert, 3, _SC( "an" )},
487 	{_SC( "remove" ), array_remove, 2, _SC( "an" )},
488 	{_SC( "resize" ), array_resize, -2, _SC( "an" )},
489 	{_SC( "reverse" ), array_reverse, 1, _SC( "a" )},
490 	{_SC( "sort" ), array_sort, -1, _SC( "ac" )},
491 	{_SC( "slice" ), array_slice, -1, _SC( "ann" )},
492 	{_SC( "weakref" ), obj_delegate_weakref, 1, NULL },
493 	{0, 0}
494 };
495 
496 //STRING DEFAULT DELEGATE//////////////////////////
string_slice(HSQUIRRELVM v)497 static SQInteger string_slice( HSQUIRRELVM v ) {
498 	SQInteger sidx, eidx;
499 	SQObjectPtr o;
500 	if ( SQ_FAILED( get_slice_params( v, sidx, eidx, o ) ) )return -1;
501 	if ( sidx < 0 )sidx = _string( o )->_len + sidx;
502 	if ( eidx < 0 )eidx = _string( o )->_len + eidx;
503 	if ( eidx < sidx )
504 		return sq_throwerror( v, _SC( "wrong indexes" ) );
505 	v->Push( SQString::Create( _ss( v ), &_stringval( o )[sidx], eidx - sidx ) );
506 	return 1;
507 }
508 
string_find(HSQUIRRELVM v)509 static SQInteger string_find( HSQUIRRELVM v ) {
510 	SQInteger top, start_idx = 0;
511 	const SQChar *str, *substr, *ret;
512 	if ( ( ( top = sq_gettop( v ) ) > 1 ) && SQ_SUCCEEDED( sq_getstring( v, 1, &str ) ) && SQ_SUCCEEDED( sq_getstring( v, 2, &substr ) ) ) {
513 		if ( top > 2 )sq_getinteger( v, 3, &start_idx );
514 		if ( ( sq_getsize( v, 1 ) > start_idx ) && ( start_idx >= 0 ) ) {
515 			ret = scstrstr( &str[start_idx], substr );
516 			if ( ret ) {
517 				sq_pushinteger( v, ( SQInteger )( ret - str ) );
518 				return 1;
519 			}
520 		}
521 		return 0;
522 	}
523 	return sq_throwerror( v, _SC( "invalid param" ) );
524 }
525 
526 #define STRING_TOFUNCZ(func) static SQInteger string_##func(HSQUIRRELVM v) \
527 	{ \
528 		SQObject str=stack_get(v,1); \
529 		SQInteger len=_string(str)->_len; \
530 		const SQChar *sThis=_stringval(str); \
531 		SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \
532 		for(SQInteger i=0;i<len;i++) sNew[i]=func(sThis[i]); \
533 		v->Push(SQString::Create(_ss(v),sNew,len)); \
534 		return 1; \
535 	}
536 
537 
538 STRING_TOFUNCZ( tolower )
539 STRING_TOFUNCZ( toupper )
540 
541 SQRegFunction SQSharedState::_string_default_delegate_funcz[] = {
542 	{_SC( "len" ), default_delegate_len, 1, _SC( "s" )},
543 	{_SC( "tointeger" ), default_delegate_tointeger, 1, _SC( "s" )},
544 	{_SC( "tofloat" ), default_delegate_tofloat, 1, _SC( "s" )},
545 	{_SC( "tostring" ), default_delegate_tostring, 1, _SC( "s" )},
546 	{_SC( "slice" ), string_slice, -1, _SC( " s n  n" )},
547 	{_SC( "find" ), string_find, -2, _SC( "s s n " )},
548 	{_SC( "tolower" ), string_tolower, 1, _SC( "s" )},
549 	{_SC( "toupper" ), string_toupper, 1, _SC( "s" )},
550 	{_SC( "weakref" ), obj_delegate_weakref, 1, NULL },
551 	{0, 0}
552 };
553 
554 //INTEGER DEFAULT DELEGATE//////////////////////////
555 SQRegFunction SQSharedState::_number_default_delegate_funcz[] = {
556 	{_SC( "tointeger" ), default_delegate_tointeger, 1, _SC( "n|b" )},
557 	{_SC( "tofloat" ), default_delegate_tofloat, 1, _SC( "n|b" )},
558 	{_SC( "tostring" ), default_delegate_tostring, 1, _SC( "n|b" )},
559 	{_SC( "tochar" ), number_delegate_tochar, 1, _SC( "n|b" )},
560 	{_SC( "weakref" ), obj_delegate_weakref, 1, NULL },
561 	{0, 0}
562 };
563 
564 //CLOSURE DEFAULT DELEGATE//////////////////////////
closure_call(HSQUIRRELVM v)565 static SQInteger closure_call( HSQUIRRELVM v ) {
566 	return SQ_SUCCEEDED( sq_call( v, sq_gettop( v ) - 1, SQTrue ) ) ? 1 : SQ_ERROR;
567 }
568 
closure_acall(HSQUIRRELVM v)569 static SQInteger closure_acall( HSQUIRRELVM v ) {
570 	SQArray *aparams = _array( stack_get( v, 2 ) );
571 	SQInteger nparams = aparams->Size();
572 	v->Push( stack_get( v, 1 ) );
573 	for ( SQInteger i = 0;i < nparams;i++ )v->Push( aparams->_values[i] );
574 	return SQ_SUCCEEDED( sq_call( v, nparams, SQTrue ) ) ? 1 : SQ_ERROR;
575 }
576 
577 SQRegFunction SQSharedState::_closure_default_delegate_funcz[] = {
578 	{_SC( "call" ), closure_call, -1, _SC( "c" )},
579 	{_SC( "acall" ), closure_acall, 2, _SC( "ca" )},
580 	{_SC( "weakref" ), obj_delegate_weakref, 1, NULL },
581 	{0, 0}
582 };
583 
584 //GENERATOR DEFAULT DELEGATE
generator_getstatus(HSQUIRRELVM v)585 static SQInteger generator_getstatus( HSQUIRRELVM v ) {
586 	SQObject &o = stack_get( v, 1 );
587 	switch ( _generator( o )->_state ) {
588 	case SQGenerator::eSuspended: v->Push( SQString::Create( _ss( v ), _SC( "suspended" ) ) );break;
589 	case SQGenerator::eRunning: v->Push( SQString::Create( _ss( v ), _SC( "running" ) ) );break;
590 	case SQGenerator::eDead: v->Push( SQString::Create( _ss( v ), _SC( "dead" ) ) );break;
591 	}
592 	return 1;
593 }
594 
595 SQRegFunction SQSharedState::_generator_default_delegate_funcz[] = {
596 	{_SC( "getstatus" ), generator_getstatus, 1, _SC( "g" )},
597 	{_SC( "weakref" ), obj_delegate_weakref, 1, NULL },
598 	{0, 0}
599 };
600 
601 //THREAD DEFAULT DELEGATE
602 
thread_call(HSQUIRRELVM v)603 static SQInteger thread_call( HSQUIRRELVM v ) {
604 	SQObjectPtr o = stack_get( v, 1 );
605 	if ( squirrel_type( o ) == OT_THREAD ) {
606 		SQInteger nparams = sq_gettop( v );
607 		_thread( o )->Push( _thread( o )->_roottable );
608 		for ( SQInteger i = 2; i < ( nparams + 1 ); i++ )
609 			sq_move( _thread( o ), v, i );
610 		if ( SQ_SUCCEEDED( sq_call( _thread( o ), nparams, SQTrue ) ) ) {
611 			sq_move( v, _thread( o ), -1 );
612 			return 1;
613 		}
614 		return SQ_ERROR;
615 	}
616 	return sq_throwerror( v, _SC( "wrong parameter" ) );
617 }
618 
thread_wakeup(HSQUIRRELVM v)619 static SQInteger thread_wakeup( HSQUIRRELVM v ) {
620 	SQObjectPtr o = stack_get( v, 1 );
621 	if ( squirrel_type( o ) == OT_THREAD ) {
622 		SQVM *thread = _thread( o );
623 		SQInteger state = sq_getvmstate( thread );
624 		if ( state != SQ_VMSTATE_SUSPENDED ) {
625 			switch ( state ) {
626 			case SQ_VMSTATE_IDLE:
627 				return sq_throwerror( v, _SC( "cannot wakeup a idle thread" ) );
628 				break;
629 			case SQ_VMSTATE_RUNNING:
630 				return sq_throwerror( v, _SC( "cannot wakeup a running thread" ) );
631 				break;
632 			}
633 		}
634 
635 		SQInteger wakeupret = sq_gettop( v ) > 1 ? 1 : 0;
636 		if ( wakeupret ) {
637 			sq_move( thread, v, 2 );
638 		}
639 		if ( SQ_SUCCEEDED( sq_wakeupvm( thread, wakeupret, 1 ) ) ) {
640 			sq_move( v, thread, -1 );
641 			sq_pop( thread, 1 );
642 			if ( sq_getvmstate( thread ) == SQ_VMSTATE_IDLE ) {
643 				sq_pop( thread, 1 );
644 			}
645 			return 1;
646 		}
647 		return SQ_ERROR;
648 	}
649 	return sq_throwerror( v, _SC( "wrong parameter" ) );
650 }
651 
thread_getstatus(HSQUIRRELVM v)652 static SQInteger thread_getstatus( HSQUIRRELVM v ) {
653 	SQObjectPtr &o = stack_get( v, 1 );
654 	switch ( sq_getvmstate( _thread( o ) ) ) {
655 	case SQ_VMSTATE_IDLE:
656 		sq_pushstring( v, _SC( "idle" ), -1 );
657 		break;
658 	case SQ_VMSTATE_RUNNING:
659 		sq_pushstring( v, _SC( "running" ), -1 );
660 		break;
661 	case SQ_VMSTATE_SUSPENDED:
662 		sq_pushstring( v, _SC( "suspended" ), -1 );
663 		break;
664 	default:
665 		return sq_throwerror( v, _SC( "internal VM error" ) );
666 	}
667 	return 1;
668 }
669 
670 SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {
671 	{_SC( "call" ), thread_call, -1, _SC( "v" )},
672 	{_SC( "wakeup" ), thread_wakeup, -1, _SC( "v" )},
673 	{_SC( "getstatus" ), thread_getstatus, 1, _SC( "v" )},
674 	{_SC( "weakref" ), obj_delegate_weakref, 1, NULL },
675 	{0, 0},
676 };
677 
class_getattributes(HSQUIRRELVM v)678 static SQInteger class_getattributes( HSQUIRRELVM v ) {
679 	if ( SQ_SUCCEEDED( sq_getattributes( v, -2 ) ) )
680 		return 1;
681 	return SQ_ERROR;
682 }
683 
class_setattributes(HSQUIRRELVM v)684 static SQInteger class_setattributes( HSQUIRRELVM v ) {
685 	if ( SQ_SUCCEEDED( sq_setattributes( v, -3 ) ) )
686 		return 1;
687 	return SQ_ERROR;
688 }
689 
690 SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {
691 	{_SC( "getattributes" ), class_getattributes, 2, _SC( "y." )},
692 	{_SC( "setattributes" ), class_setattributes, 3, _SC( "y.." )},
693 	{_SC( "rawin" ), container_rawexists, 2, _SC( "y" )},
694 	{_SC( "weakref" ), obj_delegate_weakref, 1, NULL },
695 	{0, 0}
696 };
697 
instance_getclass(HSQUIRRELVM v)698 static SQInteger instance_getclass( HSQUIRRELVM v ) {
699 	if ( SQ_SUCCEEDED( sq_getclass( v, 1 ) ) )
700 		return 1;
701 	return SQ_ERROR;
702 }
703 
704 SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {
705 	{_SC( "getclass" ), instance_getclass, 1, _SC( "x" )},
706 	{_SC( "rawin" ), container_rawexists, 2, _SC( "x" )},
707 	{_SC( "weakref" ), obj_delegate_weakref, 1, NULL },
708 	{0, 0}
709 };
710 
weakref_ref(HSQUIRRELVM v)711 static SQInteger weakref_ref( HSQUIRRELVM v ) {
712 	if ( SQ_FAILED( sq_getweakrefval( v, 1 ) ) )
713 		return SQ_ERROR;
714 	return 1;
715 }
716 
717 SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = {
718 	{_SC( "ref" ), weakref_ref, 1, _SC( "r" )},
719 	{_SC( "weakref" ), obj_delegate_weakref, 1, NULL },
720 	{0, 0}
721 };
722 
723 
724