#include <sys/types.h>
#include <dirent.h>
#include <unistd.h>
+#include <assert.h>
#ifndef WIN32
#include <libgen.h>
#endif
: noinstall
;
IncludeDir squirrel : include ;
-C++Flags squirrel : -Wno-error -Wno-switch -Wno-uninitialized
--Wno-unused -Wno-parentheses -Wno-non-virtual-dtor -Wno-sign-compare ;
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQSTD_AUXLIB_H_\r
-#define _SQSTD_AUXLIB_H_\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-SQUIRREL_API void sqstd_seterrorhandlers(HSQUIRRELVM v);\r
-SQUIRREL_API void sqstd_printcallstack(HSQUIRRELVM v);\r
-\r
-#ifdef __cplusplus\r
-} /*extern "C"*/\r
-#endif\r
-\r
-#endif /* _SQSTD_AUXLIB_H_ */\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQSTD_AUXLIB_H_
+#define _SQSTD_AUXLIB_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SQUIRREL_API void sqstd_seterrorhandlers(HSQUIRRELVM v);
+SQUIRREL_API void sqstd_printcallstack(HSQUIRRELVM v);
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /* _SQSTD_AUXLIB_H_ */
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQSTDBLOB_H_\r
-#define _SQSTDBLOB_H_\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-SQUIRREL_API SQUserPointer sqstd_createblob(HSQUIRRELVM v, int size);\r
-SQUIRREL_API SQRESULT sqstd_getblob(HSQUIRRELVM v,int idx,SQUserPointer *ptr);\r
-SQUIRREL_API int sqstd_getblobsize(HSQUIRRELVM v,int idx);\r
-\r
-SQUIRREL_API SQRESULT sqstd_register_bloblib(HSQUIRRELVM v);\r
-\r
-#ifdef __cplusplus\r
-} /*extern "C"*/\r
-#endif\r
-\r
-#endif /*_SQSTDBLOB_H_*/\r
-\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQSTDBLOB_H_
+#define _SQSTDBLOB_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SQUIRREL_API SQUserPointer sqstd_createblob(HSQUIRRELVM v, int size);
+SQUIRREL_API SQRESULT sqstd_getblob(HSQUIRRELVM v,int idx,SQUserPointer *ptr);
+SQUIRREL_API int sqstd_getblobsize(HSQUIRRELVM v,int idx);
+
+SQUIRREL_API SQRESULT sqstd_register_bloblib(HSQUIRRELVM v);
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*_SQSTDBLOB_H_*/
+
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQSTDIO_H_\r
-#define _SQSTDIO_H_\r
-\r
-#ifdef __cplusplus\r
-\r
-#define SQSTD_STREAM_TYPE_TAG 0x80000000\r
-\r
-struct SQStream {\r
- virtual SQInteger Read(void *buffer, SQInteger size) = 0;\r
- virtual SQInteger Write(void *buffer, SQInteger size) = 0;\r
- virtual int Flush() = 0;\r
- virtual long Tell() = 0;\r
- virtual SQInteger Len() = 0;\r
- virtual SQInteger Seek(long offset, int origin) = 0;\r
- virtual bool IsValid() = 0;\r
- virtual bool EOS() = 0;\r
-};\r
-\r
-extern "C" {\r
-#endif\r
-\r
-#define SQ_SEEK_CUR 0\r
-#define SQ_SEEK_END 1\r
-#define SQ_SEEK_SET 2\r
-\r
-typedef void* SQFILE;\r
-\r
-SQUIRREL_API SQFILE sqstd_fopen(const SQChar *,const SQChar *);\r
-SQUIRREL_API SQInteger sqstd_fread(SQUserPointer, SQInteger, SQInteger, SQFILE);\r
-SQUIRREL_API SQInteger sqstd_fwrite(const SQUserPointer, SQInteger, SQInteger, SQFILE);\r
-SQUIRREL_API SQInteger sqstd_fseek(SQFILE , long , int);\r
-SQUIRREL_API long sqstd_ftell(SQFILE);\r
-SQUIRREL_API SQInteger sqstd_fflush(SQFILE);\r
-SQUIRREL_API SQInteger sqstd_fclose(SQFILE);\r
-SQUIRREL_API SQInteger sqstd_feof(SQFILE);\r
-\r
-SQUIRREL_API SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own);\r
-SQUIRREL_API SQRESULT sqstd_getfile(HSQUIRRELVM v, int idx, SQFILE *file);\r
-\r
-//compiler helpers\r
-SQUIRREL_API SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror);\r
-SQUIRREL_API SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror);\r
-SQUIRREL_API SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename);\r
-\r
-SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v);\r
-\r
-#ifdef __cplusplus\r
-} /*extern "C"*/\r
-#endif\r
-\r
-#endif /*_SQSTDIO_H_*/\r
-\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQSTDIO_H_
+#define _SQSTDIO_H_
+
+#ifdef __cplusplus
+
+#define SQSTD_STREAM_TYPE_TAG 0x80000000
+
+struct SQStream {
+ virtual ~SQStream()
+ {}
+ virtual SQInteger Read(void *buffer, SQInteger size) = 0;
+ virtual SQInteger Write(void *buffer, SQInteger size) = 0;
+ virtual int Flush() = 0;
+ virtual long Tell() = 0;
+ virtual SQInteger Len() = 0;
+ virtual SQInteger Seek(long offset, int origin) = 0;
+ virtual bool IsValid() = 0;
+ virtual bool EOS() = 0;
+};
+
+extern "C" {
+#endif
+
+#define SQ_SEEK_CUR 0
+#define SQ_SEEK_END 1
+#define SQ_SEEK_SET 2
+
+typedef void* SQFILE;
+
+SQUIRREL_API SQFILE sqstd_fopen(const SQChar *,const SQChar *);
+SQUIRREL_API SQInteger sqstd_fread(SQUserPointer, SQInteger, SQInteger, SQFILE);
+SQUIRREL_API SQInteger sqstd_fwrite(const SQUserPointer, SQInteger, SQInteger, SQFILE);
+SQUIRREL_API SQInteger sqstd_fseek(SQFILE , long , int);
+SQUIRREL_API long sqstd_ftell(SQFILE);
+SQUIRREL_API SQInteger sqstd_fflush(SQFILE);
+SQUIRREL_API SQInteger sqstd_fclose(SQFILE);
+SQUIRREL_API SQInteger sqstd_feof(SQFILE);
+
+SQUIRREL_API SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own);
+SQUIRREL_API SQRESULT sqstd_getfile(HSQUIRRELVM v, int idx, SQFILE *file);
+
+//compiler helpers
+SQUIRREL_API SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror);
+SQUIRREL_API SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror);
+SQUIRREL_API SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename);
+
+SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v);
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*_SQSTDIO_H_*/
+
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQSTD_MATH_H_\r
-#define _SQSTD_MATH_H_\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-SQUIRREL_API SQRESULT sqstd_register_mathlib(HSQUIRRELVM v);\r
-\r
-#ifdef __cplusplus\r
-} /*extern "C"*/\r
-#endif\r
-\r
-#endif /*_SQSTD_MATH_H_*/\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQSTD_MATH_H_
+#define _SQSTD_MATH_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SQUIRREL_API SQRESULT sqstd_register_mathlib(HSQUIRRELVM v);
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*_SQSTD_MATH_H_*/
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQSTD_STRING_H_\r
-#define _SQSTD_STRING_H_\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-//#define SQRex_True 1\r
-//#define SQRex_False 0\r
-\r
-typedef unsigned int SQRexBool;\r
-typedef struct SQRex SQRex;\r
-\r
-typedef struct {\r
- const SQChar *begin;\r
- int len;\r
-} SQRexMatch;\r
-\r
-SQUIRREL_API SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error);\r
-SQUIRREL_API void sqstd_rex_free(SQRex *exp);\r
-SQUIRREL_API SQBool sqstd_rex_match(SQRex* exp,const SQChar* text);\r
-SQUIRREL_API SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end);\r
-SQUIRREL_API SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end);\r
-SQUIRREL_API int sqstd_rex_getsubexpcount(SQRex* exp);\r
-SQUIRREL_API SQBool sqstd_rex_getsubexp(SQRex* exp, int n, SQRexMatch *subexp);\r
-\r
-SQUIRREL_API SQRESULT sqstd_register_stringlib(HSQUIRRELVM v);\r
-\r
-#ifdef __cplusplus\r
-} /*extern "C"*/\r
-#endif\r
-\r
-#endif /*_SQSTD_STRING_H_*/\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQSTD_STRING_H_
+#define _SQSTD_STRING_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+//#define SQRex_True 1
+//#define SQRex_False 0
+
+typedef unsigned int SQRexBool;
+typedef struct SQRex SQRex;
+
+typedef struct {
+ const SQChar *begin;
+ int len;
+} SQRexMatch;
+
+SQUIRREL_API SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error);
+SQUIRREL_API void sqstd_rex_free(SQRex *exp);
+SQUIRREL_API SQBool sqstd_rex_match(SQRex* exp,const SQChar* text);
+SQUIRREL_API SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end);
+SQUIRREL_API SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end);
+SQUIRREL_API int sqstd_rex_getsubexpcount(SQRex* exp);
+SQUIRREL_API SQBool sqstd_rex_getsubexp(SQRex* exp, int n, SQRexMatch *subexp);
+
+SQUIRREL_API SQRESULT sqstd_register_stringlib(HSQUIRRELVM v);
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*_SQSTD_STRING_H_*/
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQSTD_SYSTEMLIB_H_\r
-#define _SQSTD_SYSTEMLIB_H_\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-SQUIRREL_API int sqstd_register_systemlib(HSQUIRRELVM v);\r
-\r
-#ifdef __cplusplus\r
-} /*extern "C"*/\r
-#endif\r
-\r
-#endif /* _SQSTD_SYSTEMLIB_H_ */\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQSTD_SYSTEMLIB_H_
+#define _SQSTD_SYSTEMLIB_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SQUIRREL_API int sqstd_register_systemlib(HSQUIRRELVM v);
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /* _SQSTD_SYSTEMLIB_H_ */
-/*\r
-Copyright (c) 2003-2005 Alberto Demichelis\r
-\r
-This software is provided 'as-is', without any \r
-express or implied warranty. In no event will the \r
-authors be held liable for any damages arising from \r
-the use of this software.\r
-\r
-Permission is granted to anyone to use this software \r
-for any purpose, including commercial applications, \r
-and to alter it and redistribute it freely, subject \r
-to the following restrictions:\r
-\r
- 1. The origin of this software must not be \r
- misrepresented; you must not claim that \r
- you wrote the original software. If you \r
- use this software in a product, an \r
- acknowledgment in the product \r
- documentation would be appreciated but is \r
- not required.\r
-\r
- 2. Altered source versions must be plainly \r
- marked as such, and must not be \r
- misrepresented as being the original \r
- software.\r
-\r
- 3. This notice may not be removed or \r
- altered from any source distribution.\r
-\r
-*/\r
-#ifndef _SQUIRREL_H_\r
-#define _SQUIRREL_H_\r
-\r
-#ifdef __cplusplus\r
-extern "C" {\r
-#endif\r
-\r
-#ifndef SQUIRREL_API\r
-#define SQUIRREL_API extern\r
-#endif\r
-\r
-typedef float SQFloat;\r
-typedef int SQInteger;\r
-typedef void* SQUserPointer;\r
-typedef unsigned int SQBool;\r
-typedef int SQRESULT;\r
-\r
-#define SQTrue 1\r
-#define SQFalse 0\r
-\r
-\r
-struct SQVM;\r
-struct SQTable;\r
-struct SQArray;\r
-struct SQString;\r
-struct SQClosure;\r
-struct SQGenerator;\r
-struct SQNativeClosure;\r
-struct SQUserData;\r
-struct SQFunctionProto;\r
-struct SQRefCounted;\r
-struct SQClass;\r
-struct SQInstance;\r
-struct SQDelegable;\r
-\r
-#ifdef _UNICODE\r
-#define SQUNICODE\r
-#endif\r
-\r
-#ifdef SQUNICODE\r
-typedef unsigned short SQChar;\r
-#define _SC(a) L##a\r
-#define scstrcmp wcscmp\r
-#define scsprintf swprintf\r
-#define scstrlen wcslen\r
-#define scstrtod wcstod\r
-#define scatoi _wtoi\r
-#define scstrtoul wcstoul\r
-#define scvsprintf vswprintf\r
-#define scstrstr wcsstr\r
-#define scisspace iswspace\r
-#define scisdigit iswdigit\r
-#define scisalpha iswalpha\r
-#define sciscntrl iswcntrl\r
-#define scisalnum iswalnum\r
-#define scprintf wprintf\r
-#define MAX_CHAR 0xFFFF\r
-#else\r
-typedef char SQChar;\r
-#define _SC(a) a\r
-#define scstrcmp strcmp\r
-#define scsprintf sprintf\r
-#define scstrlen strlen\r
-#define scstrtod strtod\r
-#define scatoi atoi\r
-#define scstrtoul strtoul\r
-#define scvsprintf vsprintf\r
-#define scstrstr strstr\r
-#define scisspace isspace\r
-#define scisdigit isdigit\r
-#define sciscntrl iscntrl\r
-#define scisalpha isalpha\r
-#define scisalnum isalnum\r
-#define scprintf printf\r
-#define MAX_CHAR 0xFF\r
-#endif\r
-\r
-#define SQUIRREL_VERSION _SC("Squirrel 2.0.1 stable")\r
-#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2005 Alberto Demichelis")\r
-#define SQUIRREL_AUTHOR _SC("Alberto Demichelis")\r
-\r
-#define SQ_VMSTATE_IDLE 0\r
-#define SQ_VMSTATE_RUNNING 1\r
-#define SQ_VMSTATE_SUSPENDED 2\r
-\r
-#define SQUIRREL_EOB 0\r
-#define SQ_BYTECODE_STREAM_TAG 0xFAFA\r
-\r
-#define SQOBJECT_REF_COUNTED 0x00800000\r
-#define SQOBJECT_NUMERIC 0x00080000\r
-#define SQOBJECT_DELEGABLE 0x08000000\r
-#define SQOBJECT_CANBEFALSE 0x80000000\r
-//typedef unsigned int SQObjectType;\r
-\r
-#define _RT_MASK 0x0000FFFF\r
-#define _RAW_TYPE(type) (type&_RT_MASK)\r
-\r
-#define _RT_NULL 0x00000000\r
-#define _RT_INTEGER 0x00000001\r
-#define _RT_FLOAT 0x00000002\r
-#define _RT_BOOL 0x00000004\r
-#define _RT_STRING 0x00000008\r
-#define _RT_TABLE 0x00000010\r
-#define _RT_ARRAY 0x00000020\r
-#define _RT_USERDATA 0x00000040\r
-#define _RT_CLOSURE 0x00000080\r
-#define _RT_NATIVECLOSURE 0x00000100\r
-#define _RT_GENERATOR 0x00000200\r
-#define _RT_USERPOINTER 0x00000400\r
-#define _RT_THREAD 0x00000800\r
-#define _RT_FUNCPROTO 0x00001000\r
-#define _RT_CLASS 0x00002000\r
-#define _RT_INSTANCE 0x00004000\r
-\r
-typedef enum {\r
- OT_NULL = (_RT_NULL|SQOBJECT_CANBEFALSE),\r
- OT_INTEGER = (_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE),\r
- OT_FLOAT = (_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE),\r
- OT_BOOL = (_RT_BOOL|SQOBJECT_CANBEFALSE),\r
- OT_STRING = (_RT_STRING|SQOBJECT_REF_COUNTED),\r
- OT_TABLE = (_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),\r
- OT_ARRAY = (_RT_ARRAY|SQOBJECT_REF_COUNTED),\r
- OT_USERDATA = (_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),\r
- OT_CLOSURE = (_RT_CLOSURE|SQOBJECT_REF_COUNTED),\r
- OT_NATIVECLOSURE = (_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED),\r
- OT_GENERATOR = (_RT_GENERATOR|SQOBJECT_REF_COUNTED),\r
- OT_USERPOINTER = _RT_USERPOINTER,\r
- OT_THREAD = (_RT_THREAD|SQOBJECT_REF_COUNTED) ,\r
- OT_FUNCPROTO = (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only\r
- OT_CLASS = (_RT_CLASS|SQOBJECT_REF_COUNTED),\r
- OT_INSTANCE = (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE)\r
-}SQObjectType;\r
-\r
-#define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED)\r
-\r
-\r
-typedef union tagSQObjectValue\r
-{\r
- struct SQTable *pTable;\r
- struct SQArray *pArray;\r
- struct SQClosure *pClosure;\r
- struct SQGenerator *pGenerator;\r
- struct SQNativeClosure *pNativeClosure;\r
- struct SQString *pString;\r
- struct SQUserData *pUserData;\r
- SQInteger nInteger;\r
- SQFloat fFloat;\r
- SQUserPointer pUserPointer;\r
- struct SQFunctionProto *pFunctionProto;\r
- struct SQRefCounted *pRefCounted;\r
- struct SQDelegable *pDelegable;\r
- struct SQVM *pThread;\r
- struct SQClass *pClass;\r
- struct SQInstance *pInstance;\r
-}SQObjectValue;\r
-\r
-\r
-typedef struct tagSQObject\r
-{\r
- SQObjectValue _unVal;\r
- SQObjectType _type;\r
-}SQObject;\r
-\r
-typedef struct tagSQStackInfos{\r
- const SQChar* funcname;\r
- const SQChar* source;\r
- int line;\r
-}SQStackInfos;\r
-\r
-typedef struct SQVM* HSQUIRRELVM;\r
-typedef SQObject HSQOBJECT;\r
-typedef int (*SQFUNCTION)(HSQUIRRELVM);\r
-typedef int (*SQRELEASEHOOK)(SQUserPointer,int size);\r
-typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,int /*line*/,int /*column*/);\r
-typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...);\r
-\r
-typedef int (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,int);\r
-typedef int (*SQREADFUNC)(SQUserPointer,SQUserPointer,int);\r
-\r
-typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer);\r
-\r
-typedef struct tagSQRegFunction{\r
- const SQChar *name;\r
- SQFUNCTION f;\r
- int nparamscheck;\r
- const SQChar *typemask;\r
-}SQRegFunction;\r
-\r
-/*vm*/\r
-SQUIRREL_API HSQUIRRELVM sq_open(int initialstacksize);\r
-SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, int initialstacksize);\r
-SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v);\r
-SQUIRREL_API void sq_close(HSQUIRRELVM v);\r
-SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p);\r
-SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v);\r
-SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc);\r
-SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v);\r
-SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v);\r
-SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval);\r
-SQUIRREL_API int sq_getvmstate(HSQUIRRELVM v);\r
-\r
-/*compiler*/\r
-SQUIRREL_API SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror);\r
-SQUIRREL_API SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,int size,const SQChar *sourcename,SQBool raiseerror);\r
-SQUIRREL_API void sq_enabledebuginfo(HSQUIRRELVM v, SQBool debuginfo);\r
-SQUIRREL_API void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f);\r
-\r
-/*stack operations*/\r
-SQUIRREL_API void sq_push(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API void sq_pop(HSQUIRRELVM v,int nelemstopop);\r
-SQUIRREL_API void sq_remove(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API int sq_gettop(HSQUIRRELVM v);\r
-SQUIRREL_API void sq_settop(HSQUIRRELVM v,int newtop);\r
-SQUIRREL_API void sq_reservestack(HSQUIRRELVM v,int nsize);\r
-SQUIRREL_API int sq_cmp(HSQUIRRELVM v);\r
-SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,int idx);\r
-\r
-/*object creation handling*/\r
-SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,unsigned int size);\r
-SQUIRREL_API void sq_newtable(HSQUIRRELVM v);\r
-SQUIRREL_API void sq_newarray(HSQUIRRELVM v,int size);\r
-SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,unsigned int nfreevars);\r
-SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,int nparamscheck,const SQChar *typemask);\r
-SQUIRREL_API void sq_pushstring(HSQUIRRELVM v,const SQChar *s,int len);\r
-SQUIRREL_API void sq_pushfloat(HSQUIRRELVM v,SQFloat f);\r
-SQUIRREL_API void sq_pushinteger(HSQUIRRELVM v,SQInteger n);\r
-SQUIRREL_API void sq_pushbool(HSQUIRRELVM v,SQBool b);\r
-SQUIRREL_API void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p);\r
-SQUIRREL_API void sq_pushnull(HSQUIRRELVM v);\r
-SQUIRREL_API SQObjectType sq_gettype(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,int idx,const SQChar **c);\r
-SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,int idx,SQInteger *i);\r
-SQUIRREL_API SQRESULT sq_getfloat(HSQUIRRELVM v,int idx,SQFloat *f);\r
-SQUIRREL_API SQRESULT sq_getbool(HSQUIRRELVM v,int idx,SQBool *b);\r
-SQUIRREL_API SQRESULT sq_getthread(HSQUIRRELVM v,int idx,HSQUIRRELVM *thread);\r
-SQUIRREL_API SQRESULT sq_getuserpointer(HSQUIRRELVM v,int idx,SQUserPointer *p);\r
-SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,int idx,SQUserPointer *p,unsigned int *typetag);\r
-SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,int idx,unsigned int typetag);\r
-SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,int idx,unsigned int *typetag);\r
-SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,int idx,SQRELEASEHOOK hook);\r
-SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,int minsize);\r
-SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,int idx,unsigned int *nparams,unsigned int *nfreevars);\r
-SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,int idx,const SQChar *name);\r
-SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, int idx, SQUserPointer p);\r
-SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, int idx, SQUserPointer *p,unsigned int typetag);\r
-SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase);\r
-SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_setattributes(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,int idx);\r
-\r
-/*object manipulation*/\r
-SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v);\r
-SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v);\r
-SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v);\r
-SQUIRREL_API SQRESULT sq_createslot(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,int idx,SQBool pushval);\r
-SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,int idx,SQBool pushval);\r
-SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,int idx,SQBool pushval); \r
-SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,int idx,int newsize); \r
-SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,int idx); \r
-SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,int idx);\r
-SQUIRREL_API SQRESULT sq_setfreevariable(HSQUIRRELVM v,int idx,unsigned int nval);\r
-SQUIRREL_API SQRESULT sq_next(HSQUIRRELVM v,int idx);\r
-\r
-/*calls*/\r
-SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,int params,SQBool retval);\r
-SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval);\r
-SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,unsigned int level,unsigned int idx);\r
-SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err);\r
-SQUIRREL_API void sq_reseterror(HSQUIRRELVM v);\r
-SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v);\r
-\r
-/*raw object handling*/\r
-SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,int idx,HSQOBJECT *po);\r
-SQUIRREL_API void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj);\r
-SQUIRREL_API void sq_addref(HSQUIRRELVM v,HSQOBJECT *po);\r
-SQUIRREL_API SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po);\r
-SQUIRREL_API void sq_resetobject(HSQOBJECT *po);\r
-SQUIRREL_API const SQChar *sq_objtostring(HSQOBJECT *o);\r
-SQUIRREL_API SQInteger sq_objtointeger(HSQOBJECT *o);\r
-SQUIRREL_API SQFloat sq_objtofloat(HSQOBJECT *o);\r
-\r
-/*GC*/\r
-SQUIRREL_API int sq_collectgarbage(HSQUIRRELVM v);\r
-\r
-/*serialization*/\r
-SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up);\r
-SQUIRREL_API SQRESULT sq_readclosure(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up);\r
-\r
-/*mem allocation*/\r
-SQUIRREL_API void *sq_malloc(unsigned int size);\r
-SQUIRREL_API void *sq_realloc(void* p,unsigned int oldsize,unsigned int newsize);\r
-SQUIRREL_API void sq_free(void *p,unsigned int size);\r
-\r
-/*debug*/\r
-SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,int level,SQStackInfos *si);\r
-SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v);\r
-\r
-/*UTILITY MACRO*/\r
-#define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC)\r
-#define sq_istable(o) ((o)._type==OT_TABLE)\r
-#define sq_isarray(o) ((o)._type==OT_ARRAY)\r
-#define sq_isfunction(o) ((o)._type==OT_FUNCPROTO)\r
-#define sq_isclosure(o) ((o)._type==OT_CLOSURE)\r
-#define sq_isgenerator(o) ((o)._type==OT_GENERATOR)\r
-#define sq_isnativeclosure(o) ((o)._type==OT_NATIVECLOSURE)\r
-#define sq_isstring(o) ((o)._type==OT_STRING)\r
-#define sq_isinteger(o) ((o)._type==OT_INTEGER)\r
-#define sq_isfloat(o) ((o)._type==OT_FLOAT)\r
-#define sq_isuserpointer(o) ((o)._type==OT_USERPOINTER)\r
-#define sq_isuserdata(o) ((o)._type==OT_USERDATA)\r
-#define sq_isthread(o) ((o)._type==OT_THREAD)\r
-#define sq_isnull(o) ((o)._type==OT_NULL)\r
-#define sq_isclass(o) ((o)._type==OT_CLASS)\r
-#define sq_isinstance(o) ((o)._type==OT_INSTANCE)\r
-#define sq_isbool(o) ((o)._type==OT_BOOL)\r
-#define sq_type(o) ((o)._type)\r
-\r
-#define SQ_OK (0)\r
-#define SQ_ERROR (-1)\r
-\r
-#define SQ_FAILED(res) (res<0)\r
-#define SQ_SUCCEEDED(res) (res>=0)\r
-\r
-#ifdef __cplusplus\r
-} /*extern "C"*/\r
-#endif\r
-\r
-#endif /*_SQUIRREL_H_*/\r
+/*
+Copyright (c) 2003-2005 Alberto Demichelis
+
+This software is provided 'as-is', without any
+express or implied warranty. In no event will the
+authors be held liable for any damages arising from
+the use of this software.
+
+Permission is granted to anyone to use this software
+for any purpose, including commercial applications,
+and to alter it and redistribute it freely, subject
+to the following restrictions:
+
+ 1. The origin of this software must not be
+ misrepresented; you must not claim that
+ you wrote the original software. If you
+ use this software in a product, an
+ acknowledgment in the product
+ documentation would be appreciated but is
+ not required.
+
+ 2. Altered source versions must be plainly
+ marked as such, and must not be
+ misrepresented as being the original
+ software.
+
+ 3. This notice may not be removed or
+ altered from any source distribution.
+
+*/
+#ifndef _SQUIRREL_H_
+#define _SQUIRREL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SQUIRREL_API
+#define SQUIRREL_API extern
+#endif
+
+typedef float SQFloat;
+typedef int SQInteger;
+typedef void* SQUserPointer;
+typedef unsigned int SQBool;
+typedef int SQRESULT;
+
+#define SQTrue 1
+#define SQFalse 0
+
+
+struct SQVM;
+struct SQTable;
+struct SQArray;
+struct SQString;
+struct SQClosure;
+struct SQGenerator;
+struct SQNativeClosure;
+struct SQUserData;
+struct SQFunctionProto;
+struct SQRefCounted;
+struct SQClass;
+struct SQInstance;
+struct SQDelegable;
+
+#ifdef _UNICODE
+#define SQUNICODE
+#endif
+
+#ifdef SQUNICODE
+typedef unsigned short SQChar;
+#define _SC(a) L##a
+#define scstrcmp wcscmp
+#define scsprintf swprintf
+#define scstrlen wcslen
+#define scstrtod wcstod
+#define scatoi _wtoi
+#define scstrtoul wcstoul
+#define scvsprintf vswprintf
+#define scstrstr wcsstr
+#define scisspace iswspace
+#define scisdigit iswdigit
+#define scisalpha iswalpha
+#define sciscntrl iswcntrl
+#define scisalnum iswalnum
+#define scprintf wprintf
+#define MAX_CHAR 0xFFFF
+#else
+typedef char SQChar;
+#define _SC(a) a
+#define scstrcmp strcmp
+#define scsprintf sprintf
+#define scstrlen strlen
+#define scstrtod strtod
+#define scatoi atoi
+#define scstrtoul strtoul
+#define scvsprintf vsprintf
+#define scstrstr strstr
+#define scisspace isspace
+#define scisdigit isdigit
+#define sciscntrl iscntrl
+#define scisalpha isalpha
+#define scisalnum isalnum
+#define scprintf printf
+#define MAX_CHAR 0xFF
+#endif
+
+#define SQUIRREL_VERSION _SC("Squirrel 2.0.1 stable")
+#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2005 Alberto Demichelis")
+#define SQUIRREL_AUTHOR _SC("Alberto Demichelis")
+
+#define SQ_VMSTATE_IDLE 0
+#define SQ_VMSTATE_RUNNING 1
+#define SQ_VMSTATE_SUSPENDED 2
+
+#define SQUIRREL_EOB 0
+#define SQ_BYTECODE_STREAM_TAG 0xFAFA
+
+#define SQOBJECT_REF_COUNTED 0x00800000
+#define SQOBJECT_NUMERIC 0x00080000
+#define SQOBJECT_DELEGABLE 0x08000000
+#define SQOBJECT_CANBEFALSE 0x80000000
+//typedef unsigned int SQObjectType;
+
+#define _RT_MASK 0x0000FFFF
+#define _RAW_TYPE(type) (type&_RT_MASK)
+
+#define _RT_NULL 0x00000000
+#define _RT_INTEGER 0x00000001
+#define _RT_FLOAT 0x00000002
+#define _RT_BOOL 0x00000004
+#define _RT_STRING 0x00000008
+#define _RT_TABLE 0x00000010
+#define _RT_ARRAY 0x00000020
+#define _RT_USERDATA 0x00000040
+#define _RT_CLOSURE 0x00000080
+#define _RT_NATIVECLOSURE 0x00000100
+#define _RT_GENERATOR 0x00000200
+#define _RT_USERPOINTER 0x00000400
+#define _RT_THREAD 0x00000800
+#define _RT_FUNCPROTO 0x00001000
+#define _RT_CLASS 0x00002000
+#define _RT_INSTANCE 0x00004000
+
+typedef enum {
+ OT_NULL = (_RT_NULL|SQOBJECT_CANBEFALSE),
+ OT_INTEGER = (_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE),
+ OT_FLOAT = (_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE),
+ OT_BOOL = (_RT_BOOL|SQOBJECT_CANBEFALSE),
+ OT_STRING = (_RT_STRING|SQOBJECT_REF_COUNTED),
+ OT_TABLE = (_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),
+ OT_ARRAY = (_RT_ARRAY|SQOBJECT_REF_COUNTED),
+ OT_USERDATA = (_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),
+ OT_CLOSURE = (_RT_CLOSURE|SQOBJECT_REF_COUNTED),
+ OT_NATIVECLOSURE = (_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED),
+ OT_GENERATOR = (_RT_GENERATOR|SQOBJECT_REF_COUNTED),
+ OT_USERPOINTER = _RT_USERPOINTER,
+ OT_THREAD = (_RT_THREAD|SQOBJECT_REF_COUNTED) ,
+ OT_FUNCPROTO = (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only
+ OT_CLASS = (_RT_CLASS|SQOBJECT_REF_COUNTED),
+ OT_INSTANCE = (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE)
+}SQObjectType;
+
+#define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED)
+
+
+typedef union tagSQObjectValue
+{
+ struct SQTable *pTable;
+ struct SQArray *pArray;
+ struct SQClosure *pClosure;
+ struct SQGenerator *pGenerator;
+ struct SQNativeClosure *pNativeClosure;
+ struct SQString *pString;
+ struct SQUserData *pUserData;
+ SQInteger nInteger;
+ SQFloat fFloat;
+ SQUserPointer pUserPointer;
+ struct SQFunctionProto *pFunctionProto;
+ struct SQRefCounted *pRefCounted;
+ struct SQDelegable *pDelegable;
+ struct SQVM *pThread;
+ struct SQClass *pClass;
+ struct SQInstance *pInstance;
+}SQObjectValue;
+
+
+typedef struct tagSQObject
+{
+ SQObjectValue _unVal;
+ SQObjectType _type;
+}SQObject;
+
+typedef struct tagSQStackInfos{
+ const SQChar* funcname;
+ const SQChar* source;
+ int line;
+}SQStackInfos;
+
+typedef struct SQVM* HSQUIRRELVM;
+typedef SQObject HSQOBJECT;
+typedef int (*SQFUNCTION)(HSQUIRRELVM);
+typedef int (*SQRELEASEHOOK)(SQUserPointer,int size);
+typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,int /*line*/,int /*column*/);
+typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...);
+
+typedef int (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,int);
+typedef int (*SQREADFUNC)(SQUserPointer,SQUserPointer,int);
+
+typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer);
+
+typedef struct tagSQRegFunction{
+ const SQChar *name;
+ SQFUNCTION f;
+ int nparamscheck;
+ const SQChar *typemask;
+}SQRegFunction;
+
+/*vm*/
+SQUIRREL_API HSQUIRRELVM sq_open(int initialstacksize);
+SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, int initialstacksize);
+SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v);
+SQUIRREL_API void sq_close(HSQUIRRELVM v);
+SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p);
+SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v);
+SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc);
+SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval);
+SQUIRREL_API int sq_getvmstate(HSQUIRRELVM v);
+
+/*compiler*/
+SQUIRREL_API SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror);
+SQUIRREL_API SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,int size,const SQChar *sourcename,SQBool raiseerror);
+SQUIRREL_API void sq_enabledebuginfo(HSQUIRRELVM v, SQBool debuginfo);
+SQUIRREL_API void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f);
+
+/*stack operations*/
+SQUIRREL_API void sq_push(HSQUIRRELVM v,int idx);
+SQUIRREL_API void sq_pop(HSQUIRRELVM v,int nelemstopop);
+SQUIRREL_API void sq_remove(HSQUIRRELVM v,int idx);
+SQUIRREL_API int sq_gettop(HSQUIRRELVM v);
+SQUIRREL_API void sq_settop(HSQUIRRELVM v,int newtop);
+SQUIRREL_API void sq_reservestack(HSQUIRRELVM v,int nsize);
+SQUIRREL_API int sq_cmp(HSQUIRRELVM v);
+SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,int idx);
+
+/*object creation handling*/
+SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,unsigned int size);
+SQUIRREL_API void sq_newtable(HSQUIRRELVM v);
+SQUIRREL_API void sq_newarray(HSQUIRRELVM v,int size);
+SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,unsigned int nfreevars);
+SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,int nparamscheck,const SQChar *typemask);
+SQUIRREL_API void sq_pushstring(HSQUIRRELVM v,const SQChar *s,int len);
+SQUIRREL_API void sq_pushfloat(HSQUIRRELVM v,SQFloat f);
+SQUIRREL_API void sq_pushinteger(HSQUIRRELVM v,SQInteger n);
+SQUIRREL_API void sq_pushbool(HSQUIRRELVM v,SQBool b);
+SQUIRREL_API void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p);
+SQUIRREL_API void sq_pushnull(HSQUIRRELVM v);
+SQUIRREL_API SQObjectType sq_gettype(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,int idx,const SQChar **c);
+SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,int idx,SQInteger *i);
+SQUIRREL_API SQRESULT sq_getfloat(HSQUIRRELVM v,int idx,SQFloat *f);
+SQUIRREL_API SQRESULT sq_getbool(HSQUIRRELVM v,int idx,SQBool *b);
+SQUIRREL_API SQRESULT sq_getthread(HSQUIRRELVM v,int idx,HSQUIRRELVM *thread);
+SQUIRREL_API SQRESULT sq_getuserpointer(HSQUIRRELVM v,int idx,SQUserPointer *p);
+SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,int idx,SQUserPointer *p,unsigned int *typetag);
+SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,int idx,unsigned int typetag);
+SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,int idx,unsigned int *typetag);
+SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,int idx,SQRELEASEHOOK hook);
+SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,int minsize);
+SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,int idx,unsigned int *nparams,unsigned int *nfreevars);
+SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,int idx,const SQChar *name);
+SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, int idx, SQUserPointer p);
+SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, int idx, SQUserPointer *p,unsigned int typetag);
+SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase);
+SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_setattributes(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,int idx);
+
+/*object manipulation*/
+SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v);
+SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_createslot(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,int idx,SQBool pushval);
+SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,int idx,SQBool pushval);
+SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,int idx,SQBool pushval);
+SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,int idx,int newsize);
+SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,int idx);
+SQUIRREL_API SQRESULT sq_setfreevariable(HSQUIRRELVM v,int idx,unsigned int nval);
+SQUIRREL_API SQRESULT sq_next(HSQUIRRELVM v,int idx);
+
+/*calls*/
+SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,int params,SQBool retval);
+SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval);
+SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,unsigned int level,unsigned int idx);
+SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err);
+SQUIRREL_API void sq_reseterror(HSQUIRRELVM v);
+SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v);
+
+/*raw object handling*/
+SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,int idx,HSQOBJECT *po);
+SQUIRREL_API void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj);
+SQUIRREL_API void sq_addref(HSQUIRRELVM v,HSQOBJECT *po);
+SQUIRREL_API SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po);
+SQUIRREL_API void sq_resetobject(HSQOBJECT *po);
+SQUIRREL_API const SQChar *sq_objtostring(HSQOBJECT *o);
+SQUIRREL_API SQInteger sq_objtointeger(HSQOBJECT *o);
+SQUIRREL_API SQFloat sq_objtofloat(HSQOBJECT *o);
+
+/*GC*/
+SQUIRREL_API int sq_collectgarbage(HSQUIRRELVM v);
+
+/*serialization*/
+SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up);
+SQUIRREL_API SQRESULT sq_readclosure(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up);
+
+/*mem allocation*/
+SQUIRREL_API void *sq_malloc(unsigned int size);
+SQUIRREL_API void *sq_realloc(void* p,unsigned int oldsize,unsigned int newsize);
+SQUIRREL_API void sq_free(void *p,unsigned int size);
+
+/*debug*/
+SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,int level,SQStackInfos *si);
+SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v);
+
+/*UTILITY MACRO*/
+#define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC)
+#define sq_istable(o) ((o)._type==OT_TABLE)
+#define sq_isarray(o) ((o)._type==OT_ARRAY)
+#define sq_isfunction(o) ((o)._type==OT_FUNCPROTO)
+#define sq_isclosure(o) ((o)._type==OT_CLOSURE)
+#define sq_isgenerator(o) ((o)._type==OT_GENERATOR)
+#define sq_isnativeclosure(o) ((o)._type==OT_NATIVECLOSURE)
+#define sq_isstring(o) ((o)._type==OT_STRING)
+#define sq_isinteger(o) ((o)._type==OT_INTEGER)
+#define sq_isfloat(o) ((o)._type==OT_FLOAT)
+#define sq_isuserpointer(o) ((o)._type==OT_USERPOINTER)
+#define sq_isuserdata(o) ((o)._type==OT_USERDATA)
+#define sq_isthread(o) ((o)._type==OT_THREAD)
+#define sq_isnull(o) ((o)._type==OT_NULL)
+#define sq_isclass(o) ((o)._type==OT_CLASS)
+#define sq_isinstance(o) ((o)._type==OT_INSTANCE)
+#define sq_isbool(o) ((o)._type==OT_BOOL)
+#define sq_type(o) ((o)._type)
+
+#define SQ_OK (0)
+#define SQ_ERROR (-1)
+
+#define SQ_FAILED(res) (res<0)
+#define SQ_SUCCEEDED(res) (res>=0)
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*_SQUIRREL_H_*/
-/* see copyright notice in squirrel.h */\r
-#include <squirrel.h>\r
-#include <sqstdaux.h>\r
-\r
-void sqstd_printcallstack(HSQUIRRELVM v)\r
-{\r
- SQPRINTFUNCTION pf = sq_getprintfunc(v);\r
- if(pf) {\r
- SQStackInfos si;\r
- SQInteger i;\r
- SQFloat f;\r
- const SQChar *s;\r
- int level=1; //1 is to skip this function that is level 0\r
- const SQChar *name=0; \r
- int seq=0;\r
- pf(v,_SC("\nCALLSTACK\n"));\r
- while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si)))\r
- {\r
- const SQChar *fn=_SC("unknown");\r
- const SQChar *src=_SC("unknown");\r
- if(si.funcname)fn=si.funcname;\r
- if(si.source)src=si.source;\r
- pf(v,_SC("*FUNCTION [%s()] %s line [%d]\n"),fn,src,si.line);\r
- level++;\r
- }\r
- level=0;\r
- pf(v,_SC("\nLOCALS\n"));\r
-\r
- for(level=0;level<10;level++){\r
- seq=0;\r
- while(name=sq_getlocal(v,level,seq))\r
- {\r
- seq++;\r
- switch(sq_gettype(v,-1))\r
- {\r
- case OT_NULL:\r
- pf(v,_SC("[%s] NULL\n"),name);\r
- break;\r
- case OT_INTEGER:\r
- sq_getinteger(v,-1,&i);\r
- pf(v,_SC("[%s] %d\n"),name,i);\r
- break;\r
- case OT_FLOAT:\r
- sq_getfloat(v,-1,&f);\r
- pf(v,_SC("[%s] %.14g\n"),name,f);\r
- break;\r
- case OT_USERPOINTER:\r
- pf(v,_SC("[%s] USERPOINTER\n"),name);\r
- break;\r
- case OT_STRING:\r
- sq_getstring(v,-1,&s);\r
- pf(v,_SC("[%s] \"%s\"\n"),name,s);\r
- break;\r
- case OT_TABLE:\r
- pf(v,_SC("[%s] TABLE\n"),name);\r
- break;\r
- case OT_ARRAY:\r
- pf(v,_SC("[%s] ARRAY\n"),name);\r
- break;\r
- case OT_CLOSURE:\r
- pf(v,_SC("[%s] CLOSURE\n"),name);\r
- break;\r
- case OT_NATIVECLOSURE:\r
- pf(v,_SC("[%s] NATIVECLOSURE\n"),name);\r
- break;\r
- case OT_USERDATA:\r
- pf(v,_SC("[%s] USERDATA\n"),name);\r
- break;\r
- case OT_THREAD:\r
- pf(v,_SC("[%s] THREAD\n"),name);\r
- break;\r
- case OT_CLASS:\r
- pf(v,_SC("[%s] CLASS\n"),name);\r
- break;\r
- case OT_INSTANCE:\r
- pf(v,_SC("[%s] INSTANCE\n"),name);\r
- break;\r
- }\r
- sq_pop(v,1);\r
- }\r
- }\r
- }\r
-}\r
-\r
-static int _sqstd_aux_printerror(HSQUIRRELVM v)\r
-{\r
- SQPRINTFUNCTION pf = sq_getprintfunc(v);\r
- if(pf) {\r
- const SQChar *sErr = 0;\r
- if(sq_gettop(v)>=1) {\r
- if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) {\r
- pf(v,_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr);\r
- }\r
- else{\r
- pf(v,_SC("\nAN ERROR HAS OCCURED [unknown]\n"));\r
- }\r
- sqstd_printcallstack(v);\r
- }\r
- }\r
- return 0;\r
-}\r
-\r
-void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSource,int line,int column)\r
-{\r
- SQPRINTFUNCTION pf = sq_getprintfunc(v);\r
- if(pf) {\r
- pf(v,_SC("ERROR %s line=(%d) column=(%d) [%s]\n"),sErr,line,column,sSource);\r
- }\r
-}\r
-\r
-void sqstd_seterrorhandlers(HSQUIRRELVM v)\r
-{\r
- sq_setcompilererrorhandler(v,_sqstd_compiler_error);\r
- sq_newclosure(v,_sqstd_aux_printerror,0);\r
- sq_seterrorhandler(v);\r
-}\r
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <sqstdaux.h>
+
+void sqstd_printcallstack(HSQUIRRELVM v)
+{
+ SQPRINTFUNCTION pf = sq_getprintfunc(v);
+ if(pf) {
+ SQStackInfos si;
+ SQInteger i;
+ SQFloat f;
+ const SQChar *s;
+ int level=1; //1 is to skip this function that is level 0
+ const SQChar *name=0;
+ int seq=0;
+ pf(v,_SC("\nCALLSTACK\n"));
+ while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si)))
+ {
+ const SQChar *fn=_SC("unknown");
+ const SQChar *src=_SC("unknown");
+ if(si.funcname)fn=si.funcname;
+ if(si.source)src=si.source;
+ pf(v,_SC("*FUNCTION [%s()] %s line [%d]\n"),fn,src,si.line);
+ level++;
+ }
+ level=0;
+ pf(v,_SC("\nLOCALS\n"));
+
+ for(level=0;level<10;level++){
+ seq=0;
+ while( (name=sq_getlocal(v,level,seq)) )
+ {
+ seq++;
+ switch(sq_gettype(v,-1))
+ {
+ case OT_NULL:
+ pf(v,_SC("[%s] NULL\n"),name);
+ break;
+ case OT_INTEGER:
+ sq_getinteger(v,-1,&i);
+ pf(v,_SC("[%s] %d\n"),name,i);
+ break;
+ case OT_FLOAT:
+ sq_getfloat(v,-1,&f);
+ pf(v,_SC("[%s] %.14g\n"),name,f);
+ break;
+ case OT_USERPOINTER:
+ pf(v,_SC("[%s] USERPOINTER\n"),name);
+ break;
+ case OT_STRING:
+ sq_getstring(v,-1,&s);
+ pf(v,_SC("[%s] \"%s\"\n"),name,s);
+ break;
+ case OT_TABLE:
+ pf(v,_SC("[%s] TABLE\n"),name);
+ break;
+ case OT_ARRAY:
+ pf(v,_SC("[%s] ARRAY\n"),name);
+ break;
+ case OT_CLOSURE:
+ pf(v,_SC("[%s] CLOSURE\n"),name);
+ break;
+ case OT_NATIVECLOSURE:
+ pf(v,_SC("[%s] NATIVECLOSURE\n"),name);
+ break;
+ case OT_USERDATA:
+ pf(v,_SC("[%s] USERDATA\n"),name);
+ break;
+ case OT_THREAD:
+ pf(v,_SC("[%s] THREAD\n"),name);
+ break;
+ case OT_CLASS:
+ pf(v,_SC("[%s] CLASS\n"),name);
+ break;
+ case OT_INSTANCE:
+ pf(v,_SC("[%s] INSTANCE\n"),name);
+ break;
+ default:
+ break;
+ }
+ sq_pop(v,1);
+ }
+ }
+ }
+}
+
+static int _sqstd_aux_printerror(HSQUIRRELVM v)
+{
+ SQPRINTFUNCTION pf = sq_getprintfunc(v);
+ if(pf) {
+ const SQChar *sErr = 0;
+ if(sq_gettop(v)>=1) {
+ if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) {
+ pf(v,_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr);
+ }
+ else{
+ pf(v,_SC("\nAN ERROR HAS OCCURED [unknown]\n"));
+ }
+ sqstd_printcallstack(v);
+ }
+ }
+ return 0;
+}
+
+void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSource,int line,int column)
+{
+ SQPRINTFUNCTION pf = sq_getprintfunc(v);
+ if(pf) {
+ pf(v,_SC("ERROR %s line=(%d) column=(%d) [%s]\n"),sErr,line,column,sSource);
+ }
+}
+
+void sqstd_seterrorhandlers(HSQUIRRELVM v)
+{
+ sq_setcompilererrorhandler(v,_sqstd_compiler_error);
+ sq_newclosure(v,_sqstd_aux_printerror,0);
+ sq_seterrorhandler(v);
+}
-/* see copyright notice in squirrel.h */\r
-#include <new>\r
-#include <squirrel.h>\r
-#include <sqstdio.h>\r
-#include <string.h>\r
-#include <sqstdblob.h>\r
-#include "sqstdstream.h"\r
-#include "sqstdblobimpl.h"\r
-\r
-#define SQSTD_BLOB_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000002)\r
-\r
-//Blob\r
-\r
-\r
-#define SETUP_BLOB(v) \\r
- SQBlob *self = NULL; \\r
- { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,SQSTD_BLOB_TYPE_TAG))) \\r
- return SQ_ERROR; }\r
-\r
-\r
-static int _blob_resize(HSQUIRRELVM v)\r
-{\r
- SETUP_BLOB(v);\r
- SQInteger size;\r
- sq_getinteger(v,2,&size);\r
- if(!self->Resize(size))\r
- return sq_throwerror(v,_SC("resize failed"));\r
- return 0;\r
-}\r
-\r
-static void __swap_dword(unsigned int *n)\r
-{\r
- *n=(unsigned int)(((*n&0xFF000000)>>24) |\r
- ((*n&0x00FF0000)>>8) |\r
- ((*n&0x0000FF00)<<8) |\r
- ((*n&0x000000FF)<<24));\r
-}\r
-\r
-static void __swap_word(unsigned short *n)\r
-{\r
- *n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00);\r
-}\r
-\r
-static int _blob_swap4(HSQUIRRELVM v)\r
-{\r
- SETUP_BLOB(v);\r
- int num=(self->Len()-(self->Len()%4))>>2;\r
- unsigned int *t=(unsigned int *)self->GetBuf();\r
- for(int i = 0; i < num; i++) {\r
- __swap_dword(&t[i]);\r
- }\r
- return 0;\r
-}\r
-\r
-static int _blob_swap2(HSQUIRRELVM v)\r
-{\r
- SETUP_BLOB(v);\r
- int num=(self->Len()-(self->Len()%2))>>1;\r
- unsigned short *t = (unsigned short *)self->GetBuf();\r
- for(int i = 0; i < num; i++) {\r
- __swap_word(&t[i]);\r
- }\r
- return 0;\r
-}\r
-\r
-static int _blob__set(HSQUIRRELVM v)\r
-{\r
- SETUP_BLOB(v);\r
- SQInteger idx,val;\r
- sq_getinteger(v,2,&idx);\r
- sq_getinteger(v,3,&val);\r
- if(idx < 0 || idx >= self->Len())\r
- return sq_throwerror(v,_SC("index out of range"));\r
- ((unsigned char *)self->GetBuf())[idx] = (unsigned char) val;\r
- sq_push(v,3);\r
- return 1;\r
-}\r
-\r
-static int _blob__get(HSQUIRRELVM v)\r
-{\r
- SETUP_BLOB(v);\r
- SQInteger idx;\r
- sq_getinteger(v,2,&idx);\r
- if(idx < 0 || idx >= self->Len())\r
- return sq_throwerror(v,_SC("index out of range"));\r
- sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]);\r
- return 1;\r
-}\r
-\r
-static int _blob__nexti(HSQUIRRELVM v)\r
-{\r
- SETUP_BLOB(v);\r
- if(sq_gettype(v,2) == OT_NULL) {\r
- sq_pushinteger(v, 0);\r
- return 1;\r
- }\r
- SQInteger idx;\r
- if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) {\r
- if(idx+1 < self->Len()) {\r
- sq_pushinteger(v, idx+1);\r
- return 1;\r
- }\r
- sq_pushnull(v);\r
- return 1;\r
- }\r
- return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type"));\r
-}\r
-\r
-static int _blob__typeof(HSQUIRRELVM v)\r
-{\r
- sq_pushstring(v,_SC("blob"),-1);\r
- return 1;\r
-}\r
-\r
-static int _blob_releasehook(SQUserPointer p, int size)\r
-{\r
- SQBlob *self = (SQBlob*)p;\r
- delete self;\r
- return 1;\r
-}\r
-\r
-static int _blob_constructor(HSQUIRRELVM v)\r
-{\r
- SQInteger nparam = sq_gettop(v);\r
- SQInteger size = 0;\r
- if(nparam == 2) {\r
- sq_getinteger(v, 2, &size);\r
- }\r
- if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size"));\r
- SQBlob *b = new SQBlob(size);\r
- if(SQ_FAILED(sq_setinstanceup(v,1,b))) {\r
- delete b;\r
- return sq_throwerror(v, _SC("cannot create blob with negative size"));\r
- }\r
- sq_setreleasehook(v,1,_blob_releasehook);\r
- return 0;\r
-}\r
-\r
-#define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck}\r
-static SQRegFunction _blob_methods[] = {\r
- _DECL_BLOB_FUNC(constructor,-1,_SC("xn")),\r
- _DECL_BLOB_FUNC(resize,2,_SC("xn")),\r
- _DECL_BLOB_FUNC(swap2,1,_SC("x")),\r
- _DECL_BLOB_FUNC(swap4,1,_SC("x")),\r
- _DECL_BLOB_FUNC(_set,3,_SC("xnn")),\r
- _DECL_BLOB_FUNC(_get,2,_SC("xn")),\r
- _DECL_BLOB_FUNC(_typeof,1,_SC("x")),\r
- _DECL_BLOB_FUNC(_nexti,2,_SC("x")),\r
- {0,0,0,0}\r
-};\r
-\r
-\r
-\r
-//GLOBAL FUNCTIONS\r
-\r
-static int _g_blob_casti2f(HSQUIRRELVM v)\r
-{\r
- SQInteger i;\r
- sq_getinteger(v,2,&i);\r
- sq_pushfloat(v,*((SQFloat *)&i));\r
- return 1;\r
-}\r
-\r
-static int _g_blob_castf2i(HSQUIRRELVM v)\r
-{\r
- SQFloat f;\r
- sq_getfloat(v,2,&f);\r
- sq_pushinteger(v,*((SQInteger *)&f));\r
- return 1;\r
-}\r
-\r
-static int _g_blob_swap2(HSQUIRRELVM v)\r
-{\r
- SQInteger i;\r
- sq_getinteger(v,2,&i);\r
- short s=(short)i;\r
- sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF));\r
- return 1;\r
-}\r
-\r
-static int _g_blob_swap4(HSQUIRRELVM v)\r
-{\r
- SQInteger i;\r
- sq_getinteger(v,2,&i);\r
- __swap_dword((unsigned int *)&i);\r
- sq_pushinteger(v,i);\r
- return 1;\r
-}\r
-\r
-static int _g_blob_swapfloat(HSQUIRRELVM v)\r
-{\r
- SQFloat f;\r
- sq_getfloat(v,2,&f);\r
- __swap_dword((unsigned int *)&f);\r
- sq_pushfloat(v,f);\r
- return 1;\r
-}\r
-\r
-#define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck}\r
-static SQRegFunction bloblib_funcs[]={\r
- _DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")),\r
- _DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")),\r
- _DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")),\r
- _DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")),\r
- _DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")),\r
- {0,0}\r
-};\r
-\r
-SQRESULT sqstd_getblob(HSQUIRRELVM v,int idx,SQUserPointer *ptr)\r
-{\r
- SQBlob *blob;\r
- if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,SQSTD_BLOB_TYPE_TAG)))\r
- return -1;\r
- *ptr = blob->GetBuf();\r
- return SQ_OK;\r
-}\r
-\r
-int sqstd_getblobsize(HSQUIRRELVM v,int idx)\r
-{\r
- SQBlob *blob;\r
- if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,SQSTD_BLOB_TYPE_TAG)))\r
- return -1;\r
- return blob->Len();\r
-}\r
-\r
-SQUserPointer sqstd_createblob(HSQUIRRELVM v, int size)\r
-{\r
- int top = sq_gettop(v);\r
-// SQUserPointer p = sq_newuserdata(v, sizeof(SQBlob));\r
-// sq_setreleasehook(v,-1,_blob_releasehook);\r
-// sq_settypetag(v,-1,SQSTD_BLOB_TYPE_TAG);\r
-// new (p) SQBlob(size);\r
- sq_pushregistrytable(v);\r
- sq_pushstring(v,_SC("std_blob"),-1);\r
- if(SQ_SUCCEEDED(sq_get(v,-2))) {\r
- sq_remove(v,-2); //removes the registry\r
- sq_push(v,1); // push the this\r
- sq_pushinteger(v,size); //size\r
- SQBlob *blob = NULL;\r
- if(SQ_SUCCEEDED(sq_call(v,2,SQTrue))\r
- && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,SQSTD_BLOB_TYPE_TAG))) {\r
- sq_remove(v,-2);\r
- sq_remove(v,-2);\r
- return blob->GetBuf();\r
- }\r
- }\r
- sq_settop(v,top);\r
- return NULL;\r
-}\r
-\r
-SQRESULT sqstd_register_bloblib(HSQUIRRELVM v)\r
-{\r
- return declare_stream(v,_SC("blob"),SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);\r
-}\r
-\r
+/* see copyright notice in squirrel.h */
+#include <new>
+#include <squirrel.h>
+#include <sqstdio.h>
+#include <string.h>
+#include <sqstdblob.h>
+#include "sqstdstream.h"
+#include "sqstdblobimpl.h"
+
+#define SQSTD_BLOB_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000002)
+
+//Blob
+
+
+#define SETUP_BLOB(v) \
+ SQBlob *self = NULL; \
+ { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,SQSTD_BLOB_TYPE_TAG))) \
+ return SQ_ERROR; }
+
+
+static int _blob_resize(HSQUIRRELVM v)
+{
+ SETUP_BLOB(v);
+ SQInteger size;
+ sq_getinteger(v,2,&size);
+ if(!self->Resize(size))
+ return sq_throwerror(v,_SC("resize failed"));
+ return 0;
+}
+
+static void __swap_dword(unsigned int *n)
+{
+ *n=(unsigned int)(((*n&0xFF000000)>>24) |
+ ((*n&0x00FF0000)>>8) |
+ ((*n&0x0000FF00)<<8) |
+ ((*n&0x000000FF)<<24));
+}
+
+static void __swap_word(unsigned short *n)
+{
+ *n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00);
+}
+
+static int _blob_swap4(HSQUIRRELVM v)
+{
+ SETUP_BLOB(v);
+ int num=(self->Len()-(self->Len()%4))>>2;
+ unsigned int *t=(unsigned int *)self->GetBuf();
+ for(int i = 0; i < num; i++) {
+ __swap_dword(&t[i]);
+ }
+ return 0;
+}
+
+static int _blob_swap2(HSQUIRRELVM v)
+{
+ SETUP_BLOB(v);
+ int num=(self->Len()-(self->Len()%2))>>1;
+ unsigned short *t = (unsigned short *)self->GetBuf();
+ for(int i = 0; i < num; i++) {
+ __swap_word(&t[i]);
+ }
+ return 0;
+}
+
+static int _blob__set(HSQUIRRELVM v)
+{
+ SETUP_BLOB(v);
+ SQInteger idx,val;
+ sq_getinteger(v,2,&idx);
+ sq_getinteger(v,3,&val);
+ if(idx < 0 || idx >= self->Len())
+ return sq_throwerror(v,_SC("index out of range"));
+ ((unsigned char *)self->GetBuf())[idx] = (unsigned char) val;
+ sq_push(v,3);
+ return 1;
+}
+
+static int _blob__get(HSQUIRRELVM v)
+{
+ SETUP_BLOB(v);
+ SQInteger idx;
+ sq_getinteger(v,2,&idx);
+ if(idx < 0 || idx >= self->Len())
+ return sq_throwerror(v,_SC("index out of range"));
+ sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]);
+ return 1;
+}
+
+static int _blob__nexti(HSQUIRRELVM v)
+{
+ SETUP_BLOB(v);
+ if(sq_gettype(v,2) == OT_NULL) {
+ sq_pushinteger(v, 0);
+ return 1;
+ }
+ SQInteger idx;
+ if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) {
+ if(idx+1 < self->Len()) {
+ sq_pushinteger(v, idx+1);
+ return 1;
+ }
+ sq_pushnull(v);
+ return 1;
+ }
+ return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type"));
+}
+
+static int _blob__typeof(HSQUIRRELVM v)
+{
+ sq_pushstring(v,_SC("blob"),-1);
+ return 1;
+}
+
+static int _blob_releasehook(SQUserPointer p, int )
+{
+ SQBlob *self = (SQBlob*)p;
+ delete self;
+ return 1;
+}
+
+static int _blob_constructor(HSQUIRRELVM v)
+{
+ SQInteger nparam = sq_gettop(v);
+ SQInteger size = 0;
+ if(nparam == 2) {
+ sq_getinteger(v, 2, &size);
+ }
+ if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size"));
+ SQBlob *b = new SQBlob(size);
+ if(SQ_FAILED(sq_setinstanceup(v,1,b))) {
+ delete b;
+ return sq_throwerror(v, _SC("cannot create blob with negative size"));
+ }
+ sq_setreleasehook(v,1,_blob_releasehook);
+ return 0;
+}
+
+#define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck}
+static SQRegFunction _blob_methods[] = {
+ _DECL_BLOB_FUNC(constructor,-1,_SC("xn")),
+ _DECL_BLOB_FUNC(resize,2,_SC("xn")),
+ _DECL_BLOB_FUNC(swap2,1,_SC("x")),
+ _DECL_BLOB_FUNC(swap4,1,_SC("x")),
+ _DECL_BLOB_FUNC(_set,3,_SC("xnn")),
+ _DECL_BLOB_FUNC(_get,2,_SC("xn")),
+ _DECL_BLOB_FUNC(_typeof,1,_SC("x")),
+ _DECL_BLOB_FUNC(_nexti,2,_SC("x")),
+ {0,0,0,0}
+};
+
+
+
+//GLOBAL FUNCTIONS
+
+static int _g_blob_casti2f(HSQUIRRELVM v)
+{
+ SQInteger i;
+ sq_getinteger(v,2,&i);
+ sq_pushfloat(v,*((SQFloat *)&i));
+ return 1;
+}
+
+static int _g_blob_castf2i(HSQUIRRELVM v)
+{
+ SQFloat f;
+ sq_getfloat(v,2,&f);
+ sq_pushinteger(v,*((SQInteger *)&f));
+ return 1;
+}
+
+static int _g_blob_swap2(HSQUIRRELVM v)
+{
+ SQInteger i;
+ sq_getinteger(v,2,&i);
+ short s=(short)i;
+ sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF));
+ return 1;
+}
+
+static int _g_blob_swap4(HSQUIRRELVM v)
+{
+ SQInteger i;
+ sq_getinteger(v,2,&i);
+ __swap_dword((unsigned int *)&i);
+ sq_pushinteger(v,i);
+ return 1;
+}
+
+static int _g_blob_swapfloat(HSQUIRRELVM v)
+{
+ SQFloat f;
+ sq_getfloat(v,2,&f);
+ __swap_dword((unsigned int *)&f);
+ sq_pushfloat(v,f);
+ return 1;
+}
+
+#define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck}
+static SQRegFunction bloblib_funcs[]={
+ _DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")),
+ _DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")),
+ _DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")),
+ _DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")),
+ _DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")),
+ {0,0,0,0}
+};
+
+SQRESULT sqstd_getblob(HSQUIRRELVM v,int idx,SQUserPointer *ptr)
+{
+ SQBlob *blob;
+ if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,SQSTD_BLOB_TYPE_TAG)))
+ return -1;
+ *ptr = blob->GetBuf();
+ return SQ_OK;
+}
+
+int sqstd_getblobsize(HSQUIRRELVM v,int idx)
+{
+ SQBlob *blob;
+ if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,SQSTD_BLOB_TYPE_TAG)))
+ return -1;
+ return blob->Len();
+}
+
+SQUserPointer sqstd_createblob(HSQUIRRELVM v, int size)
+{
+ int top = sq_gettop(v);
+// SQUserPointer p = sq_newuserdata(v, sizeof(SQBlob));
+// sq_setreleasehook(v,-1,_blob_releasehook);
+// sq_settypetag(v,-1,SQSTD_BLOB_TYPE_TAG);
+// new (p) SQBlob(size);
+ sq_pushregistrytable(v);
+ sq_pushstring(v,_SC("std_blob"),-1);
+ if(SQ_SUCCEEDED(sq_get(v,-2))) {
+ sq_remove(v,-2); //removes the registry
+ sq_push(v,1); // push the this
+ sq_pushinteger(v,size); //size
+ SQBlob *blob = NULL;
+ if(SQ_SUCCEEDED(sq_call(v,2,SQTrue))
+ && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,SQSTD_BLOB_TYPE_TAG))) {
+ sq_remove(v,-2);
+ sq_remove(v,-2);
+ return blob->GetBuf();
+ }
+ }
+ sq_settop(v,top);
+ return NULL;
+}
+
+SQRESULT sqstd_register_bloblib(HSQUIRRELVM v)
+{
+ return declare_stream(v,_SC("blob"),SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);
+}
+
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQSTD_BLOBIMPL_H_\r
-#define _SQSTD_BLOBIMPL_H_\r
-\r
-struct SQBlob : public SQStream\r
-{\r
- SQBlob(int size) {\r
- _size = size;\r
- _allocated = size;\r
- _buf = (unsigned char *)sq_malloc(size);\r
- memset(_buf, 0, _size);\r
- _ptr = 0;\r
- _owns = true;\r
- }\r
- ~SQBlob() {\r
- sq_free(_buf, _size);\r
- }\r
- SQInteger Write(void *buffer, SQInteger size) {\r
- if(!CanAdvance(size)) {\r
- GrowBufOf(_ptr + size - _size);\r
- }\r
- memcpy(&_buf[_ptr], buffer, size);\r
- _ptr += size;\r
- return size;\r
- }\r
- SQInteger Read(void *buffer,SQInteger size) {\r
- int n = size;\r
- if(!CanAdvance(size)) {\r
- if((_size - _ptr) > 0)\r
- n = _size - _ptr;\r
- else return 0;\r
- }\r
- memcpy(buffer, &_buf[_ptr], n);\r
- _ptr += n;\r
- return n;\r
- }\r
- bool Resize(int n) {\r
- if(!_owns) return false;\r
- if(n != _allocated) {\r
- unsigned char *newbuf = (unsigned char *)sq_malloc(n);\r
- memset(newbuf,0,n);\r
- if(_size > n)\r
- memcpy(newbuf,_buf,n);\r
- else\r
- memcpy(newbuf,_buf,_size);\r
- sq_free(_buf,_allocated);\r
- _buf=newbuf;\r
- _allocated = n;\r
- if(_size > _allocated)\r
- _size = _allocated;\r
- if(_ptr > _allocated)\r
- _ptr = _allocated;\r
- }\r
- return true;\r
- }\r
- bool GrowBufOf(int n)\r
- {\r
- bool ret = true;\r
- if(_size + n > _allocated) {\r
- if(_size + n > _size * 2)\r
- ret = Resize(_size + n);\r
- else\r
- ret = Resize(_size * 2);\r
- }\r
- _size = _size + n;\r
- return ret;\r
- }\r
- bool CanAdvance(int n) {\r
- if(_ptr+n>_size)return false;\r
- return true;\r
- }\r
- SQInteger Seek(long offset, int origin) {\r
- switch(origin) {\r
- case SQ_SEEK_SET:\r
- if(offset >= _size || offset < 0) return -1;\r
- _ptr = offset;\r
- break;\r
- case SQ_SEEK_CUR:\r
- if(_ptr + offset >= _size || _ptr + offset < 0) return -1;\r
- _ptr += offset;\r
- break;\r
- case SQ_SEEK_END:\r
- if(_size + offset >= _size || _size + offset < 0) return -1;\r
- _ptr = _size + offset;\r
- break;\r
- default: return -1;\r
- }\r
- return 0;\r
- }\r
- bool IsValid() {\r
- return _buf?true:false;\r
- }\r
- bool EOS() {\r
- return _ptr == _size;\r
- }\r
- int Flush() { return 0; }\r
- long Tell() { return _ptr; }\r
- SQInteger Len() { return _size; }\r
- SQUserPointer GetBuf(){ return _buf; }\r
-private:\r
- int _size;\r
- int _allocated;\r
- int _ptr;\r
- unsigned char *_buf;\r
- bool _owns;\r
-};\r
-\r
-#endif //_SQSTD_BLOBIMPL_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQSTD_BLOBIMPL_H_
+#define _SQSTD_BLOBIMPL_H_
+
+struct SQBlob : public SQStream
+{
+ SQBlob(int size) {
+ _size = size;
+ _allocated = size;
+ _buf = (unsigned char *)sq_malloc(size);
+ memset(_buf, 0, _size);
+ _ptr = 0;
+ _owns = true;
+ }
+ ~SQBlob() {
+ sq_free(_buf, _size);
+ }
+ SQInteger Write(void *buffer, SQInteger size) {
+ if(!CanAdvance(size)) {
+ GrowBufOf(_ptr + size - _size);
+ }
+ memcpy(&_buf[_ptr], buffer, size);
+ _ptr += size;
+ return size;
+ }
+ SQInteger Read(void *buffer,SQInteger size) {
+ int n = size;
+ if(!CanAdvance(size)) {
+ if((_size - _ptr) > 0)
+ n = _size - _ptr;
+ else return 0;
+ }
+ memcpy(buffer, &_buf[_ptr], n);
+ _ptr += n;
+ return n;
+ }
+ bool Resize(int n) {
+ if(!_owns) return false;
+ if(n != _allocated) {
+ unsigned char *newbuf = (unsigned char *)sq_malloc(n);
+ memset(newbuf,0,n);
+ if(_size > n)
+ memcpy(newbuf,_buf,n);
+ else
+ memcpy(newbuf,_buf,_size);
+ sq_free(_buf,_allocated);
+ _buf=newbuf;
+ _allocated = n;
+ if(_size > _allocated)
+ _size = _allocated;
+ if(_ptr > _allocated)
+ _ptr = _allocated;
+ }
+ return true;
+ }
+ bool GrowBufOf(int n)
+ {
+ bool ret = true;
+ if(_size + n > _allocated) {
+ if(_size + n > _size * 2)
+ ret = Resize(_size + n);
+ else
+ ret = Resize(_size * 2);
+ }
+ _size = _size + n;
+ return ret;
+ }
+ bool CanAdvance(int n) {
+ if(_ptr+n>_size)return false;
+ return true;
+ }
+ SQInteger Seek(long offset, int origin) {
+ switch(origin) {
+ case SQ_SEEK_SET:
+ if(offset >= _size || offset < 0) return -1;
+ _ptr = offset;
+ break;
+ case SQ_SEEK_CUR:
+ if(_ptr + offset >= _size || _ptr + offset < 0) return -1;
+ _ptr += offset;
+ break;
+ case SQ_SEEK_END:
+ if(_size + offset >= _size || _size + offset < 0) return -1;
+ _ptr = _size + offset;
+ break;
+ default: return -1;
+ }
+ return 0;
+ }
+ bool IsValid() {
+ return _buf?true:false;
+ }
+ bool EOS() {
+ return _ptr == _size;
+ }
+ int Flush() { return 0; }
+ long Tell() { return _ptr; }
+ SQInteger Len() { return _size; }
+ SQUserPointer GetBuf(){ return _buf; }
+private:
+ int _size;
+ int _allocated;
+ int _ptr;
+ unsigned char *_buf;
+ bool _owns;
+};
+
+#endif //_SQSTD_BLOBIMPL_H_
-/* see copyright notice in squirrel.h */\r
-#include <new>\r
-#include <stdio.h>\r
-#include <squirrel.h>\r
-#include <sqstdio.h>\r
-#include "sqstdstream.h"\r
-\r
-#define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001)\r
-//basic API\r
-SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode)\r
-{\r
-#ifndef _UNICODE\r
- return (SQFILE)fopen(filename,mode);\r
-#else\r
- return (SQFILE)_wfopen(filename,mode);\r
-#endif\r
-}\r
-\r
-SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file)\r
-{\r
- return (SQInteger)fread(buffer,size,count,(FILE *)file);\r
-}\r
-\r
-SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file)\r
-{\r
- return (SQInteger)fwrite(buffer,size,count,(FILE *)file);\r
-}\r
-\r
-SQInteger sqstd_fseek(SQFILE file, long offset, int origin)\r
-{\r
- int realorigin;\r
- switch(origin) {\r
- case SQ_SEEK_CUR: realorigin = SEEK_CUR; break;\r
- case SQ_SEEK_END: realorigin = SEEK_END; break;\r
- case SQ_SEEK_SET: realorigin = SEEK_SET; break;\r
- default: return -1; //failed\r
- }\r
- return fseek((FILE *)file,offset,realorigin);\r
-}\r
-\r
-long sqstd_ftell(SQFILE file)\r
-{\r
- return ftell((FILE *)file);\r
-}\r
-\r
-SQInteger sqstd_fflush(SQFILE file)\r
-{\r
- return fflush((FILE *)file);\r
-}\r
-\r
-SQInteger sqstd_fclose(SQFILE file)\r
-{\r
- return fclose((FILE *)file);\r
-}\r
-\r
-SQInteger sqstd_feof(SQFILE file)\r
-{\r
- return feof((FILE *)file);\r
-}\r
-\r
-//File\r
-struct SQFile : public SQStream {\r
- SQFile() { _handle = NULL; _owns = false;}\r
- SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;}\r
- ~SQFile() { Close(); }\r
- bool Open(const SQChar *filename ,const SQChar *mode) {\r
- Close();\r
- if(_handle = sqstd_fopen(filename,mode)) {\r
- _owns = true;\r
- return true;\r
- }\r
- return false;\r
- }\r
- void Close() {\r
- if(_handle && _owns) { \r
- sqstd_fclose(_handle);\r
- _handle = NULL;\r
- _owns = false;\r
- }\r
- }\r
- SQInteger Read(void *buffer,SQInteger size) {\r
- return sqstd_fread(buffer,1,size,_handle);\r
- }\r
- SQInteger Write(void *buffer,SQInteger size) {\r
- return sqstd_fwrite(buffer,1,size,_handle);\r
- }\r
- int Flush() {\r
- return sqstd_fflush(_handle);\r
- }\r
- long Tell() {\r
- return sqstd_ftell(_handle);\r
- }\r
- SQInteger Len() {\r
- int prevpos=Tell();\r
- Seek(0,SQ_SEEK_END);\r
- int size=Tell();\r
- Seek(prevpos,SQ_SEEK_SET);\r
- return size;\r
- }\r
- SQInteger Seek(long offset, int origin) {\r
- return sqstd_fseek(_handle,offset,origin);\r
- }\r
- bool IsValid() { return _handle?true:false; }\r
- bool EOS() { return Tell()==Len()?true:false;}\r
- SQFILE GetHandle() {return _handle;}\r
-private:\r
- SQFILE _handle;\r
- bool _owns;\r
-};\r
-\r
-static int _file__typeof(HSQUIRRELVM v)\r
-{\r
- sq_pushstring(v,_SC("file"),-1);\r
- return 1;\r
-}\r
-\r
-static int _file_releasehook(SQUserPointer p, int size)\r
-{\r
- SQFile *self = (SQFile*)p;\r
- delete self;\r
- return 1;\r
-}\r
-\r
-static int _file_constructor(HSQUIRRELVM v)\r
-{\r
- const SQChar *filename,*mode;\r
- bool owns = true;\r
- SQFile *f;\r
- SQFILE newf;\r
- if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {\r
- sq_getstring(v, 2, &filename);\r
- sq_getstring(v, 3, &mode);\r
- newf = sqstd_fopen(filename, mode);\r
- if(!newf) return sq_throwerror(v, _SC("cannot open file"));\r
- } else if(sq_gettype(v,2) == OT_USERPOINTER) {\r
- owns = !(sq_gettype(v,3) == OT_NULL);\r
- sq_getuserpointer(v,2,&newf);\r
- } else {\r
- return sq_throwerror(v,_SC("wrong parameter"));\r
- }\r
- f = new SQFile(newf,owns);\r
- if(SQ_FAILED(sq_setinstanceup(v,1,f))) {\r
- delete f;\r
- return sq_throwerror(v, _SC("cannot create blob with negative size"));\r
- }\r
- sq_setreleasehook(v,1,_file_releasehook);\r
- return 0;\r
-}\r
-\r
-//bindings\r
-#define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck}\r
-static SQRegFunction _file_methods[] = {\r
- _DECL_FILE_FUNC(constructor,3,_SC("x")),\r
- _DECL_FILE_FUNC(_typeof,1,_SC("x")),\r
- {0,0,0,0},\r
-};\r
-\r
-\r
-\r
-SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own)\r
-{\r
- int top = sq_gettop(v);\r
- sq_pushregistrytable(v);\r
- sq_pushstring(v,_SC("std_file"),-1);\r
- if(SQ_SUCCEEDED(sq_get(v,-2))) {\r
- sq_remove(v,-2); //removes the registry\r
- sq_pushroottable(v); // push the this\r
- sq_pushuserpointer(v,file); //file\r
- if(own){\r
- sq_pushinteger(v,1); //true\r
- }\r
- else{\r
- sq_pushnull(v); //false\r
- }\r
- if(SQ_SUCCEEDED( sq_call(v,3,SQTrue) )) {\r
- sq_remove(v,-2);\r
- return SQ_OK;\r
- }\r
- }\r
- sq_settop(v,top);\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sqstd_getfile(HSQUIRRELVM v, int idx, SQFILE *file)\r
-{\r
- SQFile *fileobj = NULL;\r
- if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,SQSTD_FILE_TYPE_TAG))) {\r
- *file = fileobj->GetHandle();\r
- return SQ_OK;\r
- }\r
- return sq_throwerror(v,_SC("not a file"));\r
-}\r
-\r
-\r
-static SQInteger _io_file_lexfeedASCII(SQUserPointer file)\r
-{\r
- int ret;\r
- char c;\r
- if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )\r
- return c;\r
- return 0;\r
-}\r
-\r
-static SQInteger _io_file_lexfeedWCHAR(SQUserPointer file)\r
-{\r
- int ret;\r
- wchar_t c;\r
- if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )\r
- return (SQChar)c;\r
- return 0;\r
-}\r
-\r
-int file_read(SQUserPointer file,SQUserPointer buf,int size)\r
-{\r
- int ret;\r
- if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;\r
- return -1;\r
-}\r
-\r
-int file_write(SQUserPointer file,SQUserPointer p,int size)\r
-{\r
- return sqstd_fwrite(p,1,size,(SQFILE)file);\r
-}\r
-\r
-SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror)\r
-{\r
- SQFILE file = sqstd_fopen(filename,_SC("rb"));\r
- int ret;\r
- unsigned short uc;\r
- SQLEXREADFUNC func = _io_file_lexfeedASCII;\r
- if(file && (ret=sqstd_fread(&uc,1,2,file))){\r
- if(ret!=2) {\r
- sqstd_fclose(file);\r
- return sq_throwerror(v,_SC("io error"));\r
- }\r
- if(uc==SQ_BYTECODE_STREAM_TAG) { //BYTECODE\r
- sqstd_fseek(file,0,SQ_SEEK_SET);\r
- if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) {\r
- sqstd_fclose(file);\r
- return SQ_OK;\r
- }\r
- }\r
- else { //SCRIPT\r
- if(uc==0xFEFF)\r
- func = _io_file_lexfeedWCHAR;\r
- else\r
- sqstd_fseek(file,0,SQ_SEEK_SET);\r
-\r
- if(SQ_SUCCEEDED(sq_compile(v,func,file,filename,printerror))){\r
- sqstd_fclose(file);\r
- return SQ_OK;\r
- }\r
- }\r
- sqstd_fclose(file);\r
- return SQ_ERROR;\r
- }\r
- return sq_throwerror(v,_SC("cannot open the file"));\r
-}\r
-\r
-SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror)\r
-{\r
- if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) {\r
- sq_push(v,-2);\r
- int ntop = sq_gettop(v);\r
- if(SQ_SUCCEEDED(sq_call(v,1,retval))) {\r
- sq_remove(v,retval?-2:-1); //removes the closure\r
- return 1;\r
- }\r
- sq_pop(v,1); //removes the closure\r
- }\r
- return SQ_ERROR;\r
-}\r
-\r
-SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename)\r
-{\r
- SQFILE file = sqstd_fopen(filename,_SC("wb+"));\r
- if(!file) return sq_throwerror(v,_SC("cannot open the file"));\r
- if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) {\r
- sqstd_fclose(file);\r
- return SQ_OK;\r
- }\r
- sqstd_fclose(file);\r
- return SQ_ERROR; //forward the error\r
-}\r
-\r
-int _g_io_loadfile(HSQUIRRELVM v)\r
-{\r
- const SQChar *filename;\r
- SQBool printerror = SQFalse;\r
- sq_getstring(v,2,&filename);\r
- if(sq_gettop(v) >= 3) {\r
- sq_getbool(v,3,&printerror);\r
- }\r
- if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror)))\r
- return 1;\r
- return SQ_ERROR; //propagates the error\r
-}\r
-\r
-int _g_io_dofile(HSQUIRRELVM v)\r
-{\r
- const SQChar *filename;\r
- SQBool printerror = SQFalse;\r
- sq_getstring(v,2,&filename);\r
- if(sq_gettop(v) >= 3) {\r
- sq_getbool(v,3,&printerror);\r
- }\r
- sq_push(v,1); //repush the this\r
- if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror)))\r
- return 1;\r
- return SQ_ERROR; //propagates the error\r
-}\r
-\r
-#define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck}\r
-static SQRegFunction iolib_funcs[]={\r
- _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")),\r
- _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")),\r
- {0,0}\r
-};\r
-\r
-SQRESULT sqstd_register_iolib(HSQUIRRELVM v)\r
-{\r
- int top = sq_gettop(v);\r
- //create delegate\r
- declare_stream(v,_SC("file"),SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);\r
- sq_pushstring(v,_SC("stdout"),-1);\r
- sqstd_createfile(v,stdout,0);\r
- sq_createslot(v,-3);\r
- sq_pushstring(v,_SC("stdin"),-1);\r
- sqstd_createfile(v,stdin,0);\r
- sq_createslot(v,-3);\r
- sq_pushstring(v,_SC("stderr"),-1);\r
- sqstd_createfile(v,stderr,0);\r
- sq_createslot(v,-3);\r
- sq_settop(v,top);\r
- return SQ_OK;\r
-}\r
+/* see copyright notice in squirrel.h */
+#include <new>
+#include <stdio.h>
+#include <squirrel.h>
+#include <sqstdio.h>
+#include "sqstdstream.h"
+
+#define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001)
+//basic API
+SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode)
+{
+#ifndef _UNICODE
+ return (SQFILE)fopen(filename,mode);
+#else
+ return (SQFILE)_wfopen(filename,mode);
+#endif
+}
+
+SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file)
+{
+ return (SQInteger)fread(buffer,size,count,(FILE *)file);
+}
+
+SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file)
+{
+ return (SQInteger)fwrite(buffer,size,count,(FILE *)file);
+}
+
+SQInteger sqstd_fseek(SQFILE file, long offset, int origin)
+{
+ int realorigin;
+ switch(origin) {
+ case SQ_SEEK_CUR: realorigin = SEEK_CUR; break;
+ case SQ_SEEK_END: realorigin = SEEK_END; break;
+ case SQ_SEEK_SET: realorigin = SEEK_SET; break;
+ default: return -1; //failed
+ }
+ return fseek((FILE *)file,offset,realorigin);
+}
+
+long sqstd_ftell(SQFILE file)
+{
+ return ftell((FILE *)file);
+}
+
+SQInteger sqstd_fflush(SQFILE file)
+{
+ return fflush((FILE *)file);
+}
+
+SQInteger sqstd_fclose(SQFILE file)
+{
+ return fclose((FILE *)file);
+}
+
+SQInteger sqstd_feof(SQFILE file)
+{
+ return feof((FILE *)file);
+}
+
+//File
+struct SQFile : public SQStream {
+ SQFile() { _handle = NULL; _owns = false;}
+ SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;}
+ virtual ~SQFile() { Close(); }
+ bool Open(const SQChar *filename ,const SQChar *mode) {
+ Close();
+ if( (_handle = sqstd_fopen(filename,mode)) ) {
+ _owns = true;
+ return true;
+ }
+ return false;
+ }
+ void Close() {
+ if(_handle && _owns) {
+ sqstd_fclose(_handle);
+ _handle = NULL;
+ _owns = false;
+ }
+ }
+ SQInteger Read(void *buffer,SQInteger size) {
+ return sqstd_fread(buffer,1,size,_handle);
+ }
+ SQInteger Write(void *buffer,SQInteger size) {
+ return sqstd_fwrite(buffer,1,size,_handle);
+ }
+ int Flush() {
+ return sqstd_fflush(_handle);
+ }
+ long Tell() {
+ return sqstd_ftell(_handle);
+ }
+ SQInteger Len() {
+ int prevpos=Tell();
+ Seek(0,SQ_SEEK_END);
+ int size=Tell();
+ Seek(prevpos,SQ_SEEK_SET);
+ return size;
+ }
+ SQInteger Seek(long offset, int origin) {
+ return sqstd_fseek(_handle,offset,origin);
+ }
+ bool IsValid() { return _handle?true:false; }
+ bool EOS() { return Tell()==Len()?true:false;}
+ SQFILE GetHandle() {return _handle;}
+private:
+ SQFILE _handle;
+ bool _owns;
+};
+
+static int _file__typeof(HSQUIRRELVM v)
+{
+ sq_pushstring(v,_SC("file"),-1);
+ return 1;
+}
+
+static int _file_releasehook(SQUserPointer p, int size)
+{
+ (void) size;
+ SQFile *self = (SQFile*)p;
+ delete self;
+ return 1;
+}
+
+static int _file_constructor(HSQUIRRELVM v)
+{
+ const SQChar *filename,*mode;
+ bool owns = true;
+ SQFile *f;
+ SQFILE newf;
+ if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {
+ sq_getstring(v, 2, &filename);
+ sq_getstring(v, 3, &mode);
+ newf = sqstd_fopen(filename, mode);
+ if(!newf) return sq_throwerror(v, _SC("cannot open file"));
+ } else if(sq_gettype(v,2) == OT_USERPOINTER) {
+ owns = !(sq_gettype(v,3) == OT_NULL);
+ sq_getuserpointer(v,2,&newf);
+ } else {
+ return sq_throwerror(v,_SC("wrong parameter"));
+ }
+ f = new SQFile(newf,owns);
+ if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
+ delete f;
+ return sq_throwerror(v, _SC("cannot create blob with negative size"));
+ }
+ sq_setreleasehook(v,1,_file_releasehook);
+ return 0;
+}
+
+//bindings
+#define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck}
+static SQRegFunction _file_methods[] = {
+ _DECL_FILE_FUNC(constructor,3,_SC("x")),
+ _DECL_FILE_FUNC(_typeof,1,_SC("x")),
+ {0,0,0,0},
+};
+
+
+
+SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own)
+{
+ int top = sq_gettop(v);
+ sq_pushregistrytable(v);
+ sq_pushstring(v,_SC("std_file"),-1);
+ if(SQ_SUCCEEDED(sq_get(v,-2))) {
+ sq_remove(v,-2); //removes the registry
+ sq_pushroottable(v); // push the this
+ sq_pushuserpointer(v,file); //file
+ if(own){
+ sq_pushinteger(v,1); //true
+ }
+ else{
+ sq_pushnull(v); //false
+ }
+ if(SQ_SUCCEEDED( sq_call(v,3,SQTrue) )) {
+ sq_remove(v,-2);
+ return SQ_OK;
+ }
+ }
+ sq_settop(v,top);
+ return SQ_OK;
+}
+
+SQRESULT sqstd_getfile(HSQUIRRELVM v, int idx, SQFILE *file)
+{
+ SQFile *fileobj = NULL;
+ if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,SQSTD_FILE_TYPE_TAG))) {
+ *file = fileobj->GetHandle();
+ return SQ_OK;
+ }
+ return sq_throwerror(v,_SC("not a file"));
+}
+
+
+static SQInteger _io_file_lexfeedASCII(SQUserPointer file)
+{
+ int ret;
+ char c;
+ if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )
+ return c;
+ return 0;
+}
+
+static SQInteger _io_file_lexfeedWCHAR(SQUserPointer file)
+{
+ int ret;
+ wchar_t c;
+ if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )
+ return (SQChar)c;
+ return 0;
+}
+
+int file_read(SQUserPointer file,SQUserPointer buf,int size)
+{
+ int ret;
+ if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;
+ return -1;
+}
+
+int file_write(SQUserPointer file,SQUserPointer p,int size)
+{
+ return sqstd_fwrite(p,1,size,(SQFILE)file);
+}
+
+SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror)
+{
+ SQFILE file = sqstd_fopen(filename,_SC("rb"));
+ int ret;
+ unsigned short uc;
+ SQLEXREADFUNC func = _io_file_lexfeedASCII;
+ if(file && (ret=sqstd_fread(&uc,1,2,file))){
+ if(ret!=2) {
+ sqstd_fclose(file);
+ return sq_throwerror(v,_SC("io error"));
+ }
+ if(uc==SQ_BYTECODE_STREAM_TAG) { //BYTECODE
+ sqstd_fseek(file,0,SQ_SEEK_SET);
+ if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) {
+ sqstd_fclose(file);
+ return SQ_OK;
+ }
+ }
+ else { //SCRIPT
+ if(uc==0xFEFF)
+ func = _io_file_lexfeedWCHAR;
+ else
+ sqstd_fseek(file,0,SQ_SEEK_SET);
+
+ if(SQ_SUCCEEDED(sq_compile(v,func,file,filename,printerror))){
+ sqstd_fclose(file);
+ return SQ_OK;
+ }
+ }
+ sqstd_fclose(file);
+ return SQ_ERROR;
+ }
+ return sq_throwerror(v,_SC("cannot open the file"));
+}
+
+SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror)
+{
+ if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) {
+ sq_push(v,-2);
+ //int ntop = sq_gettop(v);
+ if(SQ_SUCCEEDED(sq_call(v,1,retval))) {
+ sq_remove(v,retval?-2:-1); //removes the closure
+ return 1;
+ }
+ sq_pop(v,1); //removes the closure
+ }
+ return SQ_ERROR;
+}
+
+SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename)
+{
+ SQFILE file = sqstd_fopen(filename,_SC("wb+"));
+ if(!file) return sq_throwerror(v,_SC("cannot open the file"));
+ if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) {
+ sqstd_fclose(file);
+ return SQ_OK;
+ }
+ sqstd_fclose(file);
+ return SQ_ERROR; //forward the error
+}
+
+int _g_io_loadfile(HSQUIRRELVM v)
+{
+ const SQChar *filename;
+ SQBool printerror = SQFalse;
+ sq_getstring(v,2,&filename);
+ if(sq_gettop(v) >= 3) {
+ sq_getbool(v,3,&printerror);
+ }
+ if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror)))
+ return 1;
+ return SQ_ERROR; //propagates the error
+}
+
+int _g_io_dofile(HSQUIRRELVM v)
+{
+ const SQChar *filename;
+ SQBool printerror = SQFalse;
+ sq_getstring(v,2,&filename);
+ if(sq_gettop(v) >= 3) {
+ sq_getbool(v,3,&printerror);
+ }
+ sq_push(v,1); //repush the this
+ if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror)))
+ return 1;
+ return SQ_ERROR; //propagates the error
+}
+
+#define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck}
+static SQRegFunction iolib_funcs[]={
+ _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")),
+ _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")),
+ {0,0,0,0}
+};
+
+SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
+{
+ int top = sq_gettop(v);
+ //create delegate
+ declare_stream(v,_SC("file"),SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);
+ sq_pushstring(v,_SC("stdout"),-1);
+ sqstd_createfile(v,stdout,0);
+ sq_createslot(v,-3);
+ sq_pushstring(v,_SC("stdin"),-1);
+ sqstd_createfile(v,stdin,0);
+ sq_createslot(v,-3);
+ sq_pushstring(v,_SC("stderr"),-1);
+ sqstd_createfile(v,stderr,0);
+ sq_createslot(v,-3);
+ sq_settop(v,top);
+ return SQ_OK;
+}
-# Microsoft Developer Studio Project File - Name="sqstdlib" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Static Library" 0x0104\r
-\r
-CFG=sqstdlib - Win32 Release\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "sqstdlib.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "sqstdlib.mak" CFG="sqstdlib - Win32 Release"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "sqstdlib - Win32 Release" (based on "Win32 (x86) Static Library")\r
-!MESSAGE "sqstdlib - Win32 Debug" (based on "Win32 (x86) Static Library")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_LocalPath ".."\r
-CPP=cl.exe\r
-RSC=rc.exe\r
-\r
-!IF "$(CFG)" == "sqstdlib - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release"\r
-# PROP BASE Intermediate_Dir "Release"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release"\r
-# PROP Intermediate_Dir "Release"\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c\r
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c\r
-# ADD BASE RSC /l 0x410 /d "NDEBUG"\r
-# ADD RSC /l 0x410 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LIB32=link.exe -lib\r
-# ADD BASE LIB32 /nologo\r
-# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"\r
-\r
-!ELSEIF "$(CFG)" == "sqstdlib - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug"\r
-# PROP BASE Intermediate_Dir "Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug"\r
-# PROP Intermediate_Dir "Debug"\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c\r
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c\r
-# ADD BASE RSC /l 0x410 /d "_DEBUG"\r
-# ADD RSC /l 0x410 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LIB32=link.exe -lib\r
-# ADD BASE LIB32 /nologo\r
-# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "sqstdlib - Win32 Release"\r
-# Name "sqstdlib - Win32 Debug"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstdblob.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstdio.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstdmath.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstdrex.c\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstdstream.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstdstring.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstdaux.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstdsystem.cpp\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstdblobimpl.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstdstream.h\r
-# End Source File\r
-# End Group\r
-# End Target\r
-# End Project\r
+# Microsoft Developer Studio Project File - Name="sqstdlib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=sqstdlib - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "sqstdlib.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "sqstdlib.mak" CFG="sqstdlib - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "sqstdlib - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "sqstdlib - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "sqstdlib - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x410 /d "NDEBUG"
+# ADD RSC /l 0x410 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"
+
+!ELSEIF "$(CFG)" == "sqstdlib - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x410 /d "_DEBUG"
+# ADD RSC /l 0x410 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "sqstdlib - Win32 Release"
+# Name "sqstdlib - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\sqstdblob.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdmath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdrex.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdstream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdstring.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdaux.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdsystem.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\sqstdblobimpl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdstream.h
+# End Source File
+# End Group
+# End Target
+# End Project
-/* see copyright notice in squirrel.h */\r
-#include <squirrel.h>\r
-#include <math.h>\r
-#include <stdlib.h>\r
-#include <sqstdmath.h>\r
-\r
-#define SINGLE_ARG_FUNC(_funcname) static int math_##_funcname(HSQUIRRELVM v){ \\r
- SQFloat f; \\r
- sq_getfloat(v,2,&f); \\r
- sq_pushfloat(v,(SQFloat)_funcname(f)); \\r
- return 1; \\r
-}\r
-\r
-#define TWO_ARGS_FUNC(_funcname) static int math_##_funcname(HSQUIRRELVM v){ \\r
- SQFloat p1,p2; \\r
- sq_getfloat(v,2,&p1); \\r
- sq_getfloat(v,3,&p2); \\r
- sq_pushfloat(v,(SQFloat)_funcname(p1,p2)); \\r
- return 1; \\r
-}\r
-\r
-static int math_srand(HSQUIRRELVM v)\r
-{\r
- SQInteger i;\r
- if(!sq_getinteger(v,2,&i))return sq_throwerror(v,_SC("invalid param"));\r
- srand(i);\r
- return 0;\r
-}\r
-\r
-static int math_rand(HSQUIRRELVM v)\r
-{\r
- sq_pushinteger(v,rand());\r
- return 1;\r
-}\r
-\r
-static int math_abs(HSQUIRRELVM v)\r
-{\r
- SQInteger n;\r
- sq_getinteger(v,2,&n);\r
- sq_pushinteger(v,(SQInteger)abs(n)); \r
- return 1; \r
-}\r
-\r
-SINGLE_ARG_FUNC(sqrt)\r
-SINGLE_ARG_FUNC(fabs)\r
-SINGLE_ARG_FUNC(sin)\r
-SINGLE_ARG_FUNC(cos)\r
-SINGLE_ARG_FUNC(asin)\r
-SINGLE_ARG_FUNC(acos)\r
-SINGLE_ARG_FUNC(log)\r
-SINGLE_ARG_FUNC(log10)\r
-SINGLE_ARG_FUNC(tan)\r
-SINGLE_ARG_FUNC(atan)\r
-TWO_ARGS_FUNC(atan2)\r
-TWO_ARGS_FUNC(pow)\r
-SINGLE_ARG_FUNC(floor)\r
-SINGLE_ARG_FUNC(ceil)\r
-SINGLE_ARG_FUNC(exp)\r
-\r
-#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),math_##name,nparams,tycheck}\r
-static SQRegFunction mathlib_funcs[] = {\r
- _DECL_FUNC(sqrt,2,_SC(".n")),\r
- _DECL_FUNC(sin,2,_SC(".n")),\r
- _DECL_FUNC(cos,2,_SC(".n")),\r
- _DECL_FUNC(asin,2,_SC(".n")),\r
- _DECL_FUNC(acos,2,_SC(".n")),\r
- _DECL_FUNC(log,2,_SC(".n")),\r
- _DECL_FUNC(log10,2,_SC(".n")),\r
- _DECL_FUNC(tan,2,_SC(".n")),\r
- _DECL_FUNC(atan,2,_SC(".n")),\r
- _DECL_FUNC(atan2,3,_SC(".nn")),\r
- _DECL_FUNC(pow,3,_SC(".nn")),\r
- _DECL_FUNC(floor,2,_SC(".n")),\r
- _DECL_FUNC(ceil,2,_SC(".n")),\r
- _DECL_FUNC(exp,2,_SC(".n")),\r
- _DECL_FUNC(srand,2,_SC(".n")),\r
- _DECL_FUNC(rand,1,NULL),\r
- _DECL_FUNC(fabs,2,_SC(".n")),\r
- _DECL_FUNC(abs,2,_SC(".n")),\r
- {0,0},\r
-};\r
-\r
-#ifndef M_PI\r
-#define M_PI (3.14159265358979323846)\r
-#endif\r
-\r
-SQRESULT sqstd_register_mathlib(HSQUIRRELVM v)\r
-{\r
- int i=0;\r
- while(mathlib_funcs[i].name!=0) {\r
- sq_pushstring(v,mathlib_funcs[i].name,-1);\r
- sq_newclosure(v,mathlib_funcs[i].f,0);\r
- sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask);\r
- sq_setnativeclosurename(v,-1,mathlib_funcs[i].name);\r
- sq_createslot(v,-3);\r
- i++;\r
- }\r
- sq_pushstring(v,_SC("RAND_MAX"),-1);\r
- sq_pushinteger(v,RAND_MAX);\r
- sq_createslot(v,-3);\r
- sq_pushstring(v,_SC("PI"),-1);\r
- sq_pushfloat(v,(SQFloat)M_PI);\r
- sq_createslot(v,-3);\r
- return SQ_OK;\r
-}\r
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <math.h>
+#include <stdlib.h>
+#include <sqstdmath.h>
+
+#define SINGLE_ARG_FUNC(_funcname) static int math_##_funcname(HSQUIRRELVM v){ \
+ SQFloat f; \
+ sq_getfloat(v,2,&f); \
+ sq_pushfloat(v,(SQFloat)_funcname(f)); \
+ return 1; \
+}
+
+#define TWO_ARGS_FUNC(_funcname) static int math_##_funcname(HSQUIRRELVM v){ \
+ SQFloat p1,p2; \
+ sq_getfloat(v,2,&p1); \
+ sq_getfloat(v,3,&p2); \
+ sq_pushfloat(v,(SQFloat)_funcname(p1,p2)); \
+ return 1; \
+}
+
+static int math_srand(HSQUIRRELVM v)
+{
+ SQInteger i;
+ if(!sq_getinteger(v,2,&i))return sq_throwerror(v,_SC("invalid param"));
+ srand(i);
+ return 0;
+}
+
+static int math_rand(HSQUIRRELVM v)
+{
+ sq_pushinteger(v,rand());
+ return 1;
+}
+
+static int math_abs(HSQUIRRELVM v)
+{
+ SQInteger n;
+ sq_getinteger(v,2,&n);
+ sq_pushinteger(v,(SQInteger)abs(n));
+ return 1;
+}
+
+SINGLE_ARG_FUNC(sqrt)
+SINGLE_ARG_FUNC(fabs)
+SINGLE_ARG_FUNC(sin)
+SINGLE_ARG_FUNC(cos)
+SINGLE_ARG_FUNC(asin)
+SINGLE_ARG_FUNC(acos)
+SINGLE_ARG_FUNC(log)
+SINGLE_ARG_FUNC(log10)
+SINGLE_ARG_FUNC(tan)
+SINGLE_ARG_FUNC(atan)
+TWO_ARGS_FUNC(atan2)
+TWO_ARGS_FUNC(pow)
+SINGLE_ARG_FUNC(floor)
+SINGLE_ARG_FUNC(ceil)
+SINGLE_ARG_FUNC(exp)
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),math_##name,nparams,tycheck}
+static SQRegFunction mathlib_funcs[] = {
+ _DECL_FUNC(sqrt,2,_SC(".n")),
+ _DECL_FUNC(sin,2,_SC(".n")),
+ _DECL_FUNC(cos,2,_SC(".n")),
+ _DECL_FUNC(asin,2,_SC(".n")),
+ _DECL_FUNC(acos,2,_SC(".n")),
+ _DECL_FUNC(log,2,_SC(".n")),
+ _DECL_FUNC(log10,2,_SC(".n")),
+ _DECL_FUNC(tan,2,_SC(".n")),
+ _DECL_FUNC(atan,2,_SC(".n")),
+ _DECL_FUNC(atan2,3,_SC(".nn")),
+ _DECL_FUNC(pow,3,_SC(".nn")),
+ _DECL_FUNC(floor,2,_SC(".n")),
+ _DECL_FUNC(ceil,2,_SC(".n")),
+ _DECL_FUNC(exp,2,_SC(".n")),
+ _DECL_FUNC(srand,2,_SC(".n")),
+ _DECL_FUNC(rand,1,NULL),
+ _DECL_FUNC(fabs,2,_SC(".n")),
+ _DECL_FUNC(abs,2,_SC(".n")),
+ {0,0,0,0},
+};
+
+#ifndef M_PI
+#define M_PI (3.14159265358979323846)
+#endif
+
+SQRESULT sqstd_register_mathlib(HSQUIRRELVM v)
+{
+ int i=0;
+ while(mathlib_funcs[i].name!=0) {
+ sq_pushstring(v,mathlib_funcs[i].name,-1);
+ sq_newclosure(v,mathlib_funcs[i].f,0);
+ sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask);
+ sq_setnativeclosurename(v,-1,mathlib_funcs[i].name);
+ sq_createslot(v,-3);
+ i++;
+ }
+ sq_pushstring(v,_SC("RAND_MAX"),-1);
+ sq_pushinteger(v,RAND_MAX);
+ sq_createslot(v,-3);
+ sq_pushstring(v,_SC("PI"),-1);
+ sq_pushfloat(v,(SQFloat)M_PI);
+ sq_createslot(v,-3);
+ return SQ_OK;
+}
-/* see copyright notice in squirrel.h */\r
-#include <squirrel.h>\r
-#include <string.h>\r
-#include <ctype.h>\r
-#include <setjmp.h>\r
-#include "sqstdstring.h"\r
-\r
-#ifdef _DEBUG\r
-#include <stdio.h>\r
-\r
-static const SQChar *g_nnames[] =\r
-{\r
- _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"),\r
- _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"),\r
- _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),\r
- _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB")\r
-};\r
-\r
-#endif\r
-\r
-#define OP_GREEDY MAX_CHAR+1 // * + ? {n}\r
-#define OP_OR MAX_CHAR+2\r
-#define OP_EXPR MAX_CHAR+3 //parentesis ()\r
-#define OP_NOCAPEXPR MAX_CHAR+4 //parentesis (?:)\r
-#define OP_DOT MAX_CHAR+5\r
-#define OP_CLASS MAX_CHAR+6\r
-#define OP_CCLASS MAX_CHAR+7\r
-#define OP_NCLASS MAX_CHAR+8 //negates class the [^\r
-#define OP_RANGE MAX_CHAR+9\r
-#define OP_CHAR MAX_CHAR+10\r
-#define OP_EOL MAX_CHAR+11\r
-#define OP_BOL MAX_CHAR+12\r
-#define OP_WB MAX_CHAR+13\r
-\r
-#define SQREX_SYMBOL_ANY_CHAR '.'\r
-#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE '+'\r
-#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE '*'\r
-#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE '?'\r
-#define SQREX_SYMBOL_BRANCH '|'\r
-#define SQREX_SYMBOL_END_OF_STRING '$'\r
-#define SQREX_SYMBOL_BEGINNING_OF_STRING '^'\r
-#define SQREX_SYMBOL_ESCAPE_CHAR '\\'\r
-\r
-\r
-typedef int SQRexNodeType;\r
-\r
-typedef struct tagSQRexNode{\r
- SQRexNodeType type;\r
- long left;\r
- long right;\r
- int next;\r
-}SQRexNode;\r
-\r
-struct SQRex{\r
- const SQChar *_eol;\r
- const SQChar *_bol;\r
- const SQChar *_p;\r
- int _first;\r
- int _op;\r
- SQRexNode *_nodes;\r
- int _nallocated;\r
- int _nsize;\r
- int _nsubexpr;\r
- SQRexMatch *_matches;\r
- int _currsubexp;\r
- void *_jmpbuf;\r
- const SQChar **_error;\r
-};\r
-\r
-static int sqstd_rex_list(SQRex *exp);\r
-\r
-static int sqstd_rex_newnode(SQRex *exp, SQRexNodeType type)\r
-{\r
- SQRexNode n;\r
- n.type = type;\r
- n.next = n.right = n.left = -1;\r
- if(type == OP_EXPR)\r
- n.right = exp->_nsubexpr++;\r
- if(exp->_nallocated < (exp->_nsize + 1)) {\r
- int oldsize = exp->_nallocated;\r
- exp->_nallocated *= 2;\r
- exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode));\r
- }\r
- exp->_nodes[exp->_nsize++] = n;\r
- return (int)exp->_nsize - 1;\r
-}\r
-\r
-static void sqstd_rex_error(SQRex *exp,const SQChar *error)\r
-{\r
- if(exp->_error) *exp->_error = error;\r
- longjmp(*((jmp_buf*)exp->_jmpbuf),-1);\r
-}\r
-\r
-static void sqstd_rex_expect(SQRex *exp, int n){\r
- if((*exp->_p) != n) \r
- sqstd_rex_error(exp, _SC("expected paren"));\r
- exp->_p++;\r
-}\r
-\r
-static SQBool sqstd_rex_ischar(SQChar c)\r
-{\r
- switch(c) {\r
- case SQREX_SYMBOL_BRANCH:case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE:\r
- case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE:case SQREX_SYMBOL_GREEDY_ONE_OR_MORE:\r
- case SQREX_SYMBOL_BEGINNING_OF_STRING:case SQREX_SYMBOL_END_OF_STRING:\r
- case SQREX_SYMBOL_ANY_CHAR:case SQREX_SYMBOL_ESCAPE_CHAR:case '(':case ')':case '[':case '{': case '}':\r
- return SQFalse;\r
- }\r
- return SQTrue;\r
-}\r
-\r
-static SQChar sqstd_rex_escapechar(SQRex *exp)\r
-{\r
- if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){\r
- exp->_p++;\r
- switch(*exp->_p) {\r
- case 'v': exp->_p++; return '\v';\r
- case 'n': exp->_p++; return '\n';\r
- case 't': exp->_p++; return '\t';\r
- case 'r': exp->_p++; return '\r';\r
- case 'f': exp->_p++; return '\f';\r
- default: return (*exp->_p++);\r
- }\r
- } else if(!sqstd_rex_ischar(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected"));\r
- return (*exp->_p++);\r
-}\r
-\r
-static int sqstd_rex_charclass(SQRex *exp,int classid)\r
-{\r
- int n = sqstd_rex_newnode(exp,OP_CCLASS);\r
- exp->_nodes[n].left = classid;\r
- return n;\r
-}\r
-\r
-static int sqstd_rex_charnode(SQRex *exp,SQBool isclass)\r
-{\r
- if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) {\r
- exp->_p++;\r
- switch(*exp->_p) {\r
- case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n');\r
- case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t');\r
- case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r');\r
- case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f');\r
- case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v');\r
- case 'a': case 'A': case 'w': case 'W': case 's': case 'S': \r
- case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': \r
- case 'p': case 'P': case 'l': case 'u': \r
- {\r
- SQChar t = *exp->_p;\r
- exp->_p++; \r
- return sqstd_rex_charclass(exp,t);\r
- }\r
- case 'b': \r
- case 'B':\r
- if(!isclass) {\r
- int node = sqstd_rex_newnode(exp,OP_WB);\r
- exp->_nodes[node].left = *exp->_p;\r
- exp->_p++; \r
- return node;\r
- } //else default\r
- default: return sqstd_rex_newnode(exp,(*exp->_p++));\r
- }\r
- }\r
- else if(!sqstd_rex_ischar(*exp->_p)) {\r
- \r
- sqstd_rex_error(exp,_SC("letter expected"));\r
- }\r
- return sqstd_rex_newnode(exp,*exp->_p++);\r
-}\r
-static int sqstd_rex_class(SQRex *exp)\r
-{\r
- int ret = -1;\r
- int first = -1,chain;\r
- if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){\r
- ret = sqstd_rex_newnode(exp,OP_NCLASS);\r
- exp->_p++;\r
- }else ret = sqstd_rex_newnode(exp,OP_CLASS);\r
- \r
- if(*exp->_p == ']' || *exp->_p == '-'){\r
- first = *exp->_p;\r
- exp->_p++;\r
- }\r
- chain = ret;\r
- while(*exp->_p != ']' && exp->_p != exp->_eol) {\r
- if(*exp->_p == '-' && first != -1){ \r
- int r;\r
- if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range"));\r
- r = sqstd_rex_newnode(exp,OP_RANGE);\r
- if(first>*exp->_p) sqstd_rex_error(exp,_SC("invalid range"));\r
- if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges"));\r
- exp->_nodes[r].left = exp->_nodes[first].type;\r
- exp->_nodes[r].right = sqstd_rex_escapechar(exp);\r
- exp->_nodes[chain].next = r;\r
- chain = r;\r
- first = -1;\r
- }\r
- else{\r
- if(first!=-1){\r
- int c = first;\r
- exp->_nodes[chain].next = c;\r
- chain = c;\r
- first = sqstd_rex_charnode(exp,SQTrue);\r
- }\r
- else{\r
- first = sqstd_rex_charnode(exp,SQTrue);\r
- }\r
- }\r
- }\r
- if(first!=-1){\r
- int c = first;\r
- exp->_nodes[chain].next = c;\r
- chain = c;\r
- first = -1;\r
- }\r
- /* hack? */\r
- exp->_nodes[ret].left = exp->_nodes[ret].next;\r
- exp->_nodes[ret].next = -1;\r
- return ret;\r
-}\r
-\r
-static int sqstd_rex_parsenumber(SQRex *exp)\r
-{\r
- int ret = *exp->_p-'0';\r
- int positions = 10;\r
- exp->_p++;\r
- while(isdigit(*exp->_p)) {\r
- ret = ret*10+(*exp->_p++-'0');\r
- if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant"));\r
- positions *= 10;\r
- };\r
- return ret;\r
-}\r
-\r
-static int sqstd_rex_element(SQRex *exp)\r
-{\r
- int ret;\r
- switch(*exp->_p)\r
- {\r
- case '(': {\r
- int expr;\r
- exp->_p++;\r
- \r
- \r
- if(*exp->_p =='?') {\r
- exp->_p++;\r
- sqstd_rex_expect(exp,':');\r
- expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR);\r
- }\r
- else\r
- expr = sqstd_rex_newnode(exp,OP_EXPR);\r
- exp->_nodes[expr].left = sqstd_rex_list(exp);\r
- ret = expr;\r
- sqstd_rex_expect(exp,')');\r
- }\r
- break;\r
- case '[':\r
- exp->_p++;\r
- ret = sqstd_rex_class(exp);\r
- sqstd_rex_expect(exp,']');\r
- break;\r
- case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break;\r
- case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break;\r
- default:\r
- ret = sqstd_rex_charnode(exp,SQFalse);\r
- break;\r
- }\r
- /* scope block */\r
- {\r
- int op;\r
- unsigned short p0 = 0, p1 = 0;\r
- switch(*exp->_p){\r
- case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; goto __end;\r
- case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; goto __end;\r
- case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; goto __end;\r
- case '{':{\r
- exp->_p++;\r
- if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected"));\r
- p0 = sqstd_rex_parsenumber(exp);\r
- switch(*exp->_p) {\r
- case '}':\r
- p1 = p0; exp->_p++;\r
- goto __end;\r
- case ',':\r
- exp->_p++;\r
- p1 = 0xFFFF;\r
- if(isdigit(*exp->_p)){\r
- p1 = sqstd_rex_parsenumber(exp);\r
- }\r
- sqstd_rex_expect(exp,'}');\r
- goto __end;\r
- default:\r
- sqstd_rex_error(exp,_SC(", or } expected"));\r
- }\r
- }\r
- __end: {\r
- int nnode = sqstd_rex_newnode(exp,OP_GREEDY);\r
- op = OP_GREEDY;\r
- exp->_nodes[nnode].left = ret;\r
- exp->_nodes[nnode].right = ((p0)<<16)|p1;\r
- ret = nnode;\r
- }\r
- }\r
- }\r
- if(*exp->_p != SQREX_SYMBOL_BRANCH && *exp->_p != ')' && *exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE && *exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE && *exp->_p != '\0')\r
- exp->_nodes[ret].next = sqstd_rex_element(exp);\r
- return ret;\r
-}\r
-\r
-static int sqstd_rex_list(SQRex *exp)\r
-{\r
- int ret=-1,e;\r
- if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) {\r
- exp->_p++;\r
- ret = sqstd_rex_newnode(exp,OP_BOL);\r
- }\r
- e = sqstd_rex_element(exp);\r
- if(ret != -1) {\r
- exp->_nodes[ret].next = e;\r
- }\r
- else ret = e;\r
-\r
- if(*exp->_p == SQREX_SYMBOL_BRANCH) {\r
- int temp;\r
- exp->_p++;\r
- temp = sqstd_rex_newnode(exp,OP_OR);\r
- exp->_nodes[temp].left = ret;\r
- exp->_nodes[temp].right = sqstd_rex_list(exp);\r
- ret = temp;\r
- }\r
- return ret;\r
-}\r
-\r
-static SQBool sqstd_rex_matchcclass(int cclass,SQChar c)\r
-{\r
- switch(cclass) {\r
- case 'a': return isalpha(c)?SQTrue:SQFalse;\r
- case 'A': return !isalpha(c)?SQTrue:SQFalse;\r
- case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse;\r
- case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse;\r
- case 's': return isspace(c)?SQTrue:SQFalse;\r
- case 'S': return !isspace(c)?SQTrue:SQFalse;\r
- case 'd': return isdigit(c)?SQTrue:SQFalse;\r
- case 'D': return !isdigit(c)?SQTrue:SQFalse;\r
- case 'x': return isxdigit(c)?SQTrue:SQFalse;\r
- case 'X': return !isxdigit(c)?SQTrue:SQFalse;\r
- case 'c': return iscntrl(c)?SQTrue:SQFalse;\r
- case 'C': return !iscntrl(c)?SQTrue:SQFalse;\r
- case 'p': return ispunct(c)?SQTrue:SQFalse;\r
- case 'P': return !ispunct(c)?SQTrue:SQFalse;\r
- case 'l': return islower(c)?SQTrue:SQFalse;\r
- case 'u': return isupper(c)?SQTrue:SQFalse;\r
- }\r
- return SQFalse; /*cannot happen*/\r
-}\r
-\r
-static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c)\r
-{\r
- do {\r
- switch(node->type) {\r
- case OP_RANGE:\r
- if(c >= node->left && c <= node->right) return SQTrue;\r
- break;\r
- case OP_CCLASS:\r
- if(sqstd_rex_matchcclass(node->left,c)) return SQTrue;\r
- break;\r
- default:\r
- if(c == node->type)return SQTrue;\r
- }\r
- } while((node->next != -1) && (node = &exp->_nodes[node->next]));\r
- return SQFalse;\r
-}\r
-\r
-static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str)\r
-{\r
- SQRexNodeType type = node->type;\r
- switch(type) {\r
- case OP_GREEDY: {\r
- int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;\r
- const SQChar *s=str, *good = str;\r
- while((nmaches == 0xFFFF || nmaches < p1) \r
- && (s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s))) {\r
- good=s;\r
- nmaches++;\r
- if(s >= exp->_eol)\r
- break;\r
- }\r
- if(p0 == p1 && p0 == nmaches) return good;\r
- else if(nmaches >= p0 && p1 == 0xFFFF) return good;\r
- else if(nmaches >= p0 && nmaches <= p1) return good;\r
- return NULL;\r
- }\r
- case OP_OR: {\r
- const SQChar *asd = str;\r
- SQRexNode *temp=&exp->_nodes[node->left];\r
- while(asd = sqstd_rex_matchnode(exp,temp,asd)) {\r
- if(temp->next != -1)\r
- temp = &exp->_nodes[temp->next];\r
- else\r
- return asd;\r
- }\r
- asd = str;\r
- temp = &exp->_nodes[node->right];\r
- while(asd = sqstd_rex_matchnode(exp,temp,asd)) {\r
- if(temp->next != -1)\r
- temp = &exp->_nodes[temp->next];\r
- else\r
- return asd;\r
- }\r
- return NULL;\r
- break;\r
- }\r
- case OP_EXPR:\r
- case OP_NOCAPEXPR:{\r
- SQRexNode *n = &exp->_nodes[node->left];\r
- const SQChar *cur = str;\r
- int capture = -1;\r
- if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {\r
- capture = exp->_currsubexp;\r
- exp->_matches[capture].begin = cur;\r
- exp->_currsubexp++;\r
- }\r
-\r
- do {\r
- if(!(cur = sqstd_rex_matchnode(exp,n,cur))) {\r
- if(capture != -1){\r
- exp->_matches[capture].begin = 0;\r
- exp->_matches[capture].len = 0;\r
- }\r
- return NULL;\r
- }\r
- } while((n->next != -1) && (n = &exp->_nodes[n->next]));\r
-\r
- if(capture != -1) \r
- exp->_matches[capture].len = cur - exp->_matches[capture].begin;\r
- return cur;\r
- } \r
- case OP_WB:\r
- if(str == exp->_bol && !isspace(*str)\r
- || (str == exp->_eol && !isspace(*(str-1)))\r
- || (!isspace(*str) && isspace(*(str+1)))\r
- || (isspace(*str) && !isspace(*(str+1))) ) {\r
- return (node->left == 'b')?str:NULL;\r
- }\r
- return (node->left == 'b')?NULL:str;\r
- case OP_BOL:\r
- if(str == exp->_bol) return str;\r
- return NULL;\r
- case OP_EOL:\r
- if(str == exp->_eol) return str;\r
- return NULL;\r
- case OP_DOT:\r
- *str++;\r
- return str;\r
- case OP_NCLASS:\r
- case OP_CLASS:\r
- if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) {\r
- *str++;\r
- return str;\r
- }\r
- return NULL;\r
- case OP_CCLASS:\r
- if(sqstd_rex_matchcclass(node->left,*str)) {\r
- *str++;\r
- return str;\r
- }\r
- return NULL;\r
- default: /* char */\r
- if(*str != node->type) return NULL;\r
- *str++;\r
- return str;\r
- }\r
- return NULL;\r
-}\r
-\r
-/* public api */\r
-SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error)\r
-{\r
- SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex));\r
- exp->_p = pattern;\r
- exp->_nallocated = (int)scstrlen(pattern) * sizeof(SQChar);\r
- exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode));\r
- exp->_nsize = 0;\r
- exp->_matches = 0;\r
- exp->_nsubexpr = 0;\r
- exp->_first = sqstd_rex_newnode(exp,OP_EXPR);\r
- exp->_error = error;\r
- exp->_jmpbuf = sq_malloc(sizeof(jmp_buf));\r
- if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {\r
- exp->_nodes[exp->_first].left=sqstd_rex_list(exp);\r
- if(*exp->_p!='\0')\r
- sqstd_rex_error(exp,_SC("unexpected character"));\r
-#ifdef _DEBUG\r
- {\r
- int nsize,i;\r
- SQRexNode *t;\r
- nsize = exp->_nsize;\r
- t = &exp->_nodes[0];\r
- scprintf(_SC("\n"));\r
- for(i = 0;i < nsize; i++) {\r
- if(exp->_nodes[i].type>MAX_CHAR)\r
- scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);\r
- else\r
- scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type);\r
- scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next);\r
- }\r
- scprintf(_SC("\n"));\r
- }\r
-#endif\r
- exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch));\r
- memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch));\r
- }\r
- else{\r
- sqstd_rex_free(exp);\r
- return NULL;\r
- }\r
- return exp;\r
-}\r
-\r
-void sqstd_rex_free(SQRex *exp)\r
-{\r
- if(exp) {\r
- if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode));\r
- if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf));\r
- if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch));\r
- sq_free(exp,sizeof(SQRex));\r
- }\r
-}\r
-\r
-SQBool sqstd_rex_match(SQRex* exp,const SQChar* text)\r
-{\r
- const SQChar* res = NULL;\r
- exp->_bol = text;\r
- exp->_eol = text + scstrlen(text);\r
- exp->_currsubexp = 0;\r
- res = sqstd_rex_matchnode(exp,exp->_nodes,text);\r
- if(res == NULL || res != exp->_eol)\r
- return SQFalse;\r
- return SQTrue;\r
-}\r
-\r
-SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end)\r
-{\r
- const SQChar *cur = NULL;\r
- int node = exp->_first;\r
- if(text_begin >= text_end) return SQFalse;\r
- exp->_bol = text_begin;\r
- exp->_eol = text_end;\r
- do {\r
- cur = text_begin;\r
- while(node != -1) {\r
- exp->_currsubexp = 0;\r
- cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur);\r
- if(!cur)\r
- break;\r
- node = exp->_nodes[node].next;\r
- }\r
- *text_begin++;\r
- } while(cur == NULL && text_begin != text_end);\r
-\r
- if(cur == NULL)\r
- return SQFalse;\r
-\r
- --text_begin;\r
-\r
- if(out_begin) *out_begin = text_begin;\r
- if(out_end) *out_end = cur;\r
- return SQTrue;\r
-}\r
-\r
-SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end)\r
-{\r
- return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end);\r
-}\r
-\r
-int sqstd_rex_getsubexpcount(SQRex* exp)\r
-{\r
- return exp->_nsubexpr;\r
-}\r
-\r
-SQBool sqstd_rex_getsubexp(SQRex* exp, int n, SQRexMatch *subexp)\r
-{\r
- if( n<0 || n >= exp->_nsubexpr) return SQFalse;\r
- *subexp = exp->_matches[n];\r
- return SQTrue;\r
-}\r
-\r
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <string.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include "sqstdstring.h"
+
+#ifdef _DEBUG
+#include <stdio.h>
+
+static const SQChar *g_nnames[] =
+{
+ _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"),
+ _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"),
+ _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),
+ _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB")
+};
+
+#endif
+
+#define OP_GREEDY MAX_CHAR+1 // * + ? {n}
+#define OP_OR MAX_CHAR+2
+#define OP_EXPR MAX_CHAR+3 //parentesis ()
+#define OP_NOCAPEXPR MAX_CHAR+4 //parentesis (?:)
+#define OP_DOT MAX_CHAR+5
+#define OP_CLASS MAX_CHAR+6
+#define OP_CCLASS MAX_CHAR+7
+#define OP_NCLASS MAX_CHAR+8 //negates class the [^
+#define OP_RANGE MAX_CHAR+9
+#define OP_CHAR MAX_CHAR+10
+#define OP_EOL MAX_CHAR+11
+#define OP_BOL MAX_CHAR+12
+#define OP_WB MAX_CHAR+13
+
+#define SQREX_SYMBOL_ANY_CHAR '.'
+#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE '+'
+#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE '*'
+#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE '?'
+#define SQREX_SYMBOL_BRANCH '|'
+#define SQREX_SYMBOL_END_OF_STRING '$'
+#define SQREX_SYMBOL_BEGINNING_OF_STRING '^'
+#define SQREX_SYMBOL_ESCAPE_CHAR '\\'
+
+
+typedef int SQRexNodeType;
+
+typedef struct tagSQRexNode{
+ SQRexNodeType type;
+ long left;
+ long right;
+ int next;
+}SQRexNode;
+
+struct SQRex{
+ const SQChar *_eol;
+ const SQChar *_bol;
+ const SQChar *_p;
+ int _first;
+ int _op;
+ SQRexNode *_nodes;
+ int _nallocated;
+ int _nsize;
+ int _nsubexpr;
+ SQRexMatch *_matches;
+ int _currsubexp;
+ void *_jmpbuf;
+ const SQChar **_error;
+};
+
+static int sqstd_rex_list(SQRex *exp);
+
+static int sqstd_rex_newnode(SQRex *exp, SQRexNodeType type)
+{
+ SQRexNode n;
+ n.type = type;
+ n.next = n.right = n.left = -1;
+ if(type == OP_EXPR)
+ n.right = exp->_nsubexpr++;
+ if(exp->_nallocated < (exp->_nsize + 1)) {
+ int oldsize = exp->_nallocated;
+ exp->_nallocated *= 2;
+ exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode));
+ }
+ exp->_nodes[exp->_nsize++] = n;
+ return (int)exp->_nsize - 1;
+}
+
+static void sqstd_rex_error(SQRex *exp,const SQChar *error)
+{
+ if(exp->_error) *exp->_error = error;
+ longjmp(*((jmp_buf*)exp->_jmpbuf),-1);
+}
+
+static void sqstd_rex_expect(SQRex *exp, int n){
+ if((*exp->_p) != n)
+ sqstd_rex_error(exp, _SC("expected paren"));
+ exp->_p++;
+}
+
+static SQBool sqstd_rex_ischar(SQChar c)
+{
+ switch(c) {
+ case SQREX_SYMBOL_BRANCH:case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE:
+ case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE:case SQREX_SYMBOL_GREEDY_ONE_OR_MORE:
+ case SQREX_SYMBOL_BEGINNING_OF_STRING:case SQREX_SYMBOL_END_OF_STRING:
+ case SQREX_SYMBOL_ANY_CHAR:case SQREX_SYMBOL_ESCAPE_CHAR:case '(':case ')':case '[':case '{': case '}':
+ return SQFalse;
+ }
+ return SQTrue;
+}
+
+static SQChar sqstd_rex_escapechar(SQRex *exp)
+{
+ if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){
+ exp->_p++;
+ switch(*exp->_p) {
+ case 'v': exp->_p++; return '\v';
+ case 'n': exp->_p++; return '\n';
+ case 't': exp->_p++; return '\t';
+ case 'r': exp->_p++; return '\r';
+ case 'f': exp->_p++; return '\f';
+ default: return (*exp->_p++);
+ }
+ } else if(!sqstd_rex_ischar(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected"));
+ return (*exp->_p++);
+}
+
+static int sqstd_rex_charclass(SQRex *exp,int classid)
+{
+ int n = sqstd_rex_newnode(exp,OP_CCLASS);
+ exp->_nodes[n].left = classid;
+ return n;
+}
+
+static int sqstd_rex_charnode(SQRex *exp,SQBool isclass)
+{
+ if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) {
+ exp->_p++;
+ switch(*exp->_p) {
+ case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n');
+ case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t');
+ case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r');
+ case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f');
+ case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v');
+ case 'a': case 'A': case 'w': case 'W': case 's': case 'S':
+ case 'd': case 'D': case 'x': case 'X': case 'c': case 'C':
+ case 'p': case 'P': case 'l': case 'u':
+ {
+ SQChar t = *exp->_p;
+ exp->_p++;
+ return sqstd_rex_charclass(exp,t);
+ }
+ case 'b':
+ case 'B':
+ if(!isclass) {
+ int node = sqstd_rex_newnode(exp,OP_WB);
+ exp->_nodes[node].left = *exp->_p;
+ exp->_p++;
+ return node;
+ } //else default
+ default: return sqstd_rex_newnode(exp,(*exp->_p++));
+ }
+ }
+ else if(!sqstd_rex_ischar(*exp->_p)) {
+
+ sqstd_rex_error(exp,_SC("letter expected"));
+ }
+ return sqstd_rex_newnode(exp,*exp->_p++);
+}
+static int sqstd_rex_class(SQRex *exp)
+{
+ int ret = -1;
+ int first = -1,chain;
+ if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){
+ ret = sqstd_rex_newnode(exp,OP_NCLASS);
+ exp->_p++;
+ }else ret = sqstd_rex_newnode(exp,OP_CLASS);
+
+ if(*exp->_p == ']' || *exp->_p == '-'){
+ first = *exp->_p;
+ exp->_p++;
+ }
+ chain = ret;
+ while(*exp->_p != ']' && exp->_p != exp->_eol) {
+ if(*exp->_p == '-' && first != -1){
+ int r;
+ if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range"));
+ r = sqstd_rex_newnode(exp,OP_RANGE);
+ if(first>*exp->_p) sqstd_rex_error(exp,_SC("invalid range"));
+ if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges"));
+ exp->_nodes[r].left = exp->_nodes[first].type;
+ exp->_nodes[r].right = sqstd_rex_escapechar(exp);
+ exp->_nodes[chain].next = r;
+ chain = r;
+ first = -1;
+ }
+ else{
+ if(first!=-1){
+ int c = first;
+ exp->_nodes[chain].next = c;
+ chain = c;
+ first = sqstd_rex_charnode(exp,SQTrue);
+ }
+ else{
+ first = sqstd_rex_charnode(exp,SQTrue);
+ }
+ }
+ }
+ if(first!=-1){
+ int c = first;
+ exp->_nodes[chain].next = c;
+ chain = c;
+ first = -1;
+ }
+ /* hack? */
+ exp->_nodes[ret].left = exp->_nodes[ret].next;
+ exp->_nodes[ret].next = -1;
+ return ret;
+}
+
+static int sqstd_rex_parsenumber(SQRex *exp)
+{
+ int ret = *exp->_p-'0';
+ int positions = 10;
+ exp->_p++;
+ while(isdigit(*exp->_p)) {
+ ret = ret*10+(*exp->_p++-'0');
+ if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant"));
+ positions *= 10;
+ };
+ return ret;
+}
+
+static int sqstd_rex_element(SQRex *exp)
+{
+ int ret;
+ switch(*exp->_p)
+ {
+ case '(': {
+ int expr;
+ exp->_p++;
+
+
+ if(*exp->_p =='?') {
+ exp->_p++;
+ sqstd_rex_expect(exp,':');
+ expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR);
+ }
+ else
+ expr = sqstd_rex_newnode(exp,OP_EXPR);
+ exp->_nodes[expr].left = sqstd_rex_list(exp);
+ ret = expr;
+ sqstd_rex_expect(exp,')');
+ }
+ break;
+ case '[':
+ exp->_p++;
+ ret = sqstd_rex_class(exp);
+ sqstd_rex_expect(exp,']');
+ break;
+ case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break;
+ case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break;
+ default:
+ ret = sqstd_rex_charnode(exp,SQFalse);
+ break;
+ }
+ /* scope block */
+ {
+ int op;
+ unsigned short p0 = 0, p1 = 0;
+ switch(*exp->_p){
+ case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; goto __end;
+ case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; goto __end;
+ case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; goto __end;
+ case '{':{
+ exp->_p++;
+ if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected"));
+ p0 = sqstd_rex_parsenumber(exp);
+ switch(*exp->_p) {
+ case '}':
+ p1 = p0; exp->_p++;
+ goto __end;
+ case ',':
+ exp->_p++;
+ p1 = 0xFFFF;
+ if(isdigit(*exp->_p)){
+ p1 = sqstd_rex_parsenumber(exp);
+ }
+ sqstd_rex_expect(exp,'}');
+ goto __end;
+ default:
+ sqstd_rex_error(exp,_SC(", or } expected"));
+ }
+ }
+ __end: {
+ int nnode = sqstd_rex_newnode(exp,OP_GREEDY);
+ op = OP_GREEDY;
+ exp->_nodes[nnode].left = ret;
+ exp->_nodes[nnode].right = ((p0)<<16)|p1;
+ ret = nnode;
+ }
+ }
+ }
+ if(*exp->_p != SQREX_SYMBOL_BRANCH && *exp->_p != ')' && *exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE && *exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE && *exp->_p != '\0')
+ exp->_nodes[ret].next = sqstd_rex_element(exp);
+ return ret;
+}
+
+static int sqstd_rex_list(SQRex *exp)
+{
+ int ret=-1,e;
+ if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) {
+ exp->_p++;
+ ret = sqstd_rex_newnode(exp,OP_BOL);
+ }
+ e = sqstd_rex_element(exp);
+ if(ret != -1) {
+ exp->_nodes[ret].next = e;
+ }
+ else ret = e;
+
+ if(*exp->_p == SQREX_SYMBOL_BRANCH) {
+ int temp;
+ exp->_p++;
+ temp = sqstd_rex_newnode(exp,OP_OR);
+ exp->_nodes[temp].left = ret;
+ exp->_nodes[temp].right = sqstd_rex_list(exp);
+ ret = temp;
+ }
+ return ret;
+}
+
+static SQBool sqstd_rex_matchcclass(int cclass,SQChar c)
+{
+ switch(cclass) {
+ case 'a': return isalpha(c)?SQTrue:SQFalse;
+ case 'A': return !isalpha(c)?SQTrue:SQFalse;
+ case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse;
+ case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse;
+ case 's': return isspace(c)?SQTrue:SQFalse;
+ case 'S': return !isspace(c)?SQTrue:SQFalse;
+ case 'd': return isdigit(c)?SQTrue:SQFalse;
+ case 'D': return !isdigit(c)?SQTrue:SQFalse;
+ case 'x': return isxdigit(c)?SQTrue:SQFalse;
+ case 'X': return !isxdigit(c)?SQTrue:SQFalse;
+ case 'c': return iscntrl(c)?SQTrue:SQFalse;
+ case 'C': return !iscntrl(c)?SQTrue:SQFalse;
+ case 'p': return ispunct(c)?SQTrue:SQFalse;
+ case 'P': return !ispunct(c)?SQTrue:SQFalse;
+ case 'l': return islower(c)?SQTrue:SQFalse;
+ case 'u': return isupper(c)?SQTrue:SQFalse;
+ }
+ return SQFalse; /*cannot happen*/
+}
+
+static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c)
+{
+ do {
+ switch(node->type) {
+ case OP_RANGE:
+ if(c >= node->left && c <= node->right) return SQTrue;
+ break;
+ case OP_CCLASS:
+ if(sqstd_rex_matchcclass(node->left,c)) return SQTrue;
+ break;
+ default:
+ if(c == node->type)return SQTrue;
+ }
+ } while((node->next != -1) && (node = &exp->_nodes[node->next]));
+ return SQFalse;
+}
+
+static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str)
+{
+ SQRexNodeType type = node->type;
+ switch(type) {
+ case OP_GREEDY: {
+ int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
+ const SQChar *s=str, *good = str;
+ while((nmaches == 0xFFFF || nmaches < p1)
+ && (s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s))) {
+ good=s;
+ nmaches++;
+ if(s >= exp->_eol)
+ break;
+ }
+ if(p0 == p1 && p0 == nmaches) return good;
+ else if(nmaches >= p0 && p1 == 0xFFFF) return good;
+ else if(nmaches >= p0 && nmaches <= p1) return good;
+ return NULL;
+ }
+ case OP_OR: {
+ const SQChar *asd = str;
+ SQRexNode *temp=&exp->_nodes[node->left];
+ while(asd = sqstd_rex_matchnode(exp,temp,asd)) {
+ if(temp->next != -1)
+ temp = &exp->_nodes[temp->next];
+ else
+ return asd;
+ }
+ asd = str;
+ temp = &exp->_nodes[node->right];
+ while(asd = sqstd_rex_matchnode(exp,temp,asd)) {
+ if(temp->next != -1)
+ temp = &exp->_nodes[temp->next];
+ else
+ return asd;
+ }
+ return NULL;
+ break;
+ }
+ case OP_EXPR:
+ case OP_NOCAPEXPR:{
+ SQRexNode *n = &exp->_nodes[node->left];
+ const SQChar *cur = str;
+ int capture = -1;
+ if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
+ capture = exp->_currsubexp;
+ exp->_matches[capture].begin = cur;
+ exp->_currsubexp++;
+ }
+
+ do {
+ if(!(cur = sqstd_rex_matchnode(exp,n,cur))) {
+ if(capture != -1){
+ exp->_matches[capture].begin = 0;
+ exp->_matches[capture].len = 0;
+ }
+ return NULL;
+ }
+ } while((n->next != -1) && (n = &exp->_nodes[n->next]));
+
+ if(capture != -1)
+ exp->_matches[capture].len = cur - exp->_matches[capture].begin;
+ return cur;
+ }
+ case OP_WB:
+ if(str == exp->_bol && !isspace(*str)
+ || (str == exp->_eol && !isspace(*(str-1)))
+ || (!isspace(*str) && isspace(*(str+1)))
+ || (isspace(*str) && !isspace(*(str+1))) ) {
+ return (node->left == 'b')?str:NULL;
+ }
+ return (node->left == 'b')?NULL:str;
+ case OP_BOL:
+ if(str == exp->_bol) return str;
+ return NULL;
+ case OP_EOL:
+ if(str == exp->_eol) return str;
+ return NULL;
+ case OP_DOT:
+ *str++;
+ return str;
+ case OP_NCLASS:
+ case OP_CLASS:
+ if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) {
+ *str++;
+ return str;
+ }
+ return NULL;
+ case OP_CCLASS:
+ if(sqstd_rex_matchcclass(node->left,*str)) {
+ *str++;
+ return str;
+ }
+ return NULL;
+ default: /* char */
+ if(*str != node->type) return NULL;
+ *str++;
+ return str;
+ }
+ return NULL;
+}
+
+/* public api */
+SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error)
+{
+ SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex));
+ exp->_p = pattern;
+ exp->_nallocated = (int)scstrlen(pattern) * sizeof(SQChar);
+ exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode));
+ exp->_nsize = 0;
+ exp->_matches = 0;
+ exp->_nsubexpr = 0;
+ exp->_first = sqstd_rex_newnode(exp,OP_EXPR);
+ exp->_error = error;
+ exp->_jmpbuf = sq_malloc(sizeof(jmp_buf));
+ if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {
+ exp->_nodes[exp->_first].left=sqstd_rex_list(exp);
+ if(*exp->_p!='\0')
+ sqstd_rex_error(exp,_SC("unexpected character"));
+#ifdef _DEBUG
+ {
+ int nsize,i;
+ SQRexNode *t;
+ nsize = exp->_nsize;
+ t = &exp->_nodes[0];
+ scprintf(_SC("\n"));
+ for(i = 0;i < nsize; i++) {
+ if(exp->_nodes[i].type>MAX_CHAR)
+ scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);
+ else
+ scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type);
+ scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next);
+ }
+ scprintf(_SC("\n"));
+ }
+#endif
+ exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch));
+ memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch));
+ }
+ else{
+ sqstd_rex_free(exp);
+ return NULL;
+ }
+ return exp;
+}
+
+void sqstd_rex_free(SQRex *exp)
+{
+ if(exp) {
+ if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode));
+ if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf));
+ if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch));
+ sq_free(exp,sizeof(SQRex));
+ }
+}
+
+SQBool sqstd_rex_match(SQRex* exp,const SQChar* text)
+{
+ const SQChar* res = NULL;
+ exp->_bol = text;
+ exp->_eol = text + scstrlen(text);
+ exp->_currsubexp = 0;
+ res = sqstd_rex_matchnode(exp,exp->_nodes,text);
+ if(res == NULL || res != exp->_eol)
+ return SQFalse;
+ return SQTrue;
+}
+
+SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end)
+{
+ const SQChar *cur = NULL;
+ int node = exp->_first;
+ if(text_begin >= text_end) return SQFalse;
+ exp->_bol = text_begin;
+ exp->_eol = text_end;
+ do {
+ cur = text_begin;
+ while(node != -1) {
+ exp->_currsubexp = 0;
+ cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur);
+ if(!cur)
+ break;
+ node = exp->_nodes[node].next;
+ }
+ *text_begin++;
+ } while(cur == NULL && text_begin != text_end);
+
+ if(cur == NULL)
+ return SQFalse;
+
+ --text_begin;
+
+ if(out_begin) *out_begin = text_begin;
+ if(out_end) *out_end = cur;
+ return SQTrue;
+}
+
+SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end)
+{
+ return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end);
+}
+
+int sqstd_rex_getsubexpcount(SQRex* exp)
+{
+ return exp->_nsubexpr;
+}
+
+SQBool sqstd_rex_getsubexp(SQRex* exp, int n, SQRexMatch *subexp)
+{
+ if( n<0 || n >= exp->_nsubexpr) return SQFalse;
+ *subexp = exp->_matches[n];
+ return SQTrue;
+}
+
-/* see copyright notice in squirrel.h */\r
-#include <new>\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <squirrel.h>\r
-#include <sqstdio.h>\r
-#include <sqstdblob.h>\r
-#include "sqstdstream.h"\r
-#include "sqstdblobimpl.h"\r
-\r
-#define SETUP_STREAM(v) \\r
- SQStream *self = NULL; \\r
- if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,SQSTD_STREAM_TYPE_TAG))) \\r
- return sq_throwerror(v,_SC("invalid type tag")); \\r
- if(!self->IsValid()) \\r
- return sq_throwerror(v,_SC("the stream is invalid"));\r
-\r
-int _stream_readstr(HSQUIRRELVM v)\r
-{\r
- SETUP_STREAM(v);\r
- SQInteger type = _SC('a'), size = 0;\r
- sq_getinteger(v, 2, &size);\r
- if(size <= 0) return sq_throwerror(v,_SC("invalid size"));\r
- if(sq_gettop(v) > 2)\r
- sq_getinteger(v, 3, &type);\r
- SQChar *dest = NULL;\r
- switch(type) {\r
- case _SC('a'): {\r
- char *temp;\r
- if(self->Read(sq_getscratchpad(v, size+1), size) != size)\r
- return sq_throwerror(v, _SC("io failure"));\r
-#ifdef _UNICODE\r
- temp = (char*) sq_getscratchpad(v, size + (size * sizeof(SQChar)));\r
- dest = (SQChar*) &temp[size];\r
- size = (SQInteger)mbstowcs(dest, (const char*)temp, size);\r
-#else\r
- temp = (char *) sq_getscratchpad(v, -1);\r
- dest = temp;\r
-#endif\r
- }\r
- break;\r
- case _SC('u'): {\r
- wchar_t *temp;\r
- if(self->Read(sq_getscratchpad(v, (size + 1) * sizeof(wchar_t)),size * sizeof(wchar_t)) != (size * sizeof(wchar_t)))\r
- return sq_throwerror(v, _SC("io failure"));\r
- \r
-#ifdef _UNICODE\r
- temp = (wchar_t*) sq_getscratchpad(v, -1);\r
- dest = (SQChar*) temp;\r
-#else\r
- temp = (wchar_t*) sq_getscratchpad(v,(size * 3) + (size * sizeof(wchar_t)));\r
- dest = (char*) &temp[size];\r
- size = (SQInteger)wcstombs(dest, (const wchar_t*)temp, size);\r
-#endif\r
- }\r
- break;\r
- default:\r
- return sq_throwerror(v, _SC("invalid coding"));\r
- }\r
-\r
- sq_pushstring(v, dest, size);\r
- return 1;\r
-}\r
-\r
-int _stream_readblob(HSQUIRRELVM v)\r
-{\r
- SETUP_STREAM(v);\r
- SQUserPointer data,blobp;\r
- SQInteger size,res;\r
- sq_getinteger(v,2,&size);\r
- if(size > self->Len()) {\r
- size = self->Len();\r
- }\r
- data = sq_getscratchpad(v,size);\r
- res = self->Read(data,size);\r
- if(res <= 0)\r
- return sq_throwerror(v,_SC("no data left to read"));\r
- blobp = sqstd_createblob(v,res);\r
- memcpy(blobp,data,res);\r
- return 1;\r
-}\r
-\r
-#define SAFE_READN(ptr,len) { \\r
- if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \\r
- }\r
-int _stream_readn(HSQUIRRELVM v)\r
-{\r
- SETUP_STREAM(v);\r
- SQInteger format;\r
- sq_getinteger(v, 2, &format);\r
- switch(format) {\r
- case 'i': {\r
- int i;\r
- SAFE_READN(&i, sizeof(i));\r
- sq_pushinteger(v, i);\r
- }\r
- break;\r
- case 's': {\r
- short s;\r
- SAFE_READN(&s, sizeof(short));\r
- sq_pushinteger(v, s);\r
- }\r
- break;\r
- case 'w': {\r
- unsigned short w;\r
- SAFE_READN(&w, sizeof(unsigned short));\r
- sq_pushinteger(v, w);\r
- }\r
- break;\r
- case 'c': {\r
- char c;\r
- SAFE_READN(&c, sizeof(char));\r
- sq_pushinteger(v, c);\r
- }\r
- break;\r
- case 'b': {\r
- unsigned char c;\r
- SAFE_READN(&c, sizeof(unsigned char));\r
- sq_pushinteger(v, c);\r
- }\r
- break;\r
- case 'f': {\r
- float f;\r
- SAFE_READN(&f, sizeof(float));\r
- sq_pushfloat(v, f);\r
- }\r
- break;\r
- case 'd': {\r
- double d;\r
- SAFE_READN(&d, sizeof(double));\r
- sq_pushfloat(v, (SQFloat)d);\r
- }\r
- break;\r
- default:\r
- return sq_throwerror(v, _SC("invalid format"));\r
- }\r
- return 1;\r
-}\r
-\r
-int _stream_writestr(HSQUIRRELVM v)\r
-{\r
- SETUP_STREAM(v);\r
- const SQChar *str,*res;\r
- SQInteger trgformat = 'a',len = 0;\r
- sq_getstring(v,2,&str);\r
- len = sq_getsize(v,2);\r
- if(sq_gettop(v)>2)\r
- sq_getinteger(v,3,&trgformat);\r
- switch(trgformat)\r
- {\r
- case 'a':\r
-#ifdef _UNICODE\r
- res = sq_getscratchpad(v,len*3);\r
- len = (SQInteger) wcstombs((char *)res, (const wchar_t*)str, len);\r
-#else\r
- res = str;\r
-#endif\r
- self->Write((void *)res,len);\r
- break;\r
- case 'u':\r
-#ifdef _UNICODE\r
- res = str;\r
-#else\r
- res = sq_getscratchpad(v,len*sizeof(wchar_t));\r
- len = (SQInteger) mbstowcs((wchar_t*)res, str, len);\r
-#endif\r
- self->Write((void *)res,len*sizeof(wchar_t));\r
- break;\r
- default:\r
- return sq_throwerror(v,_SC("wrong encoding"));\r
- }\r
- \r
- return 0;\r
-}\r
-\r
-int _stream_writeblob(HSQUIRRELVM v)\r
-{\r
- SQUserPointer data;\r
- int size;\r
- SETUP_STREAM(v);\r
- if(SQ_FAILED(sqstd_getblob(v,2,&data)))\r
- return sq_throwerror(v,_SC("invalid parameter"));\r
- size = sqstd_getblobsize(v,2);\r
- if(self->Write(data,size) != size)\r
- return sq_throwerror(v,_SC("io error"));\r
- sq_pushinteger(v,size);\r
- return 1;\r
-}\r
-\r
-int _stream_writen(HSQUIRRELVM v)\r
-{\r
- SETUP_STREAM(v);\r
- SQInteger format, ti;\r
- SQFloat tf;\r
- sq_getinteger(v, 3, &format);\r
- switch(format) {\r
- case 'i': {\r
- int i;\r
- sq_getinteger(v, 2, &ti);\r
- i = ti;\r
- self->Write(&i, sizeof(int));\r
- }\r
- break;\r
- case 's': {\r
- short s;\r
- sq_getinteger(v, 2, &ti);\r
- s = ti;\r
- self->Write(&s, sizeof(short));\r
- }\r
- break;\r
- case 'w': {\r
- unsigned short w;\r
- sq_getinteger(v, 2, &ti);\r
- w = ti;\r
- self->Write(&w, sizeof(unsigned short));\r
- }\r
- break;\r
- case 'c': {\r
- char c;\r
- sq_getinteger(v, 2, &ti);\r
- c = ti;\r
- self->Write(&c, sizeof(char));\r
- }\r
- break;\r
- case 'b': {\r
- unsigned char b;\r
- sq_getinteger(v, 2, &ti);\r
- b = ti;\r
- self->Write(&b, sizeof(unsigned char));\r
- }\r
- break;\r
- case 'f': {\r
- float f;\r
- sq_getfloat(v, 2, &tf);\r
- f = tf;\r
- self->Write(&f, sizeof(float));\r
- }\r
- break;\r
- case 'd': {\r
- double d;\r
- sq_getfloat(v, 2, &tf);\r
- d = tf;\r
- self->Write(&d, sizeof(double));\r
- }\r
- break;\r
- default:\r
- return sq_throwerror(v, _SC("invalid format"));\r
- }\r
- return 0;\r
-}\r
-\r
-int _stream_seek(HSQUIRRELVM v)\r
-{\r
- SETUP_STREAM(v);\r
- SQInteger offset, origin = SQ_SEEK_SET;\r
- sq_getinteger(v, 2, &offset);\r
- if(sq_gettop(v) > 2) {\r
- SQInteger t;\r
- sq_getinteger(v, 3, &t);\r
- switch(t) {\r
- case 'b': origin = SQ_SEEK_SET; break;\r
- case 'c': origin = SQ_SEEK_CUR; break;\r
- case 'e': origin = SQ_SEEK_END; break;\r
- default: return sq_throwerror(v,_SC("invalid origin"));\r
- }\r
- }\r
- sq_pushinteger(v, self->Seek(offset, origin));\r
- return 1;\r
-}\r
-\r
-int _stream_tell(HSQUIRRELVM v)\r
-{\r
- SETUP_STREAM(v);\r
- sq_pushinteger(v, self->Tell());\r
- return 1;\r
-}\r
-\r
-int _stream_len(HSQUIRRELVM v)\r
-{\r
- SETUP_STREAM(v);\r
- sq_pushinteger(v, self->Len());\r
- return 1;\r
-}\r
-\r
-int _stream_flush(HSQUIRRELVM v)\r
-{\r
- SETUP_STREAM(v);\r
- if(!self->Flush())\r
- sq_pushinteger(v, 1);\r
- else\r
- sq_pushnull(v);\r
- return 1;\r
-}\r
-\r
-int _stream_eos(HSQUIRRELVM v)\r
-{\r
- SETUP_STREAM(v);\r
- if(self->EOS())\r
- sq_pushinteger(v, 1);\r
- else\r
- sq_pushnull(v);\r
- return 1;\r
-}\r
-\r
-static SQRegFunction _stream_methods[] = {\r
- _DECL_STREAM_FUNC(readstr,-2,_SC("xnn")),\r
- _DECL_STREAM_FUNC(readblob,2,_SC("xn")),\r
- _DECL_STREAM_FUNC(readn,2,_SC("xn")),\r
- _DECL_STREAM_FUNC(writestr,-2,_SC("xsn")),\r
- _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),\r
- _DECL_STREAM_FUNC(writen,3,_SC("xnn")),\r
- _DECL_STREAM_FUNC(seek,-2,_SC("xnn")),\r
- _DECL_STREAM_FUNC(tell,1,_SC("x")),\r
- _DECL_STREAM_FUNC(len,1,_SC("x")),\r
- _DECL_STREAM_FUNC(eos,1,_SC("x")),\r
- _DECL_STREAM_FUNC(flush,1,_SC("x")),\r
- {0,0}\r
-};\r
-\r
-void init_streamclass(HSQUIRRELVM v)\r
-{\r
- sq_pushregistrytable(v);\r
- sq_pushstring(v,_SC("std_stream"),-1);\r
- if(SQ_FAILED(sq_get(v,-2))) {\r
- sq_pushstring(v,_SC("std_stream"),-1);\r
- sq_newclass(v,SQFalse);\r
- sq_settypetag(v,-1,SQSTD_STREAM_TYPE_TAG);\r
- int i = 0;\r
- while(_stream_methods[i].name != 0) {\r
- SQRegFunction &f = _stream_methods[i];\r
- sq_pushstring(v,f.name,-1);\r
- sq_newclosure(v,f.f,0);\r
- sq_setparamscheck(v,f.nparamscheck,f.typemask);\r
- sq_createslot(v,-3);\r
- i++;\r
- }\r
- sq_createslot(v,-3);\r
- }\r
- else {\r
- sq_pop(v,1); //result\r
- }\r
- sq_pop(v,1);\r
-}\r
-\r
-SQRESULT declare_stream(HSQUIRRELVM v,SQChar* name,int typetag,SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals)\r
-{\r
- if(sq_gettype(v,-1) != OT_TABLE)\r
- return sq_throwerror(v,_SC("table expected"));\r
- int top = sq_gettop(v);\r
- //create delegate\r
- init_streamclass(v);\r
- sq_pushregistrytable(v);\r
- sq_pushstring(v,reg_name,-1);\r
- sq_pushstring(v,_SC("std_stream"),-1);\r
- if(SQ_SUCCEEDED(sq_get(v,-3))) {\r
- sq_newclass(v,SQTrue);\r
- sq_settypetag(v,-1,typetag);\r
- int i = 0;\r
- while(methods[i].name != 0) {\r
- SQRegFunction &f = methods[i];\r
- sq_pushstring(v,f.name,-1);\r
- sq_newclosure(v,f.f,0);\r
- sq_setparamscheck(v,f.nparamscheck,f.typemask);\r
- sq_setnativeclosurename(v,-1,f.name);\r
- sq_createslot(v,-3);\r
- i++;\r
- }\r
- sq_createslot(v,-3);\r
- sq_pop(v,1);\r
- \r
- i = 0;\r
- while(globals[i].name!=0)\r
- {\r
- SQRegFunction &f = globals[i];\r
- sq_pushstring(v,f.name,-1);\r
- sq_newclosure(v,f.f,0);\r
- sq_setparamscheck(v,f.nparamscheck,f.typemask);\r
- sq_setnativeclosurename(v,-1,f.name);\r
- sq_createslot(v,-3);\r
- i++;\r
- }\r
- //register the class in the target table\r
- sq_pushstring(v,name,-1);\r
- sq_pushregistrytable(v);\r
- sq_pushstring(v,reg_name,-1);\r
- sq_get(v,-2);\r
- sq_remove(v,-2);\r
- sq_createslot(v,-3);\r
-\r
- sq_settop(v,top);\r
- return SQ_OK;\r
- }\r
- sq_settop(v,top);\r
- return SQ_ERROR;\r
-}\r
+/* see copyright notice in squirrel.h */
+#include <new>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <squirrel.h>
+#include <sqstdio.h>
+#include <sqstdblob.h>
+#include "sqstdstream.h"
+#include "sqstdblobimpl.h"
+
+#define SETUP_STREAM(v) \
+ SQStream *self = NULL; \
+ if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,SQSTD_STREAM_TYPE_TAG))) \
+ return sq_throwerror(v,_SC("invalid type tag")); \
+ if(!self->IsValid()) \
+ return sq_throwerror(v,_SC("the stream is invalid"));
+
+int _stream_readstr(HSQUIRRELVM v)
+{
+ SETUP_STREAM(v);
+ SQInteger type = _SC('a'), size = 0;
+ sq_getinteger(v, 2, &size);
+ if(size <= 0) return sq_throwerror(v,_SC("invalid size"));
+ if(sq_gettop(v) > 2)
+ sq_getinteger(v, 3, &type);
+ SQChar *dest = NULL;
+ switch(type) {
+ case _SC('a'): {
+ char *temp;
+ if(self->Read(sq_getscratchpad(v, size+1), size) != size)
+ return sq_throwerror(v, _SC("io failure"));
+#ifdef _UNICODE
+ temp = (char*) sq_getscratchpad(v, size + (size * sizeof(SQChar)));
+ dest = (SQChar*) &temp[size];
+ size = (SQInteger)mbstowcs(dest, (const char*)temp, size);
+#else
+ temp = (char *) sq_getscratchpad(v, -1);
+ dest = temp;
+#endif
+ }
+ break;
+ case _SC('u'): {
+ wchar_t *temp;
+ if(self->Read(sq_getscratchpad(v, (size + 1) * sizeof(wchar_t)), size * sizeof(wchar_t)) != (int) (size * sizeof(wchar_t)))
+ return sq_throwerror(v, _SC("io failure"));
+
+#ifdef _UNICODE
+ temp = (wchar_t*) sq_getscratchpad(v, -1);
+ dest = (SQChar*) temp;
+#else
+ temp = (wchar_t*) sq_getscratchpad(v,(size * 3) + (size * sizeof(wchar_t)));
+ dest = (char*) &temp[size];
+ size = (SQInteger)wcstombs(dest, (const wchar_t*)temp, size);
+#endif
+ }
+ break;
+ default:
+ return sq_throwerror(v, _SC("invalid coding"));
+ }
+
+ sq_pushstring(v, dest, size);
+ return 1;
+}
+
+int _stream_readblob(HSQUIRRELVM v)
+{
+ SETUP_STREAM(v);
+ SQUserPointer data,blobp;
+ SQInteger size,res;
+ sq_getinteger(v,2,&size);
+ if(size > self->Len()) {
+ size = self->Len();
+ }
+ data = sq_getscratchpad(v,size);
+ res = self->Read(data,size);
+ if(res <= 0)
+ return sq_throwerror(v,_SC("no data left to read"));
+ blobp = sqstd_createblob(v,res);
+ memcpy(blobp,data,res);
+ return 1;
+}
+
+#define SAFE_READN(ptr,len) { \
+ if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \
+ }
+int _stream_readn(HSQUIRRELVM v)
+{
+ SETUP_STREAM(v);
+ SQInteger format;
+ sq_getinteger(v, 2, &format);
+ switch(format) {
+ case 'i': {
+ int i;
+ SAFE_READN(&i, sizeof(i));
+ sq_pushinteger(v, i);
+ }
+ break;
+ case 's': {
+ short s;
+ SAFE_READN(&s, sizeof(short));
+ sq_pushinteger(v, s);
+ }
+ break;
+ case 'w': {
+ unsigned short w;
+ SAFE_READN(&w, sizeof(unsigned short));
+ sq_pushinteger(v, w);
+ }
+ break;
+ case 'c': {
+ char c;
+ SAFE_READN(&c, sizeof(char));
+ sq_pushinteger(v, c);
+ }
+ break;
+ case 'b': {
+ unsigned char c;
+ SAFE_READN(&c, sizeof(unsigned char));
+ sq_pushinteger(v, c);
+ }
+ break;
+ case 'f': {
+ float f;
+ SAFE_READN(&f, sizeof(float));
+ sq_pushfloat(v, f);
+ }
+ break;
+ case 'd': {
+ double d;
+ SAFE_READN(&d, sizeof(double));
+ sq_pushfloat(v, (SQFloat)d);
+ }
+ break;
+ default:
+ return sq_throwerror(v, _SC("invalid format"));
+ }
+ return 1;
+}
+
+int _stream_writestr(HSQUIRRELVM v)
+{
+ SETUP_STREAM(v);
+ const SQChar *str,*res;
+ SQInteger trgformat = 'a',len = 0;
+ sq_getstring(v,2,&str);
+ len = sq_getsize(v,2);
+ if(sq_gettop(v)>2)
+ sq_getinteger(v,3,&trgformat);
+ switch(trgformat)
+ {
+ case 'a':
+#ifdef _UNICODE
+ res = sq_getscratchpad(v,len*3);
+ len = (SQInteger) wcstombs((char *)res, (const wchar_t*)str, len);
+#else
+ res = str;
+#endif
+ self->Write((void *)res,len);
+ break;
+ case 'u':
+#ifdef _UNICODE
+ res = str;
+#else
+ res = sq_getscratchpad(v,len*sizeof(wchar_t));
+ len = (SQInteger) mbstowcs((wchar_t*)res, str, len);
+#endif
+ self->Write((void *)res,len*sizeof(wchar_t));
+ break;
+ default:
+ return sq_throwerror(v,_SC("wrong encoding"));
+ }
+
+ return 0;
+}
+
+int _stream_writeblob(HSQUIRRELVM v)
+{
+ SQUserPointer data;
+ int size;
+ SETUP_STREAM(v);
+ if(SQ_FAILED(sqstd_getblob(v,2,&data)))
+ return sq_throwerror(v,_SC("invalid parameter"));
+ size = sqstd_getblobsize(v,2);
+ if(self->Write(data,size) != size)
+ return sq_throwerror(v,_SC("io error"));
+ sq_pushinteger(v,size);
+ return 1;
+}
+
+int _stream_writen(HSQUIRRELVM v)
+{
+ SETUP_STREAM(v);
+ SQInteger format, ti;
+ SQFloat tf;
+ sq_getinteger(v, 3, &format);
+ switch(format) {
+ case 'i': {
+ int i;
+ sq_getinteger(v, 2, &ti);
+ i = ti;
+ self->Write(&i, sizeof(int));
+ }
+ break;
+ case 's': {
+ short s;
+ sq_getinteger(v, 2, &ti);
+ s = ti;
+ self->Write(&s, sizeof(short));
+ }
+ break;
+ case 'w': {
+ unsigned short w;
+ sq_getinteger(v, 2, &ti);
+ w = ti;
+ self->Write(&w, sizeof(unsigned short));
+ }
+ break;
+ case 'c': {
+ char c;
+ sq_getinteger(v, 2, &ti);
+ c = ti;
+ self->Write(&c, sizeof(char));
+ }
+ break;
+ case 'b': {
+ unsigned char b;
+ sq_getinteger(v, 2, &ti);
+ b = ti;
+ self->Write(&b, sizeof(unsigned char));
+ }
+ break;
+ case 'f': {
+ float f;
+ sq_getfloat(v, 2, &tf);
+ f = tf;
+ self->Write(&f, sizeof(float));
+ }
+ break;
+ case 'd': {
+ double d;
+ sq_getfloat(v, 2, &tf);
+ d = tf;
+ self->Write(&d, sizeof(double));
+ }
+ break;
+ default:
+ return sq_throwerror(v, _SC("invalid format"));
+ }
+ return 0;
+}
+
+int _stream_seek(HSQUIRRELVM v)
+{
+ SETUP_STREAM(v);
+ SQInteger offset, origin = SQ_SEEK_SET;
+ sq_getinteger(v, 2, &offset);
+ if(sq_gettop(v) > 2) {
+ SQInteger t;
+ sq_getinteger(v, 3, &t);
+ switch(t) {
+ case 'b': origin = SQ_SEEK_SET; break;
+ case 'c': origin = SQ_SEEK_CUR; break;
+ case 'e': origin = SQ_SEEK_END; break;
+ default: return sq_throwerror(v,_SC("invalid origin"));
+ }
+ }
+ sq_pushinteger(v, self->Seek(offset, origin));
+ return 1;
+}
+
+int _stream_tell(HSQUIRRELVM v)
+{
+ SETUP_STREAM(v);
+ sq_pushinteger(v, self->Tell());
+ return 1;
+}
+
+int _stream_len(HSQUIRRELVM v)
+{
+ SETUP_STREAM(v);
+ sq_pushinteger(v, self->Len());
+ return 1;
+}
+
+int _stream_flush(HSQUIRRELVM v)
+{
+ SETUP_STREAM(v);
+ if(!self->Flush())
+ sq_pushinteger(v, 1);
+ else
+ sq_pushnull(v);
+ return 1;
+}
+
+int _stream_eos(HSQUIRRELVM v)
+{
+ SETUP_STREAM(v);
+ if(self->EOS())
+ sq_pushinteger(v, 1);
+ else
+ sq_pushnull(v);
+ return 1;
+}
+
+static SQRegFunction _stream_methods[] = {
+ _DECL_STREAM_FUNC(readstr,-2,_SC("xnn")),
+ _DECL_STREAM_FUNC(readblob,2,_SC("xn")),
+ _DECL_STREAM_FUNC(readn,2,_SC("xn")),
+ _DECL_STREAM_FUNC(writestr,-2,_SC("xsn")),
+ _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
+ _DECL_STREAM_FUNC(writen,3,_SC("xnn")),
+ _DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
+ _DECL_STREAM_FUNC(tell,1,_SC("x")),
+ _DECL_STREAM_FUNC(len,1,_SC("x")),
+ _DECL_STREAM_FUNC(eos,1,_SC("x")),
+ _DECL_STREAM_FUNC(flush,1,_SC("x")),
+ {0,0,0,0}
+};
+
+void init_streamclass(HSQUIRRELVM v)
+{
+ sq_pushregistrytable(v);
+ sq_pushstring(v,_SC("std_stream"),-1);
+ if(SQ_FAILED(sq_get(v,-2))) {
+ sq_pushstring(v,_SC("std_stream"),-1);
+ sq_newclass(v,SQFalse);
+ sq_settypetag(v,-1,SQSTD_STREAM_TYPE_TAG);
+ int i = 0;
+ while(_stream_methods[i].name != 0) {
+ SQRegFunction &f = _stream_methods[i];
+ sq_pushstring(v,f.name,-1);
+ sq_newclosure(v,f.f,0);
+ sq_setparamscheck(v,f.nparamscheck,f.typemask);
+ sq_createslot(v,-3);
+ i++;
+ }
+ sq_createslot(v,-3);
+ }
+ else {
+ sq_pop(v,1); //result
+ }
+ sq_pop(v,1);
+}
+
+SQRESULT declare_stream(HSQUIRRELVM v,SQChar* name,int typetag,SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals)
+{
+ if(sq_gettype(v,-1) != OT_TABLE)
+ return sq_throwerror(v,_SC("table expected"));
+ int top = sq_gettop(v);
+ //create delegate
+ init_streamclass(v);
+ sq_pushregistrytable(v);
+ sq_pushstring(v,reg_name,-1);
+ sq_pushstring(v,_SC("std_stream"),-1);
+ if(SQ_SUCCEEDED(sq_get(v,-3))) {
+ sq_newclass(v,SQTrue);
+ sq_settypetag(v,-1,typetag);
+ int i = 0;
+ while(methods[i].name != 0) {
+ SQRegFunction &f = methods[i];
+ sq_pushstring(v,f.name,-1);
+ sq_newclosure(v,f.f,0);
+ sq_setparamscheck(v,f.nparamscheck,f.typemask);
+ sq_setnativeclosurename(v,-1,f.name);
+ sq_createslot(v,-3);
+ i++;
+ }
+ sq_createslot(v,-3);
+ sq_pop(v,1);
+
+ i = 0;
+ while(globals[i].name!=0)
+ {
+ SQRegFunction &f = globals[i];
+ sq_pushstring(v,f.name,-1);
+ sq_newclosure(v,f.f,0);
+ sq_setparamscheck(v,f.nparamscheck,f.typemask);
+ sq_setnativeclosurename(v,-1,f.name);
+ sq_createslot(v,-3);
+ i++;
+ }
+ //register the class in the target table
+ sq_pushstring(v,name,-1);
+ sq_pushregistrytable(v);
+ sq_pushstring(v,reg_name,-1);
+ sq_get(v,-2);
+ sq_remove(v,-2);
+ sq_createslot(v,-3);
+
+ sq_settop(v,top);
+ return SQ_OK;
+ }
+ sq_settop(v,top);
+ return SQ_ERROR;
+}
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQSTD_STREAM_H_\r
-#define _SQSTD_STREAM_H_\r
-\r
-int _stream_readstr(HSQUIRRELVM v);\r
-int _stream_readblob(HSQUIRRELVM v);\r
-int _stream_readline(HSQUIRRELVM v);\r
-int _stream_readn(HSQUIRRELVM v);\r
-int _stream_writestr(HSQUIRRELVM v);\r
-int _stream_writeblob(HSQUIRRELVM v);\r
-int _stream_writen(HSQUIRRELVM v);\r
-int _stream_seek(HSQUIRRELVM v);\r
-int _stream_tell(HSQUIRRELVM v);\r
-int _stream_len(HSQUIRRELVM v);\r
-int _stream_eos(HSQUIRRELVM v);\r
-int _stream_flush(HSQUIRRELVM v);\r
-\r
-#define _DECL_STREAM_FUNC(name,nparams,typecheck) {_SC(#name),_stream_##name,nparams,typecheck}\r
-SQRESULT declare_stream(HSQUIRRELVM v,SQChar* name,int typetag,SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals);\r
-#endif /*_SQSTD_STREAM_H_*/\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQSTD_STREAM_H_
+#define _SQSTD_STREAM_H_
+
+int _stream_readstr(HSQUIRRELVM v);
+int _stream_readblob(HSQUIRRELVM v);
+int _stream_readline(HSQUIRRELVM v);
+int _stream_readn(HSQUIRRELVM v);
+int _stream_writestr(HSQUIRRELVM v);
+int _stream_writeblob(HSQUIRRELVM v);
+int _stream_writen(HSQUIRRELVM v);
+int _stream_seek(HSQUIRRELVM v);
+int _stream_tell(HSQUIRRELVM v);
+int _stream_len(HSQUIRRELVM v);
+int _stream_eos(HSQUIRRELVM v);
+int _stream_flush(HSQUIRRELVM v);
+
+#define _DECL_STREAM_FUNC(name,nparams,typecheck) {_SC(#name),_stream_##name,nparams,typecheck}
+SQRESULT declare_stream(HSQUIRRELVM v,SQChar* name,int typetag,SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals);
+#endif /*_SQSTD_STREAM_H_*/
-/* see copyright notice in squirrel.h */\r
-#include <squirrel.h>\r
-#include <sqstdstring.h>\r
-#include <string.h>\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <ctype.h>\r
-\r
-#ifdef _UNICODE\r
-#define scstrchr wcschr\r
-#define scsnprintf wsnprintf\r
-#define scatoi _wtoi\r
-#else\r
-#define scstrchr strchr\r
-#define scsnprintf snprintf\r
-#define scatoi atoi\r
-#endif\r
-#define MAX_FORMAT_LEN 20\r
-#define MAX_WFORMAT_LEN 3\r
-#define ADDITIONAL_FORMAT_SPACE (100*sizeof(SQChar))\r
-\r
-static int validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, int n,int &width)\r
-{\r
- SQChar swidth[MAX_WFORMAT_LEN];\r
- int wc = 0;\r
- int start = n;\r
- fmt[0] = '%';\r
- while (scstrchr(_SC("-+ #0"), src[n])) n++;\r
- while (scisdigit(src[n])) {\r
- swidth[wc] = src[n];\r
- n++;\r
- wc++;\r
- if(wc>=MAX_WFORMAT_LEN)\r
- return sq_throwerror(v,_SC("width format too long"));\r
- }\r
- swidth[wc] = '\0';\r
- if(wc > 0) {\r
- width = scatoi(swidth);\r
- }\r
- else\r
- width = 0;\r
- if (src[n] == '.') {\r
- n++;\r
- \r
- wc = 0;\r
- while (scisdigit(src[n])) {\r
- swidth[wc] = src[n];\r
- n++;\r
- wc++;\r
- if(wc>=MAX_WFORMAT_LEN)\r
- return sq_throwerror(v,_SC("precision format too long"));\r
- }\r
- swidth[wc] = '\0';\r
- if(wc > 0) {\r
- width += scatoi(swidth);\r
- }\r
- }\r
- if (n-start > MAX_FORMAT_LEN )\r
- return sq_throwerror(v,_SC("format too long"));\r
- memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar));\r
- fmt[(n-start)+2] = '\0';\r
- return n;\r
-}\r
-\r
-static int _string_format(HSQUIRRELVM v)\r
-{\r
- const SQChar *format;\r
- SQChar *dest;\r
- SQChar fmt[MAX_FORMAT_LEN];\r
- sq_getstring(v,2,&format);\r
- int allocated = (sq_getsize(v,2)+1)*sizeof(SQChar);\r
- dest = sq_getscratchpad(v,allocated);\r
- int n = 0,i = 0, nparam = 3, w;\r
- while(format[n] != '\0') {\r
- if(format[n] != '%') {\r
- dest[i++] = format[n];\r
- n++;\r
- }\r
- else if(format[++n] == '%') {\r
- dest[i++] = '%';\r
- }\r
- else {\r
- if( nparam > sq_gettop(v) )\r
- return sq_throwerror(v,_SC("not enough paramters for the given format string"));\r
- n = validate_format(v,fmt,format,n,w);\r
- if(n < 0) return -1;\r
- int addlen = 0;\r
- int valtype = 0;\r
- const SQChar *ts;\r
- SQInteger ti;\r
- SQFloat tf;\r
- switch(format[n]) {\r
- case 's':\r
- if(SQ_FAILED(sq_getstring(v,nparam,&ts))) \r
- return sq_throwerror(v,_SC("string expected for the specified format"));\r
- addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar));\r
- valtype = 's';\r
- break;\r
- case 'i': case 'd': case 'c':case 'o': case 'u': case 'x': case 'X':\r
- if(SQ_FAILED(sq_getinteger(v,nparam,&ti))) \r
- return sq_throwerror(v,_SC("integer expected for the specified format"));\r
- addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));\r
- valtype = 'i';\r
- break;\r
- case 'f': case 'g': case 'G': case 'e': case 'E':\r
- if(SQ_FAILED(sq_getfloat(v,nparam,&tf))) \r
- return sq_throwerror(v,_SC("float expected for the specified format"));\r
- addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));\r
- valtype = 'f';\r
- break;\r
- default:\r
- return sq_throwerror(v,_SC("invalid format"));\r
- }\r
- n++;\r
- if((allocated-i) < addlen)\r
- allocated += addlen - (allocated-i);\r
- dest = sq_getscratchpad(v,allocated);\r
- switch(valtype) {\r
- case 's': i += scsprintf(&dest[i],fmt,ts); break;\r
- case 'i': i += scsprintf(&dest[i],fmt,ti); break;\r
- case 'f': i += scsprintf(&dest[i],fmt,tf); break;\r
- };\r
- nparam ++;\r
- }\r
- }\r
- sq_pushstring(v,dest,i);\r
- return 1;\r
-}\r
-\r
-#define SETUP_REX(v) \\r
- SQRex *self = NULL; \\r
- sq_getinstanceup(v,1,(SQUserPointer *)&self,0); \r
-\r
-static int _rexobj_releasehook(SQUserPointer p, int size)\r
-{\r
- SQRex *self = ((SQRex *)p);\r
- sqstd_rex_free(self);\r
- return 1;\r
-}\r
-\r
-static int _regexp_match(HSQUIRRELVM v)\r
-{\r
- SETUP_REX(v);\r
- const SQChar *str;\r
- sq_getstring(v,2,&str);\r
- if(sqstd_rex_match(self,str) == SQTrue)\r
- {\r
- sq_pushinteger(v,1);\r
- return 1;\r
- }\r
- return 0;\r
-}\r
-\r
-static void _addrexmatch(HSQUIRRELVM v,const SQChar *str,const SQChar *begin,const SQChar *end)\r
-{\r
- sq_newtable(v);\r
- sq_pushstring(v,_SC("begin"),-1);\r
- sq_pushinteger(v,begin - str);\r
- sq_rawset(v,-3);\r
- sq_pushstring(v,_SC("end"),-1);\r
- sq_pushinteger(v,end - str);\r
- sq_rawset(v,-3);\r
-}\r
-\r
-static int _regexp_search(HSQUIRRELVM v)\r
-{\r
- SETUP_REX(v);\r
- const SQChar *str,*begin,*end;\r
- SQInteger start = 0;\r
- sq_getstring(v,2,&str);\r
- if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);\r
- if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {\r
- _addrexmatch(v,str,begin,end);\r
- return 1;\r
- }\r
- return 0;\r
-}\r
-\r
-static int _regexp_capture(HSQUIRRELVM v)\r
-{\r
- SETUP_REX(v);\r
- const SQChar *str,*begin,*end;\r
- SQInteger start = 0;\r
- sq_getstring(v,2,&str);\r
- if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);\r
- if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {\r
- SQInteger n = sqstd_rex_getsubexpcount(self);\r
- SQRexMatch match;\r
- sq_newarray(v,0);\r
- for(SQInteger i = 0;i < n; i++) {\r
- sqstd_rex_getsubexp(self,i,&match);\r
- if(match.len > 0)\r
- _addrexmatch(v,str,match.begin,match.begin+match.len);\r
- else\r
- _addrexmatch(v,str,str,str); //empty match\r
- sq_arrayappend(v,-2);\r
- }\r
- return 1;\r
- }\r
- return 0;\r
-}\r
-\r
-static int _regexp_subexpcount(HSQUIRRELVM v)\r
-{\r
- SETUP_REX(v);\r
- sq_pushinteger(v,sqstd_rex_getsubexpcount(self));\r
- return 1;\r
-}\r
-\r
-static int _regexp_constructor(HSQUIRRELVM v)\r
-{\r
- const SQChar *error,*pattern;\r
- sq_getstring(v,2,&pattern);\r
- SQRex *rex = sqstd_rex_compile(pattern,&error);\r
- if(!rex) return sq_throwerror(v,error);\r
- sq_setinstanceup(v,1,rex);\r
- sq_setreleasehook(v,1,_rexobj_releasehook);\r
- return 0;\r
-}\r
-\r
-static int _regexp__typeof(HSQUIRRELVM v)\r
-{\r
- sq_pushstring(v,_SC("regexp"),-1);\r
- return 1;\r
-}\r
-\r
-#define _DECL_REX_FUNC(name,nparams,pmask) {_SC(#name),_regexp_##name,nparams,pmask}\r
-static SQRegFunction rexobj_funcs[]={\r
- _DECL_REX_FUNC(constructor,2,_SC(".s")),\r
- _DECL_REX_FUNC(search,-2,_SC("xsn")),\r
- _DECL_REX_FUNC(match,2,_SC("xs")),\r
- _DECL_REX_FUNC(capture,-2,_SC("xsn")),\r
- _DECL_REX_FUNC(subexpcount,1,_SC("x")),\r
- _DECL_REX_FUNC(_typeof,1,_SC("x")),\r
- {0,0}\r
-};\r
-\r
-#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask}\r
-static SQRegFunction stringlib_funcs[]={\r
- _DECL_FUNC(format,-2,_SC(".s")),\r
- {0,0}\r
-};\r
-\r
-\r
-int sqstd_register_stringlib(HSQUIRRELVM v)\r
-{\r
- sq_pushstring(v,_SC("regexp"),-1);\r
- sq_newclass(v,SQFalse);\r
- int i = 0;\r
- while(rexobj_funcs[i].name != 0) {\r
- SQRegFunction &f = rexobj_funcs[i];\r
- sq_pushstring(v,f.name,-1);\r
- sq_newclosure(v,f.f,0);\r
- sq_setparamscheck(v,f.nparamscheck,f.typemask);\r
- sq_setnativeclosurename(v,-1,f.name);\r
- sq_createslot(v,-3);\r
- i++;\r
- }\r
- sq_createslot(v,-3);\r
-\r
- i = 0;\r
- while(stringlib_funcs[i].name!=0)\r
- {\r
- sq_pushstring(v,stringlib_funcs[i].name,-1);\r
- sq_newclosure(v,stringlib_funcs[i].f,0);\r
- sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask);\r
- sq_setnativeclosurename(v,-1,stringlib_funcs[i].name);\r
- sq_createslot(v,-3);\r
- i++;\r
- }\r
- return 1;\r
-}\r
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <sqstdstring.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+
+#ifdef _UNICODE
+#define scstrchr wcschr
+#define scsnprintf wsnprintf
+#define scatoi _wtoi
+#else
+#define scstrchr strchr
+#define scsnprintf snprintf
+#define scatoi atoi
+#endif
+#define MAX_FORMAT_LEN 20
+#define MAX_WFORMAT_LEN 3
+#define ADDITIONAL_FORMAT_SPACE (100*sizeof(SQChar))
+
+static int validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, int n,int &width)
+{
+ SQChar swidth[MAX_WFORMAT_LEN];
+ int wc = 0;
+ int start = n;
+ fmt[0] = '%';
+ while (scstrchr(_SC("-+ #0"), src[n])) n++;
+ while (scisdigit(src[n])) {
+ swidth[wc] = src[n];
+ n++;
+ wc++;
+ if(wc>=MAX_WFORMAT_LEN)
+ return sq_throwerror(v,_SC("width format too long"));
+ }
+ swidth[wc] = '\0';
+ if(wc > 0) {
+ width = scatoi(swidth);
+ }
+ else
+ width = 0;
+ if (src[n] == '.') {
+ n++;
+
+ wc = 0;
+ while (scisdigit(src[n])) {
+ swidth[wc] = src[n];
+ n++;
+ wc++;
+ if(wc>=MAX_WFORMAT_LEN)
+ return sq_throwerror(v,_SC("precision format too long"));
+ }
+ swidth[wc] = '\0';
+ if(wc > 0) {
+ width += scatoi(swidth);
+ }
+ }
+ if (n-start > MAX_FORMAT_LEN )
+ return sq_throwerror(v,_SC("format too long"));
+ memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar));
+ fmt[(n-start)+2] = '\0';
+ return n;
+}
+
+static int _string_format(HSQUIRRELVM v)
+{
+ const SQChar *format;
+ SQChar *dest;
+ SQChar fmt[MAX_FORMAT_LEN];
+ sq_getstring(v,2,&format);
+ int allocated = (sq_getsize(v,2)+1)*sizeof(SQChar);
+ dest = sq_getscratchpad(v,allocated);
+ int n = 0,i = 0, nparam = 3, w;
+ while(format[n] != '\0') {
+ if(format[n] != '%') {
+ dest[i++] = format[n];
+ n++;
+ }
+ else if(format[++n] == '%') {
+ dest[i++] = '%';
+ }
+ else {
+ if( nparam > sq_gettop(v) )
+ return sq_throwerror(v,_SC("not enough paramters for the given format string"));
+ n = validate_format(v,fmt,format,n,w);
+ if(n < 0) return -1;
+ int addlen = 0;
+ int valtype = 0;
+ const SQChar *ts;
+ SQInteger ti;
+ SQFloat tf;
+ switch(format[n]) {
+ case 's':
+ if(SQ_FAILED(sq_getstring(v,nparam,&ts)))
+ return sq_throwerror(v,_SC("string expected for the specified format"));
+ addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar));
+ valtype = 's';
+ break;
+ case 'i': case 'd': case 'c':case 'o': case 'u': case 'x': case 'X':
+ if(SQ_FAILED(sq_getinteger(v,nparam,&ti)))
+ return sq_throwerror(v,_SC("integer expected for the specified format"));
+ addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
+ valtype = 'i';
+ break;
+ case 'f': case 'g': case 'G': case 'e': case 'E':
+ if(SQ_FAILED(sq_getfloat(v,nparam,&tf)))
+ return sq_throwerror(v,_SC("float expected for the specified format"));
+ addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
+ valtype = 'f';
+ break;
+ default:
+ return sq_throwerror(v,_SC("invalid format"));
+ }
+ n++;
+ if((allocated-i) < addlen)
+ allocated += addlen - (allocated-i);
+ dest = sq_getscratchpad(v,allocated);
+ switch(valtype) {
+ case 's': i += scsprintf(&dest[i],fmt,ts); break;
+ case 'i': i += scsprintf(&dest[i],fmt,ti); break;
+ case 'f': i += scsprintf(&dest[i],fmt,tf); break;
+ };
+ nparam ++;
+ }
+ }
+ sq_pushstring(v,dest,i);
+ return 1;
+}
+
+#define SETUP_REX(v) \
+ SQRex *self = NULL; \
+ sq_getinstanceup(v,1,(SQUserPointer *)&self,0);
+
+static int _rexobj_releasehook(SQUserPointer p, int size)
+{
+ (void) size;
+ SQRex *self = ((SQRex *)p);
+ sqstd_rex_free(self);
+ return 1;
+}
+
+static int _regexp_match(HSQUIRRELVM v)
+{
+ SETUP_REX(v);
+ const SQChar *str;
+ sq_getstring(v,2,&str);
+ if(sqstd_rex_match(self,str) == SQTrue)
+ {
+ sq_pushinteger(v,1);
+ return 1;
+ }
+ return 0;
+}
+
+static void _addrexmatch(HSQUIRRELVM v,const SQChar *str,const SQChar *begin,const SQChar *end)
+{
+ sq_newtable(v);
+ sq_pushstring(v,_SC("begin"),-1);
+ sq_pushinteger(v,begin - str);
+ sq_rawset(v,-3);
+ sq_pushstring(v,_SC("end"),-1);
+ sq_pushinteger(v,end - str);
+ sq_rawset(v,-3);
+}
+
+static int _regexp_search(HSQUIRRELVM v)
+{
+ SETUP_REX(v);
+ const SQChar *str,*begin,*end;
+ SQInteger start = 0;
+ sq_getstring(v,2,&str);
+ if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
+ if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
+ _addrexmatch(v,str,begin,end);
+ return 1;
+ }
+ return 0;
+}
+
+static int _regexp_capture(HSQUIRRELVM v)
+{
+ SETUP_REX(v);
+ const SQChar *str,*begin,*end;
+ SQInteger start = 0;
+ sq_getstring(v,2,&str);
+ if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
+ if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
+ SQInteger n = sqstd_rex_getsubexpcount(self);
+ SQRexMatch match;
+ sq_newarray(v,0);
+ for(SQInteger i = 0;i < n; i++) {
+ sqstd_rex_getsubexp(self,i,&match);
+ if(match.len > 0)
+ _addrexmatch(v,str,match.begin,match.begin+match.len);
+ else
+ _addrexmatch(v,str,str,str); //empty match
+ sq_arrayappend(v,-2);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+static int _regexp_subexpcount(HSQUIRRELVM v)
+{
+ SETUP_REX(v);
+ sq_pushinteger(v,sqstd_rex_getsubexpcount(self));
+ return 1;
+}
+
+static int _regexp_constructor(HSQUIRRELVM v)
+{
+ const SQChar *error,*pattern;
+ sq_getstring(v,2,&pattern);
+ SQRex *rex = sqstd_rex_compile(pattern,&error);
+ if(!rex) return sq_throwerror(v,error);
+ sq_setinstanceup(v,1,rex);
+ sq_setreleasehook(v,1,_rexobj_releasehook);
+ return 0;
+}
+
+static int _regexp__typeof(HSQUIRRELVM v)
+{
+ sq_pushstring(v,_SC("regexp"),-1);
+ return 1;
+}
+
+#define _DECL_REX_FUNC(name,nparams,pmask) {_SC(#name),_regexp_##name,nparams,pmask}
+static SQRegFunction rexobj_funcs[]={
+ _DECL_REX_FUNC(constructor,2,_SC(".s")),
+ _DECL_REX_FUNC(search,-2,_SC("xsn")),
+ _DECL_REX_FUNC(match,2,_SC("xs")),
+ _DECL_REX_FUNC(capture,-2,_SC("xsn")),
+ _DECL_REX_FUNC(subexpcount,1,_SC("x")),
+ _DECL_REX_FUNC(_typeof,1,_SC("x")),
+ {0,0,0,0}
+};
+
+#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask}
+static SQRegFunction stringlib_funcs[]={
+ _DECL_FUNC(format,-2,_SC(".s")),
+ {0,0,0,0}
+};
+
+
+int sqstd_register_stringlib(HSQUIRRELVM v)
+{
+ sq_pushstring(v,_SC("regexp"),-1);
+ sq_newclass(v,SQFalse);
+ int i = 0;
+ while(rexobj_funcs[i].name != 0) {
+ SQRegFunction &f = rexobj_funcs[i];
+ sq_pushstring(v,f.name,-1);
+ sq_newclosure(v,f.f,0);
+ sq_setparamscheck(v,f.nparamscheck,f.typemask);
+ sq_setnativeclosurename(v,-1,f.name);
+ sq_createslot(v,-3);
+ i++;
+ }
+ sq_createslot(v,-3);
+
+ i = 0;
+ while(stringlib_funcs[i].name!=0)
+ {
+ sq_pushstring(v,stringlib_funcs[i].name,-1);
+ sq_newclosure(v,stringlib_funcs[i].f,0);
+ sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask);
+ sq_setnativeclosurename(v,-1,stringlib_funcs[i].name);
+ sq_createslot(v,-3);
+ i++;
+ }
+ return 1;
+}
-/* see copyright notice in squirrel.h */\r
-#include <squirrel.h>\r
-#include <time.h>\r
-#include <stdlib.h>\r
-#include <stdio.h>\r
-#include <sqstdsystem.h>\r
-\r
-#ifdef SQUNICODE\r
-#include <wchar.h>\r
-#define scgetenv _wgetenv\r
-#define scsystem _wsystem\r
-#define scasctime _wasctime\r
-#define scremove _wremove\r
-#define screname _wrename\r
-#else\r
-#define scgetenv getenv\r
-#define scsystem system\r
-#define scasctime asctime\r
-#define scremove remove\r
-#define screname rename\r
-#endif\r
-\r
-static int _system_getenv(HSQUIRRELVM v)\r
-{\r
- const SQChar *s;\r
- if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){\r
- sq_pushstring(v,scgetenv(s),-1);\r
- return 1;\r
- }\r
- return 0;\r
-}\r
-\r
-\r
-static int _system_system(HSQUIRRELVM v)\r
-{\r
- const SQChar *s;\r
- if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){\r
- sq_pushinteger(v,scsystem(s));\r
- return 1;\r
- }\r
- return sq_throwerror(v,_SC("wrong param"));\r
-}\r
-\r
-\r
-static int _system_clock(HSQUIRRELVM v)\r
-{\r
- sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC);\r
- return 1;\r
-}\r
-\r
-static int _system_time(HSQUIRRELVM v)\r
-{\r
- time_t t;\r
- time(&t);\r
- sq_pushinteger(v,*((SQInteger *)&t));\r
- return 1;\r
-}\r
-\r
-static int _system_remove(HSQUIRRELVM v)\r
-{\r
- const SQChar *s;\r
- sq_getstring(v,2,&s);\r
- if(scremove(s)==-1)\r
- return sq_throwerror(v,_SC("remove() failed"));\r
- return 0;\r
-}\r
-\r
-static int _system_rename(HSQUIRRELVM v)\r
-{\r
- const SQChar *oldn,*newn;\r
- sq_getstring(v,2,&oldn);\r
- sq_getstring(v,3,&newn);\r
- if(screname(oldn,newn)==-1)\r
- return sq_throwerror(v,_SC("rename() failed"));\r
- return 0;\r
-}\r
-\r
-static void _set_integer_slot(HSQUIRRELVM v,const SQChar *name,SQInteger val)\r
-{\r
- sq_pushstring(v,name,-1);\r
- sq_pushinteger(v,val);\r
- sq_rawset(v,-3);\r
-}\r
-\r
-static int _system_date(HSQUIRRELVM v)\r
-{\r
- time_t t;\r
- SQInteger format = 'l';\r
- if(sq_gettop(v) > 1) {\r
- sq_getinteger(v,2,(SQInteger*)&t);\r
- if(sq_gettop(v) > 2) {\r
- sq_getinteger(v,3,(SQInteger*)&format);\r
- }\r
- }\r
- else {\r
- time(&t);\r
- }\r
- tm *date;\r
- if(format == 'u')\r
- date = gmtime(&t);\r
- else\r
- date = localtime(&t);\r
- if(!date)\r
- return sq_throwerror(v,_SC("crt api failure"));\r
- sq_newtable(v);\r
- _set_integer_slot(v, _SC("sec"), date->tm_sec);\r
- _set_integer_slot(v, _SC("min"), date->tm_min);\r
- _set_integer_slot(v, _SC("hour"), date->tm_hour);\r
- _set_integer_slot(v, _SC("day"), date->tm_mday);\r
- _set_integer_slot(v, _SC("month"), date->tm_mon);\r
- _set_integer_slot(v, _SC("year"), date->tm_year+1900);\r
- _set_integer_slot(v, _SC("wday"), date->tm_wday);\r
- _set_integer_slot(v, _SC("yday"), date->tm_yday);\r
- return 1;\r
-}\r
-\r
-\r
-\r
-#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_system_##name,nparams,pmask}\r
-static SQRegFunction systemlib_funcs[]={\r
- _DECL_FUNC(getenv,2,_SC(".s")),\r
- _DECL_FUNC(system,2,_SC(".s")),\r
- _DECL_FUNC(clock,1,NULL),\r
- _DECL_FUNC(time,1,NULL),\r
- _DECL_FUNC(date,-1,_SC(".nn")),\r
- _DECL_FUNC(remove,2,_SC(".s")),\r
- _DECL_FUNC(rename,3,_SC(".ss")),\r
- {0,0}\r
-};\r
-\r
-\r
-int sqstd_register_systemlib(HSQUIRRELVM v)\r
-{\r
- int i=0;\r
- while(systemlib_funcs[i].name!=0)\r
- {\r
- sq_pushstring(v,systemlib_funcs[i].name,-1);\r
- sq_newclosure(v,systemlib_funcs[i].f,0);\r
- sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask);\r
- sq_setnativeclosurename(v,-1,systemlib_funcs[i].name);\r
- sq_createslot(v,-3);\r
- i++;\r
- }\r
- return 1;\r
-}\r
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sqstdsystem.h>
+
+#ifdef SQUNICODE
+#include <wchar.h>
+#define scgetenv _wgetenv
+#define scsystem _wsystem
+#define scasctime _wasctime
+#define scremove _wremove
+#define screname _wrename
+#else
+#define scgetenv getenv
+#define scsystem system
+#define scasctime asctime
+#define scremove remove
+#define screname rename
+#endif
+
+static int _system_getenv(HSQUIRRELVM v)
+{
+ const SQChar *s;
+ if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){
+ sq_pushstring(v,scgetenv(s),-1);
+ return 1;
+ }
+ return 0;
+}
+
+
+static int _system_system(HSQUIRRELVM v)
+{
+ const SQChar *s;
+ if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){
+ sq_pushinteger(v,scsystem(s));
+ return 1;
+ }
+ return sq_throwerror(v,_SC("wrong param"));
+}
+
+
+static int _system_clock(HSQUIRRELVM v)
+{
+ sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC);
+ return 1;
+}
+
+static int _system_time(HSQUIRRELVM v)
+{
+ time_t t;
+ time(&t);
+ sq_pushinteger(v,*((SQInteger *)&t));
+ return 1;
+}
+
+static int _system_remove(HSQUIRRELVM v)
+{
+ const SQChar *s;
+ sq_getstring(v,2,&s);
+ if(scremove(s)==-1)
+ return sq_throwerror(v,_SC("remove() failed"));
+ return 0;
+}
+
+static int _system_rename(HSQUIRRELVM v)
+{
+ const SQChar *oldn,*newn;
+ sq_getstring(v,2,&oldn);
+ sq_getstring(v,3,&newn);
+ if(screname(oldn,newn)==-1)
+ return sq_throwerror(v,_SC("rename() failed"));
+ return 0;
+}
+
+static void _set_integer_slot(HSQUIRRELVM v,const SQChar *name,SQInteger val)
+{
+ sq_pushstring(v,name,-1);
+ sq_pushinteger(v,val);
+ sq_rawset(v,-3);
+}
+
+static int _system_date(HSQUIRRELVM v)
+{
+ time_t t;
+ SQInteger format = 'l';
+ if(sq_gettop(v) > 1) {
+ sq_getinteger(v,2,(SQInteger*)&t);
+ if(sq_gettop(v) > 2) {
+ sq_getinteger(v,3,(SQInteger*)&format);
+ }
+ }
+ else {
+ time(&t);
+ }
+ tm *date;
+ if(format == 'u')
+ date = gmtime(&t);
+ else
+ date = localtime(&t);
+ if(!date)
+ return sq_throwerror(v,_SC("crt api failure"));
+ sq_newtable(v);
+ _set_integer_slot(v, _SC("sec"), date->tm_sec);
+ _set_integer_slot(v, _SC("min"), date->tm_min);
+ _set_integer_slot(v, _SC("hour"), date->tm_hour);
+ _set_integer_slot(v, _SC("day"), date->tm_mday);
+ _set_integer_slot(v, _SC("month"), date->tm_mon);
+ _set_integer_slot(v, _SC("year"), date->tm_year+1900);
+ _set_integer_slot(v, _SC("wday"), date->tm_wday);
+ _set_integer_slot(v, _SC("yday"), date->tm_yday);
+ return 1;
+}
+
+
+
+#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_system_##name,nparams,pmask}
+static SQRegFunction systemlib_funcs[]={
+ _DECL_FUNC(getenv,2,_SC(".s")),
+ _DECL_FUNC(system,2,_SC(".s")),
+ _DECL_FUNC(clock,1,NULL),
+ _DECL_FUNC(time,1,NULL),
+ _DECL_FUNC(date,-1,_SC(".nn")),
+ _DECL_FUNC(remove,2,_SC(".s")),
+ _DECL_FUNC(rename,3,_SC(".ss")),
+ {0,0,0,0}
+};
+
+
+int sqstd_register_systemlib(HSQUIRRELVM v)
+{
+ int i=0;
+ while(systemlib_funcs[i].name!=0)
+ {
+ sq_pushstring(v,systemlib_funcs[i].name,-1);
+ sq_newclosure(v,systemlib_funcs[i].f,0);
+ sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask);
+ sq_setnativeclosurename(v,-1,systemlib_funcs[i].name);
+ sq_createslot(v,-3);
+ i++;
+ }
+ return 1;
+}
-/*\r
- see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include "sqvm.h"\r
-#include "sqstring.h"\r
-#include "sqtable.h"\r
-#include "sqarray.h"\r
-#include "sqfuncproto.h"\r
-#include "sqclosure.h"\r
-#include "squserdata.h"\r
-#include "sqfuncstate.h"\r
-#include "sqcompiler.h"\r
-#include "sqclass.h"\r
-\r
-bool sq_aux_gettypedarg(HSQUIRRELVM v,int idx,SQObjectType type,SQObjectPtr **o)\r
-{\r
- *o = &stack_get(v,idx);\r
- if(type(**o) != type){\r
- SQObjectPtr oval = v->PrintObjVal(**o);\r
- v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval));\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-#define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; }\r
-\r
-#define sq_aux_paramscheck(v,count) \\r
-{ \\r
- if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\\r
-} \r
-\r
-int sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e)\r
-{\r
- v->_lasterror = e;\r
- return SQ_ERROR;\r
-}\r
-\r
-int sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type)\r
-{\r
- scsprintf(_ss(v)->GetScratchPad(100), _SC("unexpected type %s"), IdType2Name(type));\r
- return sq_throwerror(v, _ss(v)->GetScratchPad(-1));\r
-}\r
-\r
-HSQUIRRELVM sq_open(int initialstacksize)\r
-{\r
- SQSharedState *ss;\r
- SQVM *v;\r
- sq_new(ss, SQSharedState);\r
- ss->Init();\r
- v = (SQVM *)SQ_MALLOC(sizeof(SQVM));\r
- new (v) SQVM(ss);\r
- ss->_root_vm = v;\r
- if(v->Init(NULL, initialstacksize)) {\r
- return v;\r
- } else {\r
- sq_delete(v, SQVM);\r
- return NULL;\r
- }\r
- return v;\r
-}\r
-\r
-HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, int initialstacksize)\r
-{\r
- SQSharedState *ss;\r
- SQVM *v;\r
- ss=_ss(friendvm);\r
- \r
- v= (SQVM *)SQ_MALLOC(sizeof(SQVM));\r
- new (v) SQVM(ss);\r
- \r
- if(v->Init(friendvm, initialstacksize)) {\r
- friendvm->Push(v);\r
- return v;\r
- } else {\r
- sq_delete(v, SQVM);\r
- return NULL;\r
- }\r
-}\r
-\r
-int sq_getvmstate(HSQUIRRELVM v)\r
-{\r
- if(v->_suspended)\r
- return SQ_VMSTATE_SUSPENDED;\r
- else { \r
- if(v->_callsstack.size() != 0) return SQ_VMSTATE_RUNNING;\r
- else return SQ_VMSTATE_IDLE;\r
- }\r
-}\r
-\r
-void sq_seterrorhandler(HSQUIRRELVM v)\r
-{\r
- SQObject o = stack_get(v, -1);\r
- if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {\r
- v->_errorhandler = o;\r
- v->Pop();\r
- }\r
-}\r
-\r
-void sq_setdebughook(HSQUIRRELVM v)\r
-{\r
- SQObject o = stack_get(v,-1);\r
- if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {\r
- v->_debughook = o;\r
- v->Pop();\r
- }\r
-}\r
-\r
-void sq_close(HSQUIRRELVM v)\r
-{\r
- SQSharedState *ss = _ss(v);\r
- _thread(ss->_root_vm)->Finalize();\r
- sq_delete(ss, SQSharedState);\r
-}\r
-\r
-SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror)\r
-{\r
- SQObjectPtr o;\r
- if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) {\r
- v->Push(SQClosure::Create(_ss(v), _funcproto(o)));\r
- return SQ_OK;\r
- }\r
- return SQ_ERROR;\r
-}\r
-\r
-void sq_enabledebuginfo(HSQUIRRELVM v, SQBool debuginfo)\r
-{\r
- _ss(v)->_debuginfo = debuginfo?true:false;\r
-}\r
-\r
-void sq_addref(HSQUIRRELVM v,HSQOBJECT *po)\r
-{\r
- SQObjectPtr refs;\r
- if(!ISREFCOUNTED(type(*po))) return;\r
- if(_table(_ss(v)->_refs_table)->Get(*po, refs)) {\r
- refs = _integer(refs) + 1;\r
- }\r
- else{\r
- refs = 1;\r
- }\r
- _table(_ss(v)->_refs_table)->NewSlot(*po, refs);\r
-}\r
-\r
-SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)\r
-{\r
- SQObjectPtr refs;\r
- if(!ISREFCOUNTED(type(*po))) return SQTrue;\r
- if(_table(_ss(v)->_refs_table)->Get(*po, refs)) {\r
- int n = _integer(refs) - 1;\r
- if(n <= 0) {\r
- _table(_ss(v)->_refs_table)->Remove(*po);\r
- sq_resetobject(po);\r
- }\r
- else {\r
- refs = n;_table(_ss(v)->_refs_table)->Set(*po, refs);\r
- return SQFalse;\r
- }\r
- }\r
- return SQTrue;\r
-}\r
-\r
-const SQChar *sq_objtostring(HSQOBJECT *o) \r
-{\r
- if(sq_type(*o) == OT_STRING) {\r
- return o->_unVal.pString->_val;\r
- }\r
- return NULL;\r
-}\r
-\r
-SQInteger sq_objtointeger(HSQOBJECT *o) \r
-{\r
- if(sq_isnumeric(*o)) {\r
- return tointeger(*o);\r
- }\r
- return 0;\r
-}\r
-\r
-SQFloat sq_objtofloat(HSQOBJECT *o) \r
-{\r
- if(sq_isnumeric(*o)) {\r
- return tofloat(*o);\r
- }\r
- return 0;\r
-}\r
-\r
-void sq_pushnull(HSQUIRRELVM v)\r
-{\r
- v->Push(_null_);\r
-}\r
-\r
-void sq_pushstring(HSQUIRRELVM v,const SQChar *s,int len)\r
-{\r
- if(s)\r
- v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len)));\r
- else v->Push(_null_);\r
-}\r
-\r
-void sq_pushinteger(HSQUIRRELVM v,SQInteger n)\r
-{\r
- v->Push(n);\r
-}\r
-\r
-void sq_pushbool(HSQUIRRELVM v,SQBool b)\r
-{\r
- v->Push(b?true:false);\r
-}\r
-\r
-void sq_pushfloat(HSQUIRRELVM v,SQFloat n)\r
-{\r
- v->Push(n);\r
-}\r
-\r
-void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p)\r
-{\r
- v->Push(p);\r
-}\r
-\r
-SQUserPointer sq_newuserdata(HSQUIRRELVM v,unsigned int size)\r
-{\r
- SQUserData *ud = SQUserData::Create(_ss(v), size);\r
- v->Push(ud);\r
- return ud->_val;\r
-}\r
-\r
-void sq_newtable(HSQUIRRELVM v)\r
-{\r
- v->Push(SQTable::Create(_ss(v), 0)); \r
-}\r
-\r
-void sq_newarray(HSQUIRRELVM v,int size)\r
-{\r
- v->Push(SQArray::Create(_ss(v), size)); \r
-}\r
-\r
-SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase)\r
-{\r
- SQClass *baseclass = NULL;\r
- if(hasbase) {\r
- SQObjectPtr &base = stack_get(v,-1);\r
- if(type(base) != OT_CLASS)\r
- return sq_throwerror(v,_SC("invalid base type"));\r
- baseclass = _class(base);\r
- }\r
- SQClass *newclass = SQClass::Create(_ss(v), baseclass);\r
- if(baseclass) v->Pop();\r
- v->Push(newclass); \r
- return SQ_OK;\r
-}\r
-\r
-int sq_instanceof(HSQUIRRELVM v)\r
-{\r
- SQObjectPtr &inst = stack_get(v,-1);\r
- SQObjectPtr &cl = stack_get(v,-2);\r
- if(type(inst) != OT_INSTANCE || type(cl) != OT_CLASS)\r
- return sq_throwerror(v,_SC("invalid param type"));\r
- return _instance(inst)->InstanceOf(_class(cl))?1:0;\r
-}\r
-\r
-SQRESULT sq_arrayappend(HSQUIRRELVM v,int idx)\r
-{\r
- sq_aux_paramscheck(v,2);\r
- SQObjectPtr *arr;\r
- _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
- _array(*arr)->Append(v->GetUp(-1));\r
- v->Pop(1);\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_arraypop(HSQUIRRELVM v,int idx,SQBool pushval)\r
-{\r
- sq_aux_paramscheck(v, 1);\r
- SQObjectPtr *arr;\r
- _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
- if(_array(*arr)->Size() > 0) {\r
- if(pushval != 0){ v->Push(_array(*arr)->Top()); }\r
- _array(*arr)->Pop();\r
- return SQ_OK;\r
- }\r
- return sq_throwerror(v, _SC("empty array"));\r
-}\r
-\r
-SQRESULT sq_arrayresize(HSQUIRRELVM v,int idx,int newsize)\r
-{\r
- sq_aux_paramscheck(v,1);\r
- SQObjectPtr *arr;\r
- _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
- if(_array(*arr)->Size() > 0) {\r
- _array(*arr)->Resize(newsize);\r
- return SQ_OK;\r
- }\r
- return sq_throwerror(v, _SC("empty array"));\r
-}\r
-\r
-SQRESULT sq_arrayreverse(HSQUIRRELVM v,int idx)\r
-{\r
- sq_aux_paramscheck(v, 1);\r
- SQObjectPtr *o;\r
- _GETSAFE_OBJ(v, idx, OT_ARRAY,o);\r
- SQArray *arr = _array(*o);\r
- if(arr->Size() > 0) {\r
- SQObjectPtr t;\r
- int size = arr->Size();\r
- int n = size >> 1; size -= 1;\r
- for(int i = 0; i < n; i++) {\r
- t = arr->_values[i];\r
- arr->_values[i] = arr->_values[size-i];\r
- arr->_values[size-i] = t;\r
- }\r
- return SQ_OK;\r
- }\r
- return sq_throwerror(v, _SC("empty array"));\r
-}\r
-\r
-void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,unsigned int nfreevars)\r
-{\r
- SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func);\r
- nc->_nparamscheck = 0;\r
- for(unsigned int i = 0; i < nfreevars; i++) {\r
- nc->_outervalues.push_back(v->Top());\r
- v->Pop();\r
- }\r
- v->Push(SQObjectPtr(nc)); \r
-}\r
-\r
-SQRESULT sq_getclosureinfo(HSQUIRRELVM v,int idx,unsigned int *nparams,unsigned int *nfreevars)\r
-{\r
- SQObject o = stack_get(v, idx);\r
- if(sq_isclosure(o)) {\r
- SQClosure *c = _closure(o);\r
- SQFunctionProto *proto = _funcproto(c->_function);\r
- *nparams = (unsigned int)proto->_parameters.size();\r
- *nfreevars = (unsigned int)c->_outervalues.size();\r
- return SQ_OK;\r
- }\r
- return sq_throwerror(v,_SC("the object is not a closure"));\r
-}\r
-\r
-SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,int idx,const SQChar *name)\r
-{\r
- SQObject o = stack_get(v, idx);\r
- if(sq_isnativeclosure(o)) {\r
- SQNativeClosure *nc = _nativeclosure(o);\r
- nc->_name = SQString::Create(_ss(v),name);\r
- return SQ_OK;\r
- }\r
- return sq_throwerror(v,_SC("the object is not a nativeclosure"));\r
-}\r
-\r
-SQRESULT sq_setparamscheck(HSQUIRRELVM v,int nparamscheck,const SQChar *typemask)\r
-{\r
- SQObject o = stack_get(v, -1);\r
- if(!sq_isnativeclosure(o))\r
- return sq_throwerror(v, _SC("native closure expected"));\r
- SQNativeClosure *nc = _nativeclosure(o);\r
- nc->_nparamscheck = nparamscheck;\r
- if(typemask) {\r
- SQIntVec res;\r
- if(!CompileTypemask(res, typemask))\r
- return sq_throwerror(v, _SC("invalid typemask"));\r
- nc->_typecheck.copy(res);\r
- }\r
- else {\r
- nc->_typecheck.resize(0);\r
- }\r
- return SQ_OK;\r
-}\r
-\r
-void sq_pushroottable(HSQUIRRELVM v)\r
-{\r
- v->Push(v->_roottable);\r
-}\r
-\r
-void sq_pushregistrytable(HSQUIRRELVM v)\r
-{\r
- v->Push(_ss(v)->_registry);\r
-}\r
-\r
-SQRESULT sq_setroottable(HSQUIRRELVM v)\r
-{\r
- SQObject o = stack_get(v, -1);\r
- if(sq_istable(o) || sq_isnull(o)) {\r
- v->_roottable = o;\r
- v->Pop();\r
- return SQ_OK;\r
- }\r
- return sq_throwerror(v, _SC("ivalid type"));\r
-}\r
-\r
-void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p)\r
-{\r
- v->_foreignptr = p;\r
-}\r
-\r
-SQUserPointer sq_getforeignptr(HSQUIRRELVM v)\r
-{\r
- return v->_foreignptr;\r
-}\r
-\r
-void sq_push(HSQUIRRELVM v,int idx)\r
-{\r
- v->Push(stack_get(v, idx));\r
-}\r
-\r
-SQObjectType sq_gettype(HSQUIRRELVM v,int idx)\r
-{\r
- return type(stack_get(v, idx));\r
-}\r
-\r
-SQRESULT sq_getinteger(HSQUIRRELVM v,int idx,SQInteger *i)\r
-{\r
- SQObjectPtr &o = stack_get(v, idx);\r
- if(sq_isnumeric(o)) {\r
- *i = tointeger(o);\r
- return SQ_OK;\r
- }\r
- return SQ_ERROR;\r
-}\r
-\r
-SQRESULT sq_getfloat(HSQUIRRELVM v,int idx,SQFloat *f)\r
-{\r
- SQObjectPtr &o = stack_get(v, idx);\r
- if(sq_isnumeric(o)) {\r
- *f = tofloat(o);\r
- return SQ_OK;\r
- }\r
- return SQ_ERROR;\r
-}\r
-\r
-SQRESULT sq_getbool(HSQUIRRELVM v,int idx,SQBool *b)\r
-{\r
- SQObjectPtr &o = stack_get(v, idx);\r
- if(sq_isbool(o)) {\r
- *b = _integer(o);\r
- return SQ_OK;\r
- }\r
- return SQ_ERROR;\r
-}\r
-\r
-SQRESULT sq_getstring(HSQUIRRELVM v,int idx,const SQChar **c)\r
-{\r
- SQObjectPtr *o = NULL;\r
- _GETSAFE_OBJ(v, idx, OT_STRING,o);\r
- *c = _stringval(*o);\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_getthread(HSQUIRRELVM v,int idx,HSQUIRRELVM *thread)\r
-{\r
- SQObjectPtr *o = NULL;\r
- _GETSAFE_OBJ(v, idx, OT_THREAD,o);\r
- *thread = _thread(*o);\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_clone(HSQUIRRELVM v,int idx)\r
-{\r
- SQObjectPtr &o = stack_get(v,idx);\r
- v->Push(_null_);\r
- if(!v->Clone(o, stack_get(v, -1))){\r
- v->Pop();\r
- return sq_aux_invalidtype(v, type(o));\r
- }\r
- return SQ_OK;\r
-}\r
-\r
-SQInteger sq_getsize(HSQUIRRELVM v, int idx)\r
-{\r
- SQObjectPtr &o = stack_get(v, idx);\r
- SQObjectType type = type(o);\r
- switch(type) {\r
- case OT_STRING: return _string(o)->_len;\r
- case OT_TABLE: return _table(o)->CountUsed();\r
- case OT_ARRAY: return _array(o)->Size();\r
- case OT_USERDATA: return _userdata(o)->_size;\r
- default:\r
- return sq_aux_invalidtype(v, type);\r
- }\r
-}\r
-\r
-SQRESULT sq_getuserdata(HSQUIRRELVM v,int idx,SQUserPointer *p,unsigned int *typetag)\r
-{\r
- SQObjectPtr *o = NULL;\r
- _GETSAFE_OBJ(v, idx, OT_USERDATA,o);\r
- (*p) = _userdataval(*o);\r
- if(typetag) *typetag = _userdata(*o)->_typetag;\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_settypetag(HSQUIRRELVM v,int idx,unsigned int typetag)\r
-{\r
- SQObjectPtr &o = stack_get(v,idx);\r
- switch(type(o)) {\r
- case OT_USERDATA: _userdata(o)->_typetag = typetag; break;\r
- case OT_CLASS: _class(o)->_typetag = typetag; break;\r
- default: return sq_throwerror(v,_SC("invalid object type"));\r
- }\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_gettypetag(HSQUIRRELVM v,int idx,unsigned int *typetag)\r
-{\r
- SQObjectPtr &o = stack_get(v,idx);\r
- switch(type(o)) {\r
- case OT_USERDATA: *typetag = _userdata(o)->_typetag; break;\r
- case OT_CLASS: *typetag = _class(o)->_typetag; break;\r
- default: return sq_throwerror(v,_SC("invalid object type"));\r
- }\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_getuserpointer(HSQUIRRELVM v, int idx, SQUserPointer *p)\r
-{\r
- SQObjectPtr *o = NULL;\r
- _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o);\r
- (*p) = _userpointer(*o);\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_setinstanceup(HSQUIRRELVM v, int idx, SQUserPointer p)\r
-{\r
- SQObjectPtr &o = stack_get(v,idx);\r
- if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));\r
- _instance(o)->_userpointer = p;\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_getinstanceup(HSQUIRRELVM v, int idx, SQUserPointer *p,unsigned int typetag)\r
-{\r
- SQObjectPtr &o = stack_get(v,idx);\r
- if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));\r
- (*p) = _instance(o)->_userpointer;\r
- if(typetag != 0) {\r
- SQClass *cl = _instance(o)->_class;\r
- do{\r
- if(cl->_typetag == typetag)\r
- return SQ_OK;\r
- cl = cl->_base;\r
- }while(cl != NULL);\r
- return sq_throwerror(v,_SC("invalid type tag"));\r
- }\r
- return SQ_OK;\r
-}\r
-\r
-int sq_gettop(HSQUIRRELVM v)\r
-{\r
- return (v->_top) - v->_stackbase;\r
-}\r
-\r
-void sq_settop(HSQUIRRELVM v, int newtop)\r
-{\r
- int top = sq_gettop(v);\r
- if(top > newtop)\r
- sq_pop(v, top - newtop);\r
- else\r
- while(top < newtop) sq_pushnull(v);\r
-}\r
-\r
-void sq_pop(HSQUIRRELVM v, int nelemstopop)\r
-{\r
- assert(v->_top >= nelemstopop);\r
- v->Pop(nelemstopop);\r
-}\r
-\r
-void sq_remove(HSQUIRRELVM v, int idx)\r
-{\r
- v->Remove(idx);\r
-}\r
-\r
-int sq_cmp(HSQUIRRELVM v)\r
-{\r
- int res;\r
- v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res);\r
- return res;\r
-}\r
-\r
-SQRESULT sq_createslot(HSQUIRRELVM v, int idx)\r
-{\r
- sq_aux_paramscheck(v, 3);\r
- SQObjectPtr &self = stack_get(v, idx);\r
- if(type(self) == OT_TABLE || type(self) == OT_CLASS) {\r
- SQObjectPtr &key = v->GetUp(-2);\r
- if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));\r
- v->NewSlot(self, key, v->GetUp(-1));\r
- v->Pop(2);\r
- }\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_deleteslot(HSQUIRRELVM v,int idx,SQBool pushval)\r
-{\r
- sq_aux_paramscheck(v, 2);\r
- SQObjectPtr *self;\r
- _GETSAFE_OBJ(v, idx, OT_TABLE,self);\r
- SQObjectPtr &key = v->GetUp(-1);\r
- if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));\r
- SQObjectPtr res;\r
- if(!v->DeleteSlot(*self, key, res)){\r
- return SQ_ERROR;\r
- }\r
- if(pushval) v->GetUp(-1) = res;\r
- else v->Pop(1);\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_set(HSQUIRRELVM v,int idx)\r
-{\r
- SQObjectPtr &self = stack_get(v, idx);\r
- if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) {\r
- v->Pop(2);\r
- return SQ_OK;\r
- }\r
- v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;\r
-}\r
-\r
-SQRESULT sq_rawset(HSQUIRRELVM v,int idx)\r
-{\r
- SQObjectPtr &self = stack_get(v, idx);\r
- if(type(v->GetUp(-2)) == OT_NULL) return sq_throwerror(v, _SC("null key"));\r
- switch(type(self)) {\r
- case OT_TABLE:\r
- _table(self)->NewSlot(v->GetUp(-2), v->GetUp(-1));\r
- v->Pop(2);\r
- return SQ_OK;\r
- break;\r
- case OT_CLASS:\r
- _class(self)->NewSlot(v->GetUp(-2), v->GetUp(-1));\r
- v->Pop(2);\r
- return SQ_OK;\r
- break;\r
- case OT_INSTANCE:\r
- if(_instance(self)->Set(v->GetUp(-2), v->GetUp(-1))) {\r
- v->Pop(2);\r
- return SQ_OK;\r
- }\r
- break;\r
- case OT_ARRAY:\r
- if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) {\r
- v->Pop(2);\r
- return SQ_OK;\r
- }\r
- break;\r
- default:\r
- v->Pop(2);\r
- return sq_throwerror(v, _SC("rawset works only on arrays,tables,calsses and instances"));\r
- }\r
- v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;\r
-}\r
-\r
-SQRESULT sq_setdelegate(HSQUIRRELVM v,int idx)\r
-{\r
- SQObjectPtr &self = stack_get(v, idx);\r
- SQObjectPtr &mt = v->GetUp(-1);\r
- SQObjectType type = type(self);\r
- switch(type) {\r
- case OT_TABLE:\r
- if(type(mt) == OT_TABLE) {\r
- if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, _SC("delagate cycle")); v->Pop();}\r
- else if(type(mt)==OT_NULL) {\r
- _table(self)->SetDelegate(NULL); v->Pop(); }\r
- else return sq_aux_invalidtype(v,type);\r
- break;\r
- case OT_USERDATA:\r
- if(type(mt)==OT_TABLE) {\r
- _userdata(self)->SetDelegate(_table(mt)); v->Pop(); }\r
- else if(type(mt)==OT_NULL) {\r
- _userdata(self)->SetDelegate(NULL); v->Pop(); }\r
- else return sq_aux_invalidtype(v, type);\r
- break;\r
- default:\r
- return sq_aux_invalidtype(v, type);\r
- break;\r
- }\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,int idx,SQBool pushval)\r
-{\r
- sq_aux_paramscheck(v, 2);\r
- SQObjectPtr *self;\r
- _GETSAFE_OBJ(v, idx, OT_TABLE,self);\r
- SQObjectPtr &key = v->GetUp(-1);\r
- SQObjectPtr t;\r
- if(_table(*self)->Get(key,t)) {\r
- _table(*self)->Remove(key);\r
- }\r
- if(pushval != 0)\r
- if(pushval) v->GetUp(-1) = t;\r
- else\r
- v->Pop(1);\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_getdelegate(HSQUIRRELVM v,int idx)\r
-{\r
- SQObjectPtr &self=stack_get(v,idx);\r
- switch(type(self)){\r
- case OT_TABLE:\r
- if(!_table(self)->_delegate)break;\r
- v->Push(SQObjectPtr(_table(self)->_delegate));\r
- return SQ_OK;\r
- break;\r
- case OT_USERDATA:\r
- if(!_userdata(self)->_delegate)break;\r
- v->Push(SQObjectPtr(_userdata(self)->_delegate));\r
- return SQ_OK;\r
- break;\r
- }\r
- return sq_throwerror(v,_SC("wrong type"));\r
-}\r
-\r
-SQRESULT sq_get(HSQUIRRELVM v,int idx)\r
-{\r
- SQObjectPtr &self=stack_get(v,idx);\r
- if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false))\r
- return SQ_OK;\r
- v->Pop(1);\r
- return sq_throwerror(v,_SC("the index doesn't exist"));\r
-}\r
-\r
-SQRESULT sq_rawget(HSQUIRRELVM v,int idx)\r
-{\r
- SQObjectPtr &self=stack_get(v,idx);\r
- switch(type(self)) {\r
- case OT_TABLE:\r
- if(_table(self)->Get(v->GetUp(-1),v->GetUp(-1)))\r
- return SQ_OK;\r
- break;\r
- case OT_CLASS:\r
- if(_class(self)->Get(v->GetUp(-1),v->GetUp(-1)))\r
- return SQ_OK;\r
- break;\r
- case OT_INSTANCE:\r
- if(_instance(self)->Get(v->GetUp(-1),v->GetUp(-1)))\r
- return SQ_OK;\r
- break;\r
- case OT_ARRAY:\r
- if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false))\r
- return SQ_OK;\r
- break;\r
- default:\r
- v->Pop(1);\r
- return sq_throwerror(v,_SC("rawget works only on arrays and tables"));\r
- } \r
- v->Pop(1);\r
- return sq_throwerror(v,_SC("the index doesn't exist"));\r
-}\r
-\r
-SQRESULT sq_getstackobj(HSQUIRRELVM v,int idx,HSQOBJECT *po)\r
-{\r
- *po=stack_get(v,idx);\r
- return SQ_OK;\r
-}\r
-\r
-const SQChar *sq_getlocal(HSQUIRRELVM v,unsigned int level,unsigned int idx)\r
-{\r
- unsigned int cstksize=v->_callsstack.size();\r
- unsigned int lvl=(cstksize-level)-1;\r
- int stackbase=v->_stackbase;\r
- if(lvl<cstksize){\r
- for(unsigned int i=0;i<level;i++){\r
- SQVM::CallInfo &ci=v->_callsstack[(cstksize-i)-1];\r
- stackbase-=ci._prevstkbase;\r
- }\r
- SQVM::CallInfo &ci=v->_callsstack[lvl];\r
- if(type(ci._closure)!=OT_CLOSURE)\r
- return NULL;\r
- SQClosure *c=_closure(ci._closure);\r
- SQFunctionProto *func=_funcproto(c->_function);\r
- return func->GetLocal(v,stackbase,idx,(ci._ip-func->_instructions._vals)-1);\r
- }\r
- return NULL;\r
-}\r
-\r
-void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj)\r
-{\r
- v->Push(SQObjectPtr(obj));\r
-}\r
-\r
-void sq_resetobject(HSQOBJECT *po)\r
-{\r
- po->_unVal.pUserPointer=NULL;po->_type=OT_NULL;\r
-}\r
-\r
-SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err)\r
-{\r
- v->_lasterror=SQString::Create(_ss(v),err);\r
- return -1;\r
-}\r
-\r
-void sq_reseterror(HSQUIRRELVM v)\r
-{\r
- v->_lasterror = _null_;\r
-}\r
-\r
-void sq_getlasterror(HSQUIRRELVM v)\r
-{\r
- v->Push(v->_lasterror);\r
-}\r
-\r
-void sq_reservestack(HSQUIRRELVM v,int nsize)\r
-{\r
- if (((unsigned int)v->_top + nsize) > v->_stack.size()) {\r
- v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size()));\r
- }\r
-}\r
-\r
-SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval)\r
-{\r
- if(type(v->GetUp(-1))==OT_GENERATOR){\r
- v->Push(_null_); //retval\r
- if(!v->Execute(v->GetUp(-2),v->_top,0,v->_top,v->GetUp(-1),SQVM::ET_RESUME_GENERATOR))\r
- {v->Raise_Error(v->_lasterror); return SQ_ERROR;}\r
- if(!retval)\r
- v->Pop();\r
- return SQ_OK;\r
- }\r
- return sq_throwerror(v,_SC("only generators can be resumed"));\r
-}\r
-\r
-SQRESULT sq_call(HSQUIRRELVM v,int params,SQBool retval)\r
-{\r
- SQObjectPtr res;\r
- if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res)){\r
- v->Pop(params);//pop closure and args\r
- if(retval){\r
- v->Push(res); return SQ_OK;\r
- }\r
- return SQ_OK;\r
- }\r
- else {\r
- v->Pop(params);\r
- return SQ_ERROR;\r
- }\r
- if(!v->_suspended)\r
- v->Pop(params);\r
- return sq_throwerror(v,_SC("call failed"));\r
-}\r
-\r
-SQRESULT sq_suspendvm(HSQUIRRELVM v)\r
-{\r
- return v->Suspend();\r
-}\r
-\r
-SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval)\r
-{\r
- SQObjectPtr ret;\r
- if(!v->_suspended)\r
- return sq_throwerror(v,_SC("cannot resume a vm that is not running any code"));\r
- if(wakeupret) {\r
- v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval\r
- v->Pop();\r
- } else v->GetAt(v->_stackbase+v->_suspended_target)=_null_;\r
- if(!v->Execute(_null_,v->_top,-1,-1,ret,SQVM::ET_RESUME_VM))\r
- return SQ_ERROR;\r
- if(sq_getvmstate(v) == SQ_VMSTATE_IDLE) {\r
- while (v->_top > 1) v->_stack[--v->_top] = _null_;\r
- }\r
- if(retval)\r
- v->Push(ret);\r
- return SQ_OK;\r
-}\r
-\r
-void sq_setreleasehook(HSQUIRRELVM v,int idx,SQRELEASEHOOK hook)\r
-{\r
- if(sq_gettop(v) >= 1){\r
- SQObjectPtr &ud=stack_get(v,idx);\r
- switch( type(ud) ) {\r
- case OT_USERDATA:\r
- _userdata(ud)->_hook = hook;\r
- break;\r
- case OT_INSTANCE:\r
- _instance(ud)->_hook = hook;\r
- break;\r
- }\r
- }\r
-}\r
-\r
-void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f)\r
-{\r
- _ss(v)->_compilererrorhandler = f;\r
-}\r
-\r
-SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)\r
-{\r
- SQObjectPtr *o = NULL;\r
- _GETSAFE_OBJ(v, -1, OT_CLOSURE,o);\r
- SQClosure *c=_closure(*o);\r
- unsigned short tag = SQ_BYTECODE_STREAM_TAG;\r
- if(w(up,&tag,2) != 2)\r
- return sq_throwerror(v,_SC("io error"));\r
- if(!_closure(*o)->Save(v,up,w))\r
- return SQ_ERROR;\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)\r
-{\r
- SQObjectPtr func=SQFunctionProto::Create();\r
- SQObjectPtr closure=SQClosure::Create(_ss(v),_funcproto(func));\r
- unsigned short tag;\r
- if(r(up,&tag,2) != 2)\r
- return sq_throwerror(v,_SC("io error"));\r
- if(tag != SQ_BYTECODE_STREAM_TAG)\r
- return sq_throwerror(v,_SC("invalid stream"));\r
- if(!_closure(closure)->Load(v,up,r))\r
- return SQ_ERROR;\r
- v->Push(closure);\r
- return SQ_OK;\r
-}\r
-\r
-SQChar *sq_getscratchpad(HSQUIRRELVM v,int minsize)\r
-{\r
- return _ss(v)->GetScratchPad(minsize);\r
-}\r
-\r
-int sq_collectgarbage(HSQUIRRELVM v)\r
-{\r
-#ifndef NO_GARBAGE_COLLECTOR\r
- return _ss(v)->CollectGarbage(v);\r
-#else\r
- return -1;\r
-#endif\r
-}\r
-\r
-SQRESULT sq_setfreevariable(HSQUIRRELVM v,int idx,unsigned int nval)\r
-{\r
- SQObjectPtr &self=stack_get(v,idx);\r
- switch(type(self))\r
- {\r
- case OT_CLOSURE:\r
- if(_closure(self)->_outervalues.size()>nval){\r
- _closure(self)->_outervalues[nval]=stack_get(v,-1);\r
- }\r
- else return sq_throwerror(v,_SC("invalid free var index"));\r
- break;\r
- case OT_NATIVECLOSURE:\r
- if(_nativeclosure(self)->_outervalues.size()>nval){\r
- _nativeclosure(self)->_outervalues[nval]=stack_get(v,-1);\r
- }\r
- else return sq_throwerror(v,_SC("invalid free var index"));\r
- break;\r
- default:\r
- return sq_aux_invalidtype(v,type(self));\r
- }\r
- v->Pop(1);\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_setattributes(HSQUIRRELVM v,int idx)\r
-{\r
- SQObjectPtr *o = NULL;\r
- _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
- SQObjectPtr &key = stack_get(v,-2);\r
- SQObjectPtr &val = stack_get(v,-1);\r
- SQObjectPtr attrs;\r
- if(type(key) == OT_NULL) {\r
- attrs = _class(*o)->_attributes;\r
- _class(*o)->_attributes = val;\r
- v->Pop(2);\r
- v->Push(attrs);\r
- return SQ_OK;\r
- }else if(_class(*o)->GetAttributes(key,attrs)) {\r
- _class(*o)->SetAttributes(key,val);\r
- v->Pop(2);\r
- v->Push(attrs);\r
- return SQ_OK;\r
- }\r
- return sq_throwerror(v,_SC("wrong index"));\r
-}\r
-\r
-SQRESULT sq_getattributes(HSQUIRRELVM v,int idx)\r
-{\r
- SQObjectPtr *o = NULL;\r
- _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
- SQObjectPtr &key = stack_get(v,-1);\r
- SQObjectPtr attrs;\r
- if(type(key) == OT_NULL) {\r
- attrs = _class(*o)->_attributes;\r
- v->Pop();\r
- v->Push(attrs);\r
- return SQ_OK;\r
- }\r
- else if(_class(*o)->GetAttributes(key,attrs)) {\r
- v->Pop();\r
- v->Push(attrs);\r
- return SQ_OK;\r
- }\r
- return sq_throwerror(v,_SC("wrong index"));\r
-}\r
-\r
-SQRESULT sq_getclass(HSQUIRRELVM v,int idx)\r
-{\r
- SQObjectPtr *o = NULL;\r
- _GETSAFE_OBJ(v, idx, OT_INSTANCE,o);\r
- v->Push(SQObjectPtr(_instance(*o)->_class));\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_createinstance(HSQUIRRELVM v,int idx)\r
-{\r
- SQObjectPtr *o = NULL;\r
- _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
- v->Push(_class(*o)->CreateInstance());\r
- return SQ_OK;\r
-}\r
-\r
-SQRESULT sq_next(HSQUIRRELVM v,int idx)\r
-{\r
- SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val;\r
- if(type(o) == OT_GENERATOR) {\r
- return sq_throwerror(v,_SC("cannot iterate a generator"));\r
- }\r
- bool finished;\r
- if(!v->FOREACH_OP(o,realkey,val,refpos,0,finished))\r
- return SQ_ERROR;\r
- if(!finished) {\r
- v->Push(realkey);\r
- v->Push(val);\r
- return SQ_OK;\r
- }\r
- return SQ_ERROR;\r
-}\r
-\r
-struct BufState{\r
- const SQChar *buf;\r
- int ptr;\r
- int size;\r
-};\r
-\r
-SQInteger buf_lexfeed(SQUserPointer file)\r
-{\r
- BufState *buf=(BufState*)file;\r
- if(buf->size<(buf->ptr+1))\r
- return 0;\r
- return buf->buf[buf->ptr++];\r
-}\r
-\r
-SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,int size,const SQChar *sourcename,SQBool raiseerror) {\r
- BufState buf;\r
- buf.buf = s;\r
- buf.size = size;\r
- buf.ptr = 0;\r
- return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror);\r
-}\r
-\r
-void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,int idx)\r
-{\r
- dest->Push(stack_get(src,idx));\r
-}\r
-\r
-void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc)\r
-{\r
- _ss(v)->_printfunc = printfunc;\r
-}\r
-\r
-SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)\r
-{\r
- return _ss(v)->_printfunc;\r
-}\r
-\r
-void *sq_malloc(unsigned int size)\r
-{\r
- return SQ_MALLOC(size);\r
-}\r
-\r
-void *sq_realloc(void* p,unsigned int oldsize,unsigned int newsize)\r
-{\r
- return SQ_REALLOC(p,oldsize,newsize);\r
-}\r
-void sq_free(void *p,unsigned int size)\r
-{\r
- SQ_FREE(p,size);\r
-}\r
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqvm.h"
+#include "sqstring.h"
+#include "sqtable.h"
+#include "sqarray.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+#include "squserdata.h"
+#include "sqfuncstate.h"
+#include "sqcompiler.h"
+#include "sqclass.h"
+
+bool sq_aux_gettypedarg(HSQUIRRELVM v,int idx,SQObjectType type,SQObjectPtr **o)
+{
+ *o = &stack_get(v,idx);
+ if(type(**o) != type){
+ SQObjectPtr oval = v->PrintObjVal(**o);
+ v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval));
+ return false;
+ }
+ return true;
+}
+
+#define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; }
+
+#define sq_aux_paramscheck(v,count) \
+{ \
+ if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\
+}
+
+int sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e)
+{
+ v->_lasterror = e;
+ return SQ_ERROR;
+}
+
+int sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type)
+{
+ scsprintf(_ss(v)->GetScratchPad(100), _SC("unexpected type %s"), IdType2Name(type));
+ return sq_throwerror(v, _ss(v)->GetScratchPad(-1));
+}
+
+HSQUIRRELVM sq_open(int initialstacksize)
+{
+ SQSharedState *ss;
+ SQVM *v;
+ sq_new(ss, SQSharedState);
+ ss->Init();
+ v = (SQVM *)SQ_MALLOC(sizeof(SQVM));
+ new (v) SQVM(ss);
+ ss->_root_vm = v;
+ if(v->Init(NULL, initialstacksize)) {
+ return v;
+ } else {
+ sq_delete(v, SQVM);
+ return NULL;
+ }
+ return v;
+}
+
+HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, int initialstacksize)
+{
+ SQSharedState *ss;
+ SQVM *v;
+ ss=_ss(friendvm);
+
+ v= (SQVM *)SQ_MALLOC(sizeof(SQVM));
+ new (v) SQVM(ss);
+
+ if(v->Init(friendvm, initialstacksize)) {
+ friendvm->Push(v);
+ return v;
+ } else {
+ sq_delete(v, SQVM);
+ return NULL;
+ }
+}
+
+int sq_getvmstate(HSQUIRRELVM v)
+{
+ if(v->_suspended)
+ return SQ_VMSTATE_SUSPENDED;
+ else {
+ if(v->_callsstack.size() != 0) return SQ_VMSTATE_RUNNING;
+ else return SQ_VMSTATE_IDLE;
+ }
+}
+
+void sq_seterrorhandler(HSQUIRRELVM v)
+{
+ SQObject o = stack_get(v, -1);
+ if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
+ v->_errorhandler = o;
+ v->Pop();
+ }
+}
+
+void sq_setdebughook(HSQUIRRELVM v)
+{
+ SQObject o = stack_get(v,-1);
+ if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
+ v->_debughook = o;
+ v->Pop();
+ }
+}
+
+void sq_close(HSQUIRRELVM v)
+{
+ SQSharedState *ss = _ss(v);
+ _thread(ss->_root_vm)->Finalize();
+ sq_delete(ss, SQSharedState);
+}
+
+SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror)
+{
+ SQObjectPtr o;
+ if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) {
+ v->Push(SQClosure::Create(_ss(v), _funcproto(o)));
+ return SQ_OK;
+ }
+ return SQ_ERROR;
+}
+
+void sq_enabledebuginfo(HSQUIRRELVM v, SQBool debuginfo)
+{
+ _ss(v)->_debuginfo = debuginfo?true:false;
+}
+
+void sq_addref(HSQUIRRELVM v,HSQOBJECT *po)
+{
+ SQObjectPtr refs;
+ if(!ISREFCOUNTED(type(*po))) return;
+ if(_table(_ss(v)->_refs_table)->Get(*po, refs)) {
+ refs = _integer(refs) + 1;
+ }
+ else{
+ refs = 1;
+ }
+ _table(_ss(v)->_refs_table)->NewSlot(*po, refs);
+}
+
+SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)
+{
+ SQObjectPtr refs;
+ if(!ISREFCOUNTED(type(*po))) return SQTrue;
+ if(_table(_ss(v)->_refs_table)->Get(*po, refs)) {
+ int n = _integer(refs) - 1;
+ if(n <= 0) {
+ _table(_ss(v)->_refs_table)->Remove(*po);
+ sq_resetobject(po);
+ }
+ else {
+ refs = n;_table(_ss(v)->_refs_table)->Set(*po, refs);
+ return SQFalse;
+ }
+ }
+ return SQTrue;
+}
+
+const SQChar *sq_objtostring(HSQOBJECT *o)
+{
+ if(sq_type(*o) == OT_STRING) {
+ return o->_unVal.pString->_val;
+ }
+ return NULL;
+}
+
+SQInteger sq_objtointeger(HSQOBJECT *o)
+{
+ if(sq_isnumeric(*o)) {
+ return tointeger(*o);
+ }
+ return 0;
+}
+
+SQFloat sq_objtofloat(HSQOBJECT *o)
+{
+ if(sq_isnumeric(*o)) {
+ return tofloat(*o);
+ }
+ return 0;
+}
+
+void sq_pushnull(HSQUIRRELVM v)
+{
+ v->Push(_null_);
+}
+
+void sq_pushstring(HSQUIRRELVM v,const SQChar *s,int len)
+{
+ if(s)
+ v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len)));
+ else v->Push(_null_);
+}
+
+void sq_pushinteger(HSQUIRRELVM v,SQInteger n)
+{
+ v->Push(n);
+}
+
+void sq_pushbool(HSQUIRRELVM v,SQBool b)
+{
+ v->Push(b?true:false);
+}
+
+void sq_pushfloat(HSQUIRRELVM v,SQFloat n)
+{
+ v->Push(n);
+}
+
+void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p)
+{
+ v->Push(p);
+}
+
+SQUserPointer sq_newuserdata(HSQUIRRELVM v,unsigned int size)
+{
+ SQUserData *ud = SQUserData::Create(_ss(v), size);
+ v->Push(ud);
+ return ud->_val;
+}
+
+void sq_newtable(HSQUIRRELVM v)
+{
+ v->Push(SQTable::Create(_ss(v), 0));
+}
+
+void sq_newarray(HSQUIRRELVM v,int size)
+{
+ v->Push(SQArray::Create(_ss(v), size));
+}
+
+SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase)
+{
+ SQClass *baseclass = NULL;
+ if(hasbase) {
+ SQObjectPtr &base = stack_get(v,-1);
+ if(type(base) != OT_CLASS)
+ return sq_throwerror(v,_SC("invalid base type"));
+ baseclass = _class(base);
+ }
+ SQClass *newclass = SQClass::Create(_ss(v), baseclass);
+ if(baseclass) v->Pop();
+ v->Push(newclass);
+ return SQ_OK;
+}
+
+int sq_instanceof(HSQUIRRELVM v)
+{
+ SQObjectPtr &inst = stack_get(v,-1);
+ SQObjectPtr &cl = stack_get(v,-2);
+ if(type(inst) != OT_INSTANCE || type(cl) != OT_CLASS)
+ return sq_throwerror(v,_SC("invalid param type"));
+ return _instance(inst)->InstanceOf(_class(cl))?1:0;
+}
+
+SQRESULT sq_arrayappend(HSQUIRRELVM v,int idx)
+{
+ sq_aux_paramscheck(v,2);
+ SQObjectPtr *arr;
+ _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
+ _array(*arr)->Append(v->GetUp(-1));
+ v->Pop(1);
+ return SQ_OK;
+}
+
+SQRESULT sq_arraypop(HSQUIRRELVM v,int idx,SQBool pushval)
+{
+ sq_aux_paramscheck(v, 1);
+ SQObjectPtr *arr;
+ _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
+ if(_array(*arr)->Size() > 0) {
+ if(pushval != 0){ v->Push(_array(*arr)->Top()); }
+ _array(*arr)->Pop();
+ return SQ_OK;
+ }
+ return sq_throwerror(v, _SC("empty array"));
+}
+
+SQRESULT sq_arrayresize(HSQUIRRELVM v,int idx,int newsize)
+{
+ sq_aux_paramscheck(v,1);
+ SQObjectPtr *arr;
+ _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
+ if(_array(*arr)->Size() > 0) {
+ _array(*arr)->Resize(newsize);
+ return SQ_OK;
+ }
+ return sq_throwerror(v, _SC("empty array"));
+}
+
+SQRESULT sq_arrayreverse(HSQUIRRELVM v,int idx)
+{
+ sq_aux_paramscheck(v, 1);
+ SQObjectPtr *o;
+ _GETSAFE_OBJ(v, idx, OT_ARRAY,o);
+ SQArray *arr = _array(*o);
+ if(arr->Size() > 0) {
+ SQObjectPtr t;
+ int size = arr->Size();
+ int n = size >> 1; size -= 1;
+ for(int i = 0; i < n; i++) {
+ t = arr->_values[i];
+ arr->_values[i] = arr->_values[size-i];
+ arr->_values[size-i] = t;
+ }
+ return SQ_OK;
+ }
+ return sq_throwerror(v, _SC("empty array"));
+}
+
+void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,unsigned int nfreevars)
+{
+ SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func);
+ nc->_nparamscheck = 0;
+ for(unsigned int i = 0; i < nfreevars; i++) {
+ nc->_outervalues.push_back(v->Top());
+ v->Pop();
+ }
+ v->Push(SQObjectPtr(nc));
+}
+
+SQRESULT sq_getclosureinfo(HSQUIRRELVM v,int idx,unsigned int *nparams,unsigned int *nfreevars)
+{
+ SQObject o = stack_get(v, idx);
+ if(sq_isclosure(o)) {
+ SQClosure *c = _closure(o);
+ SQFunctionProto *proto = _funcproto(c->_function);
+ *nparams = (unsigned int)proto->_parameters.size();
+ *nfreevars = (unsigned int)c->_outervalues.size();
+ return SQ_OK;
+ }
+ return sq_throwerror(v,_SC("the object is not a closure"));
+}
+
+SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,int idx,const SQChar *name)
+{
+ SQObject o = stack_get(v, idx);
+ if(sq_isnativeclosure(o)) {
+ SQNativeClosure *nc = _nativeclosure(o);
+ nc->_name = SQString::Create(_ss(v),name);
+ return SQ_OK;
+ }
+ return sq_throwerror(v,_SC("the object is not a nativeclosure"));
+}
+
+SQRESULT sq_setparamscheck(HSQUIRRELVM v,int nparamscheck,const SQChar *typemask)
+{
+ SQObject o = stack_get(v, -1);
+ if(!sq_isnativeclosure(o))
+ return sq_throwerror(v, _SC("native closure expected"));
+ SQNativeClosure *nc = _nativeclosure(o);
+ nc->_nparamscheck = nparamscheck;
+ if(typemask) {
+ SQIntVec res;
+ if(!CompileTypemask(res, typemask))
+ return sq_throwerror(v, _SC("invalid typemask"));
+ nc->_typecheck.copy(res);
+ }
+ else {
+ nc->_typecheck.resize(0);
+ }
+ return SQ_OK;
+}
+
+void sq_pushroottable(HSQUIRRELVM v)
+{
+ v->Push(v->_roottable);
+}
+
+void sq_pushregistrytable(HSQUIRRELVM v)
+{
+ v->Push(_ss(v)->_registry);
+}
+
+SQRESULT sq_setroottable(HSQUIRRELVM v)
+{
+ SQObject o = stack_get(v, -1);
+ if(sq_istable(o) || sq_isnull(o)) {
+ v->_roottable = o;
+ v->Pop();
+ return SQ_OK;
+ }
+ return sq_throwerror(v, _SC("ivalid type"));
+}
+
+void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p)
+{
+ v->_foreignptr = p;
+}
+
+SQUserPointer sq_getforeignptr(HSQUIRRELVM v)
+{
+ return v->_foreignptr;
+}
+
+void sq_push(HSQUIRRELVM v,int idx)
+{
+ v->Push(stack_get(v, idx));
+}
+
+SQObjectType sq_gettype(HSQUIRRELVM v,int idx)
+{
+ return type(stack_get(v, idx));
+}
+
+SQRESULT sq_getinteger(HSQUIRRELVM v,int idx,SQInteger *i)
+{
+ SQObjectPtr &o = stack_get(v, idx);
+ if(sq_isnumeric(o)) {
+ *i = tointeger(o);
+ return SQ_OK;
+ }
+ return SQ_ERROR;
+}
+
+SQRESULT sq_getfloat(HSQUIRRELVM v,int idx,SQFloat *f)
+{
+ SQObjectPtr &o = stack_get(v, idx);
+ if(sq_isnumeric(o)) {
+ *f = tofloat(o);
+ return SQ_OK;
+ }
+ return SQ_ERROR;
+}
+
+SQRESULT sq_getbool(HSQUIRRELVM v,int idx,SQBool *b)
+{
+ SQObjectPtr &o = stack_get(v, idx);
+ if(sq_isbool(o)) {
+ *b = _integer(o);
+ return SQ_OK;
+ }
+ return SQ_ERROR;
+}
+
+SQRESULT sq_getstring(HSQUIRRELVM v,int idx,const SQChar **c)
+{
+ SQObjectPtr *o = NULL;
+ _GETSAFE_OBJ(v, idx, OT_STRING,o);
+ *c = _stringval(*o);
+ return SQ_OK;
+}
+
+SQRESULT sq_getthread(HSQUIRRELVM v,int idx,HSQUIRRELVM *thread)
+{
+ SQObjectPtr *o = NULL;
+ _GETSAFE_OBJ(v, idx, OT_THREAD,o);
+ *thread = _thread(*o);
+ return SQ_OK;
+}
+
+SQRESULT sq_clone(HSQUIRRELVM v,int idx)
+{
+ SQObjectPtr &o = stack_get(v,idx);
+ v->Push(_null_);
+ if(!v->Clone(o, stack_get(v, -1))){
+ v->Pop();
+ return sq_aux_invalidtype(v, type(o));
+ }
+ return SQ_OK;
+}
+
+SQInteger sq_getsize(HSQUIRRELVM v, int idx)
+{
+ SQObjectPtr &o = stack_get(v, idx);
+ SQObjectType type = type(o);
+ switch(type) {
+ case OT_STRING: return _string(o)->_len;
+ case OT_TABLE: return _table(o)->CountUsed();
+ case OT_ARRAY: return _array(o)->Size();
+ case OT_USERDATA: return _userdata(o)->_size;
+ default:
+ return sq_aux_invalidtype(v, type);
+ }
+}
+
+SQRESULT sq_getuserdata(HSQUIRRELVM v,int idx,SQUserPointer *p,unsigned int *typetag)
+{
+ SQObjectPtr *o = NULL;
+ _GETSAFE_OBJ(v, idx, OT_USERDATA,o);
+ (*p) = _userdataval(*o);
+ if(typetag) *typetag = _userdata(*o)->_typetag;
+ return SQ_OK;
+}
+
+SQRESULT sq_settypetag(HSQUIRRELVM v,int idx,unsigned int typetag)
+{
+ SQObjectPtr &o = stack_get(v,idx);
+ switch(type(o)) {
+ case OT_USERDATA: _userdata(o)->_typetag = typetag; break;
+ case OT_CLASS: _class(o)->_typetag = typetag; break;
+ default: return sq_throwerror(v,_SC("invalid object type"));
+ }
+ return SQ_OK;
+}
+
+SQRESULT sq_gettypetag(HSQUIRRELVM v,int idx,unsigned int *typetag)
+{
+ SQObjectPtr &o = stack_get(v,idx);
+ switch(type(o)) {
+ case OT_USERDATA: *typetag = _userdata(o)->_typetag; break;
+ case OT_CLASS: *typetag = _class(o)->_typetag; break;
+ default: return sq_throwerror(v,_SC("invalid object type"));
+ }
+ return SQ_OK;
+}
+
+SQRESULT sq_getuserpointer(HSQUIRRELVM v, int idx, SQUserPointer *p)
+{
+ SQObjectPtr *o = NULL;
+ _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o);
+ (*p) = _userpointer(*o);
+ return SQ_OK;
+}
+
+SQRESULT sq_setinstanceup(HSQUIRRELVM v, int idx, SQUserPointer p)
+{
+ SQObjectPtr &o = stack_get(v,idx);
+ if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));
+ _instance(o)->_userpointer = p;
+ return SQ_OK;
+}
+
+SQRESULT sq_getinstanceup(HSQUIRRELVM v, int idx, SQUserPointer *p,unsigned int typetag)
+{
+ SQObjectPtr &o = stack_get(v,idx);
+ if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));
+ (*p) = _instance(o)->_userpointer;
+ if(typetag != 0) {
+ SQClass *cl = _instance(o)->_class;
+ do{
+ if(cl->_typetag == typetag)
+ return SQ_OK;
+ cl = cl->_base;
+ }while(cl != NULL);
+ return sq_throwerror(v,_SC("invalid type tag"));
+ }
+ return SQ_OK;
+}
+
+int sq_gettop(HSQUIRRELVM v)
+{
+ return (v->_top) - v->_stackbase;
+}
+
+void sq_settop(HSQUIRRELVM v, int newtop)
+{
+ int top = sq_gettop(v);
+ if(top > newtop)
+ sq_pop(v, top - newtop);
+ else
+ while(top < newtop) sq_pushnull(v);
+}
+
+void sq_pop(HSQUIRRELVM v, int nelemstopop)
+{
+ assert(v->_top >= nelemstopop);
+ v->Pop(nelemstopop);
+}
+
+void sq_remove(HSQUIRRELVM v, int idx)
+{
+ v->Remove(idx);
+}
+
+int sq_cmp(HSQUIRRELVM v)
+{
+ int res;
+ v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res);
+ return res;
+}
+
+SQRESULT sq_createslot(HSQUIRRELVM v, int idx)
+{
+ sq_aux_paramscheck(v, 3);
+ SQObjectPtr &self = stack_get(v, idx);
+ if(type(self) == OT_TABLE || type(self) == OT_CLASS) {
+ SQObjectPtr &key = v->GetUp(-2);
+ if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));
+ v->NewSlot(self, key, v->GetUp(-1));
+ v->Pop(2);
+ }
+ return SQ_OK;
+}
+
+SQRESULT sq_deleteslot(HSQUIRRELVM v,int idx,SQBool pushval)
+{
+ sq_aux_paramscheck(v, 2);
+ SQObjectPtr *self;
+ _GETSAFE_OBJ(v, idx, OT_TABLE,self);
+ SQObjectPtr &key = v->GetUp(-1);
+ if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));
+ SQObjectPtr res;
+ if(!v->DeleteSlot(*self, key, res)){
+ return SQ_ERROR;
+ }
+ if(pushval) v->GetUp(-1) = res;
+ else v->Pop(1);
+ return SQ_OK;
+}
+
+SQRESULT sq_set(HSQUIRRELVM v,int idx)
+{
+ SQObjectPtr &self = stack_get(v, idx);
+ if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) {
+ v->Pop(2);
+ return SQ_OK;
+ }
+ v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;
+}
+
+SQRESULT sq_rawset(HSQUIRRELVM v,int idx)
+{
+ SQObjectPtr &self = stack_get(v, idx);
+ if(type(v->GetUp(-2)) == OT_NULL) return sq_throwerror(v, _SC("null key"));
+ switch(type(self)) {
+ case OT_TABLE:
+ _table(self)->NewSlot(v->GetUp(-2), v->GetUp(-1));
+ v->Pop(2);
+ return SQ_OK;
+ break;
+ case OT_CLASS:
+ _class(self)->NewSlot(v->GetUp(-2), v->GetUp(-1));
+ v->Pop(2);
+ return SQ_OK;
+ break;
+ case OT_INSTANCE:
+ if(_instance(self)->Set(v->GetUp(-2), v->GetUp(-1))) {
+ v->Pop(2);
+ return SQ_OK;
+ }
+ break;
+ case OT_ARRAY:
+ if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) {
+ v->Pop(2);
+ return SQ_OK;
+ }
+ break;
+ default:
+ v->Pop(2);
+ return sq_throwerror(v, _SC("rawset works only on arrays,tables,calsses and instances"));
+ }
+ v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;
+}
+
+SQRESULT sq_setdelegate(HSQUIRRELVM v,int idx)
+{
+ SQObjectPtr &self = stack_get(v, idx);
+ SQObjectPtr &mt = v->GetUp(-1);
+ SQObjectType type = type(self);
+ switch(type) {
+ case OT_TABLE:
+ if(type(mt) == OT_TABLE) {
+ if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, _SC("delagate cycle")); v->Pop();}
+ else if(type(mt)==OT_NULL) {
+ _table(self)->SetDelegate(NULL); v->Pop(); }
+ else return sq_aux_invalidtype(v,type);
+ break;
+ case OT_USERDATA:
+ if(type(mt)==OT_TABLE) {
+ _userdata(self)->SetDelegate(_table(mt)); v->Pop(); }
+ else if(type(mt)==OT_NULL) {
+ _userdata(self)->SetDelegate(NULL); v->Pop(); }
+ else return sq_aux_invalidtype(v, type);
+ break;
+ default:
+ return sq_aux_invalidtype(v, type);
+ break;
+ }
+ return SQ_OK;
+}
+
+SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,int idx,SQBool pushval)
+{
+ sq_aux_paramscheck(v, 2);
+ SQObjectPtr *self;
+ _GETSAFE_OBJ(v, idx, OT_TABLE,self);
+ SQObjectPtr &key = v->GetUp(-1);
+ SQObjectPtr t;
+ if(_table(*self)->Get(key,t)) {
+ _table(*self)->Remove(key);
+ }
+ if(pushval != 0)
+ if(pushval) v->GetUp(-1) = t;
+ else
+ v->Pop(1);
+ return SQ_OK;
+}
+
+SQRESULT sq_getdelegate(HSQUIRRELVM v,int idx)
+{
+ SQObjectPtr &self=stack_get(v,idx);
+ switch(type(self)){
+ case OT_TABLE:
+ if(!_table(self)->_delegate)break;
+ v->Push(SQObjectPtr(_table(self)->_delegate));
+ return SQ_OK;
+ break;
+ case OT_USERDATA:
+ if(!_userdata(self)->_delegate)break;
+ v->Push(SQObjectPtr(_userdata(self)->_delegate));
+ return SQ_OK;
+ break;
+ default:
+ break;
+ }
+ return sq_throwerror(v,_SC("wrong type"));
+}
+
+SQRESULT sq_get(HSQUIRRELVM v,int idx)
+{
+ SQObjectPtr &self=stack_get(v,idx);
+ if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false))
+ return SQ_OK;
+ v->Pop(1);
+ return sq_throwerror(v,_SC("the index doesn't exist"));
+}
+
+SQRESULT sq_rawget(HSQUIRRELVM v,int idx)
+{
+ SQObjectPtr &self=stack_get(v,idx);
+ switch(type(self)) {
+ case OT_TABLE:
+ if(_table(self)->Get(v->GetUp(-1),v->GetUp(-1)))
+ return SQ_OK;
+ break;
+ case OT_CLASS:
+ if(_class(self)->Get(v->GetUp(-1),v->GetUp(-1)))
+ return SQ_OK;
+ break;
+ case OT_INSTANCE:
+ if(_instance(self)->Get(v->GetUp(-1),v->GetUp(-1)))
+ return SQ_OK;
+ break;
+ case OT_ARRAY:
+ if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false))
+ return SQ_OK;
+ break;
+ default:
+ v->Pop(1);
+ return sq_throwerror(v,_SC("rawget works only on arrays and tables"));
+ }
+ v->Pop(1);
+ return sq_throwerror(v,_SC("the index doesn't exist"));
+}
+
+SQRESULT sq_getstackobj(HSQUIRRELVM v,int idx,HSQOBJECT *po)
+{
+ *po=stack_get(v,idx);
+ return SQ_OK;
+}
+
+const SQChar *sq_getlocal(HSQUIRRELVM v,unsigned int level,unsigned int idx)
+{
+ unsigned int cstksize=v->_callsstack.size();
+ unsigned int lvl=(cstksize-level)-1;
+ int stackbase=v->_stackbase;
+ if(lvl<cstksize){
+ for(unsigned int i=0;i<level;i++){
+ SQVM::CallInfo &ci=v->_callsstack[(cstksize-i)-1];
+ stackbase-=ci._prevstkbase;
+ }
+ SQVM::CallInfo &ci=v->_callsstack[lvl];
+ if(type(ci._closure)!=OT_CLOSURE)
+ return NULL;
+ SQClosure *c=_closure(ci._closure);
+ SQFunctionProto *func=_funcproto(c->_function);
+ return func->GetLocal(v,stackbase,idx,(ci._ip-func->_instructions._vals)-1);
+ }
+ return NULL;
+}
+
+void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj)
+{
+ v->Push(SQObjectPtr(obj));
+}
+
+void sq_resetobject(HSQOBJECT *po)
+{
+ po->_unVal.pUserPointer=NULL;po->_type=OT_NULL;
+}
+
+SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err)
+{
+ v->_lasterror=SQString::Create(_ss(v),err);
+ return -1;
+}
+
+void sq_reseterror(HSQUIRRELVM v)
+{
+ v->_lasterror = _null_;
+}
+
+void sq_getlasterror(HSQUIRRELVM v)
+{
+ v->Push(v->_lasterror);
+}
+
+void sq_reservestack(HSQUIRRELVM v,int nsize)
+{
+ if (((unsigned int)v->_top + nsize) > v->_stack.size()) {
+ v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size()));
+ }
+}
+
+SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval)
+{
+ if(type(v->GetUp(-1))==OT_GENERATOR){
+ v->Push(_null_); //retval
+ if(!v->Execute(v->GetUp(-2),v->_top,0,v->_top,v->GetUp(-1),SQVM::ET_RESUME_GENERATOR))
+ {v->Raise_Error(v->_lasterror); return SQ_ERROR;}
+ if(!retval)
+ v->Pop();
+ return SQ_OK;
+ }
+ return sq_throwerror(v,_SC("only generators can be resumed"));
+}
+
+SQRESULT sq_call(HSQUIRRELVM v,int params,SQBool retval)
+{
+ SQObjectPtr res;
+ if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res)){
+ v->Pop(params);//pop closure and args
+ if(retval){
+ v->Push(res); return SQ_OK;
+ }
+ return SQ_OK;
+ }
+ else {
+ v->Pop(params);
+ return SQ_ERROR;
+ }
+ if(!v->_suspended)
+ v->Pop(params);
+ return sq_throwerror(v,_SC("call failed"));
+}
+
+SQRESULT sq_suspendvm(HSQUIRRELVM v)
+{
+ return v->Suspend();
+}
+
+SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval)
+{
+ SQObjectPtr ret;
+ if(!v->_suspended)
+ return sq_throwerror(v,_SC("cannot resume a vm that is not running any code"));
+ if(wakeupret) {
+ v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval
+ v->Pop();
+ } else v->GetAt(v->_stackbase+v->_suspended_target)=_null_;
+ if(!v->Execute(_null_,v->_top,-1,-1,ret,SQVM::ET_RESUME_VM))
+ return SQ_ERROR;
+ if(sq_getvmstate(v) == SQ_VMSTATE_IDLE) {
+ while (v->_top > 1) v->_stack[--v->_top] = _null_;
+ }
+ if(retval)
+ v->Push(ret);
+ return SQ_OK;
+}
+
+void sq_setreleasehook(HSQUIRRELVM v,int idx,SQRELEASEHOOK hook)
+{
+ if(sq_gettop(v) >= 1){
+ SQObjectPtr &ud=stack_get(v,idx);
+ switch( type(ud) ) {
+ case OT_USERDATA:
+ _userdata(ud)->_hook = hook;
+ break;
+ case OT_INSTANCE:
+ _instance(ud)->_hook = hook;
+ break;
+ default:
+ break;
+ }
+ }
+}
+
+void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f)
+{
+ _ss(v)->_compilererrorhandler = f;
+}
+
+SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up)
+{
+ SQObjectPtr *o = NULL;
+ _GETSAFE_OBJ(v, -1, OT_CLOSURE,o);
+ //SQClosure *c=_closure(*o);
+ unsigned short tag = SQ_BYTECODE_STREAM_TAG;
+ if(w(up,&tag,2) != 2)
+ return sq_throwerror(v,_SC("io error"));
+ if(!_closure(*o)->Save(v,up,w))
+ return SQ_ERROR;
+ return SQ_OK;
+}
+
+SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)
+{
+ SQObjectPtr func=SQFunctionProto::Create();
+ SQObjectPtr closure=SQClosure::Create(_ss(v),_funcproto(func));
+ unsigned short tag;
+ if(r(up,&tag,2) != 2)
+ return sq_throwerror(v,_SC("io error"));
+ if(tag != SQ_BYTECODE_STREAM_TAG)
+ return sq_throwerror(v,_SC("invalid stream"));
+ if(!_closure(closure)->Load(v,up,r))
+ return SQ_ERROR;
+ v->Push(closure);
+ return SQ_OK;
+}
+
+SQChar *sq_getscratchpad(HSQUIRRELVM v,int minsize)
+{
+ return _ss(v)->GetScratchPad(minsize);
+}
+
+int sq_collectgarbage(HSQUIRRELVM v)
+{
+#ifndef NO_GARBAGE_COLLECTOR
+ return _ss(v)->CollectGarbage(v);
+#else
+ return -1;
+#endif
+}
+
+SQRESULT sq_setfreevariable(HSQUIRRELVM v,int idx,unsigned int nval)
+{
+ SQObjectPtr &self=stack_get(v,idx);
+ switch(type(self))
+ {
+ case OT_CLOSURE:
+ if(_closure(self)->_outervalues.size()>nval){
+ _closure(self)->_outervalues[nval]=stack_get(v,-1);
+ }
+ else return sq_throwerror(v,_SC("invalid free var index"));
+ break;
+ case OT_NATIVECLOSURE:
+ if(_nativeclosure(self)->_outervalues.size()>nval){
+ _nativeclosure(self)->_outervalues[nval]=stack_get(v,-1);
+ }
+ else return sq_throwerror(v,_SC("invalid free var index"));
+ break;
+ default:
+ return sq_aux_invalidtype(v,type(self));
+ }
+ v->Pop(1);
+ return SQ_OK;
+}
+
+SQRESULT sq_setattributes(HSQUIRRELVM v,int idx)
+{
+ SQObjectPtr *o = NULL;
+ _GETSAFE_OBJ(v, idx, OT_CLASS,o);
+ SQObjectPtr &key = stack_get(v,-2);
+ SQObjectPtr &val = stack_get(v,-1);
+ SQObjectPtr attrs;
+ if(type(key) == OT_NULL) {
+ attrs = _class(*o)->_attributes;
+ _class(*o)->_attributes = val;
+ v->Pop(2);
+ v->Push(attrs);
+ return SQ_OK;
+ }else if(_class(*o)->GetAttributes(key,attrs)) {
+ _class(*o)->SetAttributes(key,val);
+ v->Pop(2);
+ v->Push(attrs);
+ return SQ_OK;
+ }
+ return sq_throwerror(v,_SC("wrong index"));
+}
+
+SQRESULT sq_getattributes(HSQUIRRELVM v,int idx)
+{
+ SQObjectPtr *o = NULL;
+ _GETSAFE_OBJ(v, idx, OT_CLASS,o);
+ SQObjectPtr &key = stack_get(v,-1);
+ SQObjectPtr attrs;
+ if(type(key) == OT_NULL) {
+ attrs = _class(*o)->_attributes;
+ v->Pop();
+ v->Push(attrs);
+ return SQ_OK;
+ }
+ else if(_class(*o)->GetAttributes(key,attrs)) {
+ v->Pop();
+ v->Push(attrs);
+ return SQ_OK;
+ }
+ return sq_throwerror(v,_SC("wrong index"));
+}
+
+SQRESULT sq_getclass(HSQUIRRELVM v,int idx)
+{
+ SQObjectPtr *o = NULL;
+ _GETSAFE_OBJ(v, idx, OT_INSTANCE,o);
+ v->Push(SQObjectPtr(_instance(*o)->_class));
+ return SQ_OK;
+}
+
+SQRESULT sq_createinstance(HSQUIRRELVM v,int idx)
+{
+ SQObjectPtr *o = NULL;
+ _GETSAFE_OBJ(v, idx, OT_CLASS,o);
+ v->Push(_class(*o)->CreateInstance());
+ return SQ_OK;
+}
+
+SQRESULT sq_next(HSQUIRRELVM v,int idx)
+{
+ SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val;
+ if(type(o) == OT_GENERATOR) {
+ return sq_throwerror(v,_SC("cannot iterate a generator"));
+ }
+ bool finished;
+ if(!v->FOREACH_OP(o,realkey,val,refpos,0,finished))
+ return SQ_ERROR;
+ if(!finished) {
+ v->Push(realkey);
+ v->Push(val);
+ return SQ_OK;
+ }
+ return SQ_ERROR;
+}
+
+struct BufState{
+ const SQChar *buf;
+ int ptr;
+ int size;
+};
+
+SQInteger buf_lexfeed(SQUserPointer file)
+{
+ BufState *buf=(BufState*)file;
+ if(buf->size<(buf->ptr+1))
+ return 0;
+ return buf->buf[buf->ptr++];
+}
+
+SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,int size,const SQChar *sourcename,SQBool raiseerror) {
+ BufState buf;
+ buf.buf = s;
+ buf.size = size;
+ buf.ptr = 0;
+ return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror);
+}
+
+void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,int idx)
+{
+ dest->Push(stack_get(src,idx));
+}
+
+void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc)
+{
+ _ss(v)->_printfunc = printfunc;
+}
+
+SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)
+{
+ return _ss(v)->_printfunc;
+}
+
+void *sq_malloc(unsigned int size)
+{
+ return SQ_MALLOC(size);
+}
+
+void *sq_realloc(void* p,unsigned int oldsize,unsigned int newsize)
+{
+ return SQ_REALLOC(p,oldsize,newsize);
+}
+void sq_free(void *p,unsigned int size)
+{
+ SQ_FREE(p,size);
+}
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQARRAY_H_\r
-#define _SQARRAY_H_\r
-\r
-struct SQArray : public CHAINABLE_OBJ\r
-{\r
-private:\r
- SQArray(SQSharedState *ss,int nsize){_values.resize(nsize);_uiRef=0;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}\r
- ~SQArray()\r
- {\r
- REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
- }\r
-public:\r
- static SQArray* Create(SQSharedState *ss,int nInitialSize){\r
- SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray));\r
- new (newarray) SQArray(ss,nInitialSize);\r
- return newarray;\r
- }\r
-#ifndef NO_GARBAGE_COLLECTOR\r
- void Mark(SQCollectable **chain);\r
-#endif\r
- void Finalize(){\r
- _values.resize(0);\r
- }\r
- bool Get(const int nidx,SQObjectPtr &val)\r
- {\r
- if(nidx>=0 && nidx<(int)_values.size()){\r
- val=_values[nidx];\r
- return true;\r
- }\r
- else return false;\r
- }\r
- bool Set(const int nidx,const SQObjectPtr &val)\r
- {\r
- if(nidx>=0 && nidx<(int)_values.size()){\r
- _values[nidx]=val;\r
- return true;\r
- }\r
- else return false;\r
- }\r
- int Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval)\r
- {\r
- unsigned int idx=TranslateIndex(refpos);\r
- while(idx<_values.size()){\r
- //first found\r
- outkey=(SQInteger)idx;\r
- outval=_values[idx];\r
- //return idx for the next iteration\r
- return ++idx;\r
- }\r
- //nothing to iterate anymore\r
- return -1;\r
- }\r
- SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),Size()); anew->_values.copy(_values); return anew; }\r
- int Size() const {return _values.size();}\r
- void Resize(int size,SQObjectPtr &fill = _null_) { _values.resize(size,fill); ShrinkIfNeeded(); }\r
- void Reserve(int size) { _values.reserve(size); }\r
- void Append(const SQObject &o){_values.push_back(o);}\r
- void Extend(const SQArray *a);\r
- SQObjectPtr &Top(){return _values.top();}\r
- void Pop(){_values.pop_back(); ShrinkIfNeeded(); }\r
- void Insert(const SQObject& idx,const SQObject &val){_values.insert((unsigned int)tointeger(idx),val);}\r
- void ShrinkIfNeeded() {\r
- if(_values.size() <= _values.capacity()>>2) //shrink the array\r
- _values.shrinktofit();\r
- }\r
- void Remove(unsigned int idx){\r
- _values.remove(idx);\r
- ShrinkIfNeeded();\r
- }\r
- void Release()\r
- {\r
- sq_delete(this,SQArray);\r
- }\r
- SQObjectPtrVec _values;\r
-};\r
-#endif //_SQARRAY_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQARRAY_H_
+#define _SQARRAY_H_
+
+struct SQArray : public CHAINABLE_OBJ
+{
+private:
+ SQArray(SQSharedState *ss,int nsize){_values.resize(nsize);_uiRef=0;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}
+ ~SQArray()
+ {
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+ }
+public:
+ static SQArray* Create(SQSharedState *ss,int nInitialSize){
+ SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray));
+ new (newarray) SQArray(ss,nInitialSize);
+ return newarray;
+ }
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+#endif
+ void Finalize(){
+ _values.resize(0);
+ }
+ bool Get(const int nidx,SQObjectPtr &val)
+ {
+ if(nidx>=0 && nidx<(int)_values.size()){
+ val=_values[nidx];
+ return true;
+ }
+ else return false;
+ }
+ bool Set(const int nidx,const SQObjectPtr &val)
+ {
+ if(nidx>=0 && nidx<(int)_values.size()){
+ _values[nidx]=val;
+ return true;
+ }
+ else return false;
+ }
+ int Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval)
+ {
+ unsigned int idx=TranslateIndex(refpos);
+ while(idx<_values.size()){
+ //first found
+ outkey=(SQInteger)idx;
+ outval=_values[idx];
+ //return idx for the next iteration
+ return ++idx;
+ }
+ //nothing to iterate anymore
+ return -1;
+ }
+ SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),Size()); anew->_values.copy(_values); return anew; }
+ int Size() const {return _values.size();}
+ void Resize(int size,SQObjectPtr &fill = _null_) { _values.resize(size,fill); ShrinkIfNeeded(); }
+ void Reserve(int size) { _values.reserve(size); }
+ void Append(const SQObject &o){_values.push_back(o);}
+ void Extend(const SQArray *a);
+ SQObjectPtr &Top(){return _values.top();}
+ void Pop(){_values.pop_back(); ShrinkIfNeeded(); }
+ void Insert(const SQObject& idx,const SQObject &val){_values.insert((unsigned int)tointeger(idx),val);}
+ void ShrinkIfNeeded() {
+ if(_values.size() <= _values.capacity()>>2) //shrink the array
+ _values.shrinktofit();
+ }
+ void Remove(unsigned int idx){
+ _values.remove(idx);
+ ShrinkIfNeeded();
+ }
+ void Release()
+ {
+ sq_delete(this,SQArray);
+ }
+ SQObjectPtrVec _values;
+};
+#endif //_SQARRAY_H_
-/*\r
- see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include "sqvm.h"\r
-#include "sqstring.h"\r
-#include "sqtable.h"\r
-#include "sqarray.h"\r
-#include "sqfuncproto.h"\r
-#include "sqclosure.h"\r
-#include "sqclass.h"\r
-#include <stdlib.h>\r
-#include <stdarg.h>\r
-#include <ctype.h>\r
-\r
-bool str2num(const SQChar *s,SQObjectPtr &res)\r
-{\r
- SQChar *end;\r
- if(scstrstr(s,_SC("."))){\r
- SQFloat r = SQFloat(scstrtod(s,&end));\r
- if(s == end) return false;\r
- while (scisspace((*end)) ) end++;\r
- if (*end != _SC('\0')) return false;\r
- res = r;\r
- return true;\r
- }\r
- else{\r
- const SQChar *t = s;\r
- while(*t != _SC('\0')) if(!scisdigit(*t++)) return false;\r
- res = SQInteger(scatoi(s));\r
- return true;\r
- }\r
-}\r
-\r
-#ifndef NO_GARBAGE_COLLECTOR\r
-static int base_collectgarbage(HSQUIRRELVM v)\r
-{\r
- sq_pushinteger(v, sq_collectgarbage(v));\r
- return 1;\r
-}\r
-#endif\r
-\r
-static int base_getroottable(HSQUIRRELVM v)\r
-{\r
- v->Push(v->_roottable);\r
- return 1;\r
-}\r
-\r
-static int base_setroottable(HSQUIRRELVM v)\r
-{\r
- SQObjectPtr &o=stack_get(v,2);\r
- if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR;\r
- v->Push(o);\r
- return 1;\r
-}\r
-\r
-static int base_seterrorhandler(HSQUIRRELVM v)\r
-{\r
- sq_seterrorhandler(v);\r
- return 0;\r
-}\r
-\r
-static int base_setdebughook(HSQUIRRELVM v)\r
-{\r
- sq_setdebughook(v);\r
- return 0;\r
-}\r
-\r
-static int base_enabledebuginfo(HSQUIRRELVM v)\r
-{\r
- SQObjectPtr &o=stack_get(v,2);\r
- sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0);\r
- return 0;\r
-}\r
-\r
-static int base_getstackinfos(HSQUIRRELVM v)\r
-{\r
- SQInteger level;\r
- SQStackInfos si;\r
- int seq = 0;\r
- const SQChar *name = NULL;\r
- sq_getinteger(v, -1, &level);\r
- if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))\r
- {\r
- const SQChar *fn = _SC("unknown");\r
- const SQChar *src = _SC("unknown");\r
- if(si.funcname)fn = si.funcname;\r
- if(si.source)src = si.source;\r
- sq_newtable(v);\r
- sq_pushstring(v, _SC("func"), -1);\r
- sq_pushstring(v, fn, -1);\r
- sq_createslot(v, -3);\r
- sq_pushstring(v, _SC("src"), -1);\r
- sq_pushstring(v, src, -1);\r
- sq_createslot(v, -3);\r
- sq_pushstring(v, _SC("line"), -1);\r
- sq_pushinteger(v, si.line);\r
- sq_createslot(v, -3);\r
- sq_pushstring(v, _SC("locals"), -1);\r
- sq_newtable(v);\r
- seq=0;\r
- while (name = sq_getlocal(v, level, seq)) {\r
- sq_pushstring(v, name, -1);\r
- sq_push(v, -2);\r
- sq_createslot(v, -4);\r
- sq_pop(v, 1);\r
- seq++;\r
- }\r
- sq_createslot(v, -3);\r
- return 1;\r
- }\r
-\r
- return 0;\r
-}\r
-\r
-static int base_assert(HSQUIRRELVM v)\r
-{\r
- if(v->IsFalse(stack_get(v,2))){\r
- return sq_throwerror(v,_SC("assertion failed"));\r
- }\r
- return 0;\r
-}\r
-\r
-static int get_slice_params(HSQUIRRELVM v,int &sidx,int &eidx,SQObjectPtr &o)\r
-{\r
- int top = sq_gettop(v);\r
- sidx=0;\r
- eidx=0;\r
- o=stack_get(v,1);\r
- SQObjectPtr &start=stack_get(v,2);\r
- if(type(start)!=OT_NULL && sq_isnumeric(start)){\r
- sidx=tointeger(start);\r
- }\r
- if(top>2){\r
- SQObjectPtr &end=stack_get(v,3);\r
- if(sq_isnumeric(end)){\r
- eidx=tointeger(end);\r
- }\r
- }\r
- else {\r
- eidx = sq_getsize(v,1);\r
- }\r
- return 1;\r
-}\r
-\r
-static int base_print(HSQUIRRELVM v)\r
-{\r
- SQObjectPtr &o=stack_get(v,2);\r
- switch(type(o)){\r
- case OT_STRING:\r
- if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),_stringval(o));\r
- break;\r
- case OT_INTEGER:\r
- if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%d"),_integer(o));\r
- break;\r
- case OT_FLOAT:\r
- if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%.14g"),_float(o));\r
- break;\r
- default:{\r
- SQObjectPtr tname;\r
- v->TypeOf(o,tname);\r
- if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("(%s)"),_stringval(tname));\r
- }\r
- break;\r
- }\r
- return 0;\r
-}\r
-\r
-static int base_compilestring(HSQUIRRELVM v)\r
-{\r
- int nargs=sq_gettop(v);\r
- const SQChar *src=NULL,*name=_SC("unnamedbuffer");\r
- SQInteger size;\r
- sq_getstring(v,2,&src);\r
- size=sq_getsize(v,2);\r
- if(nargs>2){\r
- sq_getstring(v,3,&name);\r
- }\r
- if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse)))\r
- return 1;\r
- else\r
- return SQ_ERROR;\r
-}\r
-\r
-static int base_newthread(HSQUIRRELVM v)\r
-{\r
- SQObjectPtr &func = stack_get(v,2);\r
- int stksize = (_funcproto(_closure(func)->_function)->_stacksize << 1) +2;\r
- HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize);\r
- sq_move(newv,v,-2);\r
- return 1;\r
-}\r
-\r
-static int base_suspend(HSQUIRRELVM v)\r
-{\r
- return sq_suspendvm(v);\r
-}\r
-\r
-static int base_array(HSQUIRRELVM v)\r
-{\r
- SQArray *a;\r
- SQObject &size = stack_get(v,2);\r
- if(sq_gettop(v) > 2) {\r
- a = SQArray::Create(_ss(v),0);\r
- a->Resize(tointeger(size),stack_get(v,3));\r
- }\r
- else {\r
- a = SQArray::Create(_ss(v),tointeger(size));\r
- }\r
- v->Push(a);\r
- return 1;\r
-}\r
-\r
-static int base_type(HSQUIRRELVM v)\r
-{\r
- SQObjectPtr &o = stack_get(v,2);\r
- v->Push(SQString::Create(_ss(v),GetTypeName(o),-1));\r
- return 1;\r
-}\r
-\r
-static SQRegFunction base_funcs[]={\r
- //generic\r
- {_SC("seterrorhandler"),base_seterrorhandler,2, NULL},\r
- {_SC("setdebughook"),base_setdebughook,2, NULL},\r
- {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL},\r
- {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},\r
- {_SC("getroottable"),base_getroottable,1, NULL},\r
- {_SC("setroottable"),base_setroottable,2, NULL},\r
- {_SC("assert"),base_assert,2, NULL},\r
- {_SC("print"),base_print,2, NULL},\r
- {_SC("compilestring"),base_compilestring,-2, _SC(".ss")},\r
- {_SC("newthread"),base_newthread,2, _SC(".c")},\r
- {_SC("suspend"),base_suspend,-1, NULL},\r
- {_SC("array"),base_array,-2, _SC(".n")},\r
- {_SC("type"),base_type,2, NULL},\r
-#ifndef NO_GARBAGE_COLLECTOR\r
- {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")},\r
-#endif\r
- {0,0}\r
-};\r
-\r
-void sq_base_register(HSQUIRRELVM v)\r
-{\r
- int i=0;\r
- sq_pushroottable(v);\r
- while(base_funcs[i].name!=0) {\r
- sq_pushstring(v,base_funcs[i].name,-1);\r
- sq_newclosure(v,base_funcs[i].f,0);\r
- sq_setnativeclosurename(v,-1,base_funcs[i].name);\r
- sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);\r
- sq_createslot(v,-3);\r
- i++;\r
- }\r
- sq_pushstring(v,_SC("_charsize_"),-1);\r
- sq_pushinteger(v,sizeof(SQChar));\r
- sq_createslot(v,-3);\r
- sq_pop(v,1);\r
-}\r
-\r
-static int default_delegate_len(HSQUIRRELVM v)\r
-{\r
- v->Push(SQInteger(sq_getsize(v,1)));\r
- return 1;\r
-}\r
-\r
-static int default_delegate_tofloat(HSQUIRRELVM v)\r
-{\r
- SQObjectPtr &o=stack_get(v,1);\r
- switch(type(o)){\r
- case OT_STRING:{\r
- SQObjectPtr res;\r
- if(str2num(_stringval(o),res)){\r
- v->Push(SQObjectPtr(tofloat(res)));\r
- break;\r
- }}\r
- case OT_INTEGER:case OT_FLOAT:\r
- v->Push(SQObjectPtr(tofloat(o)));\r
- break;\r
- case OT_BOOL:\r
- v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0)));\r
- break;\r
- default:\r
- v->Push(_null_);\r
- break;\r
- }\r
- return 1;\r
-}\r
-\r
-static int default_delegate_tointeger(HSQUIRRELVM v)\r
-{\r
- SQObjectPtr &o=stack_get(v,1);\r
- switch(type(o)){\r
- case OT_STRING:{\r
- SQObjectPtr res;\r
- if(str2num(_stringval(o),res)){\r
- v->Push(SQObjectPtr(tointeger(res)));\r
- break;\r
- }}\r
- case OT_INTEGER:case OT_FLOAT:\r
- v->Push(SQObjectPtr(tointeger(o)));\r
- break;\r
- case OT_BOOL:\r
- v->Push(SQObjectPtr(_integer(o)?1:0));\r
- break;\r
- default:\r
- v->Push(_null_);\r
- break;\r
- }\r
- return 1;\r
-}\r
-\r
-static int default_delegate_tostring(HSQUIRRELVM v)\r
-{\r
- SQObjectPtr &o=stack_get(v,1);\r
- switch(type(o)){\r
- case OT_STRING:\r
- v->Push(o);\r
- break;\r
- case OT_INTEGER:\r
- scsprintf(_ss(v)->GetScratchPad(rsl(NUMBER_MAX_CHAR+1)),_SC("%d"),_integer(o));\r
- v->Push(SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1)));\r
- break;\r
- case OT_FLOAT:\r
- scsprintf(_ss(v)->GetScratchPad(rsl(NUMBER_MAX_CHAR+1)),_SC("%.14g"),_float(o));\r
- v->Push(SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1)));\r
- break;\r
- case OT_BOOL:\r
- v->Push(SQObjectPtr(SQString::Create(_ss(v),_integer(o)?_SC("true"):_SC("false"))));\r
- break;\r
- default:\r
- v->Push(_null_);\r
- break;\r
- }\r
- return 1;\r
-}\r
-\r
-static int number_delegate_tochar(HSQUIRRELVM v)\r
-{\r
- SQObject &o=stack_get(v,1);\r
- SQChar c=tointeger(o);\r
- v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1));\r
- return 1;\r
-}\r
-\r
-\r
-/////////////////////////////////////////////////////////////////\r
-//TABLE DEFAULT DELEGATE\r
-\r
-static int table_rawdelete(HSQUIRRELVM v)\r
-{\r
- if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue)))\r
- return SQ_ERROR;\r
- return 1;\r
-}\r
-\r
-\r
-static int container_rawexists(HSQUIRRELVM v)\r
-{\r
- if(SQ_SUCCEEDED(sq_rawget(v,-2))) {\r
- sq_pushbool(v,SQTrue);\r
- return 1;\r
- }\r
- sq_pushbool(v,SQFalse);\r
- return 1;\r
-}\r
-\r
-static int table_rawset(HSQUIRRELVM v)\r
-{\r
- return sq_rawset(v,-3);\r
-}\r
-\r
-\r
-static int table_rawget(HSQUIRRELVM v)\r
-{\r
- return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;\r
-}\r
-\r
-SQRegFunction SQSharedState::_table_default_delegate_funcz[]={\r
- {_SC("len"),default_delegate_len,1, _SC("t")},\r
- {_SC("rawget"),table_rawget,2, _SC("t")},\r
- {_SC("rawset"),table_rawset,3, _SC("t")},\r
- {_SC("rawdelete"),table_rawdelete,2, _SC("t")},\r
- {_SC("rawin"),container_rawexists,2, _SC("t")},\r
- {0,0}\r
-};\r
-\r
-//ARRAY DEFAULT DELEGATE///////////////////////////////////////\r
-\r
-static int array_append(HSQUIRRELVM v)\r
-{\r
- return sq_arrayappend(v,-2);\r
-}\r
-\r
-static int array_extend(HSQUIRRELVM v)\r
-{\r
- _array(stack_get(v,1))->Extend(_array(stack_get(v,2)));\r
- return 0;\r
-}\r
-\r
-static int array_reverse(HSQUIRRELVM v)\r
-{\r
- return sq_arrayreverse(v,-1);\r
-}\r
-\r
-static int array_pop(HSQUIRRELVM v)\r
-{\r
- return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR;\r
-}\r
-\r
-static int array_top(HSQUIRRELVM v)\r
-{\r
- SQObject &o=stack_get(v,1);\r
- if(_array(o)->Size()>0){\r
- v->Push(_array(o)->Top());\r
- return 1;\r
- }\r
- else return sq_throwerror(v,_SC("top() on a empty array"));\r
-}\r
-\r
-static int array_insert(HSQUIRRELVM v)\r
-{\r
- SQObject &o=stack_get(v,1);\r
- SQObject &idx=stack_get(v,2);\r
- SQObject &val=stack_get(v,3);\r
- _array(o)->Insert(idx,val);\r
- return 0;\r
-}\r
-\r
-static int array_remove(HSQUIRRELVM v)\r
-{\r
- SQObject &o = stack_get(v, 1);\r
- SQObject &idx = stack_get(v, 2);\r
- if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type"));\r
- SQObjectPtr val;\r
- if(_array(o)->Get(tointeger(idx), val)) {\r
- _array(o)->Remove(tointeger(idx));\r
- v->Push(val);\r
- return 1;\r
- }\r
- return sq_throwerror(v, _SC("idx out of range"));\r
-}\r
-\r
-static int array_resize(HSQUIRRELVM v)\r
-{\r
- SQObject &o = stack_get(v, 1);\r
- SQObject &nsize = stack_get(v, 2);\r
- SQObjectPtr fill;\r
- if(sq_isnumeric(nsize)) {\r
- if(sq_gettop(v) > 2)\r
- fill = stack_get(v, 3);\r
- _array(o)->Resize(tointeger(nsize),fill);\r
- return 0;\r
- }\r
- return sq_throwerror(v, _SC("size must be a number"));\r
-}\r
-\r
-\r
-//QSORT ala Sedgewick\r
-bool _qsort_compare(HSQUIRRELVM v,SQObjectPtr &arr,SQObjectPtr &a,SQObjectPtr &b,int func,int &ret)\r
-{\r
- if(func < 0) {\r
- if(!v->ObjCmp(a,b,ret)) return false;\r
- }\r
- else {\r
- int top = sq_gettop(v);\r
- sq_push(v, func);\r
- sq_pushroottable(v);\r
- v->Push(a);\r
- v->Push(b);\r
- if(SQ_FAILED(sq_call(v, 3, SQTrue))) {\r
- v->Raise_Error(_SC("compare func failed"));\r
- return false;\r
- }\r
- sq_getinteger(v, -1, &ret);\r
- sq_settop(v, top);\r
- return true;\r
- }\r
- return true;\r
-}\r
-//QSORT ala Sedgewick\r
-bool _qsort(HSQUIRRELVM v,SQObjectPtr &arr, int l, int r,int func)\r
-{\r
- int i, j;\r
- SQArray *a=_array(arr);\r
- SQObjectPtr pivot,t;\r
- if( l < r ){\r
- pivot = a->_values[l];\r
- i = l; j = r+1;\r
- while(1){\r
- int ret;\r
- do { \r
- ++i; \r
- if(i > r) break;\r
- if(!_qsort_compare(v,arr,a->_values[i],pivot,func,ret))\r
- return false;\r
- } while( ret <= 0);\r
- do {\r
- --j; \r
- if(!_qsort_compare(v,arr,a->_values[j],pivot,func,ret))\r
- return false;\r
- }\r
- while( ret > 0 );\r
- if( i >= j ) break;\r
- t = a->_values[i]; a->_values[i] = a->_values[j]; a->_values[j] = t;\r
- }\r
- t = a->_values[l]; a->_values[l] = a->_values[j]; a->_values[j] = t;\r
- if(!_qsort( v, arr, l, j-1,func)) return false;\r
- if(!_qsort( v, arr, j+1, r,func)) return false;\r
- }\r
- return true;\r
-}\r
-\r
-static int array_sort(HSQUIRRELVM v)\r
-{\r
- //SQ_TRY {\r
- int func = -1;\r
- SQObjectPtr &o = stack_get(v,1);\r
- SQObject &funcobj = stack_get(v,2);\r
- if(_array(o)->Size() > 1) {\r
- if(type(funcobj) == OT_CLOSURE || type(funcobj) == OT_NATIVECLOSURE) func = 2;\r
- if(!_qsort(v, o, 0, _array(o)->Size()-1, func))\r
- return SQ_ERROR;\r
-\r
- }\r
- return 0;\r
-}\r
-static int array_slice(HSQUIRRELVM v)\r
-{\r
- int sidx,eidx;\r
- SQObjectPtr o;\r
- if(get_slice_params(v,sidx,eidx,o)==-1)return -1;\r
- if(sidx<0)sidx=_array(o)->Size()+sidx;\r
- if(eidx<0)eidx=_array(o)->Size()+eidx;\r
- if(eidx <= sidx)return sq_throwerror(v,_SC("wrong indexes"));\r
- SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);\r
- SQObjectPtr t;\r
- int count=0;\r
- for(int i=sidx;i<eidx;i++){\r
- _array(o)->Get(i,t);\r
- arr->Set(count++,t);\r
- }\r
- v->Push(arr);\r
- return 1;\r
- \r
-}\r
-\r
-SQRegFunction SQSharedState::_array_default_delegate_funcz[]={\r
- {_SC("len"),default_delegate_len,1, _SC("a")},\r
- {_SC("append"),array_append,2, _SC("a")},\r
- {_SC("extend"),array_extend,2, _SC("aa")},\r
- {_SC("push"),array_append,2, _SC("a")},\r
- {_SC("pop"),array_pop,1, _SC("a")},\r
- {_SC("top"),array_top,1, _SC("a")},\r
- {_SC("insert"),array_insert,3, _SC("an")},\r
- {_SC("remove"),array_remove,2, _SC("an")},\r
- {_SC("resize"),array_resize,-2, _SC("an")},\r
- {_SC("reverse"),array_reverse,1, _SC("a")},\r
- {_SC("sort"),array_sort,-1, _SC("ac")},\r
- {_SC("slice"),array_slice,-1, _SC("ann")},\r
- {0,0}\r
-};\r
-\r
-//STRING DEFAULT DELEGATE//////////////////////////\r
-static int string_slice(HSQUIRRELVM v)\r
-{\r
- int sidx,eidx;\r
- SQObjectPtr o;\r
- if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;\r
- if(sidx<0)sidx=_string(o)->_len+sidx;\r
- if(eidx<0)eidx=_string(o)->_len+eidx;\r
- if(eidx<sidx)\r
- return sq_throwerror(v,_SC("wrong indexes"));\r
- v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));\r
- return 1;\r
-}\r
-\r
-static int string_find(HSQUIRRELVM v)\r
-{\r
- int top,start_idx=0;\r
- const SQChar *str,*substr,*ret;\r
- if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){\r
- if(top>2)sq_getinteger(v,3,&start_idx);\r
- if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){\r
- ret=scstrstr(&str[start_idx],substr);\r
- if(ret){\r
- sq_pushinteger(v,(int)(ret-str));\r
- return 1;\r
- }\r
- }\r
- return 0;\r
- }\r
- return sq_throwerror(v,_SC("invalid param"));\r
-}\r
-\r
-#define STRING_TOFUNCZ(func) static int string_##func(HSQUIRRELVM v) \\r
-{ \\r
- SQObject str=stack_get(v,1); \\r
- int len=_string(str)->_len; \\r
- const SQChar *sThis=_stringval(str); \\r
- SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \\r
- for(int i=0;i<len;i++) sNew[i]=func(sThis[i]); \\r
- v->Push(SQString::Create(_ss(v),sNew,len)); \\r
- return 1; \\r
-}\r
-\r
-\r
-STRING_TOFUNCZ(tolower)\r
-STRING_TOFUNCZ(toupper)\r
-\r
-SQRegFunction SQSharedState::_string_default_delegate_funcz[]={\r
- {_SC("len"),default_delegate_len,1, _SC("s")},\r
- {_SC("tointeger"),default_delegate_tointeger,1, _SC("s")},\r
- {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")},\r
- {_SC("tostring"),default_delegate_tostring,1, _SC("s")},\r
- {_SC("slice"),string_slice,-1, _SC(" s n n")},\r
- {_SC("find"),string_find,-2, _SC("s s n ")},\r
- {_SC("tolower"),string_tolower,1, _SC("s")},\r
- {_SC("toupper"),string_toupper,1, _SC("s")},\r
- {0,0}\r
-};\r
-\r
-//INTEGER DEFAULT DELEGATE//////////////////////////\r
-SQRegFunction SQSharedState::_number_default_delegate_funcz[]={\r
- {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")},\r
- {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")},\r
- {_SC("tostring"),default_delegate_tostring,1, _SC("n|b")},\r
- {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},\r
- {0,0}\r
-};\r
-\r
-//CLOSURE DEFAULT DELEGATE//////////////////////////\r
-static int closure_call(HSQUIRRELVM v)\r
-{\r
- return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue))?1:SQ_ERROR;\r
-}\r
-\r
-static int closure_acall(HSQUIRRELVM v)\r
-{\r
- SQArray *aparams=_array(stack_get(v,2));\r
- int nparams=aparams->Size();\r
- v->Push(stack_get(v,1));\r
- for(int i=0;i<nparams;i++)v->Push(aparams->_values[i]);\r
- return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue))?1:SQ_ERROR;\r
-}\r
-\r
-SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={\r
- {_SC("call"),closure_call,-1, _SC("c")},\r
- {_SC("acall"),closure_acall,2, _SC("ca")},\r
- {0,0}\r
-};\r
-\r
-//GENERATOR DEFAULT DELEGATE\r
-static int generator_getstatus(HSQUIRRELVM v)\r
-{\r
- SQObject &o=stack_get(v,1);\r
- switch(_generator(o)->_state){\r
- case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break;\r
- case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break;\r
- case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break;\r
- }\r
- return 1;\r
-}\r
-\r
-SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={\r
- {_SC("getstatus"),generator_getstatus,1, _SC("g")},\r
- {0,0}\r
-};\r
-\r
-//THREAD DEFAULT DELEGATE\r
-\r
-static int thread_call(HSQUIRRELVM v)\r
-{\r
- SQObjectPtr o = stack_get(v,1);\r
- if(type(o) == OT_THREAD) {\r
- int nparams = sq_gettop(v);\r
- _thread(o)->Push(_thread(o)->_roottable);\r
- for(int i = 2; i<(nparams+1); i++)\r
- sq_move(_thread(o),v,i);\r
- if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue))) {\r
- sq_move(v,_thread(o),-1);\r
- return 1;\r
- }\r
- return SQ_ERROR;\r
- }\r
- return sq_throwerror(v,_SC("wrong parameter"));\r
-}\r
-\r
-static int thread_wakeup(HSQUIRRELVM v)\r
-{\r
- SQObjectPtr o = stack_get(v,1);\r
- if(type(o) == OT_THREAD) {\r
- SQVM *thread = _thread(o);\r
- int state = sq_getvmstate(thread);\r
- if(state != SQ_VMSTATE_SUSPENDED) {\r
- switch(state) {\r
- case SQ_VMSTATE_IDLE:\r
- return sq_throwerror(v,_SC("cannot wakeup a idle thread"));\r
- break;\r
- case SQ_VMSTATE_RUNNING:\r
- return sq_throwerror(v,_SC("cannot wakeup a running thread"));\r
- break;\r
- }\r
- }\r
- \r
- int wakeupret = sq_gettop(v)>1?1:0;\r
- if(wakeupret) {\r
- sq_move(thread,v,2);\r
- }\r
- if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,1))) {\r
- sq_move(v,thread,-1);\r
- sq_pop(thread,1);\r
- if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {\r
- sq_pop(thread,1);\r
- }\r
- return 1;\r
- }\r
- return SQ_ERROR;\r
- }\r
- return sq_throwerror(v,_SC("wrong parameter"));\r
-}\r
-\r
-static int thread_getstatus(HSQUIRRELVM v)\r
-{\r
- SQObjectPtr &o = stack_get(v,1);\r
- switch(sq_getvmstate(_thread(o))) {\r
- case SQ_VMSTATE_IDLE:\r
- sq_pushstring(v,_SC("idle"),-1);\r
- break;\r
- case SQ_VMSTATE_RUNNING:\r
- sq_pushstring(v,_SC("running"),-1);\r
- break;\r
- case SQ_VMSTATE_SUSPENDED:\r
- sq_pushstring(v,_SC("suspended"),-1);\r
- break;\r
- default:\r
- return sq_throwerror(v,_SC("internal VM error"));\r
- }\r
- return 1;\r
-}\r
-\r
-SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {\r
- {_SC("call"), thread_call, -1, _SC("v")},\r
- {_SC("wakeup"), thread_wakeup, -1, _SC("v")},\r
- {_SC("getstatus"), thread_getstatus, 1, _SC("v")},\r
- {0,0},\r
-};\r
-\r
-static int class_getattributes(HSQUIRRELVM v)\r
-{\r
- if(SQ_SUCCEEDED(sq_getattributes(v,-2)))\r
- return 1;\r
- return SQ_ERROR;\r
-}\r
-\r
-static int class_setattributes(HSQUIRRELVM v)\r
-{\r
- if(SQ_SUCCEEDED(sq_setattributes(v,-3)))\r
- return 1;\r
- return SQ_ERROR;\r
-}\r
-\r
-SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {\r
- {_SC("getattributes"), class_getattributes, 2, _SC("y.")},\r
- {_SC("setattributes"), class_setattributes, 3, _SC("y..")},\r
- {_SC("rawin"),container_rawexists,2, _SC("y")},\r
- {0,0}\r
-};\r
-\r
-static int instance_getclass(HSQUIRRELVM v)\r
-{\r
- if(SQ_SUCCEEDED(sq_getclass(v,1)))\r
- return 1;\r
- return SQ_ERROR;\r
-}\r
-\r
-SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {\r
- {_SC("getclass"), instance_getclass, 1, _SC("x")},\r
- {_SC("rawin"),container_rawexists,2, _SC("x")},\r
- {0,0}\r
-};\r
-\r
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqvm.h"
+#include "sqstring.h"
+#include "sqtable.h"
+#include "sqarray.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+#include "sqclass.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+bool str2num(const SQChar *s,SQObjectPtr &res)
+{
+ SQChar *end;
+ if(scstrstr(s,_SC("."))){
+ SQFloat r = SQFloat(scstrtod(s,&end));
+ if(s == end) return false;
+ while (scisspace((*end)) ) end++;
+ if (*end != _SC('\0')) return false;
+ res = r;
+ return true;
+ }
+ else{
+ const SQChar *t = s;
+ while(*t != _SC('\0')) if(!scisdigit(*t++)) return false;
+ res = SQInteger(scatoi(s));
+ return true;
+ }
+}
+
+#ifndef NO_GARBAGE_COLLECTOR
+static int base_collectgarbage(HSQUIRRELVM v)
+{
+ sq_pushinteger(v, sq_collectgarbage(v));
+ return 1;
+}
+#endif
+
+static int base_getroottable(HSQUIRRELVM v)
+{
+ v->Push(v->_roottable);
+ return 1;
+}
+
+static int base_setroottable(HSQUIRRELVM v)
+{
+ SQObjectPtr &o=stack_get(v,2);
+ if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR;
+ v->Push(o);
+ return 1;
+}
+
+static int base_seterrorhandler(HSQUIRRELVM v)
+{
+ sq_seterrorhandler(v);
+ return 0;
+}
+
+static int base_setdebughook(HSQUIRRELVM v)
+{
+ sq_setdebughook(v);
+ return 0;
+}
+
+static int base_enabledebuginfo(HSQUIRRELVM v)
+{
+ SQObjectPtr &o=stack_get(v,2);
+ sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0);
+ return 0;
+}
+
+static int base_getstackinfos(HSQUIRRELVM v)
+{
+ SQInteger level;
+ SQStackInfos si;
+ int seq = 0;
+ const SQChar *name = NULL;
+ sq_getinteger(v, -1, &level);
+ if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))
+ {
+ const SQChar *fn = _SC("unknown");
+ const SQChar *src = _SC("unknown");
+ if(si.funcname)fn = si.funcname;
+ if(si.source)src = si.source;
+ sq_newtable(v);
+ sq_pushstring(v, _SC("func"), -1);
+ sq_pushstring(v, fn, -1);
+ sq_createslot(v, -3);
+ sq_pushstring(v, _SC("src"), -1);
+ sq_pushstring(v, src, -1);
+ sq_createslot(v, -3);
+ sq_pushstring(v, _SC("line"), -1);
+ sq_pushinteger(v, si.line);
+ sq_createslot(v, -3);
+ sq_pushstring(v, _SC("locals"), -1);
+ sq_newtable(v);
+ seq=0;
+ while ( (name = sq_getlocal(v, level, seq)) ) {
+ sq_pushstring(v, name, -1);
+ sq_push(v, -2);
+ sq_createslot(v, -4);
+ sq_pop(v, 1);
+ seq++;
+ }
+ sq_createslot(v, -3);
+ return 1;
+ }
+
+ return 0;
+}
+
+static int base_assert(HSQUIRRELVM v)
+{
+ if(v->IsFalse(stack_get(v,2))){
+ return sq_throwerror(v,_SC("assertion failed"));
+ }
+ return 0;
+}
+
+static int get_slice_params(HSQUIRRELVM v,int &sidx,int &eidx,SQObjectPtr &o)
+{
+ int top = sq_gettop(v);
+ sidx=0;
+ eidx=0;
+ o=stack_get(v,1);
+ SQObjectPtr &start=stack_get(v,2);
+ if(type(start)!=OT_NULL && sq_isnumeric(start)){
+ sidx=tointeger(start);
+ }
+ if(top>2){
+ SQObjectPtr &end=stack_get(v,3);
+ if(sq_isnumeric(end)){
+ eidx=tointeger(end);
+ }
+ }
+ else {
+ eidx = sq_getsize(v,1);
+ }
+ return 1;
+}
+
+static int base_print(HSQUIRRELVM v)
+{
+ SQObjectPtr &o=stack_get(v,2);
+ switch(type(o)){
+ case OT_STRING:
+ if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),_stringval(o));
+ break;
+ case OT_INTEGER:
+ if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%d"),_integer(o));
+ break;
+ case OT_FLOAT:
+ if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%.14g"),_float(o));
+ break;
+ default:{
+ SQObjectPtr tname;
+ v->TypeOf(o,tname);
+ if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("(%s)"),_stringval(tname));
+ }
+ break;
+ }
+ return 0;
+}
+
+static int base_compilestring(HSQUIRRELVM v)
+{
+ int nargs=sq_gettop(v);
+ const SQChar *src=NULL,*name=_SC("unnamedbuffer");
+ SQInteger size;
+ sq_getstring(v,2,&src);
+ size=sq_getsize(v,2);
+ if(nargs>2){
+ sq_getstring(v,3,&name);
+ }
+ if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse)))
+ return 1;
+ else
+ return SQ_ERROR;
+}
+
+static int base_newthread(HSQUIRRELVM v)
+{
+ SQObjectPtr &func = stack_get(v,2);
+ int stksize = (_funcproto(_closure(func)->_function)->_stacksize << 1) +2;
+ HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize);
+ sq_move(newv,v,-2);
+ return 1;
+}
+
+static int base_suspend(HSQUIRRELVM v)
+{
+ return sq_suspendvm(v);
+}
+
+static int base_array(HSQUIRRELVM v)
+{
+ SQArray *a;
+ SQObject &size = stack_get(v,2);
+ if(sq_gettop(v) > 2) {
+ a = SQArray::Create(_ss(v),0);
+ a->Resize(tointeger(size),stack_get(v,3));
+ }
+ else {
+ a = SQArray::Create(_ss(v),tointeger(size));
+ }
+ v->Push(a);
+ return 1;
+}
+
+static int base_type(HSQUIRRELVM v)
+{
+ SQObjectPtr &o = stack_get(v,2);
+ v->Push(SQString::Create(_ss(v),GetTypeName(o),-1));
+ return 1;
+}
+
+static SQRegFunction base_funcs[]={
+ //generic
+ {_SC("seterrorhandler"),base_seterrorhandler,2, NULL},
+ {_SC("setdebughook"),base_setdebughook,2, NULL},
+ {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL},
+ {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},
+ {_SC("getroottable"),base_getroottable,1, NULL},
+ {_SC("setroottable"),base_setroottable,2, NULL},
+ {_SC("assert"),base_assert,2, NULL},
+ {_SC("print"),base_print,2, NULL},
+ {_SC("compilestring"),base_compilestring,-2, _SC(".ss")},
+ {_SC("newthread"),base_newthread,2, _SC(".c")},
+ {_SC("suspend"),base_suspend,-1, NULL},
+ {_SC("array"),base_array,-2, _SC(".n")},
+ {_SC("type"),base_type,2, NULL},
+#ifndef NO_GARBAGE_COLLECTOR
+ {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")},
+#endif
+ {0,0,0,0}
+};
+
+void sq_base_register(HSQUIRRELVM v)
+{
+ int i=0;
+ sq_pushroottable(v);
+ while(base_funcs[i].name!=0) {
+ sq_pushstring(v,base_funcs[i].name,-1);
+ sq_newclosure(v,base_funcs[i].f,0);
+ sq_setnativeclosurename(v,-1,base_funcs[i].name);
+ sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);
+ sq_createslot(v,-3);
+ i++;
+ }
+ sq_pushstring(v,_SC("_charsize_"),-1);
+ sq_pushinteger(v,sizeof(SQChar));
+ sq_createslot(v,-3);
+ sq_pop(v,1);
+}
+
+static int default_delegate_len(HSQUIRRELVM v)
+{
+ v->Push(SQInteger(sq_getsize(v,1)));
+ return 1;
+}
+
+static int default_delegate_tofloat(HSQUIRRELVM v)
+{
+ SQObjectPtr &o=stack_get(v,1);
+ switch(type(o)){
+ case OT_STRING:{
+ SQObjectPtr res;
+ if(str2num(_stringval(o),res)){
+ v->Push(SQObjectPtr(tofloat(res)));
+ break;
+ }}
+ case OT_INTEGER:case OT_FLOAT:
+ v->Push(SQObjectPtr(tofloat(o)));
+ break;
+ case OT_BOOL:
+ v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0)));
+ break;
+ default:
+ v->Push(_null_);
+ break;
+ }
+ return 1;
+}
+
+static int default_delegate_tointeger(HSQUIRRELVM v)
+{
+ SQObjectPtr &o=stack_get(v,1);
+ switch(type(o)){
+ case OT_STRING:{
+ SQObjectPtr res;
+ if(str2num(_stringval(o),res)){
+ v->Push(SQObjectPtr(tointeger(res)));
+ break;
+ }}
+ case OT_INTEGER:case OT_FLOAT:
+ v->Push(SQObjectPtr(tointeger(o)));
+ break;
+ case OT_BOOL:
+ v->Push(SQObjectPtr(_integer(o)?1:0));
+ break;
+ default:
+ v->Push(_null_);
+ break;
+ }
+ return 1;
+}
+
+static int default_delegate_tostring(HSQUIRRELVM v)
+{
+ SQObjectPtr &o=stack_get(v,1);
+ switch(type(o)){
+ case OT_STRING:
+ v->Push(o);
+ break;
+ case OT_INTEGER:
+ scsprintf(_ss(v)->GetScratchPad(rsl(NUMBER_MAX_CHAR+1)),_SC("%d"),_integer(o));
+ v->Push(SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1)));
+ break;
+ case OT_FLOAT:
+ scsprintf(_ss(v)->GetScratchPad(rsl(NUMBER_MAX_CHAR+1)),_SC("%.14g"),_float(o));
+ v->Push(SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1)));
+ break;
+ case OT_BOOL:
+ v->Push(SQObjectPtr(SQString::Create(_ss(v),_integer(o)?_SC("true"):_SC("false"))));
+ break;
+ default:
+ v->Push(_null_);
+ break;
+ }
+ return 1;
+}
+
+static int number_delegate_tochar(HSQUIRRELVM v)
+{
+ SQObject &o=stack_get(v,1);
+ SQChar c=tointeger(o);
+ v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1));
+ return 1;
+}
+
+
+/////////////////////////////////////////////////////////////////
+//TABLE DEFAULT DELEGATE
+
+static int table_rawdelete(HSQUIRRELVM v)
+{
+ if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue)))
+ return SQ_ERROR;
+ return 1;
+}
+
+
+static int container_rawexists(HSQUIRRELVM v)
+{
+ if(SQ_SUCCEEDED(sq_rawget(v,-2))) {
+ sq_pushbool(v,SQTrue);
+ return 1;
+ }
+ sq_pushbool(v,SQFalse);
+ return 1;
+}
+
+static int table_rawset(HSQUIRRELVM v)
+{
+ return sq_rawset(v,-3);
+}
+
+
+static int table_rawget(HSQUIRRELVM v)
+{
+ return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;
+}
+
+SQRegFunction SQSharedState::_table_default_delegate_funcz[]={
+ {_SC("len"),default_delegate_len,1, _SC("t")},
+ {_SC("rawget"),table_rawget,2, _SC("t")},
+ {_SC("rawset"),table_rawset,3, _SC("t")},
+ {_SC("rawdelete"),table_rawdelete,2, _SC("t")},
+ {_SC("rawin"),container_rawexists,2, _SC("t")},
+ {0,0,0,0}
+};
+
+//ARRAY DEFAULT DELEGATE///////////////////////////////////////
+
+static int array_append(HSQUIRRELVM v)
+{
+ return sq_arrayappend(v,-2);
+}
+
+static int array_extend(HSQUIRRELVM v)
+{
+ _array(stack_get(v,1))->Extend(_array(stack_get(v,2)));
+ return 0;
+}
+
+static int array_reverse(HSQUIRRELVM v)
+{
+ return sq_arrayreverse(v,-1);
+}
+
+static int array_pop(HSQUIRRELVM v)
+{
+ return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR;
+}
+
+static int array_top(HSQUIRRELVM v)
+{
+ SQObject &o=stack_get(v,1);
+ if(_array(o)->Size()>0){
+ v->Push(_array(o)->Top());
+ return 1;
+ }
+ else return sq_throwerror(v,_SC("top() on a empty array"));
+}
+
+static int array_insert(HSQUIRRELVM v)
+{
+ SQObject &o=stack_get(v,1);
+ SQObject &idx=stack_get(v,2);
+ SQObject &val=stack_get(v,3);
+ _array(o)->Insert(idx,val);
+ return 0;
+}
+
+static int array_remove(HSQUIRRELVM v)
+{
+ SQObject &o = stack_get(v, 1);
+ SQObject &idx = stack_get(v, 2);
+ if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type"));
+ SQObjectPtr val;
+ if(_array(o)->Get(tointeger(idx), val)) {
+ _array(o)->Remove(tointeger(idx));
+ v->Push(val);
+ return 1;
+ }
+ return sq_throwerror(v, _SC("idx out of range"));
+}
+
+static int array_resize(HSQUIRRELVM v)
+{
+ SQObject &o = stack_get(v, 1);
+ SQObject &nsize = stack_get(v, 2);
+ SQObjectPtr fill;
+ if(sq_isnumeric(nsize)) {
+ if(sq_gettop(v) > 2)
+ fill = stack_get(v, 3);
+ _array(o)->Resize(tointeger(nsize),fill);
+ return 0;
+ }
+ return sq_throwerror(v, _SC("size must be a number"));
+}
+
+
+//QSORT ala Sedgewick
+bool _qsort_compare(HSQUIRRELVM v,SQObjectPtr &arr,SQObjectPtr &a,SQObjectPtr &b,int func,int &ret)
+{
+ (void) arr;
+
+ if(func < 0) {
+ if(!v->ObjCmp(a,b,ret)) return false;
+ }
+ else {
+ int top = sq_gettop(v);
+ sq_push(v, func);
+ sq_pushroottable(v);
+ v->Push(a);
+ v->Push(b);
+ if(SQ_FAILED(sq_call(v, 3, SQTrue))) {
+ v->Raise_Error(_SC("compare func failed"));
+ return false;
+ }
+ sq_getinteger(v, -1, &ret);
+ sq_settop(v, top);
+ return true;
+ }
+ return true;
+}
+//QSORT ala Sedgewick
+bool _qsort(HSQUIRRELVM v,SQObjectPtr &arr, int l, int r,int func)
+{
+ int i, j;
+ SQArray *a=_array(arr);
+ SQObjectPtr pivot,t;
+ if( l < r ){
+ pivot = a->_values[l];
+ i = l; j = r+1;
+ while(1){
+ int ret;
+ do {
+ ++i;
+ if(i > r) break;
+ if(!_qsort_compare(v,arr,a->_values[i],pivot,func,ret))
+ return false;
+ } while( ret <= 0);
+ do {
+ --j;
+ if(!_qsort_compare(v,arr,a->_values[j],pivot,func,ret))
+ return false;
+ }
+ while( ret > 0 );
+ if( i >= j ) break;
+ t = a->_values[i]; a->_values[i] = a->_values[j]; a->_values[j] = t;
+ }
+ t = a->_values[l]; a->_values[l] = a->_values[j]; a->_values[j] = t;
+ if(!_qsort( v, arr, l, j-1,func)) return false;
+ if(!_qsort( v, arr, j+1, r,func)) return false;
+ }
+ return true;
+}
+
+static int array_sort(HSQUIRRELVM v)
+{
+ //SQ_TRY {
+ int func = -1;
+ SQObjectPtr &o = stack_get(v,1);
+ SQObject &funcobj = stack_get(v,2);
+ if(_array(o)->Size() > 1) {
+ if(type(funcobj) == OT_CLOSURE || type(funcobj) == OT_NATIVECLOSURE) func = 2;
+ if(!_qsort(v, o, 0, _array(o)->Size()-1, func))
+ return SQ_ERROR;
+
+ }
+ return 0;
+}
+static int array_slice(HSQUIRRELVM v)
+{
+ int sidx,eidx;
+ SQObjectPtr o;
+ if(get_slice_params(v,sidx,eidx,o)==-1)return -1;
+ if(sidx<0)sidx=_array(o)->Size()+sidx;
+ if(eidx<0)eidx=_array(o)->Size()+eidx;
+ if(eidx <= sidx)return sq_throwerror(v,_SC("wrong indexes"));
+ SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);
+ SQObjectPtr t;
+ int count=0;
+ for(int i=sidx;i<eidx;i++){
+ _array(o)->Get(i,t);
+ arr->Set(count++,t);
+ }
+ v->Push(arr);
+ return 1;
+
+}
+
+SQRegFunction SQSharedState::_array_default_delegate_funcz[]={
+ {_SC("len"),default_delegate_len,1, _SC("a")},
+ {_SC("append"),array_append,2, _SC("a")},
+ {_SC("extend"),array_extend,2, _SC("aa")},
+ {_SC("push"),array_append,2, _SC("a")},
+ {_SC("pop"),array_pop,1, _SC("a")},
+ {_SC("top"),array_top,1, _SC("a")},
+ {_SC("insert"),array_insert,3, _SC("an")},
+ {_SC("remove"),array_remove,2, _SC("an")},
+ {_SC("resize"),array_resize,-2, _SC("an")},
+ {_SC("reverse"),array_reverse,1, _SC("a")},
+ {_SC("sort"),array_sort,-1, _SC("ac")},
+ {_SC("slice"),array_slice,-1, _SC("ann")},
+ {0,0,0,0}
+};
+
+//STRING DEFAULT DELEGATE//////////////////////////
+static int string_slice(HSQUIRRELVM v)
+{
+ int sidx,eidx;
+ SQObjectPtr o;
+ if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;
+ if(sidx<0)sidx=_string(o)->_len+sidx;
+ if(eidx<0)eidx=_string(o)->_len+eidx;
+ if(eidx<sidx)
+ return sq_throwerror(v,_SC("wrong indexes"));
+ v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));
+ return 1;
+}
+
+static int string_find(HSQUIRRELVM v)
+{
+ int top,start_idx=0;
+ const SQChar *str,*substr,*ret;
+ if(((top=sq_gettop(v))>1) && SQ_SUCCEEDED(sq_getstring(v,1,&str)) && SQ_SUCCEEDED(sq_getstring(v,2,&substr))){
+ if(top>2)sq_getinteger(v,3,&start_idx);
+ if((sq_getsize(v,1)>start_idx) && (start_idx>=0)){
+ ret=scstrstr(&str[start_idx],substr);
+ if(ret){
+ sq_pushinteger(v,(int)(ret-str));
+ return 1;
+ }
+ }
+ return 0;
+ }
+ return sq_throwerror(v,_SC("invalid param"));
+}
+
+#define STRING_TOFUNCZ(func) static int string_##func(HSQUIRRELVM v) \
+{ \
+ SQObject str=stack_get(v,1); \
+ int len=_string(str)->_len; \
+ const SQChar *sThis=_stringval(str); \
+ SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \
+ for(int i=0;i<len;i++) sNew[i]=func(sThis[i]); \
+ v->Push(SQString::Create(_ss(v),sNew,len)); \
+ return 1; \
+}
+
+
+STRING_TOFUNCZ(tolower)
+STRING_TOFUNCZ(toupper)
+
+SQRegFunction SQSharedState::_string_default_delegate_funcz[]={
+ {_SC("len"),default_delegate_len,1, _SC("s")},
+ {_SC("tointeger"),default_delegate_tointeger,1, _SC("s")},
+ {_SC("tofloat"),default_delegate_tofloat,1, _SC("s")},
+ {_SC("tostring"),default_delegate_tostring,1, _SC("s")},
+ {_SC("slice"),string_slice,-1, _SC(" s n n")},
+ {_SC("find"),string_find,-2, _SC("s s n ")},
+ {_SC("tolower"),string_tolower,1, _SC("s")},
+ {_SC("toupper"),string_toupper,1, _SC("s")},
+ {0,0,0,0}
+};
+
+//INTEGER DEFAULT DELEGATE//////////////////////////
+SQRegFunction SQSharedState::_number_default_delegate_funcz[]={
+ {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")},
+ {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")},
+ {_SC("tostring"),default_delegate_tostring,1, _SC("n|b")},
+ {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},
+ {0,0,0,0}
+};
+
+//CLOSURE DEFAULT DELEGATE//////////////////////////
+static int closure_call(HSQUIRRELVM v)
+{
+ return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue))?1:SQ_ERROR;
+}
+
+static int closure_acall(HSQUIRRELVM v)
+{
+ SQArray *aparams=_array(stack_get(v,2));
+ int nparams=aparams->Size();
+ v->Push(stack_get(v,1));
+ for(int i=0;i<nparams;i++)v->Push(aparams->_values[i]);
+ return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue))?1:SQ_ERROR;
+}
+
+SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={
+ {_SC("call"),closure_call,-1, _SC("c")},
+ {_SC("acall"),closure_acall,2, _SC("ca")},
+ {0,0,0,0}
+};
+
+//GENERATOR DEFAULT DELEGATE
+static int generator_getstatus(HSQUIRRELVM v)
+{
+ SQObject &o=stack_get(v,1);
+ switch(_generator(o)->_state){
+ case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break;
+ case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break;
+ case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break;
+ }
+ return 1;
+}
+
+SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={
+ {_SC("getstatus"),generator_getstatus,1, _SC("g")},
+ {0,0,0,0}
+};
+
+//THREAD DEFAULT DELEGATE
+
+static int thread_call(HSQUIRRELVM v)
+{
+ SQObjectPtr o = stack_get(v,1);
+ if(type(o) == OT_THREAD) {
+ int nparams = sq_gettop(v);
+ _thread(o)->Push(_thread(o)->_roottable);
+ for(int i = 2; i<(nparams+1); i++)
+ sq_move(_thread(o),v,i);
+ if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue))) {
+ sq_move(v,_thread(o),-1);
+ return 1;
+ }
+ return SQ_ERROR;
+ }
+ return sq_throwerror(v,_SC("wrong parameter"));
+}
+
+static int thread_wakeup(HSQUIRRELVM v)
+{
+ SQObjectPtr o = stack_get(v,1);
+ if(type(o) == OT_THREAD) {
+ SQVM *thread = _thread(o);
+ int state = sq_getvmstate(thread);
+ if(state != SQ_VMSTATE_SUSPENDED) {
+ switch(state) {
+ case SQ_VMSTATE_IDLE:
+ return sq_throwerror(v,_SC("cannot wakeup a idle thread"));
+ break;
+ case SQ_VMSTATE_RUNNING:
+ return sq_throwerror(v,_SC("cannot wakeup a running thread"));
+ break;
+ }
+ }
+
+ int wakeupret = sq_gettop(v)>1?1:0;
+ if(wakeupret) {
+ sq_move(thread,v,2);
+ }
+ if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,1))) {
+ sq_move(v,thread,-1);
+ sq_pop(thread,1);
+ if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {
+ sq_pop(thread,1);
+ }
+ return 1;
+ }
+ return SQ_ERROR;
+ }
+ return sq_throwerror(v,_SC("wrong parameter"));
+}
+
+static int thread_getstatus(HSQUIRRELVM v)
+{
+ SQObjectPtr &o = stack_get(v,1);
+ switch(sq_getvmstate(_thread(o))) {
+ case SQ_VMSTATE_IDLE:
+ sq_pushstring(v,_SC("idle"),-1);
+ break;
+ case SQ_VMSTATE_RUNNING:
+ sq_pushstring(v,_SC("running"),-1);
+ break;
+ case SQ_VMSTATE_SUSPENDED:
+ sq_pushstring(v,_SC("suspended"),-1);
+ break;
+ default:
+ return sq_throwerror(v,_SC("internal VM error"));
+ }
+ return 1;
+}
+
+SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {
+ {_SC("call"), thread_call, -1, _SC("v")},
+ {_SC("wakeup"), thread_wakeup, -1, _SC("v")},
+ {_SC("getstatus"), thread_getstatus, 1, _SC("v")},
+ {0,0,0,0},
+};
+
+static int class_getattributes(HSQUIRRELVM v)
+{
+ if(SQ_SUCCEEDED(sq_getattributes(v,-2)))
+ return 1;
+ return SQ_ERROR;
+}
+
+static int class_setattributes(HSQUIRRELVM v)
+{
+ if(SQ_SUCCEEDED(sq_setattributes(v,-3)))
+ return 1;
+ return SQ_ERROR;
+}
+
+SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {
+ {_SC("getattributes"), class_getattributes, 2, _SC("y.")},
+ {_SC("setattributes"), class_setattributes, 3, _SC("y..")},
+ {_SC("rawin"),container_rawexists,2, _SC("y")},
+ {0,0,0,0}
+};
+
+static int instance_getclass(HSQUIRRELVM v)
+{
+ if(SQ_SUCCEEDED(sq_getclass(v,1)))
+ return 1;
+ return SQ_ERROR;
+}
+
+SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {
+ {_SC("getclass"), instance_getclass, 1, _SC("x")},
+ {_SC("rawin"),container_rawexists,2, _SC("x")},
+ {0,0,0,0}
+};
+
-/*\r
- see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include "sqvm.h"\r
-#include "sqtable.h"\r
-#include "sqclass.h"\r
-#include "sqclosure.h"\r
-\r
-SQClass::SQClass(SQSharedState *ss,SQClass *base)\r
-{\r
- _uiRef=0;\r
- _base = base;\r
- _typetag = 0;\r
- _metamethods.resize(MT_LAST); //size it to max size\r
- if(_base) {\r
- _defaultvalues.copy(base->_defaultvalues);\r
- _methods.copy(base->_methods);\r
- _metamethods.copy(base->_metamethods);\r
- __ObjAddRef(_base);\r
- }\r
- _members = base?base->_members->Clone() : SQTable::Create(ss,0);\r
- __ObjAddRef(_members);\r
- _locked = false;\r
- INIT_CHAIN();\r
- ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);\r
-}\r
-\r
-void SQClass::Finalize() { \r
- _attributes = _null_;\r
- _defaultvalues.resize(0);\r
- _methods.resize(0);\r
- _metamethods.resize(0);\r
- __ObjRelease(_members);\r
- if(_base) {\r
- __ObjRelease(_base);\r
- }\r
-}\r
-\r
-SQClass::~SQClass()\r
-{\r
- REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);\r
- Finalize();\r
-}\r
-\r
-bool SQClass::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)\r
-{\r
- SQObjectPtr temp;\r
- if(_locked) \r
- return false; //the slot already exists\r
- if(_members->Get(key,temp) && type(temp) == OT_INTEGER) //overrides the default value\r
- {\r
- _defaultvalues[_integer(temp)].val = val;\r
- return true;\r
- }\r
- if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) {\r
- SQInteger mmidx;\r
- if((mmidx = _sharedstate->GetMetaMethodIdxByName(key)) != -1) {\r
- _metamethods[mmidx] = val;\r
- } \r
- else {\r
- if(type(temp) == OT_NULL) {\r
- SQClassMemeber m;\r
- m.val = val;\r
- _members->NewSlot(key,SQObjectPtr((SQUserPointer)_methods.size()));\r
- _methods.push_back(m);\r
- }\r
- else {\r
- _methods[(int)_userpointer(temp)].val = val;\r
- }\r
- }\r
- return true;\r
- }\r
- SQClassMemeber m;\r
- m.val = val;\r
- _members->NewSlot(key,SQObjectPtr((SQInteger)_defaultvalues.size()));\r
- _defaultvalues.push_back(m);\r
- return true;\r
-}\r
-\r
-SQInstance *SQClass::CreateInstance()\r
-{\r
- if(!_locked) Lock();\r
- return SQInstance::Create(_opt_ss(this),this);\r
-}\r
-\r
-int SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)\r
-{\r
- SQObjectPtr oval;\r
- int idx = _members->Next(refpos,outkey,oval);\r
- if(idx != -1) {\r
- if(type(oval) != OT_INTEGER) {\r
- outval = _methods[(int)_userpointer(oval)].val;\r
- }\r
- else {\r
- outval = _defaultvalues[_integer(oval)].val;\r
- }\r
- }\r
- return idx;\r
-}\r
-\r
-bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)\r
-{\r
- SQObjectPtr idx;\r
- if(_members->Get(key,idx)) {\r
- if(type(idx) == OT_INTEGER)\r
- _defaultvalues[_integer(idx)].attrs = val;\r
- else\r
- _methods[(int)_userpointer(idx)].attrs = val;\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)\r
-{\r
- SQObjectPtr idx;\r
- if(_members->Get(key,idx)) {\r
- outval = (type(idx) == OT_INTEGER?_defaultvalues[_integer(idx)].attrs:_methods[(int)_userpointer(idx)].attrs);\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-///////////////////////////////////////////////////////////////////////\r
-void SQInstance::Init(SQSharedState *ss)\r
-{\r
- _uiRef = 0;\r
- _userpointer = NULL;\r
- _hook = NULL;\r
- __ObjAddRef(_class);\r
- _delegate = _class->_members;\r
- INIT_CHAIN();\r
- ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);\r
-}\r
-\r
-SQInstance::SQInstance(SQSharedState *ss, SQClass *c)\r
-{\r
- _class = c;\r
- _values.resize(_class->_defaultvalues.size());\r
- for(unsigned int i = 0; i < _class->_defaultvalues.size(); i++) {\r
- _values[i] = _class->_defaultvalues[i].val;\r
- }\r
- Init(ss);\r
-}\r
-\r
-SQInstance::SQInstance(SQSharedState *ss, SQInstance *i)\r
-{\r
- _class = i->_class;\r
- _values.copy(i->_values);\r
- Init(ss);\r
-}\r
-\r
-void SQInstance::Finalize() \r
-{\r
- __ObjRelease(_class);\r
- _values.resize(0);\r
-}\r
-\r
-SQInstance::~SQInstance()\r
-{\r
- REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);\r
- Finalize();\r
-}\r
-\r
-bool SQInstance::GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res)\r
-{\r
- if(type(_class->_metamethods[mm]) != OT_NULL) {\r
- res = _class->_metamethods[mm];\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-bool SQInstance::InstanceOf(SQClass *trg)\r
-{\r
- SQClass *parent = _class;\r
- while(parent != NULL) {\r
- if(parent == trg)\r
- return true;\r
- parent = parent->_base;\r
- }\r
- return false;\r
-}\r
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqvm.h"
+#include "sqtable.h"
+#include "sqclass.h"
+#include "sqclosure.h"
+
+SQClass::SQClass(SQSharedState *ss,SQClass *base)
+{
+ _uiRef=0;
+ _base = base;
+ _typetag = 0;
+ _metamethods.resize(MT_LAST); //size it to max size
+ if(_base) {
+ _defaultvalues.copy(base->_defaultvalues);
+ _methods.copy(base->_methods);
+ _metamethods.copy(base->_metamethods);
+ __ObjAddRef(_base);
+ }
+ _members = base?base->_members->Clone() : SQTable::Create(ss,0);
+ __ObjAddRef(_members);
+ _locked = false;
+ INIT_CHAIN();
+ ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
+}
+
+void SQClass::Finalize() {
+ _attributes = _null_;
+ _defaultvalues.resize(0);
+ _methods.resize(0);
+ _metamethods.resize(0);
+ __ObjRelease(_members);
+ if(_base) {
+ __ObjRelease(_base);
+ }
+}
+
+SQClass::~SQClass()
+{
+ REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
+ Finalize();
+}
+
+bool SQClass::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)
+{
+ SQObjectPtr temp;
+ if(_locked)
+ return false; //the slot already exists
+ if(_members->Get(key,temp) && type(temp) == OT_INTEGER) //overrides the default value
+ {
+ _defaultvalues[_integer(temp)].val = val;
+ return true;
+ }
+ if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) {
+ SQInteger mmidx;
+ if((mmidx = _sharedstate->GetMetaMethodIdxByName(key)) != -1) {
+ _metamethods[mmidx] = val;
+ }
+ else {
+ if(type(temp) == OT_NULL) {
+ SQClassMemeber m;
+ m.val = val;
+ _members->NewSlot(key,SQObjectPtr((SQUserPointer)_methods.size()));
+ _methods.push_back(m);
+ }
+ else {
+ _methods[(int)_userpointer(temp)].val = val;
+ }
+ }
+ return true;
+ }
+ SQClassMemeber m;
+ m.val = val;
+ _members->NewSlot(key,SQObjectPtr((SQInteger)_defaultvalues.size()));
+ _defaultvalues.push_back(m);
+ return true;
+}
+
+SQInstance *SQClass::CreateInstance()
+{
+ if(!_locked) Lock();
+ return SQInstance::Create(_opt_ss(this),this);
+}
+
+int SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
+{
+ SQObjectPtr oval;
+ int idx = _members->Next(refpos,outkey,oval);
+ if(idx != -1) {
+ if(type(oval) != OT_INTEGER) {
+ outval = _methods[(int)_userpointer(oval)].val;
+ }
+ else {
+ outval = _defaultvalues[_integer(oval)].val;
+ }
+ }
+ return idx;
+}
+
+bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)
+{
+ SQObjectPtr idx;
+ if(_members->Get(key,idx)) {
+ if(type(idx) == OT_INTEGER)
+ _defaultvalues[_integer(idx)].attrs = val;
+ else
+ _methods[(int)_userpointer(idx)].attrs = val;
+ return true;
+ }
+ return false;
+}
+
+bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)
+{
+ SQObjectPtr idx;
+ if(_members->Get(key,idx)) {
+ outval = (type(idx) == OT_INTEGER?_defaultvalues[_integer(idx)].attrs:_methods[(int)_userpointer(idx)].attrs);
+ return true;
+ }
+ return false;
+}
+
+///////////////////////////////////////////////////////////////////////
+void SQInstance::Init(SQSharedState *ss)
+{
+ _uiRef = 0;
+ _userpointer = NULL;
+ _hook = NULL;
+ __ObjAddRef(_class);
+ _delegate = _class->_members;
+ INIT_CHAIN();
+ ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
+}
+
+SQInstance::SQInstance(SQSharedState *ss, SQClass *c)
+{
+ _class = c;
+ _values.resize(_class->_defaultvalues.size());
+ for(unsigned int i = 0; i < _class->_defaultvalues.size(); i++) {
+ _values[i] = _class->_defaultvalues[i].val;
+ }
+ Init(ss);
+}
+
+SQInstance::SQInstance(SQSharedState *ss, SQInstance *i)
+{
+ _class = i->_class;
+ _values.copy(i->_values);
+ Init(ss);
+}
+
+void SQInstance::Finalize()
+{
+ __ObjRelease(_class);
+ _values.resize(0);
+}
+
+SQInstance::~SQInstance()
+{
+ REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
+ Finalize();
+}
+
+bool SQInstance::GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res)
+{
+ if(type(_class->_metamethods[mm]) != OT_NULL) {
+ res = _class->_metamethods[mm];
+ return true;
+ }
+ return false;
+}
+
+bool SQInstance::InstanceOf(SQClass *trg)
+{
+ SQClass *parent = _class;
+ while(parent != NULL) {
+ if(parent == trg)
+ return true;
+ parent = parent->_base;
+ }
+ return false;
+}
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQCLASS_H_\r
-#define _SQCLASS_H_\r
-\r
-struct SQInstance;\r
-\r
-struct SQClassMemeber {\r
- SQClassMemeber(){}\r
- SQClassMemeber(const SQClassMemeber &o) {\r
- val = o.val;\r
- attrs = o.attrs;\r
- }\r
- SQObjectPtr val;\r
- SQObjectPtr attrs;\r
-};\r
-\r
-typedef sqvector<SQClassMemeber> SQClassMemeberVec;\r
-\r
-struct SQClass : public CHAINABLE_OBJ\r
-{\r
- SQClass(SQSharedState *ss,SQClass *base);\r
-public:\r
- static SQClass* Create(SQSharedState *ss,SQClass *base) {\r
- SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass));\r
- new (newclass) SQClass(ss, base);\r
- return newclass;\r
- }\r
- ~SQClass();\r
- bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);\r
- bool Get(const SQObjectPtr &key,SQObjectPtr &val) {\r
- if(_members->Get(key,val)) {\r
- val = (type(val) == OT_INTEGER?_defaultvalues[_integer(val)].val:_methods[(int)_userpointer(val)].val);\r
- return true;\r
- }\r
- return false;\r
- }\r
- bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val);\r
- bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval);\r
- void Lock() { _locked = true; if(_base) _base->Lock(); }\r
- void Release() { sq_delete(this, SQClass); }\r
- void Finalize();\r
- void Mark(SQCollectable ** );\r
- int Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);\r
- SQInstance *CreateInstance();\r
- SQTable *_members;\r
- //SQTable *_properties;\r
- SQClass *_base;\r
- SQClassMemeberVec _defaultvalues;\r
- SQClassMemeberVec _methods;\r
- SQObjectPtrVec _metamethods;\r
- SQObjectPtr _attributes;\r
- unsigned int _typetag;\r
- bool _locked;\r
-};\r
-\r
-struct SQInstance : public SQDelegable \r
-{\r
- void Init(SQSharedState *ss);\r
- SQInstance(SQSharedState *ss, SQClass *c);\r
- SQInstance(SQSharedState *ss, SQInstance *c);\r
-public:\r
- static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {\r
- SQInstance *newinst = (SQInstance *)SQ_MALLOC(sizeof(SQInstance));\r
- new (newinst) SQInstance(ss, theclass);\r
- return newinst;\r
- }\r
- SQInstance *Clone(SQSharedState *ss)\r
- {\r
- SQInstance *newinst = (SQInstance *)SQ_MALLOC(sizeof(SQInstance));\r
- new (newinst) SQInstance(ss, this);\r
- return newinst;\r
- }\r
- ~SQInstance();\r
- bool Get(const SQObjectPtr &key,SQObjectPtr &val) {\r
- if(_class->_members->Get(key,val)) {\r
- val = (type(val) == OT_INTEGER?_values[_integer(val)]:_class->_methods[(int)_userpointer(val)].val);\r
- return true;\r
- }\r
- return false;\r
- }\r
- bool Set(const SQObjectPtr &key,const SQObjectPtr &val) {\r
- SQObjectPtr idx;\r
- if(_class->_members->Get(key,idx) && type(idx) == OT_INTEGER) {\r
- _values[_integer(idx)] = val;\r
- return true;\r
- }\r
- return false;\r
- }\r
- void Release() { \r
- if (_hook) { _hook(_userpointer,0);}\r
- sq_delete(this, SQInstance);\r
- }\r
- void Finalize();\r
- void Mark(SQCollectable ** );\r
- bool InstanceOf(SQClass *trg);\r
- bool GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res);\r
-\r
- SQClass *_class;\r
- SQUserPointer _userpointer;\r
- SQRELEASEHOOK _hook;\r
- SQObjectPtrVec _values;\r
-};\r
-\r
-#endif //_SQCLASS_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQCLASS_H_
+#define _SQCLASS_H_
+
+struct SQInstance;
+
+struct SQClassMemeber {
+ SQClassMemeber(){}
+ SQClassMemeber(const SQClassMemeber &o) {
+ val = o.val;
+ attrs = o.attrs;
+ }
+ SQObjectPtr val;
+ SQObjectPtr attrs;
+};
+
+typedef sqvector<SQClassMemeber> SQClassMemeberVec;
+
+struct SQClass : public CHAINABLE_OBJ
+{
+ SQClass(SQSharedState *ss,SQClass *base);
+public:
+ static SQClass* Create(SQSharedState *ss,SQClass *base) {
+ SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass));
+ new (newclass) SQClass(ss, base);
+ return newclass;
+ }
+ ~SQClass();
+ bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);
+ bool Get(const SQObjectPtr &key,SQObjectPtr &val) {
+ if(_members->Get(key,val)) {
+ val = (type(val) == OT_INTEGER?_defaultvalues[_integer(val)].val:_methods[(int)_userpointer(val)].val);
+ return true;
+ }
+ return false;
+ }
+ bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val);
+ bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval);
+ void Lock() { _locked = true; if(_base) _base->Lock(); }
+ void Release() { sq_delete(this, SQClass); }
+ void Finalize();
+ void Mark(SQCollectable ** );
+ int Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
+ SQInstance *CreateInstance();
+ SQTable *_members;
+ //SQTable *_properties;
+ SQClass *_base;
+ SQClassMemeberVec _defaultvalues;
+ SQClassMemeberVec _methods;
+ SQObjectPtrVec _metamethods;
+ SQObjectPtr _attributes;
+ unsigned int _typetag;
+ bool _locked;
+};
+
+struct SQInstance : public SQDelegable
+{
+ void Init(SQSharedState *ss);
+ SQInstance(SQSharedState *ss, SQClass *c);
+ SQInstance(SQSharedState *ss, SQInstance *c);
+public:
+ static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {
+ SQInstance *newinst = (SQInstance *)SQ_MALLOC(sizeof(SQInstance));
+ new (newinst) SQInstance(ss, theclass);
+ return newinst;
+ }
+ SQInstance *Clone(SQSharedState *ss)
+ {
+ SQInstance *newinst = (SQInstance *)SQ_MALLOC(sizeof(SQInstance));
+ new (newinst) SQInstance(ss, this);
+ return newinst;
+ }
+ ~SQInstance();
+ bool Get(const SQObjectPtr &key,SQObjectPtr &val) {
+ if(_class->_members->Get(key,val)) {
+ val = (type(val) == OT_INTEGER?_values[_integer(val)]:_class->_methods[(int)_userpointer(val)].val);
+ return true;
+ }
+ return false;
+ }
+ bool Set(const SQObjectPtr &key,const SQObjectPtr &val) {
+ SQObjectPtr idx;
+ if(_class->_members->Get(key,idx) && type(idx) == OT_INTEGER) {
+ _values[_integer(idx)] = val;
+ return true;
+ }
+ return false;
+ }
+ void Release() {
+ if (_hook) { _hook(_userpointer,0);}
+ sq_delete(this, SQInstance);
+ }
+ void Finalize();
+ void Mark(SQCollectable ** );
+ bool InstanceOf(SQClass *trg);
+ bool GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res);
+
+ SQClass *_class;
+ SQUserPointer _userpointer;
+ SQRELEASEHOOK _hook;
+ SQObjectPtrVec _values;
+};
+
+#endif //_SQCLASS_H_
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQCLOSURE_H_\r
-#define _SQCLOSURE_H_\r
-\r
-struct SQFunctionProto;\r
-\r
-struct SQClosure : public CHAINABLE_OBJ\r
-{\r
-private:\r
- SQClosure(SQSharedState *ss,SQFunctionProto *func){_uiRef=0;_function=func; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}\r
-public:\r
- static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){\r
- SQClosure *nc=(SQClosure*)SQ_MALLOC(sizeof(SQClosure));\r
- new (nc) SQClosure(ss,func);\r
- return nc;\r
- }\r
- void Release(){\r
- sq_delete(this,SQClosure);\r
- }\r
- ~SQClosure()\r
- {\r
- REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
- }\r
- bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);\r
- bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read);\r
-#ifndef NO_GARBAGE_COLLECTOR\r
- void Mark(SQCollectable **chain);\r
- void Finalize(){_outervalues.resize(0); }\r
-#endif\r
- SQObjectPtr _function;\r
- SQObjectPtrVec _outervalues;\r
-};\r
-//////////////////////////////////////////////\r
-struct SQGenerator : public CHAINABLE_OBJ \r
-{\r
- enum SQGeneratorState{eRunning,eSuspended,eDead};\r
-private:\r
- SQGenerator(SQSharedState *ss,SQClosure *closure){_uiRef=0;_closure=closure;_state=eRunning;_ci._generator=_null_;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}\r
-public:\r
- static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){\r
- SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator));\r
- new (nc) SQGenerator(ss,closure);\r
- return nc;\r
- }\r
- ~SQGenerator()\r
- {\r
- REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
- }\r
- void Kill(){\r
- _state=eDead;\r
- _stack.resize(0);\r
- _closure=_null_;}\r
- void Release(){\r
- sq_delete(this,SQGenerator);\r
- }\r
- bool Yield(SQVM *v);\r
- bool Resume(SQVM *v,int target);\r
-#ifndef NO_GARBAGE_COLLECTOR\r
- void Mark(SQCollectable **chain);\r
- void Finalize(){_stack.resize(0);_closure=_null_;}\r
-#endif\r
- SQObjectPtr _closure;\r
- SQObjectPtrVec _stack;\r
- SQObjectPtrVec _vargsstack;\r
- SQVM::CallInfo _ci;\r
- ExceptionsTraps _etraps;\r
- SQGeneratorState _state;\r
-};\r
-\r
-struct SQNativeClosure : public CHAINABLE_OBJ\r
-{\r
-private:\r
- SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_uiRef=0;_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); }\r
-public:\r
- static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func)\r
- {\r
- SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(sizeof(SQNativeClosure));\r
- new (nc) SQNativeClosure(ss,func);\r
- return nc;\r
- }\r
- ~SQNativeClosure()\r
- {\r
- REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
- }\r
- void Release(){\r
- sq_delete(this,SQNativeClosure);\r
- }\r
-#ifndef NO_GARBAGE_COLLECTOR\r
- void Mark(SQCollectable **chain);\r
- void Finalize(){_outervalues.resize(0);}\r
-#endif\r
- SQFUNCTION _function;\r
- SQObjectPtr _name;\r
- SQObjectPtrVec _outervalues;\r
- SQIntVec _typecheck;\r
- int _nparamscheck;\r
-};\r
-\r
-\r
-\r
-#endif //_SQCLOSURE_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQCLOSURE_H_
+#define _SQCLOSURE_H_
+
+struct SQFunctionProto;
+
+struct SQClosure : public CHAINABLE_OBJ
+{
+private:
+ SQClosure(SQSharedState *ss,SQFunctionProto *func){_uiRef=0;_function=func; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}
+public:
+ static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){
+ SQClosure *nc=(SQClosure*)SQ_MALLOC(sizeof(SQClosure));
+ new (nc) SQClosure(ss,func);
+ return nc;
+ }
+ void Release(){
+ sq_delete(this,SQClosure);
+ }
+ ~SQClosure()
+ {
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+ }
+ bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
+ bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read);
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+ void Finalize(){_outervalues.resize(0); }
+#endif
+ SQObjectPtr _function;
+ SQObjectPtrVec _outervalues;
+};
+//////////////////////////////////////////////
+struct SQGenerator : public CHAINABLE_OBJ
+{
+ enum SQGeneratorState{eRunning,eSuspended,eDead};
+private:
+ SQGenerator(SQSharedState *ss,SQClosure *closure){_uiRef=0;_closure=closure;_state=eRunning;_ci._generator=_null_;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}
+public:
+ static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){
+ SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator));
+ new (nc) SQGenerator(ss,closure);
+ return nc;
+ }
+ ~SQGenerator()
+ {
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+ }
+ void Kill(){
+ _state=eDead;
+ _stack.resize(0);
+ _closure=_null_;}
+ void Release(){
+ sq_delete(this,SQGenerator);
+ }
+ bool Yield(SQVM *v);
+ bool Resume(SQVM *v,int target);
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+ void Finalize(){_stack.resize(0);_closure=_null_;}
+#endif
+ SQObjectPtr _closure;
+ SQObjectPtrVec _stack;
+ SQObjectPtrVec _vargsstack;
+ SQVM::CallInfo _ci;
+ ExceptionsTraps _etraps;
+ SQGeneratorState _state;
+};
+
+struct SQNativeClosure : public CHAINABLE_OBJ
+{
+private:
+ SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_uiRef=0;_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); }
+public:
+ static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func)
+ {
+ SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(sizeof(SQNativeClosure));
+ new (nc) SQNativeClosure(ss,func);
+ return nc;
+ }
+ ~SQNativeClosure()
+ {
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+ }
+ void Release(){
+ sq_delete(this,SQNativeClosure);
+ }
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+ void Finalize(){_outervalues.resize(0);}
+#endif
+ SQFUNCTION _function;
+ SQObjectPtr _name;
+ SQObjectPtrVec _outervalues;
+ SQIntVec _typecheck;
+ int _nparamscheck;
+};
+
+
+
+#endif //_SQCLOSURE_H_
-/*\r
- see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include <stdarg.h>\r
-#include "sqopcodes.h"\r
-#include "sqstring.h"\r
-#include "sqfuncproto.h"\r
-#include "sqfuncstate.h"\r
-#include "sqcompiler.h"\r
-#include "sqlexer.h"\r
-#include "sqvm.h"\r
-\r
-#define DEREF_NO_DEREF -1\r
-#define DEREF_FIELD -2\r
-\r
-struct ExpState\r
-{\r
- ExpState()\r
- {\r
- _deref = DEREF_NO_DEREF;\r
- _freevar = false;\r
- _class_or_delete = false;\r
- _funcarg = false;\r
- }\r
- bool _class_or_delete;\r
- bool _funcarg;\r
- bool _freevar;\r
- int _deref;\r
-};\r
-\r
-typedef sqvector<ExpState> ExpStateVec;\r
-\r
-#define _exst (_expstates.top())\r
-\r
-#define BEGIN_BREAKBLE_BLOCK() int __nbreaks__=_fs->_unresolvedbreaks.size(); \\r
- int __ncontinues__=_fs->_unresolvedcontinues.size(); \\r
- _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0);\r
-\r
-#define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \\r
- __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \\r
- if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \\r
- if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \\r
- _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();}\r
-\r
-class SQCompiler\r
-{\r
-public:\r
- SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo)\r
- {\r
- _vm=v;\r
- _lex.Init(_ss(v), rg, up);\r
- _sourcename = SQString::Create(_ss(v), sourcename);\r
- _lineinfo = lineinfo;_raiseerror = raiseerror;\r
- }\r
- void Error(const SQChar *s, ...)\r
- {\r
- static SQChar temp[256];\r
- va_list vl;\r
- va_start(vl, s);\r
- scvsprintf(temp, s, vl);\r
- va_end(vl);\r
- throw ParserException(temp);\r
- }\r
- void Lex(){ _token = _lex.Lex();}\r
- void PushExpState(){ _expstates.push_back(ExpState()); }\r
- bool IsDerefToken(int tok)\r
- {\r
- switch(tok){\r
- case _SC('='): case _SC('('): case TK_NEWSLOT:\r
- case TK_MODEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return true;\r
- }\r
- return false;\r
- }\r
- ExpState PopExpState()\r
- {\r
- ExpState ret = _expstates.top();\r
- _expstates.pop_back();\r
- return ret;\r
- }\r
- SQObjectPtr Expect(int tok)\r
- {\r
- SQObjectPtr ret;\r
- if(_token != tok) {\r
- if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {\r
- //ret = SQString::Create(_ss(_vm),_SC("constructor"));\r
- //do nothing\r
- }\r
- else {\r
- if(tok > 255) {\r
- switch(tok)\r
- {\r
- case TK_IDENTIFIER:\r
- ret = SQString::Create(_ss(_vm), _SC("IDENTIFIER"));\r
- break;\r
- case TK_STRING_LITERAL:\r
- ret = SQString::Create(_ss(_vm), _SC("STRING_LITERAL"));\r
- break;\r
- case TK_INTEGER:\r
- ret = SQString::Create(_ss(_vm), _SC("INTEGER"));\r
- break;\r
- case TK_FLOAT:\r
- ret = SQString::Create(_ss(_vm), _SC("FLOAT"));\r
- break;\r
- default:\r
- ret = _lex.Tok2Str(tok);\r
- }\r
- Error(_SC("expected '%s'"), _stringval(ret));\r
- }\r
- Error(_SC("expected '%c'"), tok);\r
- }\r
- }\r
- switch(tok)\r
- {\r
- case TK_IDENTIFIER:\r
- ret = SQString::Create(_ss(_vm), _lex._svalue);\r
- break;\r
- case TK_STRING_LITERAL:\r
- ret = SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1);\r
- break;\r
- case TK_INTEGER:\r
- ret = _lex._nvalue;\r
- break;\r
- case TK_FLOAT:\r
- ret = _lex._fvalue;\r
- break;\r
- }\r
- Lex();\r
- return ret;\r
- }\r
- bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); }\r
- void OptionalSemicolon()\r
- {\r
- if(_token == _SC(';')) { Lex(); return; }\r
- if(!IsEndOfStatement()) {\r
- Error(_SC("end of statement expected (; or lf)"));\r
- }\r
- }\r
- void MoveIfCurrentTargetIsLocal() {\r
- int trg = _fs->TopTarget();\r
- if(_fs->IsLocal(trg)) {\r
- trg = _fs->PopTarget(); //no pops the target and move it\r
- _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg);\r
- }\r
- }\r
- bool Compile(SQObjectPtr &o)\r
- {\r
- SQ_TRY {\r
- _debugline = 1;\r
- _debugop = 0;\r
- Lex();\r
- SQFuncState funcstate(_ss(_vm), SQFunctionProto::Create(), NULL);\r
- _funcproto(funcstate._func)->_name = SQString::Create(_ss(_vm), _SC("main"));\r
- _fs = &funcstate;\r
- _fs->AddParameter(SQString::Create(_ss(_vm), _SC("this")));\r
- _funcproto(_fs->_func)->_sourcename = _sourcename;\r
- int stacksize = _fs->GetStackSize();\r
- while(_token > 0){\r
- Statement();\r
- if(_lex._prevtoken != _SC('}')) OptionalSemicolon();\r
- }\r
- CleanStack(stacksize);\r
- _fs->AddLineInfos(_lex._currentline, _lineinfo, true);\r
- _fs->AddInstruction(_OP_RETURN, 0xFF);\r
- _funcproto(_fs->_func)->_stacksize = _fs->_stacksize;\r
- _fs->SetStackSize(0);\r
- _fs->Finalize();\r
- o = _fs->_func;\r
-#ifdef _DEBUG_DUMP\r
- _fs->Dump();\r
-#endif\r
- }\r
- SQ_CATCH(ParserException,ex){\r
- if(_raiseerror && _ss(_vm)->_compilererrorhandler){\r
- SQObjectPtr ret;\r
- _ss(_vm)->_compilererrorhandler(_vm, ex.desc, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),\r
- _lex._currentline, _lex._currentcolumn);\r
- }\r
- _vm->_lasterror = SQString::Create(_ss(_vm), ex.desc, -1);\r
- return false;\r
- }\r
- return true;\r
- }\r
- void Statements()\r
- {\r
- while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) {\r
- Statement();\r
- if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();\r
- }\r
- }\r
- void Statement()\r
- {\r
- _fs->AddLineInfos(_lex._currentline, _lineinfo);\r
- switch(_token){\r
- case _SC(';'): Lex(); break;\r
- case TK_IF: IfStatement(); break;\r
- case TK_WHILE: WhileStatement(); break;\r
- case TK_DO: DoWhileStatement(); break;\r
- case TK_FOR: ForStatement(); break;\r
- case TK_FOREACH: ForEachStatement(); break;\r
- case TK_SWITCH: SwitchStatement(); break;\r
- case TK_LOCAL: LocalDeclStatement(); break;\r
- case TK_RETURN:\r
- case TK_YIELD: {\r
- SQOpcode op;\r
- if(_token == TK_RETURN) {\r
- op = _OP_RETURN;\r
- \r
- }\r
- else {\r
- op = _OP_YIELD;\r
- _funcproto(_fs->_func)->_bgenerator = true;\r
- }\r
- Lex();\r
- if(!IsEndOfStatement()) {\r
- int retexp = _fs->GetCurrentPos()+1;\r
- CommaExpr();\r
- if(op == _OP_RETURN && _fs->_traps > 0)\r
- _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);\r
- _fs->_returnexp = retexp;\r
- _fs->AddInstruction(op, 1, _fs->PopTarget());\r
- }\r
- else{ \r
- if(op == _OP_RETURN && _fs->_traps > 0)\r
- _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);\r
- _fs->_returnexp = -1;\r
- _fs->AddInstruction(op, 0xFF); \r
- }\r
- break;}\r
- case TK_BREAK:\r
- if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block"));\r
- if(_fs->_breaktargets.top() > 0){\r
- _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);\r
- }\r
- _fs->AddInstruction(_OP_JMP, 0, -1234);\r
- _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());\r
- Lex();\r
- break;\r
- case TK_CONTINUE:\r
- if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block"));\r
- if(_fs->_continuetargets.top() > 0) {\r
- _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);\r
- }\r
- _fs->AddInstruction(_OP_JMP, 0, -1234);\r
- _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());\r
- Lex();\r
- break;\r
- case TK_FUNCTION:\r
- FunctionStatement();\r
- break;\r
- case TK_CLASS:\r
- ClassStatement();\r
- break;\r
- case _SC('{'):{\r
- int stacksize = _fs->GetStackSize();\r
- Lex();\r
- Statements();\r
- Expect(_SC('}'));\r
- _fs->SetStackSize(stacksize);\r
- }\r
- break;\r
- case TK_TRY:\r
- TryCatchStatement();\r
- break;\r
- case TK_THROW:\r
- Lex();\r
- CommaExpr();\r
- _fs->AddInstruction(_OP_THROW, _fs->PopTarget());\r
- break;\r
- default:\r
- CommaExpr();\r
- _fs->PopTarget();\r
- break;\r
- }\r
- _fs->SnoozeOpt();\r
- }\r
- void EmitDerefOp(SQOpcode op)\r
- {\r
- int val = _fs->PopTarget();\r
- int key = _fs->PopTarget();\r
- int src = _fs->PopTarget();\r
- _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);\r
- }\r
- void Emit2ArgsOP(SQOpcode op, int p3 = 0)\r
- {\r
- int p2 = _fs->PopTarget(); //src in OP_GET\r
- int p1 = _fs->PopTarget(); //key in OP_GET\r
- _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);\r
- }\r
- void EmitCompoundArith(int tok,bool deref)\r
- {\r
- int oper;\r
- switch(tok){\r
- case TK_MINUSEQ: oper = '-'; break;\r
- case TK_PLUSEQ: oper = '+'; break;\r
- case TK_MULEQ: oper = '*'; break;\r
- case TK_DIVEQ: oper = '/'; break;\r
- case TK_MODEQ: oper = '%'; break;\r
- default: assert(0); break;\r
- };\r
- if(deref) {\r
- int val = _fs->PopTarget();\r
- int key = _fs->PopTarget();\r
- int src = _fs->PopTarget();\r
- //mixes dest obj and source val in the arg1(hack?)\r
- _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper);\r
- }\r
- else {\r
- Emit2ArgsOP(_OP_COMPARITHL, oper);\r
- }\r
- }\r
- void CommaExpr()\r
- {\r
- for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr());\r
- }\r
- ExpState Expression(bool funcarg = false)\r
- {\r
- PushExpState();\r
- _exst._class_or_delete = false;\r
- _exst._funcarg = funcarg;\r
- LogicalOrExp();\r
- switch(_token) {\r
- case _SC('='):\r
- case TK_NEWSLOT:\r
- case TK_MINUSEQ:\r
- case TK_PLUSEQ:\r
- case TK_MULEQ:\r
- case TK_DIVEQ:\r
- case TK_MODEQ:\r
- {\r
- int op = _token;\r
- int ds = _exst._deref;\r
- bool freevar = _exst._freevar;\r
- if(ds == DEREF_NO_DEREF) Error(_SC("can't assign expression"));\r
- Lex(); Expression();\r
-\r
- switch(op){\r
- case TK_NEWSLOT:\r
- if(freevar) Error(_SC("free variables cannot be modified"));\r
- if(ds == DEREF_FIELD)\r
- EmitDerefOp(_OP_NEWSLOT);\r
- else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
- Error(_SC("can't 'create' a local slot"));\r
- break;\r
- case _SC('='): //ASSIGN\r
- if(freevar) Error(_SC("free variables cannot be modified"));\r
- if(ds == DEREF_FIELD)\r
- EmitDerefOp(_OP_SET);\r
- else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
- int p2 = _fs->PopTarget(); //src in OP_GET\r
- int p1 = _fs->TopTarget(); //key in OP_GET\r
- _fs->AddInstruction(_OP_MOVE, p1, p2);\r
- }\r
- break;\r
- case TK_MINUSEQ:\r
- case TK_PLUSEQ:\r
- case TK_MULEQ:\r
- case TK_DIVEQ:\r
- case TK_MODEQ:\r
- EmitCompoundArith(op,ds == DEREF_FIELD);\r
- break;\r
- }\r
- }\r
- break;\r
- case _SC('?'): {\r
- Lex();\r
- _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
- int jzpos = _fs->GetCurrentPos();\r
- int trg = _fs->PushTarget();\r
- Expression();\r
- int first_exp = _fs->PopTarget();\r
- if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
- int endfirstexp = _fs->GetCurrentPos();\r
- _fs->AddInstruction(_OP_JMP, 0, 0);\r
- Expect(_SC(':'));\r
- int jmppos = _fs->GetCurrentPos();\r
- Expression();\r
- int second_exp = _fs->PopTarget();\r
- if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);\r
- _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);\r
- _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1);\r
- _fs->SnoozeOpt();\r
- }\r
- break;\r
- }\r
- return PopExpState();\r
- }\r
- void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),int op3 = 0)\r
- {\r
- Lex(); (this->*f)();\r
- int op1 = _fs->PopTarget();int op2 = _fs->PopTarget();\r
- _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3);\r
- }\r
- void LogicalOrExp()\r
- {\r
- LogicalAndExp();\r
- for(;;) if(_token == TK_OR) {\r
- int first_exp = _fs->PopTarget();\r
- int trg = _fs->PushTarget();\r
- _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);\r
- int jpos = _fs->GetCurrentPos();\r
- if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
- Lex(); LogicalOrExp();\r
- _fs->SnoozeOpt();\r
- int second_exp = _fs->PopTarget();\r
- if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);\r
- _fs->SnoozeOpt();\r
- _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));\r
- break;\r
- }else return;\r
- }\r
- void LogicalAndExp()\r
- {\r
- BitwiseOrExp();\r
- for(;;) switch(_token) {\r
- case TK_AND: {\r
- int first_exp = _fs->PopTarget();\r
- int trg = _fs->PushTarget();\r
- _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);\r
- int jpos = _fs->GetCurrentPos();\r
- if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
- Lex(); LogicalAndExp();\r
- _fs->SnoozeOpt();\r
- int second_exp = _fs->PopTarget();\r
- if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);\r
- _fs->SnoozeOpt();\r
- _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));\r
- break;\r
- }\r
- case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::BitwiseOrExp); break;\r
- case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::BitwiseOrExp); break;\r
- default:\r
- return;\r
- }\r
- }\r
- void BitwiseOrExp()\r
- {\r
- BitwiseXorExp();\r
- for(;;) if(_token == _SC('|'))\r
- {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR);\r
- }else return;\r
- }\r
- void BitwiseXorExp()\r
- {\r
- BitwiseAndExp();\r
- for(;;) if(_token == _SC('^'))\r
- {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR);\r
- }else return;\r
- }\r
- void BitwiseAndExp()\r
- {\r
- CompExp();\r
- for(;;) if(_token == _SC('&'))\r
- {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND);\r
- }else return;\r
- }\r
- void CompExp()\r
- {\r
- ShiftExp();\r
- for(;;) switch(_token) {\r
- case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::ShiftExp); break;\r
- case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break;\r
- case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break;\r
- case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;\r
- case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;\r
- case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break;\r
- default: return; \r
- }\r
- }\r
- void ShiftExp()\r
- {\r
- PlusExp();\r
- for(;;) switch(_token) {\r
- case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break;\r
- case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break;\r
- case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break;\r
- default: return; \r
- }\r
- }\r
- void PlusExp()\r
- {\r
- MultExp();\r
- for(;;) switch(_token) {\r
- case _SC('+'): case _SC('-'):\r
- BIN_EXP(_OP_ARITH, &SQCompiler::MultExp,_token); break;\r
- default: return;\r
- }\r
- }\r
- \r
- void MultExp()\r
- {\r
- PrefixedExpr();\r
- for(;;) switch(_token) {\r
- case _SC('*'): case _SC('/'): case _SC('%'):\r
- BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break;\r
- default: return;\r
- }\r
- }\r
- //if 'pos' != -1 the previous variable is a local variable\r
- void PrefixedExpr()\r
- {\r
- int pos = Factor();\r
- for(;;) {\r
- switch(_token) {\r
- case _SC('.'): {\r
- pos = -1;\r
- SQObjectPtr idx;\r
- Lex(); \r
- if(_token == TK_PARENT) {\r
- Lex();\r
- if(!NeedGet())\r
- Error(_SC("parent cannot be set"));\r
- int src = _fs->PopTarget();\r
- _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src);\r
- }\r
- else {\r
- idx = Expect(TK_IDENTIFIER); \r
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(idx)));\r
- if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
- }\r
- _exst._deref = DEREF_FIELD;\r
- _exst._freevar = false;\r
- }\r
- break;\r
- case _SC('['):\r
- if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));\r
- Lex(); Expression(); Expect(_SC(']')); \r
- pos = -1;\r
- if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
- _exst._deref = DEREF_FIELD;\r
- _exst._freevar = false;\r
- break;\r
- case TK_MINUSMINUS:\r
- case TK_PLUSPLUS:\r
- if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) { \r
- int tok = _token; Lex();\r
- if(pos < 0)\r
- Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1);\r
- else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local\r
- int src = _fs->PopTarget();\r
- _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1);\r
- }\r
- \r
- }\r
- return;\r
- break; \r
- case _SC('('): \r
- {\r
- if(_exst._deref != DEREF_NO_DEREF) {\r
- if(pos<0) {\r
- int key = _fs->PopTarget(); //key\r
- int table = _fs->PopTarget(); //table etc...\r
- int closure = _fs->PushTarget();\r
- int ttarget = _fs->PushTarget();\r
- _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);\r
- }\r
- else{\r
- _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);\r
- }\r
- }\r
- else\r
- _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);\r
- _exst._deref = DEREF_NO_DEREF;\r
- Lex();\r
- FunctionCallArgs();\r
- }\r
- break;\r
- default: return;\r
- }\r
- }\r
- }\r
- int Factor()\r
- {\r
- switch(_token)\r
- {\r
- case TK_STRING_LITERAL: {\r
- SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1));\r
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));\r
- Lex(); \r
- }\r
- break;\r
- case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break;\r
- case TK_VARGV: { Lex();\r
- Expect(_SC('['));\r
- Expression();\r
- Expect(_SC(']'));\r
- int src = _fs->PopTarget();\r
- _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src);\r
- }\r
- break;\r
- case TK_IDENTIFIER:\r
- case TK_CONSTRUCTOR:\r
- case TK_THIS:{\r
- _exst._freevar = false;\r
- SQObjectPtr id;\r
- switch(_token) {\r
- case TK_IDENTIFIER: id = SQString::Create(_ss(_vm), _lex._svalue); break;\r
- case TK_THIS: id = SQString::Create(_ss(_vm), _SC("this")); break;\r
- case TK_CONSTRUCTOR: id = SQString::Create(_ss(_vm), _SC("constructor")); break;\r
- }\r
- int pos = -1;\r
- Lex();\r
- if((pos = _fs->GetLocalVariable(id)) == -1) {\r
- //checks if is a free variable\r
- if((pos = _fs->GetOuterVariable(id)) != -1) {\r
- _exst._deref = _fs->PushTarget();\r
- _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos); \r
- _exst._freevar = true;\r
- } else {\r
- _fs->PushTarget(0);\r
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));\r
- if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
- _exst._deref = DEREF_FIELD;\r
- }\r
- }\r
- else{\r
- _fs->PushTarget(pos);\r
- _exst._deref = pos;\r
- }\r
- return _exst._deref;\r
- }\r
- break;\r
- case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); break;\r
- case TK_DOUBLE_COLON: // "::"\r
- _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget());\r
- _exst._deref = DEREF_FIELD;\r
- _token = _SC('.'); //hack\r
- return -1;\r
- break;\r
- case TK_NULL: \r
- _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);\r
- Lex();\r
- break;\r
- case TK_INTEGER: \r
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue));\r
- Lex();\r
- break;\r
- case TK_FLOAT: \r
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));\r
- Lex();\r
- break;\r
- case TK_TRUE: case TK_FALSE:\r
- _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);\r
- Lex();\r
- break;\r
- case _SC('['): {\r
- _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget());\r
- int apos = _fs->GetCurrentPos(),key = 0;\r
- Lex();\r
- while(_token != _SC(']')) {\r
- Expression(); \r
- if(_token == _SC(',')) Lex();\r
- int val = _fs->PopTarget();\r
- int array = _fs->TopTarget();\r
- _fs->AddInstruction(_OP_APPENDARRAY, array, val);\r
- key++;\r
- }\r
- _fs->SetIntructionParam(apos, 1, key);\r
- Lex();\r
- }\r
- break;\r
- case _SC('{'):{\r
- _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());\r
- Lex();ParseTableOrClass(_SC(','));\r
- }\r
- break;\r
- case TK_FUNCTION: FunctionExp(_token);break;\r
- case TK_CLASS: Lex(); ClassExp();break;\r
- case _SC('-'): UnaryOP(_OP_NEG); break;\r
- case _SC('!'): UnaryOP(_OP_NOT); break;\r
- case _SC('~'): UnaryOP(_OP_BWNOT); break;\r
- case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break;\r
- case TK_RESUME : UnaryOP(_OP_RESUME); break;\r
- case TK_CLONE : UnaryOP(_OP_CLONE); break;\r
- case TK_MINUSMINUS : \r
- case TK_PLUSPLUS :PrefixIncDec(_token); break;\r
- case TK_DELETE : DeleteExpr(); break;\r
- case TK_DELEGATE : DelegateExpr(); break;\r
- case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));\r
- break;\r
- default: Error(_SC("expression expected"));\r
- }\r
- return -1;\r
- }\r
- void UnaryOP(SQOpcode op)\r
- {\r
- Lex(); PrefixedExpr();\r
- int src = _fs->PopTarget();\r
- _fs->AddInstruction(op, _fs->PushTarget(), src);\r
- }\r
- bool NeedGet()\r
- {\r
- switch(_token) {\r
- case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_PLUSPLUS: case TK_MINUSMINUS:\r
- case TK_PLUSEQ: case TK_MINUSEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MODEQ:\r
- return false;\r
- }\r
- return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('[')));\r
- }\r
- \r
- void FunctionCallArgs()\r
- {\r
- int nargs = 1;//this\r
- while(_token != _SC(')')) {\r
- Expression(true);\r
- MoveIfCurrentTargetIsLocal();\r
- nargs++; \r
- if(_token == _SC(',')){ \r
- Lex(); \r
- if(_token == ')') Error(_SC("expression expected, found ')'"));\r
- }\r
- }\r
- Lex();\r
- for(int i = 0; i < (nargs - 1); i++) _fs->PopTarget();\r
- int stackbase = _fs->PopTarget();\r
- int closure = _fs->PopTarget();\r
- _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);\r
- }\r
- void ParseTableOrClass(int separator,int terminator = '}')\r
- {\r
- int tpos = _fs->GetCurrentPos(),nkeys = 0;\r
- \r
- while(_token != terminator) {\r
- bool hasattrs = false;\r
- //check if is an attribute\r
- if(separator == ';' && _token == TK_ATTR_OPEN) {\r
- _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex();\r
- ParseTableOrClass(',',TK_ATTR_CLOSE);\r
- hasattrs = true;\r
- }\r
- switch(_token) {\r
- case TK_FUNCTION:\r
- case TK_CONSTRUCTOR:{\r
- int tk = _token;\r
- Lex();\r
- SQObjectPtr id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : SQString::Create(_ss(_vm),_SC("constructor"));\r
- Expect(_SC('('));\r
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));\r
- CreateFunction(id);\r
- _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);\r
- }\r
- break;\r
- case _SC('['):\r
- Lex(); CommaExpr(); Expect(_SC(']'));\r
- Expect(_SC('=')); Expression();\r
- break;\r
- default :\r
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(Expect(TK_IDENTIFIER))));\r
- Expect(_SC('=')); Expression();\r
- }\r
-\r
- if(_token == separator) Lex();//optional comma/semicolon\r
- nkeys++;\r
- int val = _fs->PopTarget();\r
- int key = _fs->PopTarget();\r
- int attrs = hasattrs ? _fs->PopTarget():-1;\r
- assert(hasattrs && attrs == key-1 || !hasattrs);\r
- int table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE\r
- _fs->AddInstruction(hasattrs?_OP_NEWSLOTA:_OP_NEWSLOT, _fs->PushTarget(), table, key, val);\r
- _fs->PopTarget();\r
- }\r
- if(separator == _SC(',')) //hack recognizes a table from the separator\r
- _fs->SetIntructionParam(tpos, 1, nkeys);\r
- Lex();\r
- }\r
- void LocalDeclStatement()\r
- {\r
- SQObjectPtr varname;\r
- do {\r
- Lex(); varname = Expect(TK_IDENTIFIER);\r
- if(_token == _SC('=')) {\r
- Lex(); Expression();\r
- int src = _fs->PopTarget();\r
- int dest = _fs->PushTarget();\r
- if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);\r
- }\r
- else{\r
- _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);\r
- }\r
- _fs->PopTarget();\r
- _fs->PushLocalVariable(varname);\r
- \r
- } while(_token == _SC(','));\r
- }\r
- void IfStatement()\r
- {\r
- int jmppos;\r
- bool haselse = false;\r
- Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
- _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
- int jnepos = _fs->GetCurrentPos();\r
- int stacksize = _fs->GetStackSize();\r
- \r
- Statement();\r
- //\r
- if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();\r
- \r
- CleanStack(stacksize);\r
- int endifblock = _fs->GetCurrentPos();\r
- if(_token == TK_ELSE){\r
- haselse = true;\r
- stacksize = _fs->GetStackSize();\r
- _fs->AddInstruction(_OP_JMP);\r
- jmppos = _fs->GetCurrentPos();\r
- Lex();\r
- Statement(); OptionalSemicolon();\r
- CleanStack(stacksize);\r
- _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);\r
- }\r
- _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));\r
- }\r
- void WhileStatement()\r
- {\r
- int jzpos, jmppos;\r
- int stacksize = _fs->GetStackSize();\r
- jmppos = _fs->GetCurrentPos();\r
- Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
- \r
- BEGIN_BREAKBLE_BLOCK();\r
- _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
- jzpos = _fs->GetCurrentPos();\r
- stacksize = _fs->GetStackSize();\r
- \r
- Statement();\r
- \r
- CleanStack(stacksize);\r
- _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);\r
- _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);\r
- \r
- END_BREAKBLE_BLOCK(jmppos);\r
- }\r
- void DoWhileStatement()\r
- {\r
- Lex();\r
- int jzpos = _fs->GetCurrentPos();\r
- int stacksize = _fs->GetStackSize();\r
- BEGIN_BREAKBLE_BLOCK()\r
- Statement();\r
- CleanStack(stacksize);\r
- Expect(TK_WHILE);\r
- int continuetrg = _fs->GetCurrentPos();\r
- Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
- _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1);\r
- END_BREAKBLE_BLOCK(continuetrg);\r
- }\r
- void ForStatement()\r
- {\r
- Lex();\r
- int stacksize = _fs->GetStackSize();\r
- Expect(_SC('('));\r
- if(_token == TK_LOCAL) LocalDeclStatement();\r
- else if(_token != _SC(';')){\r
- CommaExpr();\r
- _fs->PopTarget();\r
- }\r
- Expect(_SC(';'));\r
- _fs->SnoozeOpt();\r
- int jmppos = _fs->GetCurrentPos();\r
- int jzpos = -1;\r
- if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }\r
- Expect(_SC(';'));\r
- _fs->SnoozeOpt();\r
- int expstart = _fs->GetCurrentPos() + 1;\r
- if(_token != _SC(')')) {\r
- CommaExpr();\r
- _fs->PopTarget();\r
- }\r
- Expect(_SC(')'));\r
- _fs->SnoozeOpt();\r
- int expend = _fs->GetCurrentPos();\r
- int expsize = (expend - expstart) + 1;\r
- SQInstructionVec exp;\r
- if(expsize > 0) {\r
- for(int i = 0; i < expsize; i++)\r
- exp.push_back(_fs->GetInstruction(expstart + i));\r
- _fs->PopInstructions(expsize);\r
- }\r
- BEGIN_BREAKBLE_BLOCK()\r
- Statement();\r
- int continuetrg = _fs->GetCurrentPos();\r
- if(expsize > 0) {\r
- for(int i = 0; i < expsize; i++)\r
- _fs->AddInstruction(exp[i]);\r
- }\r
- _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);\r
- if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);\r
- CleanStack(stacksize);\r
- \r
- END_BREAKBLE_BLOCK(continuetrg);\r
- }\r
- void ForEachStatement()\r
- {\r
- SQObjectPtr idxname, valname;\r
- Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);\r
- if(_token == _SC(',')) {\r
- idxname = valname;\r
- Lex(); valname = Expect(TK_IDENTIFIER);\r
- }\r
- else{\r
- idxname = SQString::Create(_ss(_vm), _SC("@INDEX@"));\r
- }\r
- Expect(TK_IN);\r
- \r
- //save the stack size\r
- int stacksize = _fs->GetStackSize();\r
- //put the table in the stack(evaluate the table expression)\r
- Expression(); Expect(_SC(')'));\r
- int container = _fs->TopTarget();\r
- //push the index local var\r
- int indexpos = _fs->PushLocalVariable(idxname);\r
- _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);\r
- //push the value local var\r
- int valuepos = _fs->PushLocalVariable(valname);\r
- _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);\r
- //push reference index\r
- int itrpos = _fs->PushLocalVariable(SQString::Create(_ss(_vm), _SC("@ITERATOR@"))); //use invalid id to make it inaccessible\r
- _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);\r
- int jmppos = _fs->GetCurrentPos();\r
- _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);\r
- int foreachpos = _fs->GetCurrentPos();\r
- //generate the statement code\r
- BEGIN_BREAKBLE_BLOCK()\r
- Statement();\r
- _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);\r
- _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);\r
- //restore the local variable stack(remove index,val and ref idx)\r
- CleanStack(stacksize);\r
- END_BREAKBLE_BLOCK(foreachpos - 1);\r
- }\r
- void SwitchStatement()\r
- {\r
- Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
- Expect(_SC('{'));\r
- int expr = _fs->TopTarget();\r
- bool bfirst = true;\r
- int tonextcondjmp = -1;\r
- int skipcondjmp = -1;\r
- int __nbreaks__ = _fs->_unresolvedbreaks.size();\r
- _fs->_breaktargets.push_back(0);\r
- while(_token == TK_CASE) {\r
- if(!bfirst) {\r
- _fs->AddInstruction(_OP_JMP, 0, 0);\r
- skipcondjmp = _fs->GetCurrentPos();\r
- _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);\r
- }\r
- //condition\r
- Lex(); Expression(); Expect(_SC(':'));\r
- int trg = _fs->PopTarget();\r
- _fs->AddInstruction(_OP_EQ, trg, trg, expr);\r
- _fs->AddInstruction(_OP_JZ, trg, 0);\r
- //end condition\r
- if(skipcondjmp != -1) {\r
- _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));\r
- }\r
- tonextcondjmp = _fs->GetCurrentPos();\r
- int stacksize = _fs->GetStackSize();\r
- Statements();\r
- _fs->SetStackSize(stacksize);\r
- bfirst = false;\r
- }\r
- if(tonextcondjmp != -1)\r
- _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);\r
- if(_token == TK_DEFAULT) {\r
- Lex(); Expect(_SC(':'));\r
- int stacksize = _fs->GetStackSize();\r
- Statements();\r
- _fs->SetStackSize(stacksize);\r
- }\r
- Expect(_SC('}'));\r
- _fs->PopTarget();\r
- __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;\r
- if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);\r
- _fs->_breaktargets.pop_back();\r
- \r
- }\r
- void FunctionStatement()\r
- {\r
- SQObjectPtr id;\r
- Lex(); id = Expect(TK_IDENTIFIER);\r
- _fs->PushTarget(0);\r
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));\r
- if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);\r
- \r
- while(_token == TK_DOUBLE_COLON) {\r
- Lex();\r
- id = Expect(TK_IDENTIFIER);\r
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));\r
- if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);\r
- }\r
- Expect(_SC('('));\r
- CreateFunction(id);\r
- _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);\r
- EmitDerefOp(_OP_NEWSLOT);\r
- _fs->PopTarget();\r
- }\r
- void ClassStatement()\r
- {\r
- ExpState es;\r
- Lex(); PushExpState();\r
- _exst._class_or_delete = true;\r
- _exst._funcarg = false;\r
- PrefixedExpr();\r
- es = PopExpState();\r
- if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name"));\r
- if(es._deref == DEREF_FIELD) {\r
- ClassExp();\r
- EmitDerefOp(_OP_NEWSLOT);\r
- _fs->PopTarget();\r
- }\r
- else Error(_SC("cannot create a class in a local with the syntax(class <local>)"));\r
- }\r
- void TryCatchStatement()\r
- {\r
- SQObjectPtr exid;\r
- Lex();\r
- _fs->AddInstruction(_OP_PUSHTRAP,0,0);\r
- _fs->_traps++;\r
- if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;\r
- if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;\r
- int trappos = _fs->GetCurrentPos();\r
- Statement();\r
- _fs->_traps--;\r
- _fs->AddInstruction(_OP_POPTRAP, 1, 0);\r
- if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;\r
- if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--;\r
- _fs->AddInstruction(_OP_JMP, 0, 0);\r
- int jmppos = _fs->GetCurrentPos();\r
- _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));\r
- Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));\r
- int stacksize = _fs->GetStackSize();\r
- int ex_target = _fs->PushLocalVariable(exid);\r
- _fs->SetIntructionParam(trappos, 0, ex_target);\r
- Statement();\r
- _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);\r
- CleanStack(stacksize);\r
- }\r
- void FunctionExp(int ftype)\r
- {\r
- Lex(); Expect(_SC('('));\r
- CreateFunction(_null_);\r
- _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);\r
- }\r
- void ClassExp()\r
- {\r
- int base = -1;\r
- int attrs = -1;\r
- if(_token == TK_EXTENDS) {\r
- Lex(); Expression();\r
- base = _fs->TopTarget();\r
- }\r
- if(_token == TK_ATTR_OPEN) {\r
- Lex();\r
- _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());\r
- ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);\r
- attrs = _fs->TopTarget();\r
- }\r
- Expect(_SC('{'));\r
- if(attrs != -1) _fs->PopTarget();\r
- if(base != -1) _fs->PopTarget();\r
- _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs);\r
- ParseTableOrClass(_SC(';'));\r
- }\r
- void DelegateExpr()\r
- {\r
- Lex(); CommaExpr();\r
- Expect(_SC(':'));\r
- CommaExpr();\r
- int table = _fs->PopTarget(), delegate = _fs->PopTarget();\r
- _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate);\r
- }\r
- void DeleteExpr()\r
- {\r
- ExpState es;\r
- Lex(); PushExpState();\r
- _exst._class_or_delete = true;\r
- _exst._funcarg = false;\r
- PrefixedExpr();\r
- es = PopExpState();\r
- if(es._deref == DEREF_NO_DEREF) Error(_SC("can't delete an expression"));\r
- if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE);\r
- else Error(_SC("cannot delete a local"));\r
- }\r
- void PrefixIncDec(int token)\r
- {\r
- ExpState es;\r
- Lex(); PushExpState();\r
- _exst._class_or_delete = true;\r
- _exst._funcarg = false;\r
- PrefixedExpr();\r
- es = PopExpState();\r
- if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_INC,token == TK_MINUSMINUS?-1:1);\r
- else {\r
- int src = _fs->PopTarget();\r
- _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1);\r
- }\r
- }\r
- void CreateFunction(SQObjectPtr name)\r
- {\r
- SQFuncState funcstate(_ss(_vm), SQFunctionProto::Create(), _fs);\r
- _funcproto(funcstate._func)->_name = name;\r
- SQObjectPtr paramname;\r
- funcstate.AddParameter(SQString::Create(_ss(_vm), _SC("this")));\r
- _funcproto(funcstate._func)->_sourcename = _sourcename;\r
- while(_token!=_SC(')')) {\r
- if(_token == TK_VARPARAMS) {\r
- funcstate._varparams = true;\r
- Lex();\r
- if(_token != _SC(')')) Error(_SC("expected ')'"));\r
- break;\r
- }\r
- else {\r
- paramname = Expect(TK_IDENTIFIER);\r
- funcstate.AddParameter(paramname);\r
- if(_token == _SC(',')) Lex();\r
- else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));\r
- }\r
- }\r
- Expect(_SC(')'));\r
- //outer values\r
- if(_token == _SC(':')) {\r
- Lex(); Expect(_SC('('));\r
- while(_token != _SC(')')) {\r
- paramname = Expect(TK_IDENTIFIER);\r
- //outers are treated as implicit local variables\r
- funcstate.AddOuterValue(paramname);\r
- if(_token == _SC(',')) Lex();\r
- else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));\r
- }\r
- Lex();\r
- }\r
- \r
- SQFuncState *currchunk = _fs;\r
- _fs = &funcstate;\r
- Statement();\r
- funcstate.AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);\r
- funcstate.AddInstruction(_OP_RETURN, -1);\r
- funcstate.SetStackSize(0);\r
- _funcproto(_fs->_func)->_stacksize = _fs->_stacksize;\r
- funcstate.Finalize();\r
-#ifdef _DEBUG_DUMP\r
- funcstate.Dump();\r
-#endif\r
- _fs = currchunk;\r
- _fs->_functions.push_back(funcstate._func);\r
- }\r
- void CleanStack(int stacksize)\r
- {\r
- if(_fs->GetStackSize() != stacksize)\r
- _fs->SetStackSize(stacksize);\r
- }\r
- void ResolveBreaks(SQFuncState *funcstate, int ntoresolve)\r
- {\r
- while(ntoresolve > 0) {\r
- int pos = funcstate->_unresolvedbreaks.back();\r
- funcstate->_unresolvedbreaks.pop_back();\r
- //set the jmp instruction\r
- funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0);\r
- ntoresolve--;\r
- }\r
- }\r
- void ResolveContinues(SQFuncState *funcstate, int ntoresolve, int targetpos)\r
- {\r
- while(ntoresolve > 0) {\r
- int pos = funcstate->_unresolvedcontinues.back();\r
- funcstate->_unresolvedcontinues.pop_back();\r
- //set the jmp instruction\r
- funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);\r
- ntoresolve--;\r
- }\r
- }\r
-private:\r
- int _token;\r
- SQFuncState *_fs;\r
- SQObjectPtr _sourcename;\r
- SQLexer _lex;\r
- bool _lineinfo;\r
- bool _raiseerror;\r
- int _debugline;\r
- int _debugop;\r
- ExpStateVec _expstates;\r
- SQVM *_vm;\r
-};\r
-\r
-bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)\r
-{\r
- SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);\r
- return p.Compile(out);\r
-}\r
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include <stdarg.h>
+#include "sqopcodes.h"
+#include "sqstring.h"
+#include "sqfuncproto.h"
+#include "sqfuncstate.h"
+#include "sqcompiler.h"
+#include "sqlexer.h"
+#include "sqvm.h"
+
+#define DEREF_NO_DEREF -1
+#define DEREF_FIELD -2
+
+struct ExpState
+{
+ ExpState()
+ {
+ _deref = DEREF_NO_DEREF;
+ _freevar = false;
+ _class_or_delete = false;
+ _funcarg = false;
+ }
+ bool _class_or_delete;
+ bool _funcarg;
+ bool _freevar;
+ int _deref;
+};
+
+typedef sqvector<ExpState> ExpStateVec;
+
+#define _exst (_expstates.top())
+
+#define BEGIN_BREAKBLE_BLOCK() int __nbreaks__=_fs->_unresolvedbreaks.size(); \
+ int __ncontinues__=_fs->_unresolvedcontinues.size(); \
+ _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0);
+
+#define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \
+ __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \
+ if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \
+ if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \
+ _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();}
+
+class SQCompiler
+{
+public:
+ SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo)
+ {
+ _vm=v;
+ _lex.Init(_ss(v), rg, up);
+ _sourcename = SQString::Create(_ss(v), sourcename);
+ _lineinfo = lineinfo;_raiseerror = raiseerror;
+ }
+ void Error(const SQChar *s, ...)
+ {
+ static SQChar temp[256];
+ va_list vl;
+ va_start(vl, s);
+ scvsprintf(temp, s, vl);
+ va_end(vl);
+ throw ParserException(temp);
+ }
+ void Lex(){ _token = _lex.Lex();}
+ void PushExpState(){ _expstates.push_back(ExpState()); }
+ bool IsDerefToken(int tok)
+ {
+ switch(tok){
+ case _SC('='): case _SC('('): case TK_NEWSLOT:
+ case TK_MODEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return true;
+ }
+ return false;
+ }
+ ExpState PopExpState()
+ {
+ ExpState ret = _expstates.top();
+ _expstates.pop_back();
+ return ret;
+ }
+ SQObjectPtr Expect(int tok)
+ {
+ SQObjectPtr ret;
+ if(_token != tok) {
+ if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {
+ //ret = SQString::Create(_ss(_vm),_SC("constructor"));
+ //do nothing
+ }
+ else {
+ if(tok > 255) {
+ switch(tok)
+ {
+ case TK_IDENTIFIER:
+ ret = SQString::Create(_ss(_vm), _SC("IDENTIFIER"));
+ break;
+ case TK_STRING_LITERAL:
+ ret = SQString::Create(_ss(_vm), _SC("STRING_LITERAL"));
+ break;
+ case TK_INTEGER:
+ ret = SQString::Create(_ss(_vm), _SC("INTEGER"));
+ break;
+ case TK_FLOAT:
+ ret = SQString::Create(_ss(_vm), _SC("FLOAT"));
+ break;
+ default:
+ ret = _lex.Tok2Str(tok);
+ }
+ Error(_SC("expected '%s'"), _stringval(ret));
+ }
+ Error(_SC("expected '%c'"), tok);
+ }
+ }
+ switch(tok)
+ {
+ case TK_IDENTIFIER:
+ ret = SQString::Create(_ss(_vm), _lex._svalue);
+ break;
+ case TK_STRING_LITERAL:
+ ret = SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1);
+ break;
+ case TK_INTEGER:
+ ret = _lex._nvalue;
+ break;
+ case TK_FLOAT:
+ ret = _lex._fvalue;
+ break;
+ }
+ Lex();
+ return ret;
+ }
+ bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); }
+ void OptionalSemicolon()
+ {
+ if(_token == _SC(';')) { Lex(); return; }
+ if(!IsEndOfStatement()) {
+ Error(_SC("end of statement expected (; or lf)"));
+ }
+ }
+ void MoveIfCurrentTargetIsLocal() {
+ int trg = _fs->TopTarget();
+ if(_fs->IsLocal(trg)) {
+ trg = _fs->PopTarget(); //no pops the target and move it
+ _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg);
+ }
+ }
+ bool Compile(SQObjectPtr &o)
+ {
+ SQ_TRY {
+ _debugline = 1;
+ _debugop = 0;
+ Lex();
+ SQFuncState funcstate(_ss(_vm), SQFunctionProto::Create(), NULL);
+ _funcproto(funcstate._func)->_name = SQString::Create(_ss(_vm), _SC("main"));
+ _fs = &funcstate;
+ _fs->AddParameter(SQString::Create(_ss(_vm), _SC("this")));
+ _funcproto(_fs->_func)->_sourcename = _sourcename;
+ int stacksize = _fs->GetStackSize();
+ while(_token > 0){
+ Statement();
+ if(_lex._prevtoken != _SC('}')) OptionalSemicolon();
+ }
+ CleanStack(stacksize);
+ _fs->AddLineInfos(_lex._currentline, _lineinfo, true);
+ _fs->AddInstruction(_OP_RETURN, 0xFF);
+ _funcproto(_fs->_func)->_stacksize = _fs->_stacksize;
+ _fs->SetStackSize(0);
+ _fs->Finalize();
+ o = _fs->_func;
+#ifdef _DEBUG_DUMP
+ _fs->Dump();
+#endif
+ }
+ SQ_CATCH(ParserException,ex){
+ if(_raiseerror && _ss(_vm)->_compilererrorhandler){
+ SQObjectPtr ret;
+ _ss(_vm)->_compilererrorhandler(_vm, ex.desc, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),
+ _lex._currentline, _lex._currentcolumn);
+ }
+ _vm->_lasterror = SQString::Create(_ss(_vm), ex.desc, -1);
+ return false;
+ }
+ return true;
+ }
+ void Statements()
+ {
+ while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) {
+ Statement();
+ if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
+ }
+ }
+ void Statement()
+ {
+ _fs->AddLineInfos(_lex._currentline, _lineinfo);
+ switch(_token){
+ case _SC(';'): Lex(); break;
+ case TK_IF: IfStatement(); break;
+ case TK_WHILE: WhileStatement(); break;
+ case TK_DO: DoWhileStatement(); break;
+ case TK_FOR: ForStatement(); break;
+ case TK_FOREACH: ForEachStatement(); break;
+ case TK_SWITCH: SwitchStatement(); break;
+ case TK_LOCAL: LocalDeclStatement(); break;
+ case TK_RETURN:
+ case TK_YIELD: {
+ SQOpcode op;
+ if(_token == TK_RETURN) {
+ op = _OP_RETURN;
+
+ }
+ else {
+ op = _OP_YIELD;
+ _funcproto(_fs->_func)->_bgenerator = true;
+ }
+ Lex();
+ if(!IsEndOfStatement()) {
+ int retexp = _fs->GetCurrentPos()+1;
+ CommaExpr();
+ if(op == _OP_RETURN && _fs->_traps > 0)
+ _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);
+ _fs->_returnexp = retexp;
+ _fs->AddInstruction(op, 1, _fs->PopTarget());
+ }
+ else{
+ if(op == _OP_RETURN && _fs->_traps > 0)
+ _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);
+ _fs->_returnexp = -1;
+ _fs->AddInstruction(op, 0xFF);
+ }
+ break;}
+ case TK_BREAK:
+ if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block"));
+ if(_fs->_breaktargets.top() > 0){
+ _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);
+ }
+ _fs->AddInstruction(_OP_JMP, 0, -1234);
+ _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());
+ Lex();
+ break;
+ case TK_CONTINUE:
+ if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block"));
+ if(_fs->_continuetargets.top() > 0) {
+ _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);
+ }
+ _fs->AddInstruction(_OP_JMP, 0, -1234);
+ _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());
+ Lex();
+ break;
+ case TK_FUNCTION:
+ FunctionStatement();
+ break;
+ case TK_CLASS:
+ ClassStatement();
+ break;
+ case _SC('{'):{
+ int stacksize = _fs->GetStackSize();
+ Lex();
+ Statements();
+ Expect(_SC('}'));
+ _fs->SetStackSize(stacksize);
+ }
+ break;
+ case TK_TRY:
+ TryCatchStatement();
+ break;
+ case TK_THROW:
+ Lex();
+ CommaExpr();
+ _fs->AddInstruction(_OP_THROW, _fs->PopTarget());
+ break;
+ default:
+ CommaExpr();
+ _fs->PopTarget();
+ break;
+ }
+ _fs->SnoozeOpt();
+ }
+ void EmitDerefOp(SQOpcode op)
+ {
+ int val = _fs->PopTarget();
+ int key = _fs->PopTarget();
+ int src = _fs->PopTarget();
+ _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);
+ }
+ void Emit2ArgsOP(SQOpcode op, int p3 = 0)
+ {
+ int p2 = _fs->PopTarget(); //src in OP_GET
+ int p1 = _fs->PopTarget(); //key in OP_GET
+ _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);
+ }
+ void EmitCompoundArith(int tok,bool deref)
+ {
+ int oper;
+ switch(tok){
+ case TK_MINUSEQ: oper = '-'; break;
+ case TK_PLUSEQ: oper = '+'; break;
+ case TK_MULEQ: oper = '*'; break;
+ case TK_DIVEQ: oper = '/'; break;
+ case TK_MODEQ: oper = '%'; break;
+ default: assert(0); break;
+ };
+ if(deref) {
+ int val = _fs->PopTarget();
+ int key = _fs->PopTarget();
+ int src = _fs->PopTarget();
+ //mixes dest obj and source val in the arg1(hack?)
+ _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper);
+ }
+ else {
+ Emit2ArgsOP(_OP_COMPARITHL, oper);
+ }
+ }
+ void CommaExpr()
+ {
+ for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr());
+ }
+ ExpState Expression(bool funcarg = false)
+ {
+ PushExpState();
+ _exst._class_or_delete = false;
+ _exst._funcarg = funcarg;
+ LogicalOrExp();
+ switch(_token) {
+ case _SC('='):
+ case TK_NEWSLOT:
+ case TK_MINUSEQ:
+ case TK_PLUSEQ:
+ case TK_MULEQ:
+ case TK_DIVEQ:
+ case TK_MODEQ:
+ {
+ int op = _token;
+ int ds = _exst._deref;
+ bool freevar = _exst._freevar;
+ if(ds == DEREF_NO_DEREF) Error(_SC("can't assign expression"));
+ Lex(); Expression();
+
+ switch(op){
+ case TK_NEWSLOT:
+ if(freevar) Error(_SC("free variables cannot be modified"));
+ if(ds == DEREF_FIELD)
+ EmitDerefOp(_OP_NEWSLOT);
+ else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
+ Error(_SC("can't 'create' a local slot"));
+ break;
+ case _SC('='): //ASSIGN
+ if(freevar) Error(_SC("free variables cannot be modified"));
+ if(ds == DEREF_FIELD)
+ EmitDerefOp(_OP_SET);
+ else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
+ int p2 = _fs->PopTarget(); //src in OP_GET
+ int p1 = _fs->TopTarget(); //key in OP_GET
+ _fs->AddInstruction(_OP_MOVE, p1, p2);
+ }
+ break;
+ case TK_MINUSEQ:
+ case TK_PLUSEQ:
+ case TK_MULEQ:
+ case TK_DIVEQ:
+ case TK_MODEQ:
+ EmitCompoundArith(op,ds == DEREF_FIELD);
+ break;
+ }
+ }
+ break;
+ case _SC('?'): {
+ Lex();
+ _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
+ int jzpos = _fs->GetCurrentPos();
+ int trg = _fs->PushTarget();
+ Expression();
+ int first_exp = _fs->PopTarget();
+ if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
+ int endfirstexp = _fs->GetCurrentPos();
+ _fs->AddInstruction(_OP_JMP, 0, 0);
+ Expect(_SC(':'));
+ int jmppos = _fs->GetCurrentPos();
+ Expression();
+ int second_exp = _fs->PopTarget();
+ if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
+ _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
+ _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1);
+ _fs->SnoozeOpt();
+ }
+ break;
+ }
+ return PopExpState();
+ }
+ void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),int op3 = 0)
+ {
+ Lex(); (this->*f)();
+ int op1 = _fs->PopTarget();int op2 = _fs->PopTarget();
+ _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3);
+ }
+ void LogicalOrExp()
+ {
+ LogicalAndExp();
+ for(;;) if(_token == TK_OR) {
+ int first_exp = _fs->PopTarget();
+ int trg = _fs->PushTarget();
+ _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);
+ int jpos = _fs->GetCurrentPos();
+ if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
+ Lex(); LogicalOrExp();
+ _fs->SnoozeOpt();
+ int second_exp = _fs->PopTarget();
+ if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
+ _fs->SnoozeOpt();
+ _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
+ break;
+ }else return;
+ }
+ void LogicalAndExp()
+ {
+ BitwiseOrExp();
+ for(;;) switch(_token) {
+ case TK_AND: {
+ int first_exp = _fs->PopTarget();
+ int trg = _fs->PushTarget();
+ _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);
+ int jpos = _fs->GetCurrentPos();
+ if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
+ Lex(); LogicalAndExp();
+ _fs->SnoozeOpt();
+ int second_exp = _fs->PopTarget();
+ if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
+ _fs->SnoozeOpt();
+ _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos));
+ break;
+ }
+ case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::BitwiseOrExp); break;
+ case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::BitwiseOrExp); break;
+ default:
+ return;
+ }
+ }
+ void BitwiseOrExp()
+ {
+ BitwiseXorExp();
+ for(;;) if(_token == _SC('|'))
+ {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR);
+ }else return;
+ }
+ void BitwiseXorExp()
+ {
+ BitwiseAndExp();
+ for(;;) if(_token == _SC('^'))
+ {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR);
+ }else return;
+ }
+ void BitwiseAndExp()
+ {
+ CompExp();
+ for(;;) if(_token == _SC('&'))
+ {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND);
+ }else return;
+ }
+ void CompExp()
+ {
+ ShiftExp();
+ for(;;) switch(_token) {
+ case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::ShiftExp); break;
+ case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break;
+ case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break;
+ case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;
+ case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;
+ case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break;
+ default: return;
+ }
+ }
+ void ShiftExp()
+ {
+ PlusExp();
+ for(;;) switch(_token) {
+ case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break;
+ case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break;
+ case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break;
+ default: return;
+ }
+ }
+ void PlusExp()
+ {
+ MultExp();
+ for(;;) switch(_token) {
+ case _SC('+'): case _SC('-'):
+ BIN_EXP(_OP_ARITH, &SQCompiler::MultExp,_token); break;
+ default: return;
+ }
+ }
+
+ void MultExp()
+ {
+ PrefixedExpr();
+ for(;;) switch(_token) {
+ case _SC('*'): case _SC('/'): case _SC('%'):
+ BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break;
+ default: return;
+ }
+ }
+ //if 'pos' != -1 the previous variable is a local variable
+ void PrefixedExpr()
+ {
+ int pos = Factor();
+ for(;;) {
+ switch(_token) {
+ case _SC('.'): {
+ pos = -1;
+ SQObjectPtr idx;
+ Lex();
+ if(_token == TK_PARENT) {
+ Lex();
+ if(!NeedGet())
+ Error(_SC("parent cannot be set"));
+ int src = _fs->PopTarget();
+ _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src);
+ }
+ else {
+ idx = Expect(TK_IDENTIFIER);
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(idx)));
+ if(NeedGet()) Emit2ArgsOP(_OP_GET);
+ }
+ _exst._deref = DEREF_FIELD;
+ _exst._freevar = false;
+ }
+ break;
+ case _SC('['):
+ if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));
+ Lex(); Expression(); Expect(_SC(']'));
+ pos = -1;
+ if(NeedGet()) Emit2ArgsOP(_OP_GET);
+ _exst._deref = DEREF_FIELD;
+ _exst._freevar = false;
+ break;
+ case TK_MINUSMINUS:
+ case TK_PLUSPLUS:
+ if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) {
+ int tok = _token; Lex();
+ if(pos < 0)
+ Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1);
+ else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
+ int src = _fs->PopTarget();
+ _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1);
+ }
+
+ }
+ return;
+ break;
+ case _SC('('):
+ {
+ if(_exst._deref != DEREF_NO_DEREF) {
+ if(pos<0) {
+ int key = _fs->PopTarget(); //key
+ int table = _fs->PopTarget(); //table etc...
+ int closure = _fs->PushTarget();
+ int ttarget = _fs->PushTarget();
+ _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);
+ }
+ else{
+ _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
+ }
+ }
+ else
+ _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
+ _exst._deref = DEREF_NO_DEREF;
+ Lex();
+ FunctionCallArgs();
+ }
+ break;
+ default: return;
+ }
+ }
+ }
+ int Factor()
+ {
+ switch(_token)
+ {
+ case TK_STRING_LITERAL: {
+ SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1));
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));
+ Lex();
+ }
+ break;
+ case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break;
+ case TK_VARGV: { Lex();
+ Expect(_SC('['));
+ Expression();
+ Expect(_SC(']'));
+ int src = _fs->PopTarget();
+ _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src);
+ }
+ break;
+ case TK_IDENTIFIER:
+ case TK_CONSTRUCTOR:
+ case TK_THIS:{
+ _exst._freevar = false;
+ SQObjectPtr id;
+ switch(_token) {
+ case TK_IDENTIFIER: id = SQString::Create(_ss(_vm), _lex._svalue); break;
+ case TK_THIS: id = SQString::Create(_ss(_vm), _SC("this")); break;
+ case TK_CONSTRUCTOR: id = SQString::Create(_ss(_vm), _SC("constructor")); break;
+ }
+ int pos = -1;
+ Lex();
+ if((pos = _fs->GetLocalVariable(id)) == -1) {
+ //checks if is a free variable
+ if((pos = _fs->GetOuterVariable(id)) != -1) {
+ _exst._deref = _fs->PushTarget();
+ _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos);
+ _exst._freevar = true;
+ } else {
+ _fs->PushTarget(0);
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));
+ if(NeedGet()) Emit2ArgsOP(_OP_GET);
+ _exst._deref = DEREF_FIELD;
+ }
+ }
+ else{
+ _fs->PushTarget(pos);
+ _exst._deref = pos;
+ }
+ return _exst._deref;
+ }
+ break;
+ case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); break;
+ case TK_DOUBLE_COLON: // "::"
+ _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget());
+ _exst._deref = DEREF_FIELD;
+ _token = _SC('.'); //hack
+ return -1;
+ break;
+ case TK_NULL:
+ _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
+ Lex();
+ break;
+ case TK_INTEGER:
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue));
+ Lex();
+ break;
+ case TK_FLOAT:
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));
+ Lex();
+ break;
+ case TK_TRUE: case TK_FALSE:
+ _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);
+ Lex();
+ break;
+ case _SC('['): {
+ _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget());
+ int apos = _fs->GetCurrentPos(),key = 0;
+ Lex();
+ while(_token != _SC(']')) {
+ Expression();
+ if(_token == _SC(',')) Lex();
+ int val = _fs->PopTarget();
+ int array = _fs->TopTarget();
+ _fs->AddInstruction(_OP_APPENDARRAY, array, val);
+ key++;
+ }
+ _fs->SetIntructionParam(apos, 1, key);
+ Lex();
+ }
+ break;
+ case _SC('{'):{
+ _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());
+ Lex();ParseTableOrClass(_SC(','));
+ }
+ break;
+ case TK_FUNCTION: FunctionExp(_token);break;
+ case TK_CLASS: Lex(); ClassExp();break;
+ case _SC('-'): UnaryOP(_OP_NEG); break;
+ case _SC('!'): UnaryOP(_OP_NOT); break;
+ case _SC('~'): UnaryOP(_OP_BWNOT); break;
+ case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break;
+ case TK_RESUME : UnaryOP(_OP_RESUME); break;
+ case TK_CLONE : UnaryOP(_OP_CLONE); break;
+ case TK_MINUSMINUS :
+ case TK_PLUSPLUS :PrefixIncDec(_token); break;
+ case TK_DELETE : DeleteExpr(); break;
+ case TK_DELEGATE : DelegateExpr(); break;
+ case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));
+ break;
+ default: Error(_SC("expression expected"));
+ }
+ return -1;
+ }
+ void UnaryOP(SQOpcode op)
+ {
+ Lex(); PrefixedExpr();
+ int src = _fs->PopTarget();
+ _fs->AddInstruction(op, _fs->PushTarget(), src);
+ }
+ bool NeedGet()
+ {
+ switch(_token) {
+ case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_PLUSPLUS: case TK_MINUSMINUS:
+ case TK_PLUSEQ: case TK_MINUSEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MODEQ:
+ return false;
+ }
+ return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('[')));
+ }
+
+ void FunctionCallArgs()
+ {
+ int nargs = 1;//this
+ while(_token != _SC(')')) {
+ Expression(true);
+ MoveIfCurrentTargetIsLocal();
+ nargs++;
+ if(_token == _SC(',')){
+ Lex();
+ if(_token == ')') Error(_SC("expression expected, found ')'"));
+ }
+ }
+ Lex();
+ for(int i = 0; i < (nargs - 1); i++) _fs->PopTarget();
+ int stackbase = _fs->PopTarget();
+ int closure = _fs->PopTarget();
+ _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);
+ }
+ void ParseTableOrClass(int separator,int terminator = '}')
+ {
+ int tpos = _fs->GetCurrentPos(),nkeys = 0;
+
+ while(_token != terminator) {
+ bool hasattrs = false;
+ //check if is an attribute
+ if(separator == ';' && _token == TK_ATTR_OPEN) {
+ _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex();
+ ParseTableOrClass(',',TK_ATTR_CLOSE);
+ hasattrs = true;
+ }
+ switch(_token) {
+ case TK_FUNCTION:
+ case TK_CONSTRUCTOR:{
+ int tk = _token;
+ Lex();
+ SQObjectPtr id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : SQString::Create(_ss(_vm),_SC("constructor"));
+ Expect(_SC('('));
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));
+ CreateFunction(id);
+ _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
+ }
+ break;
+ case _SC('['):
+ Lex(); CommaExpr(); Expect(_SC(']'));
+ Expect(_SC('=')); Expression();
+ break;
+ default :
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(Expect(TK_IDENTIFIER))));
+ Expect(_SC('=')); Expression();
+ }
+
+ if(_token == separator) Lex();//optional comma/semicolon
+ nkeys++;
+ int val = _fs->PopTarget();
+ int key = _fs->PopTarget();
+ int attrs = hasattrs ? _fs->PopTarget():-1;
+ assert(hasattrs && attrs == key-1 || !hasattrs);
+ int table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
+ _fs->AddInstruction(hasattrs?_OP_NEWSLOTA:_OP_NEWSLOT, _fs->PushTarget(), table, key, val);
+ _fs->PopTarget();
+ }
+ if(separator == _SC(',')) //hack recognizes a table from the separator
+ _fs->SetIntructionParam(tpos, 1, nkeys);
+ Lex();
+ }
+ void LocalDeclStatement()
+ {
+ SQObjectPtr varname;
+ do {
+ Lex(); varname = Expect(TK_IDENTIFIER);
+ if(_token == _SC('=')) {
+ Lex(); Expression();
+ int src = _fs->PopTarget();
+ int dest = _fs->PushTarget();
+ if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);
+ }
+ else{
+ _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
+ }
+ _fs->PopTarget();
+ _fs->PushLocalVariable(varname);
+
+ } while(_token == _SC(','));
+ }
+ void IfStatement()
+ {
+ int jmppos;
+ bool haselse = false;
+ Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+ _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
+ int jnepos = _fs->GetCurrentPos();
+ int stacksize = _fs->GetStackSize();
+
+ Statement();
+ //
+ if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();
+
+ CleanStack(stacksize);
+ int endifblock = _fs->GetCurrentPos();
+ if(_token == TK_ELSE){
+ haselse = true;
+ stacksize = _fs->GetStackSize();
+ _fs->AddInstruction(_OP_JMP);
+ jmppos = _fs->GetCurrentPos();
+ Lex();
+ Statement(); OptionalSemicolon();
+ CleanStack(stacksize);
+ _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
+ }
+ _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));
+ }
+ void WhileStatement()
+ {
+ int jzpos, jmppos;
+ int stacksize = _fs->GetStackSize();
+ jmppos = _fs->GetCurrentPos();
+ Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+
+ BEGIN_BREAKBLE_BLOCK();
+ _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
+ jzpos = _fs->GetCurrentPos();
+ stacksize = _fs->GetStackSize();
+
+ Statement();
+
+ CleanStack(stacksize);
+ _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
+ _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
+
+ END_BREAKBLE_BLOCK(jmppos);
+ }
+ void DoWhileStatement()
+ {
+ Lex();
+ int jzpos = _fs->GetCurrentPos();
+ int stacksize = _fs->GetStackSize();
+ BEGIN_BREAKBLE_BLOCK()
+ Statement();
+ CleanStack(stacksize);
+ Expect(TK_WHILE);
+ int continuetrg = _fs->GetCurrentPos();
+ Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+ _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1);
+ END_BREAKBLE_BLOCK(continuetrg);
+ }
+ void ForStatement()
+ {
+ Lex();
+ int stacksize = _fs->GetStackSize();
+ Expect(_SC('('));
+ if(_token == TK_LOCAL) LocalDeclStatement();
+ else if(_token != _SC(';')){
+ CommaExpr();
+ _fs->PopTarget();
+ }
+ Expect(_SC(';'));
+ _fs->SnoozeOpt();
+ int jmppos = _fs->GetCurrentPos();
+ int jzpos = -1;
+ if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }
+ Expect(_SC(';'));
+ _fs->SnoozeOpt();
+ int expstart = _fs->GetCurrentPos() + 1;
+ if(_token != _SC(')')) {
+ CommaExpr();
+ _fs->PopTarget();
+ }
+ Expect(_SC(')'));
+ _fs->SnoozeOpt();
+ int expend = _fs->GetCurrentPos();
+ int expsize = (expend - expstart) + 1;
+ SQInstructionVec exp;
+ if(expsize > 0) {
+ for(int i = 0; i < expsize; i++)
+ exp.push_back(_fs->GetInstruction(expstart + i));
+ _fs->PopInstructions(expsize);
+ }
+ BEGIN_BREAKBLE_BLOCK()
+ Statement();
+ int continuetrg = _fs->GetCurrentPos();
+ if(expsize > 0) {
+ for(int i = 0; i < expsize; i++)
+ _fs->AddInstruction(exp[i]);
+ }
+ _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
+ if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
+ CleanStack(stacksize);
+
+ END_BREAKBLE_BLOCK(continuetrg);
+ }
+ void ForEachStatement()
+ {
+ SQObjectPtr idxname, valname;
+ Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);
+ if(_token == _SC(',')) {
+ idxname = valname;
+ Lex(); valname = Expect(TK_IDENTIFIER);
+ }
+ else{
+ idxname = SQString::Create(_ss(_vm), _SC("@INDEX@"));
+ }
+ Expect(TK_IN);
+
+ //save the stack size
+ int stacksize = _fs->GetStackSize();
+ //put the table in the stack(evaluate the table expression)
+ Expression(); Expect(_SC(')'));
+ int container = _fs->TopTarget();
+ //push the index local var
+ int indexpos = _fs->PushLocalVariable(idxname);
+ _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);
+ //push the value local var
+ int valuepos = _fs->PushLocalVariable(valname);
+ _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);
+ //push reference index
+ int itrpos = _fs->PushLocalVariable(SQString::Create(_ss(_vm), _SC("@ITERATOR@"))); //use invalid id to make it inaccessible
+ _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);
+ int jmppos = _fs->GetCurrentPos();
+ _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);
+ int foreachpos = _fs->GetCurrentPos();
+ //generate the statement code
+ BEGIN_BREAKBLE_BLOCK()
+ Statement();
+ _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
+ _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);
+ //restore the local variable stack(remove index,val and ref idx)
+ CleanStack(stacksize);
+ END_BREAKBLE_BLOCK(foreachpos - 1);
+ }
+ void SwitchStatement()
+ {
+ Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+ Expect(_SC('{'));
+ int expr = _fs->TopTarget();
+ bool bfirst = true;
+ int tonextcondjmp = -1;
+ int skipcondjmp = -1;
+ int __nbreaks__ = _fs->_unresolvedbreaks.size();
+ _fs->_breaktargets.push_back(0);
+ while(_token == TK_CASE) {
+ if(!bfirst) {
+ _fs->AddInstruction(_OP_JMP, 0, 0);
+ skipcondjmp = _fs->GetCurrentPos();
+ _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
+ }
+ //condition
+ Lex(); Expression(); Expect(_SC(':'));
+ int trg = _fs->PopTarget();
+ _fs->AddInstruction(_OP_EQ, trg, trg, expr);
+ _fs->AddInstruction(_OP_JZ, trg, 0);
+ //end condition
+ if(skipcondjmp != -1) {
+ _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));
+ }
+ tonextcondjmp = _fs->GetCurrentPos();
+ int stacksize = _fs->GetStackSize();
+ Statements();
+ _fs->SetStackSize(stacksize);
+ bfirst = false;
+ }
+ if(tonextcondjmp != -1)
+ _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
+ if(_token == TK_DEFAULT) {
+ Lex(); Expect(_SC(':'));
+ int stacksize = _fs->GetStackSize();
+ Statements();
+ _fs->SetStackSize(stacksize);
+ }
+ Expect(_SC('}'));
+ _fs->PopTarget();
+ __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;
+ if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);
+ _fs->_breaktargets.pop_back();
+
+ }
+ void FunctionStatement()
+ {
+ SQObjectPtr id;
+ Lex(); id = Expect(TK_IDENTIFIER);
+ _fs->PushTarget(0);
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));
+ if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
+
+ while(_token == TK_DOUBLE_COLON) {
+ Lex();
+ id = Expect(TK_IDENTIFIER);
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetStringConstant(_stringval(id)));
+ if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
+ }
+ Expect(_SC('('));
+ CreateFunction(id);
+ _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
+ EmitDerefOp(_OP_NEWSLOT);
+ _fs->PopTarget();
+ }
+ void ClassStatement()
+ {
+ ExpState es;
+ Lex(); PushExpState();
+ _exst._class_or_delete = true;
+ _exst._funcarg = false;
+ PrefixedExpr();
+ es = PopExpState();
+ if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name"));
+ if(es._deref == DEREF_FIELD) {
+ ClassExp();
+ EmitDerefOp(_OP_NEWSLOT);
+ _fs->PopTarget();
+ }
+ else Error(_SC("cannot create a class in a local with the syntax(class <local>)"));
+ }
+ void TryCatchStatement()
+ {
+ SQObjectPtr exid;
+ Lex();
+ _fs->AddInstruction(_OP_PUSHTRAP,0,0);
+ _fs->_traps++;
+ if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;
+ if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;
+ int trappos = _fs->GetCurrentPos();
+ Statement();
+ _fs->_traps--;
+ _fs->AddInstruction(_OP_POPTRAP, 1, 0);
+ if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;
+ if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--;
+ _fs->AddInstruction(_OP_JMP, 0, 0);
+ int jmppos = _fs->GetCurrentPos();
+ _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));
+ Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));
+ int stacksize = _fs->GetStackSize();
+ int ex_target = _fs->PushLocalVariable(exid);
+ _fs->SetIntructionParam(trappos, 0, ex_target);
+ Statement();
+ _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);
+ CleanStack(stacksize);
+ }
+ void FunctionExp(int ftype)
+ {
+ Lex(); Expect(_SC('('));
+ CreateFunction(_null_);
+ _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);
+ }
+ void ClassExp()
+ {
+ int base = -1;
+ int attrs = -1;
+ if(_token == TK_EXTENDS) {
+ Lex(); Expression();
+ base = _fs->TopTarget();
+ }
+ if(_token == TK_ATTR_OPEN) {
+ Lex();
+ _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget());
+ ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);
+ attrs = _fs->TopTarget();
+ }
+ Expect(_SC('{'));
+ if(attrs != -1) _fs->PopTarget();
+ if(base != -1) _fs->PopTarget();
+ _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs);
+ ParseTableOrClass(_SC(';'));
+ }
+ void DelegateExpr()
+ {
+ Lex(); CommaExpr();
+ Expect(_SC(':'));
+ CommaExpr();
+ int table = _fs->PopTarget(), delegate = _fs->PopTarget();
+ _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate);
+ }
+ void DeleteExpr()
+ {
+ ExpState es;
+ Lex(); PushExpState();
+ _exst._class_or_delete = true;
+ _exst._funcarg = false;
+ PrefixedExpr();
+ es = PopExpState();
+ if(es._deref == DEREF_NO_DEREF) Error(_SC("can't delete an expression"));
+ if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE);
+ else Error(_SC("cannot delete a local"));
+ }
+ void PrefixIncDec(int token)
+ {
+ ExpState es;
+ Lex(); PushExpState();
+ _exst._class_or_delete = true;
+ _exst._funcarg = false;
+ PrefixedExpr();
+ es = PopExpState();
+ if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_INC,token == TK_MINUSMINUS?-1:1);
+ else {
+ int src = _fs->PopTarget();
+ _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1);
+ }
+ }
+ void CreateFunction(SQObjectPtr name)
+ {
+ SQFuncState funcstate(_ss(_vm), SQFunctionProto::Create(), _fs);
+ _funcproto(funcstate._func)->_name = name;
+ SQObjectPtr paramname;
+ funcstate.AddParameter(SQString::Create(_ss(_vm), _SC("this")));
+ _funcproto(funcstate._func)->_sourcename = _sourcename;
+ while(_token!=_SC(')')) {
+ if(_token == TK_VARPARAMS) {
+ funcstate._varparams = true;
+ Lex();
+ if(_token != _SC(')')) Error(_SC("expected ')'"));
+ break;
+ }
+ else {
+ paramname = Expect(TK_IDENTIFIER);
+ funcstate.AddParameter(paramname);
+ if(_token == _SC(',')) Lex();
+ else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
+ }
+ }
+ Expect(_SC(')'));
+ //outer values
+ if(_token == _SC(':')) {
+ Lex(); Expect(_SC('('));
+ while(_token != _SC(')')) {
+ paramname = Expect(TK_IDENTIFIER);
+ //outers are treated as implicit local variables
+ funcstate.AddOuterValue(paramname);
+ if(_token == _SC(',')) Lex();
+ else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
+ }
+ Lex();
+ }
+
+ SQFuncState *currchunk = _fs;
+ _fs = &funcstate;
+ Statement();
+ funcstate.AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);
+ funcstate.AddInstruction(_OP_RETURN, -1);
+ funcstate.SetStackSize(0);
+ _funcproto(_fs->_func)->_stacksize = _fs->_stacksize;
+ funcstate.Finalize();
+#ifdef _DEBUG_DUMP
+ funcstate.Dump();
+#endif
+ _fs = currchunk;
+ _fs->_functions.push_back(funcstate._func);
+ }
+ void CleanStack(int stacksize)
+ {
+ if(_fs->GetStackSize() != stacksize)
+ _fs->SetStackSize(stacksize);
+ }
+ void ResolveBreaks(SQFuncState *funcstate, int ntoresolve)
+ {
+ while(ntoresolve > 0) {
+ int pos = funcstate->_unresolvedbreaks.back();
+ funcstate->_unresolvedbreaks.pop_back();
+ //set the jmp instruction
+ funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0);
+ ntoresolve--;
+ }
+ }
+ void ResolveContinues(SQFuncState *funcstate, int ntoresolve, int targetpos)
+ {
+ while(ntoresolve > 0) {
+ int pos = funcstate->_unresolvedcontinues.back();
+ funcstate->_unresolvedcontinues.pop_back();
+ //set the jmp instruction
+ funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);
+ ntoresolve--;
+ }
+ }
+private:
+ int _token;
+ SQFuncState *_fs;
+ SQObjectPtr _sourcename;
+ SQLexer _lex;
+ bool _lineinfo;
+ bool _raiseerror;
+ int _debugline;
+ int _debugop;
+ ExpStateVec _expstates;
+ SQVM *_vm;
+};
+
+bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)
+{
+ SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);
+ return p.Compile(out);
+}
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQCOMPILER_H_\r
-#define _SQCOMPILER_H_\r
-\r
-struct SQVM;\r
-\r
-#define TK_IDENTIFIER 258\r
-#define TK_STRING_LITERAL 259\r
-#define TK_INTEGER 260\r
-#define TK_FLOAT 261\r
-#define TK_DELEGATE 262\r
-#define TK_DELETE 263\r
-#define TK_EQ 264\r
-#define TK_NE 265\r
-#define TK_LE 266\r
-#define TK_GE 267\r
-#define TK_SWITCH 268\r
-#define TK_ARROW 269\r
-#define TK_AND 270\r
-#define TK_OR 271\r
-#define TK_IF 272\r
-#define TK_ELSE 273\r
-#define TK_WHILE 274\r
-#define TK_BREAK 275\r
-#define TK_FOR 276\r
-#define TK_DO 277\r
-#define TK_NULL 278\r
-#define TK_FOREACH 279\r
-#define TK_IN 280\r
-#define TK_NEWSLOT 281\r
-#define TK_MODULO 282\r
-#define TK_LOCAL 283\r
-#define TK_CLONE 284\r
-#define TK_FUNCTION 285\r
-#define TK_RETURN 286\r
-#define TK_TYPEOF 287\r
-#define TK_UMINUS 288\r
-#define TK_PLUSEQ 289\r
-#define TK_MINUSEQ 290\r
-#define TK_CONTINUE 291\r
-#define TK_YIELD 292\r
-#define TK_TRY 293\r
-#define TK_CATCH 294\r
-#define TK_THROW 295\r
-#define TK_SHIFTL 296\r
-#define TK_SHIFTR 297\r
-#define TK_RESUME 298\r
-#define TK_DOUBLE_COLON 299\r
-#define TK_CASE 300\r
-#define TK_DEFAULT 301\r
-#define TK_THIS 302\r
-#define TK_PLUSPLUS 303\r
-#define TK_MINUSMINUS 304\r
-#define TK_PARENT 305\r
-#define TK_USHIFTR 306\r
-#define TK_CLASS 307\r
-#define TK_EXTENDS 308\r
-#define TK_CONSTRUCTOR 310\r
-#define TK_INSTANCEOF 311\r
-#define TK_VARPARAMS 312\r
-#define TK_VARGC 313\r
-#define TK_VARGV 314\r
-#define TK_TRUE 315\r
-#define TK_FALSE 316\r
-#define TK_MULEQ 317\r
-#define TK_DIVEQ 318\r
-#define TK_MODEQ 319\r
-#define TK_ATTR_OPEN 320\r
-#define TK_ATTR_CLOSE 321\r
-\r
-\r
-struct ParserException{ SQChar *desc; ParserException(SQChar *err):desc(err) {} };\r
-bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo);\r
-#endif //_SQCOMPILER_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQCOMPILER_H_
+#define _SQCOMPILER_H_
+
+struct SQVM;
+
+#define TK_IDENTIFIER 258
+#define TK_STRING_LITERAL 259
+#define TK_INTEGER 260
+#define TK_FLOAT 261
+#define TK_DELEGATE 262
+#define TK_DELETE 263
+#define TK_EQ 264
+#define TK_NE 265
+#define TK_LE 266
+#define TK_GE 267
+#define TK_SWITCH 268
+#define TK_ARROW 269
+#define TK_AND 270
+#define TK_OR 271
+#define TK_IF 272
+#define TK_ELSE 273
+#define TK_WHILE 274
+#define TK_BREAK 275
+#define TK_FOR 276
+#define TK_DO 277
+#define TK_NULL 278
+#define TK_FOREACH 279
+#define TK_IN 280
+#define TK_NEWSLOT 281
+#define TK_MODULO 282
+#define TK_LOCAL 283
+#define TK_CLONE 284
+#define TK_FUNCTION 285
+#define TK_RETURN 286
+#define TK_TYPEOF 287
+#define TK_UMINUS 288
+#define TK_PLUSEQ 289
+#define TK_MINUSEQ 290
+#define TK_CONTINUE 291
+#define TK_YIELD 292
+#define TK_TRY 293
+#define TK_CATCH 294
+#define TK_THROW 295
+#define TK_SHIFTL 296
+#define TK_SHIFTR 297
+#define TK_RESUME 298
+#define TK_DOUBLE_COLON 299
+#define TK_CASE 300
+#define TK_DEFAULT 301
+#define TK_THIS 302
+#define TK_PLUSPLUS 303
+#define TK_MINUSMINUS 304
+#define TK_PARENT 305
+#define TK_USHIFTR 306
+#define TK_CLASS 307
+#define TK_EXTENDS 308
+#define TK_CONSTRUCTOR 310
+#define TK_INSTANCEOF 311
+#define TK_VARPARAMS 312
+#define TK_VARGC 313
+#define TK_VARGV 314
+#define TK_TRUE 315
+#define TK_FALSE 316
+#define TK_MULEQ 317
+#define TK_DIVEQ 318
+#define TK_MODEQ 319
+#define TK_ATTR_OPEN 320
+#define TK_ATTR_CLOSE 321
+
+
+struct ParserException{ SQChar *desc; ParserException(SQChar *err):desc(err) {} };
+bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo);
+#endif //_SQCOMPILER_H_
-/*\r
- see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include <stdarg.h>\r
-#include "sqvm.h"\r
-#include "sqfuncproto.h"\r
-#include "sqclosure.h"\r
-#include "sqstring.h"\r
-\r
-SQRESULT sq_stackinfos(HSQUIRRELVM v, int level, SQStackInfos *si)\r
-{\r
- int cssize = v->_callsstack.size();\r
- if (cssize > level) {\r
- memset(si, 0, sizeof(SQStackInfos));\r
- SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];\r
- switch (type(ci._closure)) {\r
- case OT_CLOSURE:{\r
- SQFunctionProto *func = _funcproto(_closure(ci._closure)->_function);\r
- if (type(func->_name) == OT_STRING)\r
- si->funcname = _stringval(func->_name);\r
- if (type(func->_sourcename) == OT_STRING)\r
- si->source = _stringval(func->_sourcename);\r
- si->line = func->GetLine(ci._ip);\r
- }\r
- break;\r
- case OT_NATIVECLOSURE:\r
- si->source = _SC("NATIVE");\r
- si->funcname = _SC("unknown");\r
- if(type(_nativeclosure(ci._closure)->_name) == OT_STRING)\r
- si->funcname = _stringval(_nativeclosure(ci._closure)->_name);\r
- si->line = -1;\r
- break;\r
- }\r
- return SQ_OK;\r
- }\r
- return SQ_ERROR;\r
-}\r
-\r
-void SQVM::Raise_Error(const SQChar *s, ...)\r
-{\r
- va_list vl;\r
- va_start(vl, s);\r
- scvsprintf(_sp(rsl(scstrlen(s)+(NUMBER_MAX_CHAR*2))), s, vl);\r
- va_end(vl);\r
- _lasterror = SQString::Create(_ss(this),_spval,-1);\r
-}\r
-\r
-void SQVM::Raise_Error(SQObjectPtr &desc)\r
-{\r
- _lasterror = desc;\r
-}\r
-\r
-SQString *SQVM::PrintObjVal(const SQObject &o)\r
-{\r
- switch(type(o)) {\r
- case OT_STRING: return _string(o);\r
- case OT_INTEGER:\r
- scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%d"), _integer(o));\r
- return SQString::Create(_ss(this), _spval);\r
- break;\r
- case OT_FLOAT:\r
- scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%.14g"), _float(o));\r
- return SQString::Create(_ss(this), _spval);\r
- break;\r
- default:\r
- return SQString::Create(_ss(this), GetTypeName(o));\r
- }\r
-}\r
-\r
-void SQVM::Raise_IdxError(SQObject &o)\r
-{\r
- SQObjectPtr oval = PrintObjVal(o);\r
- Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval));\r
-}\r
-\r
-void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2)\r
-{\r
- SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2);\r
- Raise_Error(_SC("comparsion between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2));\r
-}\r
-\r
-\r
-void SQVM::Raise_ParamTypeError(int nparam,int typemask,int type)\r
-{\r
- SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1);\r
- int found = 0; \r
- for(int i=0; i<16; i++)\r
- {\r
- int mask = 0x00000001 << i;\r
- if(typemask & (mask)) {\r
- if(found>0) StringCat(exptypes,SQString::Create(_ss(this), _SC("|"), -1), exptypes);\r
- found ++;\r
- StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes);\r
- }\r
- }\r
- Raise_Error(_SC("parameter %d has an invalid type '%s' ; expected: '%s'"), nparam, IdType2Name((SQObjectType)type), _stringval(exptypes));\r
-}\r
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include <stdarg.h>
+#include "sqvm.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+#include "sqstring.h"
+
+SQRESULT sq_stackinfos(HSQUIRRELVM v, int level, SQStackInfos *si)
+{
+ int cssize = v->_callsstack.size();
+ if (cssize > level) {
+ memset(si, 0, sizeof(SQStackInfos));
+ SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];
+ switch (type(ci._closure)) {
+ case OT_CLOSURE:{
+ SQFunctionProto *func = _funcproto(_closure(ci._closure)->_function);
+ if (type(func->_name) == OT_STRING)
+ si->funcname = _stringval(func->_name);
+ if (type(func->_sourcename) == OT_STRING)
+ si->source = _stringval(func->_sourcename);
+ si->line = func->GetLine(ci._ip);
+ }
+ break;
+ case OT_NATIVECLOSURE:
+ si->source = _SC("NATIVE");
+ si->funcname = _SC("unknown");
+ if(type(_nativeclosure(ci._closure)->_name) == OT_STRING)
+ si->funcname = _stringval(_nativeclosure(ci._closure)->_name);
+ si->line = -1;
+ break;
+ default:
+ break;
+ }
+ return SQ_OK;
+ }
+ return SQ_ERROR;
+}
+
+void SQVM::Raise_Error(const SQChar *s, ...)
+{
+ va_list vl;
+ va_start(vl, s);
+ scvsprintf(_sp(rsl(scstrlen(s)+(NUMBER_MAX_CHAR*2))), s, vl);
+ va_end(vl);
+ _lasterror = SQString::Create(_ss(this),_spval,-1);
+}
+
+void SQVM::Raise_Error(SQObjectPtr &desc)
+{
+ _lasterror = desc;
+}
+
+SQString *SQVM::PrintObjVal(const SQObject &o)
+{
+ switch(type(o)) {
+ case OT_STRING: return _string(o);
+ case OT_INTEGER:
+ scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%d"), _integer(o));
+ return SQString::Create(_ss(this), _spval);
+ break;
+ case OT_FLOAT:
+ scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%.14g"), _float(o));
+ return SQString::Create(_ss(this), _spval);
+ break;
+ default:
+ return SQString::Create(_ss(this), GetTypeName(o));
+ }
+}
+
+void SQVM::Raise_IdxError(SQObject &o)
+{
+ SQObjectPtr oval = PrintObjVal(o);
+ Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval));
+}
+
+void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2)
+{
+ SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2);
+ Raise_Error(_SC("comparsion between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2));
+}
+
+
+void SQVM::Raise_ParamTypeError(int nparam,int typemask,int type)
+{
+ SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1);
+ int found = 0;
+ for(int i=0; i<16; i++)
+ {
+ int mask = 0x00000001 << i;
+ if(typemask & (mask)) {
+ if(found>0) StringCat(exptypes,SQString::Create(_ss(this), _SC("|"), -1), exptypes);
+ found ++;
+ StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes);
+ }
+ }
+ Raise_Error(_SC("parameter %d has an invalid type '%s' ; expected: '%s'"), nparam, IdType2Name((SQObjectType)type), _stringval(exptypes));
+}
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQFUNCTION_H_\r
-#define _SQFUNCTION_H_\r
-\r
-#include "sqopcodes.h"\r
-\r
-enum SQOuterType {\r
- otLOCAL = 0,\r
- otSYMBOL = 1,\r
- otOUTER = 2\r
-};\r
-\r
-struct SQOuterVar\r
-{\r
- \r
- SQOuterVar(){}\r
- SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t)\r
- {\r
- _name = name;\r
- _src=src;\r
- _type=t;\r
- }\r
- SQOuterVar(const SQOuterVar &ov)\r
- {\r
- _type=ov._type;\r
- _src=ov._src;\r
- _name=ov._name;\r
- }\r
- SQOuterType _type;\r
- SQObjectPtr _name;\r
- SQObjectPtr _src;\r
-};\r
-\r
-struct SQLocalVarInfo\r
-{\r
- SQLocalVarInfo():_start_op(0),_end_op(0){}\r
- SQLocalVarInfo(const SQLocalVarInfo &lvi)\r
- {\r
- _name=lvi._name;\r
- _start_op=lvi._start_op;\r
- _end_op=lvi._end_op;\r
- _pos=lvi._pos;\r
- }\r
- SQObjectPtr _name;\r
- unsigned int _start_op;\r
- unsigned int _end_op;\r
- unsigned int _pos;\r
-};\r
-\r
-struct SQLineInfo { int _line;int _op; };\r
-\r
-typedef sqvector<SQOuterVar> SQOuterVarVec;\r
-typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;\r
-typedef sqvector<SQLineInfo> SQLineInfoVec;\r
-\r
-struct SQFunctionProto : public SQRefCounted\r
-{\r
-private:\r
- SQFunctionProto(){\r
- _uiRef=0;\r
- _stacksize=0;\r
- _bgenerator=false;}\r
-public:\r
- static SQFunctionProto *Create()\r
- {\r
- SQFunctionProto *f;\r
- sq_new(f,SQFunctionProto);\r
- return f;\r
- }\r
- void Release(){ sq_delete(this,SQFunctionProto);}\r
- const SQChar* GetLocal(SQVM *v,unsigned int stackbase,unsigned int nseq,unsigned int nop);\r
- int GetLine(SQInstruction *curr);\r
- bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);\r
- bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read);\r
- SQObjectPtrVec _literals;\r
- SQObjectPtrVec _functions;\r
- SQObjectPtrVec _parameters;\r
- SQOuterVarVec _outervalues;\r
- SQInstructionVec _instructions;\r
- SQObjectPtr _sourcename;\r
- SQObjectPtr _name;\r
- SQLocalVarInfoVec _localvarinfos;\r
- SQLineInfoVec _lineinfos;\r
- int _stacksize;\r
- bool _bgenerator;\r
- bool _varparams;\r
-};\r
-\r
-#endif //_SQFUNCTION_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQFUNCTION_H_
+#define _SQFUNCTION_H_
+
+#include "sqopcodes.h"
+
+enum SQOuterType {
+ otLOCAL = 0,
+ otSYMBOL = 1,
+ otOUTER = 2
+};
+
+struct SQOuterVar
+{
+
+ SQOuterVar(){}
+ SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t)
+ {
+ _name = name;
+ _src=src;
+ _type=t;
+ }
+ SQOuterVar(const SQOuterVar &ov)
+ {
+ _type=ov._type;
+ _src=ov._src;
+ _name=ov._name;
+ }
+ SQOuterType _type;
+ SQObjectPtr _name;
+ SQObjectPtr _src;
+};
+
+struct SQLocalVarInfo
+{
+ SQLocalVarInfo():_start_op(0),_end_op(0){}
+ SQLocalVarInfo(const SQLocalVarInfo &lvi)
+ {
+ _name=lvi._name;
+ _start_op=lvi._start_op;
+ _end_op=lvi._end_op;
+ _pos=lvi._pos;
+ }
+ SQObjectPtr _name;
+ unsigned int _start_op;
+ unsigned int _end_op;
+ unsigned int _pos;
+};
+
+struct SQLineInfo { int _line;int _op; };
+
+typedef sqvector<SQOuterVar> SQOuterVarVec;
+typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;
+typedef sqvector<SQLineInfo> SQLineInfoVec;
+
+struct SQFunctionProto : public SQRefCounted
+{
+private:
+ SQFunctionProto(){
+ _uiRef=0;
+ _stacksize=0;
+ _bgenerator=false;}
+public:
+ static SQFunctionProto *Create()
+ {
+ SQFunctionProto *f;
+ sq_new(f,SQFunctionProto);
+ return f;
+ }
+ void Release(){ sq_delete(this,SQFunctionProto);}
+ const SQChar* GetLocal(SQVM *v,unsigned int stackbase,unsigned int nseq,unsigned int nop);
+ int GetLine(SQInstruction *curr);
+ bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
+ bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read);
+ SQObjectPtrVec _literals;
+ SQObjectPtrVec _functions;
+ SQObjectPtrVec _parameters;
+ SQOuterVarVec _outervalues;
+ SQInstructionVec _instructions;
+ SQObjectPtr _sourcename;
+ SQObjectPtr _name;
+ SQLocalVarInfoVec _localvarinfos;
+ SQLineInfoVec _lineinfos;
+ int _stacksize;
+ bool _bgenerator;
+ bool _varparams;
+};
+
+#endif //_SQFUNCTION_H_
-/*\r
- see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include "sqcompiler.h"\r
-#include "sqfuncproto.h"\r
-#include "sqstring.h"\r
-#include "sqtable.h"\r
-#include "sqopcodes.h"\r
-#include "sqfuncstate.h"\r
-\r
-#ifdef _DEBUG_DUMP\r
-SQInstructionDesc g_InstrDesc[]={\r
- {_SC("_OP_LINE")},\r
- {_SC("_OP_LOAD")},\r
- {_SC("_OP_TAILCALL")},\r
- {_SC("_OP_CALL")},\r
- {_SC("_OP_PREPCALL")},\r
- {_SC("_OP_PREPCALLK")},\r
- {_SC("_OP_GETK")},\r
- {_SC("_OP_MOVE")},\r
- {_SC("_OP_NEWSLOT")},\r
- {_SC("_OP_DELETE")},\r
- {_SC("_OP_SET")},\r
- {_SC("_OP_GET")},\r
- {_SC("_OP_EQ")},\r
- {_SC("_OP_NE")},\r
- {_SC("_OP_ARITH")},\r
- {_SC("_OP_BITW")},\r
- {_SC("_OP_RETURN")},\r
- {_SC("_OP_LOADNULLS")},\r
- {_SC("_OP_LOADROOTTABLE")},\r
- {_SC("_OP_DMOVE")},\r
- {_SC("_OP_JMP")},\r
- {_SC("_OP_JNZ")},\r
- {_SC("_OP_JZ")},\r
- {_SC("_OP_LOADFREEVAR")},\r
- {_SC("_OP_VARGC")},\r
- {_SC("_OP_GETVARGV")},\r
- {_SC("_OP_NEWTABLE")},\r
- {_SC("_OP_NEWARRAY")},\r
- {_SC("_OP_APPENDARRAY")},\r
- {_SC("_OP_GETPARENT")},\r
- {_SC("_OP_COMPARITH")},\r
- {_SC("_OP_COMPARITHL")},\r
- {_SC("_OP_INC")},\r
- {_SC("_OP_INCL")},\r
- {_SC("_OP_PINC")},\r
- {_SC("_OP_PINCL")},\r
- {_SC("_OP_CMP")},\r
- {_SC("_OP_EXISTS")},\r
- {_SC("_OP_INSTANCEOF")},\r
- {_SC("_OP_AND")},\r
- {_SC("_OP_OR")},\r
- {_SC("_OP_NEG")},\r
- {_SC("_OP_NOT")},\r
- {_SC("_OP_BWNOT")},\r
- {_SC("_OP_CLOSURE")},\r
- {_SC("_OP_YIELD")},\r
- {_SC("_OP_RESUME")},\r
- {_SC("_OP_FOREACH")},\r
- {_SC("_OP_DELEGATE")},\r
- {_SC("_OP_CLONE")},\r
- {_SC("_OP_TYPEOF")},\r
- {_SC("_OP_PUSHTRAP")},\r
- {_SC("_OP_POPTRAP")},\r
- {_SC("_OP_THROW")},\r
- {_SC("_OP_CLASS")},\r
- {_SC("_OP_NEWSLOTA")},\r
- {_SC("_OP_LOADBOOL")}\r
-};\r
-#endif\r
-void DumpLiteral(SQObjectPtr &o)\r
-{\r
- switch(type(o)){\r
- case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;\r
- case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;\r
- case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break;\r
- }\r
-}\r
-\r
-SQFuncState::SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent)\r
-{\r
- _nliterals = 0;\r
- _literals = SQTable::Create(ss,0);\r
- _sharedstate = ss;\r
- _lastline = 0;\r
- _optimization = true;\r
- _func = func;\r
- _parent = parent;\r
- _stacksize = 0;\r
- _traps = 0;\r
- _returnexp = 0;\r
- _varparams = false;\r
-}\r
-\r
-#ifdef _DEBUG_DUMP\r
-void SQFuncState::Dump()\r
-{\r
- unsigned int n=0,i;\r
- SQFunctionProto *func=_funcproto(_func);\r
- scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));\r
- scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));\r
- scprintf(_SC("--------------------------------------------------------------------\n"));\r
- scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));\r
- scprintf(_SC("-----LITERALS\n"));\r
- SQObjectPtr refidx,key,val;\r
- SQInteger idx;\r
- SQObjectPtrVec templiterals;\r
- templiterals.resize(_nliterals);\r
- while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {\r
- refidx=idx;\r
- templiterals[_integer(val)]=key;\r
- }\r
- for(i=0;i<templiterals.size();i++){\r
- scprintf(_SC("[%d] "),n);\r
- DumpLiteral(templiterals[i]);\r
- scprintf(_SC("\n"));\r
- n++;\r
- }\r
- scprintf(_SC("-----PARAMS\n"));\r
- if(_varparams)\r
- scprintf(_SC("<<VARPARAMS>>\n"));\r
- n=0;\r
- for(i=0;i<_parameters.size();i++){\r
- scprintf(_SC("[%d] "),n);\r
- DumpLiteral(_parameters[i]);\r
- scprintf(_SC("\n"));\r
- n++;\r
- }\r
- scprintf(_SC("-----LOCALS\n"));\r
- for(i=0;i<func->_localvarinfos.size();i++){\r
- SQLocalVarInfo lvi=func->_localvarinfos[i];\r
- scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);\r
- n++;\r
- }\r
- scprintf(_SC("-----LINE INFO\n"));\r
- for(i=0;i<_lineinfos.size();i++){\r
- SQLineInfo li=_lineinfos[i];\r
- scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);\r
- n++;\r
- }\r
- scprintf(_SC("-----dump\n"));\r
- n=0;\r
- for(i=0;i<_instructions.size();i++){\r
- SQInstruction &inst=_instructions[i];\r
- if(inst.op==_OP_LOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){\r
- \r
- int lidx = inst._arg1;\r
- scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);\r
- if(lidx >= 0xFFFFFFFF)\r
- scprintf(_SC("null"));\r
- else {\r
- int refidx;\r
- SQObjectPtr val,key,refo;\r
- while(((refidx=_table(_literals)->Next(refo,key,val))!= -1) && (_integer(val) != lidx)) {\r
- refo = refidx; \r
- }\r
- DumpLiteral(key);\r
- }\r
- scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);\r
- }\r
- else if(inst.op==_OP_ARITH){\r
- scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);\r
- }\r
- else \r
- scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);\r
- n++;\r
- }\r
- scprintf(_SC("-----\n"));\r
- scprintf(_SC("stack size[%d]\n"),func->_stacksize);\r
- scprintf(_SC("--------------------------------------------------------------------\n\n"));\r
-}\r
-#endif\r
-int SQFuncState::GetStringConstant(const SQChar *cons)\r
-{\r
- return GetConstant(SQString::Create(_sharedstate,cons));\r
-}\r
-\r
-int SQFuncState::GetNumericConstant(const SQInteger cons)\r
-{\r
- return GetConstant(cons);\r
-}\r
-\r
-int SQFuncState::GetNumericConstant(const SQFloat cons)\r
-{\r
- return GetConstant(cons);\r
-}\r
-\r
-int SQFuncState::GetConstant(SQObjectPtr cons)\r
-{\r
- int n=0;\r
- SQObjectPtr val;\r
- if(!_table(_literals)->Get(cons,val))\r
- {\r
- val = _nliterals;\r
- _table(_literals)->NewSlot(cons,val);\r
- _nliterals++;\r
- if(_nliterals > MAX_LITERALS) throw ParserException(_SC("internal compiler error: too many literals"));\r
- }\r
- return _integer(val);\r
-}\r
-\r
-void SQFuncState::SetIntructionParams(int pos,int arg0,int arg1,int arg2,int arg3)\r
-{\r
- _instructions[pos]._arg0=*((unsigned int *)&arg0);\r
- _instructions[pos]._arg1=*((unsigned int *)&arg1);\r
- _instructions[pos]._arg2=*((unsigned int *)&arg2);\r
- _instructions[pos]._arg3=*((unsigned int *)&arg3);\r
-}\r
-\r
-void SQFuncState::SetIntructionParam(int pos,int arg,int val)\r
-{\r
- switch(arg){\r
- case 0:_instructions[pos]._arg0=*((unsigned int *)&val);break;\r
- case 1:_instructions[pos]._arg1=*((unsigned int *)&val);break;\r
- case 2:_instructions[pos]._arg2=*((unsigned int *)&val);break;\r
- case 3:_instructions[pos]._arg3=*((unsigned int *)&val);break;\r
- case 4:_instructions[pos]._arg1=*((unsigned int *)&val);break;\r
- };\r
-}\r
-\r
-int SQFuncState::AllocStackPos()\r
-{\r
- int npos=_vlocals.size();\r
- _vlocals.push_back(SQLocalVarInfo());\r
- if(_vlocals.size()>((unsigned int)_stacksize)) {\r
- if(_stacksize>MAX_FUNC_STACKSIZE) throw ParserException(_SC("internal compiler error: too many locals"));\r
- _stacksize=_vlocals.size();\r
- }\r
- return npos;\r
-}\r
-\r
-int SQFuncState::PushTarget(int n)\r
-{\r
- if(n!=-1){\r
- _targetstack.push_back(n);\r
- return n;\r
- }\r
- n=AllocStackPos();\r
- _targetstack.push_back(n);\r
- return n;\r
-}\r
-\r
-int SQFuncState::GetUpTarget(int n){\r
- return _targetstack[((_targetstack.size()-1)-n)];\r
-}\r
-\r
-int SQFuncState::TopTarget(){\r
- return _targetstack.back();\r
-}\r
-int SQFuncState::PopTarget()\r
-{\r
- int npos=_targetstack.back();\r
- SQLocalVarInfo t=_vlocals[_targetstack.back()];\r
- if(type(t._name)==OT_NULL){\r
- _vlocals.pop_back();\r
- }\r
- _targetstack.pop_back();\r
- return npos;\r
-}\r
-\r
-int SQFuncState::GetStackSize()\r
-{\r
- return _vlocals.size();\r
-}\r
-\r
-void SQFuncState::SetStackSize(int n)\r
-{\r
- int size=_vlocals.size();\r
- while(size>n){\r
- size--;\r
- SQLocalVarInfo lvi=_vlocals.back();\r
- if(type(lvi._name)!=OT_NULL){\r
- lvi._end_op=GetCurrentPos();\r
- _localvarinfos.push_back(lvi);\r
- }\r
- _vlocals.pop_back();\r
- }\r
-}\r
-\r
-bool SQFuncState::IsLocal(unsigned int stkpos)\r
-{\r
- if(stkpos>=_vlocals.size())return false;\r
- else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;\r
- return false;\r
-}\r
-\r
-int SQFuncState::PushLocalVariable(const SQObjectPtr &name)\r
-{\r
- int pos=_vlocals.size();\r
- SQLocalVarInfo lvi;\r
- lvi._name=name;\r
- lvi._start_op=GetCurrentPos()+1;\r
- lvi._pos=_vlocals.size();\r
- _vlocals.push_back(lvi);\r
- if(_vlocals.size()>((unsigned int)_stacksize))_stacksize=_vlocals.size();\r
- \r
- return pos;\r
-}\r
-\r
-int SQFuncState::GetLocalVariable(const SQObjectPtr &name)\r
-{\r
- int locals=_vlocals.size();\r
- while(locals>=1){\r
- if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){\r
- return locals-1;\r
- }\r
- locals--;\r
- }\r
- return -1;\r
-}\r
-\r
-int SQFuncState::GetOuterVariable(const SQObjectPtr &name)\r
-{\r
- int outers = _outervalues.size();\r
- for(int i = 0; i<outers; i++) {\r
- if(_string(_outervalues[i]._name) == _string(name))\r
- return i;\r
- }\r
- return -1;\r
-}\r
-\r
-void SQFuncState::AddOuterValue(const SQObjectPtr &name)\r
-{\r
- //AddParameter(name);\r
- int pos=-1;\r
- if(_parent) { \r
- pos = _parent->GetLocalVariable(name);\r
- if(pos == -1) {\r
- pos = _parent->GetOuterVariable(name);\r
- if(pos != -1) {\r
- _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local\r
- return;\r
- }\r
- }\r
- else {\r
- _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local\r
- return;\r
- }\r
- } \r
- _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global\r
-}\r
-\r
-void SQFuncState::AddParameter(const SQObjectPtr &name)\r
-{\r
- PushLocalVariable(name);\r
- _parameters.push_back(name);\r
-}\r
-\r
-void SQFuncState::AddLineInfos(int line,bool lineop,bool force)\r
-{\r
- if(_lastline!=line || force){\r
- SQLineInfo li;\r
- li._line=line;li._op=(GetCurrentPos()+1);\r
- if(lineop)AddInstruction(_OP_LINE,0,line);\r
- _lineinfos.push_back(li);\r
- _lastline=line;\r
- }\r
-}\r
-\r
-void SQFuncState::AddInstruction(SQInstruction &i)\r
-{\r
- int size = _instructions.size();\r
- if(size > 0 && _optimization){ //simple optimizer\r
- SQInstruction &pi = _instructions[size-1];//previous instruction\r
- switch(i.op) {\r
- case _OP_RETURN:\r
- if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {\r
- pi.op = _OP_TAILCALL;\r
- }\r
- break;\r
- case _OP_GET:\r
- if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){\r
- pi._arg1 = pi._arg1;\r
- pi._arg2 = (unsigned char)i._arg1;\r
- pi.op = _OP_GETK;\r
- pi._arg0 = i._arg0;\r
- \r
- return;\r
- }\r
- break;\r
- case _OP_PREPCALL:\r
- if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){\r
- pi.op = _OP_PREPCALLK;\r
- pi._arg0 = i._arg0;\r
- pi._arg1 = pi._arg1;\r
- pi._arg2 = i._arg2;\r
- pi._arg3 = i._arg3;\r
- return;\r
- }\r
- break;\r
- case _OP_APPENDARRAY:\r
- if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){\r
- pi.op = _OP_APPENDARRAY;\r
- pi._arg0 = i._arg0;\r
- pi._arg1 = pi._arg1;\r
- pi._arg2 = MAX_FUNC_STACKSIZE;\r
- pi._arg3 = MAX_FUNC_STACKSIZE;\r
- return;\r
- }\r
- break;\r
- case _OP_MOVE: \r
- if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))\r
- {\r
- pi._arg0 = i._arg0;\r
- _optimization = false;\r
- return;\r
- }\r
-\r
- if(pi.op == _OP_MOVE)\r
- {\r
- pi.op = _OP_DMOVE;\r
- pi._arg2 = i._arg0;\r
- pi._arg3 = (unsigned char)i._arg1;\r
- return;\r
- }\r
- break;\r
-\r
- case _OP_EQ:case _OP_NE:\r
- if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))\r
- {\r
- pi.op = i.op;\r
- pi._arg0 = i._arg0;\r
- pi._arg1 = pi._arg1;\r
- pi._arg2 = i._arg2;\r
- pi._arg3 = MAX_FUNC_STACKSIZE;\r
- return;\r
- }\r
- break;\r
- case _OP_LOADNULLS:\r
- //case _OP_LOADNULL:\r
- if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {\r
- \r
- pi._arg1 = pi._arg1 + 1;\r
- pi.op = _OP_LOADNULLS;\r
- return;\r
- }\r
- break;\r
- case _OP_LINE:\r
- if(pi.op == _OP_LINE) {\r
- _instructions.pop_back();\r
- _lineinfos.pop_back();\r
- }\r
- break;\r
- }\r
- }\r
- _optimization = true;\r
- _instructions.push_back(i);\r
-}\r
-\r
-SQObject SQFuncState::CreateString(const SQChar *s)\r
-{\r
- SQObjectPtr ns(SQString::Create(_sharedstate,s));\r
- _stringrefs.push_back(ns);\r
- return ns;\r
-}\r
-\r
-void SQFuncState::Finalize()\r
-{\r
- SQFunctionProto *f=_funcproto(_func);\r
- f->_literals.resize(_nliterals);\r
- SQObjectPtr refidx,key,val;\r
- SQInteger idx;\r
- while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {\r
- f->_literals[_integer(val)]=key;\r
- refidx=idx;\r
- }\r
- f->_functions.resize(_functions.size());\r
- f->_functions.copy(_functions);\r
- f->_parameters.resize(_parameters.size());\r
- f->_parameters.copy(_parameters);\r
- f->_outervalues.resize(_outervalues.size());\r
- f->_outervalues.copy(_outervalues);\r
- f->_instructions.resize(_instructions.size());\r
- f->_instructions.copy(_instructions);\r
- f->_localvarinfos.resize(_localvarinfos.size());\r
- f->_localvarinfos.copy(_localvarinfos);\r
- f->_lineinfos.resize(_lineinfos.size());\r
- f->_lineinfos.copy(_lineinfos);\r
- f->_varparams = _varparams;\r
-}\r
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqcompiler.h"
+#include "sqfuncproto.h"
+#include "sqstring.h"
+#include "sqtable.h"
+#include "sqopcodes.h"
+#include "sqfuncstate.h"
+
+#ifdef _DEBUG_DUMP
+SQInstructionDesc g_InstrDesc[]={
+ {_SC("_OP_LINE")},
+ {_SC("_OP_LOAD")},
+ {_SC("_OP_TAILCALL")},
+ {_SC("_OP_CALL")},
+ {_SC("_OP_PREPCALL")},
+ {_SC("_OP_PREPCALLK")},
+ {_SC("_OP_GETK")},
+ {_SC("_OP_MOVE")},
+ {_SC("_OP_NEWSLOT")},
+ {_SC("_OP_DELETE")},
+ {_SC("_OP_SET")},
+ {_SC("_OP_GET")},
+ {_SC("_OP_EQ")},
+ {_SC("_OP_NE")},
+ {_SC("_OP_ARITH")},
+ {_SC("_OP_BITW")},
+ {_SC("_OP_RETURN")},
+ {_SC("_OP_LOADNULLS")},
+ {_SC("_OP_LOADROOTTABLE")},
+ {_SC("_OP_DMOVE")},
+ {_SC("_OP_JMP")},
+ {_SC("_OP_JNZ")},
+ {_SC("_OP_JZ")},
+ {_SC("_OP_LOADFREEVAR")},
+ {_SC("_OP_VARGC")},
+ {_SC("_OP_GETVARGV")},
+ {_SC("_OP_NEWTABLE")},
+ {_SC("_OP_NEWARRAY")},
+ {_SC("_OP_APPENDARRAY")},
+ {_SC("_OP_GETPARENT")},
+ {_SC("_OP_COMPARITH")},
+ {_SC("_OP_COMPARITHL")},
+ {_SC("_OP_INC")},
+ {_SC("_OP_INCL")},
+ {_SC("_OP_PINC")},
+ {_SC("_OP_PINCL")},
+ {_SC("_OP_CMP")},
+ {_SC("_OP_EXISTS")},
+ {_SC("_OP_INSTANCEOF")},
+ {_SC("_OP_AND")},
+ {_SC("_OP_OR")},
+ {_SC("_OP_NEG")},
+ {_SC("_OP_NOT")},
+ {_SC("_OP_BWNOT")},
+ {_SC("_OP_CLOSURE")},
+ {_SC("_OP_YIELD")},
+ {_SC("_OP_RESUME")},
+ {_SC("_OP_FOREACH")},
+ {_SC("_OP_DELEGATE")},
+ {_SC("_OP_CLONE")},
+ {_SC("_OP_TYPEOF")},
+ {_SC("_OP_PUSHTRAP")},
+ {_SC("_OP_POPTRAP")},
+ {_SC("_OP_THROW")},
+ {_SC("_OP_CLASS")},
+ {_SC("_OP_NEWSLOTA")},
+ {_SC("_OP_LOADBOOL")}
+};
+#endif
+void DumpLiteral(SQObjectPtr &o)
+{
+ switch(type(o)){
+ case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;
+ case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
+ case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break;
+ default: break;
+ }
+}
+
+SQFuncState::SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent)
+{
+ _nliterals = 0;
+ _literals = SQTable::Create(ss,0);
+ _sharedstate = ss;
+ _lastline = 0;
+ _optimization = true;
+ _func = func;
+ _parent = parent;
+ _stacksize = 0;
+ _traps = 0;
+ _returnexp = 0;
+ _varparams = false;
+}
+
+#ifdef _DEBUG_DUMP
+void SQFuncState::Dump()
+{
+ unsigned int n=0,i;
+ SQFunctionProto *func=_funcproto(_func);
+ scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
+ scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
+ scprintf(_SC("--------------------------------------------------------------------\n"));
+ scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
+ scprintf(_SC("-----LITERALS\n"));
+ SQObjectPtr refidx,key,val;
+ SQInteger idx;
+ SQObjectPtrVec templiterals;
+ templiterals.resize(_nliterals);
+ while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {
+ refidx=idx;
+ templiterals[_integer(val)]=key;
+ }
+ for(i=0;i<templiterals.size();i++){
+ scprintf(_SC("[%d] "),n);
+ DumpLiteral(templiterals[i]);
+ scprintf(_SC("\n"));
+ n++;
+ }
+ scprintf(_SC("-----PARAMS\n"));
+ if(_varparams)
+ scprintf(_SC("<<VARPARAMS>>\n"));
+ n=0;
+ for(i=0;i<_parameters.size();i++){
+ scprintf(_SC("[%d] "),n);
+ DumpLiteral(_parameters[i]);
+ scprintf(_SC("\n"));
+ n++;
+ }
+ scprintf(_SC("-----LOCALS\n"));
+ for(i=0;i<func->_localvarinfos.size();i++){
+ SQLocalVarInfo lvi=func->_localvarinfos[i];
+ scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
+ n++;
+ }
+ scprintf(_SC("-----LINE INFO\n"));
+ for(i=0;i<_lineinfos.size();i++){
+ SQLineInfo li=_lineinfos[i];
+ scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
+ n++;
+ }
+ scprintf(_SC("-----dump\n"));
+ n=0;
+ for(i=0;i<_instructions.size();i++){
+ SQInstruction &inst=_instructions[i];
+ if(inst.op==_OP_LOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
+
+ int lidx = inst._arg1;
+ scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
+ if(lidx >= 0xFFFFFFFF)
+ scprintf(_SC("null"));
+ else {
+ int refidx;
+ SQObjectPtr val,key,refo;
+ while(((refidx=_table(_literals)->Next(refo,key,val))!= -1) && (_integer(val) != lidx)) {
+ refo = refidx;
+ }
+ DumpLiteral(key);
+ }
+ scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
+ }
+ else if(inst.op==_OP_ARITH){
+ scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
+ }
+ else
+ scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
+ n++;
+ }
+ scprintf(_SC("-----\n"));
+ scprintf(_SC("stack size[%d]\n"),func->_stacksize);
+ scprintf(_SC("--------------------------------------------------------------------\n\n"));
+}
+#endif
+int SQFuncState::GetStringConstant(const SQChar *cons)
+{
+ return GetConstant(SQString::Create(_sharedstate,cons));
+}
+
+int SQFuncState::GetNumericConstant(const SQInteger cons)
+{
+ return GetConstant(cons);
+}
+
+int SQFuncState::GetNumericConstant(const SQFloat cons)
+{
+ return GetConstant(cons);
+}
+
+int SQFuncState::GetConstant(SQObjectPtr cons)
+{
+ // int n=0;
+ SQObjectPtr val;
+ if(!_table(_literals)->Get(cons,val))
+ {
+ val = _nliterals;
+ _table(_literals)->NewSlot(cons,val);
+ _nliterals++;
+ if(_nliterals > MAX_LITERALS) throw ParserException(_SC("internal compiler error: too many literals"));
+ }
+ return _integer(val);
+}
+
+void SQFuncState::SetIntructionParams(int pos,int arg0,int arg1,int arg2,int arg3)
+{
+ _instructions[pos]._arg0=*((unsigned int *)&arg0);
+ _instructions[pos]._arg1=*((unsigned int *)&arg1);
+ _instructions[pos]._arg2=*((unsigned int *)&arg2);
+ _instructions[pos]._arg3=*((unsigned int *)&arg3);
+}
+
+void SQFuncState::SetIntructionParam(int pos,int arg,int val)
+{
+ switch(arg){
+ case 0:_instructions[pos]._arg0=*((unsigned int *)&val);break;
+ case 1:_instructions[pos]._arg1=*((unsigned int *)&val);break;
+ case 2:_instructions[pos]._arg2=*((unsigned int *)&val);break;
+ case 3:_instructions[pos]._arg3=*((unsigned int *)&val);break;
+ case 4:_instructions[pos]._arg1=*((unsigned int *)&val);break;
+ };
+}
+
+int SQFuncState::AllocStackPos()
+{
+ int npos=_vlocals.size();
+ _vlocals.push_back(SQLocalVarInfo());
+ if(_vlocals.size()>((unsigned int)_stacksize)) {
+ if(_stacksize>MAX_FUNC_STACKSIZE) throw ParserException(_SC("internal compiler error: too many locals"));
+ _stacksize=_vlocals.size();
+ }
+ return npos;
+}
+
+int SQFuncState::PushTarget(int n)
+{
+ if(n!=-1){
+ _targetstack.push_back(n);
+ return n;
+ }
+ n=AllocStackPos();
+ _targetstack.push_back(n);
+ return n;
+}
+
+int SQFuncState::GetUpTarget(int n){
+ return _targetstack[((_targetstack.size()-1)-n)];
+}
+
+int SQFuncState::TopTarget(){
+ return _targetstack.back();
+}
+int SQFuncState::PopTarget()
+{
+ int npos=_targetstack.back();
+ SQLocalVarInfo t=_vlocals[_targetstack.back()];
+ if(type(t._name)==OT_NULL){
+ _vlocals.pop_back();
+ }
+ _targetstack.pop_back();
+ return npos;
+}
+
+int SQFuncState::GetStackSize()
+{
+ return _vlocals.size();
+}
+
+void SQFuncState::SetStackSize(int n)
+{
+ int size=_vlocals.size();
+ while(size>n){
+ size--;
+ SQLocalVarInfo lvi=_vlocals.back();
+ if(type(lvi._name)!=OT_NULL){
+ lvi._end_op=GetCurrentPos();
+ _localvarinfos.push_back(lvi);
+ }
+ _vlocals.pop_back();
+ }
+}
+
+bool SQFuncState::IsLocal(unsigned int stkpos)
+{
+ if(stkpos>=_vlocals.size())return false;
+ else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
+ return false;
+}
+
+int SQFuncState::PushLocalVariable(const SQObjectPtr &name)
+{
+ int pos=_vlocals.size();
+ SQLocalVarInfo lvi;
+ lvi._name=name;
+ lvi._start_op=GetCurrentPos()+1;
+ lvi._pos=_vlocals.size();
+ _vlocals.push_back(lvi);
+ if(_vlocals.size()>((unsigned int)_stacksize))_stacksize=_vlocals.size();
+
+ return pos;
+}
+
+int SQFuncState::GetLocalVariable(const SQObjectPtr &name)
+{
+ int locals=_vlocals.size();
+ while(locals>=1){
+ if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){
+ return locals-1;
+ }
+ locals--;
+ }
+ return -1;
+}
+
+int SQFuncState::GetOuterVariable(const SQObjectPtr &name)
+{
+ int outers = _outervalues.size();
+ for(int i = 0; i<outers; i++) {
+ if(_string(_outervalues[i]._name) == _string(name))
+ return i;
+ }
+ return -1;
+}
+
+void SQFuncState::AddOuterValue(const SQObjectPtr &name)
+{
+ //AddParameter(name);
+ int pos=-1;
+ if(_parent) {
+ pos = _parent->GetLocalVariable(name);
+ if(pos == -1) {
+ pos = _parent->GetOuterVariable(name);
+ if(pos != -1) {
+ _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
+ return;
+ }
+ }
+ else {
+ _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
+ return;
+ }
+ }
+ _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global
+}
+
+void SQFuncState::AddParameter(const SQObjectPtr &name)
+{
+ PushLocalVariable(name);
+ _parameters.push_back(name);
+}
+
+void SQFuncState::AddLineInfos(int line,bool lineop,bool force)
+{
+ if(_lastline!=line || force){
+ SQLineInfo li;
+ li._line=line;li._op=(GetCurrentPos()+1);
+ if(lineop)AddInstruction(_OP_LINE,0,line);
+ _lineinfos.push_back(li);
+ _lastline=line;
+ }
+}
+
+void SQFuncState::AddInstruction(SQInstruction &i)
+{
+ int size = _instructions.size();
+ if(size > 0 && _optimization){ //simple optimizer
+ SQInstruction &pi = _instructions[size-1];//previous instruction
+ switch(i.op) {
+ case _OP_RETURN:
+ if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
+ pi.op = _OP_TAILCALL;
+ }
+ break;
+ case _OP_GET:
+ if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
+ pi._arg1 = pi._arg1;
+ pi._arg2 = (unsigned char)i._arg1;
+ pi.op = _OP_GETK;
+ pi._arg0 = i._arg0;
+
+ return;
+ }
+ break;
+ case _OP_PREPCALL:
+ if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
+ pi.op = _OP_PREPCALLK;
+ pi._arg0 = i._arg0;
+ pi._arg1 = pi._arg1;
+ pi._arg2 = i._arg2;
+ pi._arg3 = i._arg3;
+ return;
+ }
+ break;
+ case _OP_APPENDARRAY:
+ if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
+ pi.op = _OP_APPENDARRAY;
+ pi._arg0 = i._arg0;
+ pi._arg1 = pi._arg1;
+ pi._arg2 = MAX_FUNC_STACKSIZE;
+ pi._arg3 = MAX_FUNC_STACKSIZE;
+ return;
+ }
+ break;
+ case _OP_MOVE:
+ if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1))
+ {
+ pi._arg0 = i._arg0;
+ _optimization = false;
+ return;
+ }
+
+ if(pi.op == _OP_MOVE)
+ {
+ pi.op = _OP_DMOVE;
+ pi._arg2 = i._arg0;
+ pi._arg3 = (unsigned char)i._arg1;
+ return;
+ }
+ break;
+
+ case _OP_EQ:case _OP_NE:
+ if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
+ {
+ pi.op = i.op;
+ pi._arg0 = i._arg0;
+ pi._arg1 = pi._arg1;
+ pi._arg2 = i._arg2;
+ pi._arg3 = MAX_FUNC_STACKSIZE;
+ return;
+ }
+ break;
+ case _OP_LOADNULLS:
+ //case _OP_LOADNULL:
+ if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
+
+ pi._arg1 = pi._arg1 + 1;
+ pi.op = _OP_LOADNULLS;
+ return;
+ }
+ break;
+ case _OP_LINE:
+ if(pi.op == _OP_LINE) {
+ _instructions.pop_back();
+ _lineinfos.pop_back();
+ }
+ break;
+ }
+ }
+ _optimization = true;
+ _instructions.push_back(i);
+}
+
+SQObject SQFuncState::CreateString(const SQChar *s)
+{
+ SQObjectPtr ns(SQString::Create(_sharedstate,s));
+ _stringrefs.push_back(ns);
+ return ns;
+}
+
+void SQFuncState::Finalize()
+{
+ SQFunctionProto *f=_funcproto(_func);
+ f->_literals.resize(_nliterals);
+ SQObjectPtr refidx,key,val;
+ SQInteger idx;
+ while((idx=_table(_literals)->Next(refidx,key,val))!=-1) {
+ f->_literals[_integer(val)]=key;
+ refidx=idx;
+ }
+ f->_functions.resize(_functions.size());
+ f->_functions.copy(_functions);
+ f->_parameters.resize(_parameters.size());
+ f->_parameters.copy(_parameters);
+ f->_outervalues.resize(_outervalues.size());
+ f->_outervalues.copy(_outervalues);
+ f->_instructions.resize(_instructions.size());
+ f->_instructions.copy(_instructions);
+ f->_localvarinfos.resize(_localvarinfos.size());
+ f->_localvarinfos.copy(_localvarinfos);
+ f->_lineinfos.resize(_lineinfos.size());
+ f->_lineinfos.copy(_lineinfos);
+ f->_varparams = _varparams;
+}
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQFUNCSTATE_H_\r
-#define _SQFUNCSTATE_H_\r
-///////////////////////////////////\r
-#include "squtils.h"\r
-\r
-\r
-\r
-struct SQFuncState\r
-{\r
- SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent);\r
-#ifdef _DEBUG_DUMP\r
- void Dump();\r
-#endif\r
- void AddInstruction(SQOpcode _op,int arg0=0,int arg1=0,int arg2=0,int arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}\r
- void AddInstruction(SQInstruction &i);\r
- void SetIntructionParams(int pos,int arg0,int arg1,int arg2=0,int arg3=0);\r
- void SetIntructionParam(int pos,int arg,int val);\r
- SQInstruction &GetInstruction(int pos){return _instructions[pos];}\r
- void PopInstructions(int size){for(int i=0;i<size;i++)_instructions.pop_back();}\r
- void SetStackSize(int n);\r
- void SnoozeOpt(){_optimization=false;}\r
- int GetCurrentPos(){return _instructions.size()-1;}\r
- int GetStringConstant(const SQChar *cons);\r
- int GetNumericConstant(const SQInteger cons);\r
- int GetNumericConstant(const SQFloat cons);\r
- int PushLocalVariable(const SQObjectPtr &name);\r
- void AddParameter(const SQObjectPtr &name);\r
- void AddOuterValue(const SQObjectPtr &name);\r
- int GetLocalVariable(const SQObjectPtr &name);\r
- int GetOuterVariable(const SQObjectPtr &name);\r
- int GenerateCode();\r
- int GetStackSize();\r
- int CalcStackFrameSize();\r
- void AddLineInfos(int line,bool lineop,bool force=false);\r
- void Finalize();\r
- int AllocStackPos();\r
- int PushTarget(int n=-1);\r
- int PopTarget();\r
- int TopTarget();\r
- int GetUpTarget(int n);\r
- bool IsLocal(unsigned int stkpos);\r
- SQObject CreateString(const SQChar *s);\r
- int _returnexp;\r
- SQLocalVarInfoVec _vlocals;\r
- SQIntVec _targetstack;\r
- int _stacksize;\r
- bool _varparams;\r
- SQIntVec _unresolvedbreaks;\r
- SQIntVec _unresolvedcontinues;\r
- SQObjectPtrVec _functions;\r
- SQObjectPtrVec _parameters;\r
- SQObjectPtrVec _stringrefs;\r
- SQOuterVarVec _outervalues;\r
- SQInstructionVec _instructions;\r
- SQLocalVarInfoVec _localvarinfos;\r
- SQObjectPtr _literals;\r
- SQInteger _nliterals;\r
- SQLineInfoVec _lineinfos;\r
- SQObjectPtr _func;\r
- SQFuncState *_parent;\r
- SQIntVec _breaktargets; //contains number of nested exception traps\r
- SQIntVec _continuetargets;\r
- int _lastline;\r
- int _traps;\r
- bool _optimization;\r
- SQSharedState *_sharedstate;\r
-private:\r
- int GetConstant(SQObjectPtr cons);\r
-};\r
-\r
-\r
-#endif //_SQFUNCSTATE_H_\r
-\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQFUNCSTATE_H_
+#define _SQFUNCSTATE_H_
+///////////////////////////////////
+#include "squtils.h"
+
+
+
+struct SQFuncState
+{
+ SQFuncState(SQSharedState *ss,SQFunctionProto *func,SQFuncState *parent);
+#ifdef _DEBUG_DUMP
+ void Dump();
+#endif
+ void AddInstruction(SQOpcode _op,int arg0=0,int arg1=0,int arg2=0,int arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}
+ void AddInstruction(SQInstruction &i);
+ void SetIntructionParams(int pos,int arg0,int arg1,int arg2=0,int arg3=0);
+ void SetIntructionParam(int pos,int arg,int val);
+ SQInstruction &GetInstruction(int pos){return _instructions[pos];}
+ void PopInstructions(int size){for(int i=0;i<size;i++)_instructions.pop_back();}
+ void SetStackSize(int n);
+ void SnoozeOpt(){_optimization=false;}
+ int GetCurrentPos(){return _instructions.size()-1;}
+ int GetStringConstant(const SQChar *cons);
+ int GetNumericConstant(const SQInteger cons);
+ int GetNumericConstant(const SQFloat cons);
+ int PushLocalVariable(const SQObjectPtr &name);
+ void AddParameter(const SQObjectPtr &name);
+ void AddOuterValue(const SQObjectPtr &name);
+ int GetLocalVariable(const SQObjectPtr &name);
+ int GetOuterVariable(const SQObjectPtr &name);
+ int GenerateCode();
+ int GetStackSize();
+ int CalcStackFrameSize();
+ void AddLineInfos(int line,bool lineop,bool force=false);
+ void Finalize();
+ int AllocStackPos();
+ int PushTarget(int n=-1);
+ int PopTarget();
+ int TopTarget();
+ int GetUpTarget(int n);
+ bool IsLocal(unsigned int stkpos);
+ SQObject CreateString(const SQChar *s);
+ int _returnexp;
+ SQLocalVarInfoVec _vlocals;
+ SQIntVec _targetstack;
+ int _stacksize;
+ bool _varparams;
+ SQIntVec _unresolvedbreaks;
+ SQIntVec _unresolvedcontinues;
+ SQObjectPtrVec _functions;
+ SQObjectPtrVec _parameters;
+ SQObjectPtrVec _stringrefs;
+ SQOuterVarVec _outervalues;
+ SQInstructionVec _instructions;
+ SQLocalVarInfoVec _localvarinfos;
+ SQObjectPtr _literals;
+ SQInteger _nliterals;
+ SQLineInfoVec _lineinfos;
+ SQObjectPtr _func;
+ SQFuncState *_parent;
+ SQIntVec _breaktargets; //contains number of nested exception traps
+ SQIntVec _continuetargets;
+ int _lastline;
+ int _traps;
+ bool _optimization;
+ SQSharedState *_sharedstate;
+private:
+ int GetConstant(SQObjectPtr cons);
+};
+
+
+#endif //_SQFUNCSTATE_H_
+
-/*\r
- see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include <ctype.h>\r
-#include <stdlib.h>\r
-#include "sqtable.h"\r
-#include "sqstring.h"\r
-#include "sqcompiler.h"\r
-#include "sqlexer.h"\r
-\r
-#define CUR_CHAR (_currdata)\r
-#define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;}\r
-#define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB)\r
-#define NEXT() {Next();_currentcolumn++;}\r
-#define INIT_TEMP_STRING() { _longstr.resize(0);}\r
-#define APPEND_CHAR(c) { _longstr.push_back(c);}\r
-#define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));}\r
-#define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id))\r
-\r
-SQLexer::SQLexer(){}\r
-SQLexer::~SQLexer()\r
-{\r
- _keywords->Release();\r
-}\r
-\r
-void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up)\r
-{\r
- _sharedstate = ss;\r
- _keywords = SQTable::Create(ss, 26);\r
- ADD_KEYWORD(while, TK_WHILE);\r
- ADD_KEYWORD(do, TK_DO);\r
- ADD_KEYWORD(if, TK_IF);\r
- ADD_KEYWORD(else, TK_ELSE);\r
- ADD_KEYWORD(break, TK_BREAK);\r
- ADD_KEYWORD(continue, TK_CONTINUE);\r
- ADD_KEYWORD(return, TK_RETURN);\r
- ADD_KEYWORD(null, TK_NULL);\r
- ADD_KEYWORD(function, TK_FUNCTION);\r
- ADD_KEYWORD(local, TK_LOCAL);\r
- ADD_KEYWORD(for, TK_FOR);\r
- ADD_KEYWORD(foreach, TK_FOREACH);\r
- ADD_KEYWORD(in, TK_IN);\r
- ADD_KEYWORD(typeof, TK_TYPEOF);\r
- ADD_KEYWORD(delegate, TK_DELEGATE);\r
- ADD_KEYWORD(delete, TK_DELETE);\r
- ADD_KEYWORD(try, TK_TRY);\r
- ADD_KEYWORD(catch, TK_CATCH);\r
- ADD_KEYWORD(throw, TK_THROW);\r
- ADD_KEYWORD(clone, TK_CLONE);\r
- ADD_KEYWORD(yield, TK_YIELD);\r
- ADD_KEYWORD(resume, TK_RESUME);\r
- ADD_KEYWORD(switch, TK_SWITCH);\r
- ADD_KEYWORD(case, TK_CASE);\r
- ADD_KEYWORD(default, TK_DEFAULT);\r
- ADD_KEYWORD(this, TK_THIS);\r
- ADD_KEYWORD(parent,TK_PARENT);\r
- ADD_KEYWORD(class,TK_CLASS);\r
- ADD_KEYWORD(extends,TK_EXTENDS);\r
- ADD_KEYWORD(constructor,TK_CONSTRUCTOR);\r
- ADD_KEYWORD(instanceof,TK_INSTANCEOF);\r
- ADD_KEYWORD(vargc,TK_VARGC);\r
- ADD_KEYWORD(vargv,TK_VARGV);\r
- ADD_KEYWORD(true,TK_TRUE);\r
- ADD_KEYWORD(false,TK_FALSE);\r
-\r
- _readf = rg;\r
- _up = up;\r
- _lasttokenline = _currentline = 1;\r
- _currentcolumn = 0;\r
- _prevtoken = -1;\r
- Next();\r
-}\r
-\r
-void SQLexer::Next()\r
-{\r
- SQInteger t = _readf(_up);\r
- if(t > MAX_CHAR) throw ParserException(_SC("Invalid character"));\r
- if(t != 0) {\r
- _currdata = t;\r
- return;\r
- }\r
- _currdata = SQUIRREL_EOB;\r
-}\r
-\r
-SQObjectPtr SQLexer::Tok2Str(int tok)\r
-{\r
- SQObjectPtr itr, key, val;\r
- int nitr;\r
- while((nitr = _keywords->Next(itr, key, val)) != -1) {\r
- itr = (SQInteger)nitr;\r
- if(((int)_integer(val)) == tok)\r
- return key;\r
- }\r
- return SQObjectPtr();\r
-}\r
-\r
-void SQLexer::LexBlockComment()\r
-{\r
- bool done = false;\r
- while(!done) {\r
- switch(CUR_CHAR) {\r
- case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;\r
- //case _SC('/'): { NEXT(); if(CUR_CHAR == _SC('*')) { nest++; NEXT(); }}; continue;\r
- case _SC('\n'): _currentline++; NEXT(); continue;\r
- case SQUIRREL_EOB: throw ParserException(_SC("missing \"*/\" in comment"));\r
- default: NEXT();\r
- }\r
- }\r
-}\r
-\r
-int SQLexer::Lex()\r
-{\r
- _lasttokenline = _currentline;\r
- while(CUR_CHAR != SQUIRREL_EOB) {\r
- switch(CUR_CHAR){\r
- case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue;\r
- case _SC('\n'):\r
- _currentline++;\r
- _prevtoken=_curtoken;\r
- _curtoken=_SC('\n');\r
- NEXT();\r
- _currentcolumn=1;\r
- continue;\r
- case _SC('/'):\r
- NEXT();\r
- switch(CUR_CHAR){\r
- case _SC('*'):\r
- NEXT();\r
- LexBlockComment();\r
- continue; \r
- case _SC('/'):\r
- do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));\r
- continue;\r
- case _SC('='):\r
- NEXT();\r
- RETURN_TOKEN(TK_DIVEQ);\r
- continue;\r
- case _SC('>'):\r
- NEXT();\r
- RETURN_TOKEN(TK_ATTR_CLOSE);\r
- continue;\r
- default:\r
- RETURN_TOKEN('/');\r
- }\r
- case _SC('='):\r
- NEXT();\r
- if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') }\r
- else { NEXT(); RETURN_TOKEN(TK_EQ); }\r
- case _SC('<'):\r
- NEXT();\r
- if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) }\r
- else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); }\r
- else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); }\r
- else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); }\r
- //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); }\r
- else { RETURN_TOKEN('<') }\r
- case _SC('>'):\r
- NEXT();\r
- if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);}\r
- else if(CUR_CHAR == _SC('>')){ \r
- NEXT(); \r
- if(CUR_CHAR == _SC('>')){\r
- NEXT();\r
- RETURN_TOKEN(TK_USHIFTR);\r
- }\r
- RETURN_TOKEN(TK_SHIFTR);\r
- }\r
- else { RETURN_TOKEN('>') }\r
- case _SC('!'):\r
- NEXT();\r
- if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')}\r
- else { NEXT(); RETURN_TOKEN(TK_NE); }\r
- case _SC('@'): {\r
- int stype;\r
- NEXT(); \r
- if(CUR_CHAR != _SC('"'))\r
- throw ParserException(_SC("string expected"));\r
- if((stype=ReadString('"',true))!=-1) {\r
- RETURN_TOKEN(stype);\r
- }\r
- throw ParserException(_SC("error parsing the string"));\r
- }\r
- case _SC('"'):\r
- case _SC('\''): {\r
- int stype;\r
- if((stype=ReadString(CUR_CHAR,false))!=-1){\r
- RETURN_TOKEN(stype);\r
- }\r
- throw ParserException(_SC("error parsing the string"));\r
- }\r
- case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'):\r
- case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'):\r
- {int ret = CUR_CHAR;\r
- NEXT(); RETURN_TOKEN(ret); }\r
- case _SC('.'):\r
- NEXT();\r
- if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') }\r
- NEXT();\r
- if (CUR_CHAR != _SC('.')){ throw ParserException(_SC("invalid token '..'")); }\r
- NEXT();\r
- RETURN_TOKEN(TK_VARPARAMS);\r
- case _SC('&'):\r
- NEXT();\r
- if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') }\r
- else { NEXT(); RETURN_TOKEN(TK_AND); }\r
- case _SC('|'):\r
- NEXT();\r
- if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') }\r
- else { NEXT(); RETURN_TOKEN(TK_OR); }\r
- case _SC(':'):\r
- NEXT();\r
- if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') }\r
- else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); }\r
- case _SC('*'):\r
- NEXT();\r
- if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);}\r
- else RETURN_TOKEN('*');\r
- case _SC('%'):\r
- NEXT();\r
- if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);}\r
- else RETURN_TOKEN('%');\r
- case _SC('-'):\r
- NEXT();\r
- if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);}\r
- else if (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);}\r
- else RETURN_TOKEN('-');\r
- case _SC('+'):\r
- NEXT();\r
- if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);}\r
- else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);}\r
- else RETURN_TOKEN('+');\r
- case SQUIRREL_EOB:\r
- return 0;\r
- default:{\r
- if (scisdigit(CUR_CHAR)) {\r
- int ret = ReadNumber();\r
- RETURN_TOKEN(ret);\r
- }\r
- else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {\r
- int t = ReadID();\r
- RETURN_TOKEN(t);\r
- }\r
- else {\r
- int c = CUR_CHAR;\r
- if (sciscntrl(c)) throw ParserException(_SC("unexpected character(control)"));\r
- NEXT();\r
- RETURN_TOKEN(c); \r
- }\r
- RETURN_TOKEN(0);\r
- }\r
- }\r
- }\r
- return 0; \r
-}\r
- \r
-int SQLexer::GetIDType(SQChar *s)\r
-{\r
- SQObjectPtr t;\r
- if(_keywords->Get(SQString::Create(_sharedstate, s), t)) {\r
- return int(_integer(t));\r
- }\r
- return TK_IDENTIFIER;\r
-}\r
-\r
-\r
-int SQLexer::ReadString(int ndelim,bool verbatim)\r
-{\r
- INIT_TEMP_STRING();\r
- NEXT();\r
- if(IS_EOB()) return -1;\r
- for(;;) {\r
- while(CUR_CHAR != ndelim) {\r
- switch(CUR_CHAR) {\r
- case SQUIRREL_EOB:\r
- throw ParserException(_SC("unfinished string"));\r
- return -1;\r
- case _SC('\n'): \r
- if(!verbatim) throw ParserException(_SC("newline in a constant")); \r
- APPEND_CHAR(CUR_CHAR); NEXT(); \r
- break;\r
- case _SC('\\'):\r
- if(verbatim) {\r
- APPEND_CHAR('\\'); NEXT(); \r
- }\r
- else {\r
-\r
- NEXT();\r
- switch(CUR_CHAR) {\r
- case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break;\r
- case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break;\r
- case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break;\r
- case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break;\r
- case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break;\r
- case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break;\r
- case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break;\r
- case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break;\r
- case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break;\r
- case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break;\r
- case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break;\r
- default:\r
- throw ParserException(_SC("unrecognised escaper char"));\r
- break;\r
- }\r
- }\r
- break;\r
- default:\r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- }\r
- }\r
- NEXT();\r
- if(verbatim && CUR_CHAR == '"') { //double quotation\r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- }\r
- else {\r
- break;\r
- }\r
- }\r
- TERMINATE_BUFFER();\r
- int len = _longstr.size()-1;\r
- if(ndelim == _SC('\'')) {\r
- if(len == 0) throw ParserException(_SC("empty constant"));\r
- if(len > 1) throw ParserException(_SC("constant too long"));\r
- _nvalue = _longstr[0];\r
- return TK_INTEGER;\r
- }\r
- _svalue = &_longstr[0];\r
- return TK_STRING_LITERAL;\r
-}\r
-\r
-int isexponent(int c) { return c == 'e' || c=='E'; }\r
-\r
-int SQLexer::ReadNumber()\r
-{\r
-#define TINT 1\r
-#define TFLOAT 2\r
-#define THEX 3\r
-#define TSCIENTIFIC 4\r
- int type = TINT, firstchar = CUR_CHAR;\r
- bool isfloat = false;\r
- SQChar *sTemp;\r
- INIT_TEMP_STRING();\r
- NEXT();\r
- if(firstchar == _SC('0') && toupper(CUR_CHAR) == _SC('X')) {\r
- NEXT();\r
- type = THEX;\r
- while(isxdigit(CUR_CHAR)) {\r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- }\r
- if(_longstr.size() > 8) throw ParserException(_SC("Hex number over 8 digits"));\r
- }\r
- else {\r
- APPEND_CHAR(firstchar);\r
- while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) {\r
- if(CUR_CHAR == _SC('.')) type = TFLOAT;\r
- if(isexponent(CUR_CHAR)) {\r
- if(type != TFLOAT) throw ParserException(_SC("invalid numeric format"));\r
- type = TSCIENTIFIC;\r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- if(CUR_CHAR == '+' || CUR_CHAR == '-'){\r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- }\r
- if(!scisdigit(CUR_CHAR)) throw ParserException(_SC("exponent expected"));\r
- }\r
- \r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- }\r
- }\r
- TERMINATE_BUFFER();\r
- switch(type) {\r
- case TSCIENTIFIC:\r
- case TFLOAT:\r
- _fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp);\r
- return TK_FLOAT;\r
- case TINT:\r
- _nvalue = (SQInteger)scatoi(&_longstr[0]);\r
- return TK_INTEGER;\r
- case THEX:\r
- *((unsigned long *)&_nvalue) = scstrtoul(&_longstr[0],&sTemp,16);\r
- return TK_INTEGER;\r
- }\r
- return 0;\r
-}\r
-\r
-int SQLexer::ReadID()\r
-{\r
- int res, size = 0;\r
- INIT_TEMP_STRING();\r
- do {\r
- APPEND_CHAR(CUR_CHAR);\r
- NEXT();\r
- } while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_'));\r
- TERMINATE_BUFFER();\r
- res = GetIDType(&_longstr[0]);\r
- if(res == TK_IDENTIFIER) {\r
- _svalue = &_longstr[0];\r
- }\r
- return res;\r
-}\r
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include "sqtable.h"
+#include "sqstring.h"
+#include "sqcompiler.h"
+#include "sqlexer.h"
+
+#define CUR_CHAR (_currdata)
+#define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;}
+#define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB)
+#define NEXT() {Next();_currentcolumn++;}
+#define INIT_TEMP_STRING() { _longstr.resize(0);}
+#define APPEND_CHAR(c) { _longstr.push_back(c);}
+#define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));}
+#define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id))
+
+SQLexer::SQLexer(){}
+SQLexer::~SQLexer()
+{
+ _keywords->Release();
+}
+
+void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up)
+{
+ _sharedstate = ss;
+ _keywords = SQTable::Create(ss, 26);
+ ADD_KEYWORD(while, TK_WHILE);
+ ADD_KEYWORD(do, TK_DO);
+ ADD_KEYWORD(if, TK_IF);
+ ADD_KEYWORD(else, TK_ELSE);
+ ADD_KEYWORD(break, TK_BREAK);
+ ADD_KEYWORD(continue, TK_CONTINUE);
+ ADD_KEYWORD(return, TK_RETURN);
+ ADD_KEYWORD(null, TK_NULL);
+ ADD_KEYWORD(function, TK_FUNCTION);
+ ADD_KEYWORD(local, TK_LOCAL);
+ ADD_KEYWORD(for, TK_FOR);
+ ADD_KEYWORD(foreach, TK_FOREACH);
+ ADD_KEYWORD(in, TK_IN);
+ ADD_KEYWORD(typeof, TK_TYPEOF);
+ ADD_KEYWORD(delegate, TK_DELEGATE);
+ ADD_KEYWORD(delete, TK_DELETE);
+ ADD_KEYWORD(try, TK_TRY);
+ ADD_KEYWORD(catch, TK_CATCH);
+ ADD_KEYWORD(throw, TK_THROW);
+ ADD_KEYWORD(clone, TK_CLONE);
+ ADD_KEYWORD(yield, TK_YIELD);
+ ADD_KEYWORD(resume, TK_RESUME);
+ ADD_KEYWORD(switch, TK_SWITCH);
+ ADD_KEYWORD(case, TK_CASE);
+ ADD_KEYWORD(default, TK_DEFAULT);
+ ADD_KEYWORD(this, TK_THIS);
+ ADD_KEYWORD(parent,TK_PARENT);
+ ADD_KEYWORD(class,TK_CLASS);
+ ADD_KEYWORD(extends,TK_EXTENDS);
+ ADD_KEYWORD(constructor,TK_CONSTRUCTOR);
+ ADD_KEYWORD(instanceof,TK_INSTANCEOF);
+ ADD_KEYWORD(vargc,TK_VARGC);
+ ADD_KEYWORD(vargv,TK_VARGV);
+ ADD_KEYWORD(true,TK_TRUE);
+ ADD_KEYWORD(false,TK_FALSE);
+
+ _readf = rg;
+ _up = up;
+ _lasttokenline = _currentline = 1;
+ _currentcolumn = 0;
+ _prevtoken = -1;
+ Next();
+}
+
+void SQLexer::Next()
+{
+ SQInteger t = _readf(_up);
+ if(t > MAX_CHAR) throw ParserException(_SC("Invalid character"));
+ if(t != 0) {
+ _currdata = t;
+ return;
+ }
+ _currdata = SQUIRREL_EOB;
+}
+
+SQObjectPtr SQLexer::Tok2Str(int tok)
+{
+ SQObjectPtr itr, key, val;
+ int nitr;
+ while((nitr = _keywords->Next(itr, key, val)) != -1) {
+ itr = (SQInteger)nitr;
+ if(((int)_integer(val)) == tok)
+ return key;
+ }
+ return SQObjectPtr();
+}
+
+void SQLexer::LexBlockComment()
+{
+ bool done = false;
+ while(!done) {
+ switch(CUR_CHAR) {
+ case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;
+ //case _SC('/'): { NEXT(); if(CUR_CHAR == _SC('*')) { nest++; NEXT(); }}; continue;
+ case _SC('\n'): _currentline++; NEXT(); continue;
+ case SQUIRREL_EOB: throw ParserException(_SC("missing \"*/\" in comment"));
+ default: NEXT();
+ }
+ }
+}
+
+int SQLexer::Lex()
+{
+ _lasttokenline = _currentline;
+ while(CUR_CHAR != SQUIRREL_EOB) {
+ switch(CUR_CHAR){
+ case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue;
+ case _SC('\n'):
+ _currentline++;
+ _prevtoken=_curtoken;
+ _curtoken=_SC('\n');
+ NEXT();
+ _currentcolumn=1;
+ continue;
+ case _SC('/'):
+ NEXT();
+ switch(CUR_CHAR){
+ case _SC('*'):
+ NEXT();
+ LexBlockComment();
+ continue;
+ case _SC('/'):
+ do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));
+ continue;
+ case _SC('='):
+ NEXT();
+ RETURN_TOKEN(TK_DIVEQ);
+ continue;
+ case _SC('>'):
+ NEXT();
+ RETURN_TOKEN(TK_ATTR_CLOSE);
+ continue;
+ default:
+ RETURN_TOKEN('/');
+ }
+ case _SC('='):
+ NEXT();
+ if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') }
+ else { NEXT(); RETURN_TOKEN(TK_EQ); }
+ case _SC('<'):
+ NEXT();
+ if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) }
+ else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); }
+ else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); }
+ else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); }
+ //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); }
+ else { RETURN_TOKEN('<') }
+ case _SC('>'):
+ NEXT();
+ if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);}
+ else if(CUR_CHAR == _SC('>')){
+ NEXT();
+ if(CUR_CHAR == _SC('>')){
+ NEXT();
+ RETURN_TOKEN(TK_USHIFTR);
+ }
+ RETURN_TOKEN(TK_SHIFTR);
+ }
+ else { RETURN_TOKEN('>') }
+ case _SC('!'):
+ NEXT();
+ if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')}
+ else { NEXT(); RETURN_TOKEN(TK_NE); }
+ case _SC('@'): {
+ int stype;
+ NEXT();
+ if(CUR_CHAR != _SC('"'))
+ throw ParserException(_SC("string expected"));
+ if((stype=ReadString('"',true))!=-1) {
+ RETURN_TOKEN(stype);
+ }
+ throw ParserException(_SC("error parsing the string"));
+ }
+ case _SC('"'):
+ case _SC('\''): {
+ int stype;
+ if((stype=ReadString(CUR_CHAR,false))!=-1){
+ RETURN_TOKEN(stype);
+ }
+ throw ParserException(_SC("error parsing the string"));
+ }
+ case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'):
+ case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'):
+ {int ret = CUR_CHAR;
+ NEXT(); RETURN_TOKEN(ret); }
+ case _SC('.'):
+ NEXT();
+ if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') }
+ NEXT();
+ if (CUR_CHAR != _SC('.')){ throw ParserException(_SC("invalid token '..'")); }
+ NEXT();
+ RETURN_TOKEN(TK_VARPARAMS);
+ case _SC('&'):
+ NEXT();
+ if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') }
+ else { NEXT(); RETURN_TOKEN(TK_AND); }
+ case _SC('|'):
+ NEXT();
+ if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') }
+ else { NEXT(); RETURN_TOKEN(TK_OR); }
+ case _SC(':'):
+ NEXT();
+ if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') }
+ else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); }
+ case _SC('*'):
+ NEXT();
+ if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);}
+ else RETURN_TOKEN('*');
+ case _SC('%'):
+ NEXT();
+ if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);}
+ else RETURN_TOKEN('%');
+ case _SC('-'):
+ NEXT();
+ if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);}
+ else if (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);}
+ else RETURN_TOKEN('-');
+ case _SC('+'):
+ NEXT();
+ if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);}
+ else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);}
+ else RETURN_TOKEN('+');
+ case SQUIRREL_EOB:
+ return 0;
+ default:{
+ if (scisdigit(CUR_CHAR)) {
+ int ret = ReadNumber();
+ RETURN_TOKEN(ret);
+ }
+ else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {
+ int t = ReadID();
+ RETURN_TOKEN(t);
+ }
+ else {
+ int c = CUR_CHAR;
+ if (sciscntrl(c)) throw ParserException(_SC("unexpected character(control)"));
+ NEXT();
+ RETURN_TOKEN(c);
+ }
+ RETURN_TOKEN(0);
+ }
+ }
+ }
+ return 0;
+}
+
+int SQLexer::GetIDType(SQChar *s)
+{
+ SQObjectPtr t;
+ if(_keywords->Get(SQString::Create(_sharedstate, s), t)) {
+ return int(_integer(t));
+ }
+ return TK_IDENTIFIER;
+}
+
+
+int SQLexer::ReadString(int ndelim,bool verbatim)
+{
+ INIT_TEMP_STRING();
+ NEXT();
+ if(IS_EOB()) return -1;
+ for(;;) {
+ while(CUR_CHAR != ndelim) {
+ switch(CUR_CHAR) {
+ case SQUIRREL_EOB:
+ throw ParserException(_SC("unfinished string"));
+ return -1;
+ case _SC('\n'):
+ if(!verbatim) throw ParserException(_SC("newline in a constant"));
+ APPEND_CHAR(CUR_CHAR); NEXT();
+ break;
+ case _SC('\\'):
+ if(verbatim) {
+ APPEND_CHAR('\\'); NEXT();
+ }
+ else {
+
+ NEXT();
+ switch(CUR_CHAR) {
+ case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break;
+ case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break;
+ case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break;
+ case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break;
+ case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break;
+ case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break;
+ case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break;
+ case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break;
+ case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break;
+ case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break;
+ case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break;
+ default:
+ throw ParserException(_SC("unrecognised escaper char"));
+ break;
+ }
+ }
+ break;
+ default:
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ }
+ }
+ NEXT();
+ if(verbatim && CUR_CHAR == '"') { //double quotation
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ }
+ else {
+ break;
+ }
+ }
+ TERMINATE_BUFFER();
+ int len = _longstr.size()-1;
+ if(ndelim == _SC('\'')) {
+ if(len == 0) throw ParserException(_SC("empty constant"));
+ if(len > 1) throw ParserException(_SC("constant too long"));
+ _nvalue = _longstr[0];
+ return TK_INTEGER;
+ }
+ _svalue = &_longstr[0];
+ return TK_STRING_LITERAL;
+}
+
+int isexponent(int c) { return c == 'e' || c=='E'; }
+
+int SQLexer::ReadNumber()
+{
+#define TINT 1
+#define TFLOAT 2
+#define THEX 3
+#define TSCIENTIFIC 4
+ int type = TINT, firstchar = CUR_CHAR;
+ //bool isfloat = false;
+ SQChar *sTemp;
+ INIT_TEMP_STRING();
+ NEXT();
+ if(firstchar == _SC('0') && toupper(CUR_CHAR) == _SC('X')) {
+ NEXT();
+ type = THEX;
+ while(isxdigit(CUR_CHAR)) {
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ }
+ if(_longstr.size() > 8) throw ParserException(_SC("Hex number over 8 digits"));
+ }
+ else {
+ APPEND_CHAR(firstchar);
+ while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) {
+ if(CUR_CHAR == _SC('.')) type = TFLOAT;
+ if(isexponent(CUR_CHAR)) {
+ if(type != TFLOAT) throw ParserException(_SC("invalid numeric format"));
+ type = TSCIENTIFIC;
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ if(CUR_CHAR == '+' || CUR_CHAR == '-'){
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ }
+ if(!scisdigit(CUR_CHAR)) throw ParserException(_SC("exponent expected"));
+ }
+
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ }
+ }
+ TERMINATE_BUFFER();
+ switch(type) {
+ case TSCIENTIFIC:
+ case TFLOAT:
+ _fvalue = (SQFloat)scstrtod(&_longstr[0],&sTemp);
+ return TK_FLOAT;
+ case TINT:
+ _nvalue = (SQInteger)scatoi(&_longstr[0]);
+ return TK_INTEGER;
+ case THEX:
+ *((unsigned long *)&_nvalue) = scstrtoul(&_longstr[0],&sTemp,16);
+ return TK_INTEGER;
+ }
+ return 0;
+}
+
+int SQLexer::ReadID()
+{
+ int res;
+ // int size = 0;
+ INIT_TEMP_STRING();
+ do {
+ APPEND_CHAR(CUR_CHAR);
+ NEXT();
+ } while(scisalnum(CUR_CHAR) || CUR_CHAR == _SC('_'));
+ TERMINATE_BUFFER();
+ res = GetIDType(&_longstr[0]);
+ if(res == TK_IDENTIFIER) {
+ _svalue = &_longstr[0];
+ }
+ return res;
+}
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQLEXER_H_\r
-#define _SQLEXER_H_\r
-\r
-#define MAX_STRING 2024\r
-\r
-struct SQLexer\r
-{\r
- SQLexer();\r
- ~SQLexer();\r
- void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up);\r
- int Lex();\r
- SQObjectPtr Tok2Str(int tok);\r
-private:\r
- int GetIDType(SQChar *s);\r
- int ReadString(int ndelim,bool verbatim);\r
- int ReadNumber();\r
- void LexBlockComment();\r
- int ReadID();\r
- void Next();\r
- int _curtoken;\r
- SQTable *_keywords;\r
-public:\r
- int _prevtoken;\r
- int _currentline;\r
- int _lasttokenline;\r
- int _currentcolumn;\r
- const SQChar *_svalue;\r
- SQInteger _nvalue;\r
- SQFloat _fvalue;\r
- SQLEXREADFUNC _readf;\r
- SQUserPointer _up;\r
-#ifdef _UNICODE\r
- SQChar _currdata;\r
-#else\r
- unsigned char _currdata;\r
-#endif\r
- SQSharedState *_sharedstate;\r
- sqvector<SQChar> _longstr;\r
-};\r
-\r
-#endif\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQLEXER_H_
+#define _SQLEXER_H_
+
+#define MAX_STRING 2024
+
+struct SQLexer
+{
+ SQLexer();
+ ~SQLexer();
+ void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up);
+ int Lex();
+ SQObjectPtr Tok2Str(int tok);
+private:
+ int GetIDType(SQChar *s);
+ int ReadString(int ndelim,bool verbatim);
+ int ReadNumber();
+ void LexBlockComment();
+ int ReadID();
+ void Next();
+ int _curtoken;
+ SQTable *_keywords;
+public:
+ int _prevtoken;
+ int _currentline;
+ int _lasttokenline;
+ int _currentcolumn;
+ const SQChar *_svalue;
+ SQInteger _nvalue;
+ SQFloat _fvalue;
+ SQLEXREADFUNC _readf;
+ SQUserPointer _up;
+#ifdef _UNICODE
+ SQChar _currdata;
+#else
+ unsigned char _currdata;
+#endif
+ SQSharedState *_sharedstate;
+ sqvector<SQChar> _longstr;
+};
+
+#endif
-/*\r
- see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-void *sq_vm_malloc(unsigned int size){ return malloc(size); }\r
-\r
-void *sq_vm_realloc(void *p, unsigned int oldsize, unsigned int size){ return realloc(p, size); }\r
-\r
-void sq_vm_free(void *p, unsigned int size){ free(p); }\r
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+void *sq_vm_malloc(unsigned int size){ return malloc(size); }
+
+void *sq_vm_realloc(void *p, unsigned int , unsigned int size){ return realloc(p, size); }
+
+void sq_vm_free(void *p, unsigned int ){ free(p); }
-/*\r
- see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include "sqvm.h"\r
-#include "sqstring.h"\r
-#include "sqarray.h"\r
-#include "sqtable.h"\r
-#include "squserdata.h"\r
-#include "sqfuncproto.h"\r
-#include "sqclass.h"\r
-#include "sqclosure.h"\r
-\r
-SQString *SQString::Create(SQSharedState *ss,const SQChar *s,int len)\r
-{\r
- SQString *str=ADD_STRING(ss,s,len);\r
- str->_sharedstate=ss;\r
- return str;\r
-}\r
-\r
-void SQString::Release()\r
-{\r
- REMOVE_STRING(_sharedstate,this);\r
-}\r
-\r
-unsigned int TranslateIndex(const SQObjectPtr &idx)\r
-{\r
- switch(type(idx)){\r
- case OT_NULL:\r
- return 0;\r
- case OT_INTEGER:\r
- return (unsigned int)_integer(idx);\r
- }\r
- assert(0);\r
- return 0;\r
-}\r
-\r
-bool SQDelegable::GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res) {\r
- if(_delegate) {\r
- return _delegate->Get((*_ss(this)->_metamethods)[mm],res);\r
- }\r
- return false;\r
-}\r
-\r
-bool SQGenerator::Yield(SQVM *v)\r
-{\r
- if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator")); return false;}\r
- if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }\r
- int size = v->_top-v->_stackbase;\r
- _ci=*v->ci;\r
- _stack.resize(size);\r
- for(int n =0; n<size; n++) {\r
- _stack._vals[n] = v->_stack[v->_stackbase+n];\r
- v->_stack[v->_stackbase+n] = _null_;\r
- }\r
- int nvargs = v->ci->_vargs.size;\r
- int vargsbase = v->ci->_vargs.base;\r
- for(int j = nvargs - 1; j >= 0; j--) {\r
- _vargsstack.push_back(v->_vargsstack[vargsbase+j]);\r
- }\r
- _ci._generator=_null_;\r
- for(int i=0;i<_ci._etraps;i++) {\r
- _etraps.push_back(v->_etraps.top());\r
- v->_etraps.pop_back();\r
- }\r
- _state=eSuspended;\r
- return true;\r
-}\r
-\r
-bool SQGenerator::Resume(SQVM *v,int target)\r
-{\r
- int size=_stack.size();\r
- if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }\r
- if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }\r
- int prevtop=v->_top-v->_stackbase;\r
- PUSH_CALLINFO(v,_ci);\r
- int oldstackbase=v->_stackbase;\r
- v->_stackbase=v->_top;\r
- v->ci->_target=target;\r
- v->ci->_generator=SQObjectPtr(this);\r
- v->ci->_vargs.size = _vargsstack.size();\r
- \r
- for(int i=0;i<_ci._etraps;i++) {\r
- v->_etraps.push_back(_etraps.top());\r
- _etraps.pop_back();\r
- }\r
- for(int n =0; n<size; n++) {\r
- v->_stack[v->_stackbase+n] = _stack._vals[n];\r
- _stack._vals[0] = _null_;\r
- }\r
- while(_vargsstack.size()) {\r
- v->_vargsstack.push_back(_vargsstack.back());\r
- _vargsstack.pop_back();\r
- }\r
- v->ci->_vargs.base = v->_vargsstack.size() - v->ci->_vargs.size;\r
- v->_top=v->_stackbase+size;\r
- v->ci->_prevtop=prevtop;\r
- v->ci->_prevstkbase=v->_stackbase-oldstackbase;\r
- _state=eRunning;\r
- return true;\r
-}\r
-\r
-void SQArray::Extend(const SQArray *a){\r
- int xlen;\r
- if((xlen=a->Size()))\r
- for(int i=0;i<xlen;i++)\r
- Append(a->_values[i]);\r
-}\r
-\r
-const SQChar* SQFunctionProto::GetLocal(SQVM *vm,unsigned int stackbase,unsigned int nseq,unsigned int nop)\r
-{\r
- unsigned int nvars=_localvarinfos.size();\r
- const SQChar *res=NULL; \r
- if(nvars>=nseq){\r
- for(unsigned int i=0;i<nvars;i++){\r
- if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)\r
- {\r
- if(nseq==0){\r
- vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]);\r
- res=_stringval(_localvarinfos[i]._name);\r
- break;\r
- }\r
- nseq--;\r
- }\r
- }\r
- }\r
- return res;\r
-}\r
-\r
-int SQFunctionProto::GetLine(SQInstruction *curr)\r
-{\r
- int op=(curr-_instructions._vals);\r
- int line=_lineinfos[0]._line;\r
- for(unsigned int i=1;i<_lineinfos.size();i++){\r
- if(_lineinfos[i]._op>=op)\r
- return line;\r
- line=_lineinfos[i]._line;\r
- }\r
- return line;\r
-}\r
-\r
-//#define _ERROR_TRAP() error_trap:\r
-#define _CHECK_IO(exp) { if(!exp)return false; }\r
-bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,int size)\r
-{\r
- if(write(up,dest,size) != size) {\r
- v->Raise_Error(_SC("io error (write function failure)"));\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,int size)\r
-{\r
- if(size && read(up,dest,size) != size) {\r
- v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,int tag)\r
-{\r
- return SafeWrite(v,write,up,&tag,sizeof(tag));\r
-}\r
-\r
-bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,int tag)\r
-{\r
- int t;\r
- _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));\r
- if(t != tag){\r
- v->Raise_Error(_SC("invalid or corrupted closure stream"));\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)\r
-{\r
- _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType)));\r
- switch(type(o)){\r
- case OT_STRING:\r
- _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));\r
- _CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len)));\r
- break;\r
- case OT_INTEGER:\r
- _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;\r
- case OT_FLOAT:\r
- _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break;\r
- case OT_NULL:\r
- break;\r
- default:\r
- v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o));\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)\r
-{\r
- SQObjectType t;\r
- _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType)));\r
- switch(t){\r
- case OT_STRING:{\r
- int len;\r
- _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger)));\r
- _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(rsl(len)),rsl(len)));\r
- o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len);\r
- }\r
- break;\r
- case OT_INTEGER:{\r
- SQInteger i;\r
- _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;\r
- }\r
- case OT_FLOAT:{\r
- SQFloat f;\r
- _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;\r
- }\r
- case OT_NULL:\r
- o=_null_;\r
- break;\r
- default:\r
- v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)\r
-{\r
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));\r
- _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));\r
- _CHECK_IO(_funcproto(_function)->Save(v,up,write));\r
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));\r
- return true;\r
-}\r
-\r
-bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)\r
-{\r
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));\r
- _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));\r
- _CHECK_IO(_funcproto(_function)->Load(v,up,read));\r
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));\r
- return true;\r
-}\r
-\r
-bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)\r
-{\r
- int i,nsize=_literals.size();\r
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
- _CHECK_IO(WriteObject(v,up,write,_sourcename));\r
- _CHECK_IO(WriteObject(v,up,write,_name));\r
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
- for(i=0;i<nsize;i++){\r
- _CHECK_IO(WriteObject(v,up,write,_literals[i]));\r
- }\r
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
- nsize=_parameters.size();\r
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
- for(i=0;i<nsize;i++){\r
- _CHECK_IO(WriteObject(v,up,write,_parameters[i]));\r
- }\r
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
- nsize=_outervalues.size();\r
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
- for(i=0;i<nsize;i++){\r
- _CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(unsigned int)));\r
- _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));\r
- _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));\r
- }\r
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
- nsize=_localvarinfos.size();\r
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
- for(i=0;i<nsize;i++){\r
- SQLocalVarInfo &lvi=_localvarinfos[i];\r
- _CHECK_IO(WriteObject(v,up,write,lvi._name));\r
- _CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(unsigned int)));\r
- _CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(unsigned int)));\r
- _CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(unsigned int)));\r
- }\r
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
- nsize=_lineinfos.size();\r
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
- _CHECK_IO(SafeWrite(v,write,up,&_lineinfos[0],sizeof(SQLineInfo)*nsize));\r
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
- nsize=_instructions.size();\r
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
- _CHECK_IO(SafeWrite(v,write,up,&_instructions[0],sizeof(SQInstruction)*nsize));\r
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
- nsize=_functions.size();\r
- _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));\r
- for(i=0;i<nsize;i++){\r
- _CHECK_IO(_funcproto(_functions[i])->Save(v,up,write));\r
- }\r
- _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));\r
- _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));\r
- _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));\r
- return true;\r
-}\r
-\r
-bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)\r
-{\r
- int i, nsize = _literals.size();\r
- SQObjectPtr o;\r
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
- _CHECK_IO(ReadObject(v, up, read, _sourcename));\r
- _CHECK_IO(ReadObject(v, up, read, _name));\r
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
- _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));\r
- for(i = 0;i < nsize; i++){\r
- _CHECK_IO(ReadObject(v, up, read, o));\r
- _literals.push_back(o);\r
- }\r
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
- _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));\r
- for(i = 0; i < nsize; i++){\r
- _CHECK_IO(ReadObject(v, up, read, o));\r
- _parameters.push_back(o);\r
- }\r
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
- _CHECK_IO(SafeRead(v,read,up,&nsize,sizeof(nsize)));\r
- for(i = 0; i < nsize; i++){\r
- unsigned int type;\r
- SQObjectPtr name;\r
- _CHECK_IO(SafeRead(v,read,up, &type, sizeof(unsigned int)));\r
- _CHECK_IO(ReadObject(v, up, read, o));\r
- _CHECK_IO(ReadObject(v, up, read, name));\r
- _outervalues.push_back(SQOuterVar(name,o, (SQOuterType)type));\r
- }\r
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
- _CHECK_IO(SafeRead(v,read,up,&nsize, sizeof(nsize)));\r
- for(i = 0; i < nsize; i++){\r
- SQLocalVarInfo lvi;\r
- _CHECK_IO(ReadObject(v, up, read, lvi._name));\r
- _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(unsigned int)));\r
- _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(unsigned int)));\r
- _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(unsigned int)));\r
- _localvarinfos.push_back(lvi);\r
- }\r
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
- _CHECK_IO(SafeRead(v,read,up, &nsize,sizeof(nsize)));\r
- _lineinfos.resize(nsize);\r
- _CHECK_IO(SafeRead(v,read,up, &_lineinfos[0], sizeof(SQLineInfo)*nsize));\r
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
- _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));\r
- _instructions.resize(nsize);\r
- _CHECK_IO(SafeRead(v,read,up, &_instructions[0], sizeof(SQInstruction)*nsize));\r
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
- _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));\r
- for(i = 0; i < nsize; i++){\r
- o = SQFunctionProto::Create();\r
- _CHECK_IO(_funcproto(o)->Load(v, up, read));\r
- _functions.push_back(o);\r
- }\r
- _CHECK_IO(SafeRead(v,read,up, &_stacksize, sizeof(_stacksize)));\r
- _CHECK_IO(SafeRead(v,read,up, &_bgenerator, sizeof(_bgenerator)));\r
- _CHECK_IO(SafeRead(v,read,up, &_varparams, sizeof(_varparams)));\r
- return true;\r
-}\r
-\r
-#ifndef NO_GARBAGE_COLLECTOR\r
-\r
-#define START_MARK() if(!(_uiRef&MARK_FLAG)){ \\r
- _uiRef|=MARK_FLAG;\r
-\r
-#define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \\r
- AddToChain(chain, this); }\r
-\r
-void SQVM::Mark(SQCollectable **chain)\r
-{\r
- START_MARK()\r
- SQSharedState::MarkObject(_lasterror,chain);\r
- SQSharedState::MarkObject(_errorhandler,chain);\r
- SQSharedState::MarkObject(_debughook,chain);\r
- SQSharedState::MarkObject(_roottable, chain);\r
- SQSharedState::MarkObject(temp_reg, chain);\r
- for(unsigned int i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
- for(unsigned int j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
- END_MARK()\r
-}\r
-\r
-void SQArray::Mark(SQCollectable **chain)\r
-{\r
- START_MARK()\r
- int len = _values.size();\r
- for(int i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain);\r
- END_MARK()\r
-}\r
-void SQTable::Mark(SQCollectable **chain)\r
-{\r
- START_MARK()\r
- if(_delegate) _delegate->Mark(chain);\r
- int len = _numofnodes;\r
- for(int i = 0; i < len; i++){\r
- SQSharedState::MarkObject(_nodes[i].key, chain);\r
- SQSharedState::MarkObject(_nodes[i].val, chain);\r
- }\r
- END_MARK()\r
-}\r
-\r
-void SQClass::Mark(SQCollectable **chain)\r
-{\r
- START_MARK()\r
- _members->Mark(chain);\r
- if(_base) _base->Mark(chain);\r
- SQSharedState::MarkObject(_attributes, chain);\r
- for(unsigned int i =0; i< _defaultvalues.size(); i++) {\r
- SQSharedState::MarkObject(_defaultvalues[i].val, chain);\r
- SQSharedState::MarkObject(_defaultvalues[i].attrs, chain);\r
- }\r
- for(unsigned int j =0; j< _methods.size(); j++) {\r
- SQSharedState::MarkObject(_methods[j].val, chain);\r
- SQSharedState::MarkObject(_methods[j].attrs, chain);\r
- }\r
- for(unsigned int k =0; k< _metamethods.size(); k++) {\r
- SQSharedState::MarkObject(_metamethods[k], chain);\r
- }\r
- END_MARK()\r
-}\r
-\r
-void SQInstance::Mark(SQCollectable **chain)\r
-{\r
- START_MARK()\r
- _class->Mark(chain);\r
- for(unsigned int i =0; i< _values.size(); i++) {\r
- SQSharedState::MarkObject(_values[i], chain);\r
- }\r
- END_MARK()\r
-}\r
-\r
-void SQGenerator::Mark(SQCollectable **chain)\r
-{\r
- START_MARK()\r
- for(unsigned int i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
- for(unsigned int j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
- SQSharedState::MarkObject(_closure, chain);\r
- END_MARK()\r
-}\r
-\r
-void SQClosure::Mark(SQCollectable **chain)\r
-{\r
- START_MARK()\r
- for(unsigned int i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
- END_MARK()\r
-}\r
-\r
-void SQNativeClosure::Mark(SQCollectable **chain)\r
-{\r
- START_MARK()\r
- for(unsigned int i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
- END_MARK()\r
-}\r
-\r
-void SQUserData::Mark(SQCollectable **chain){\r
- START_MARK()\r
- if(_delegate) _delegate->Mark(chain);\r
- END_MARK()\r
-}\r
-\r
-void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; }\r
-\r
-#endif\r
-\r
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqvm.h"
+#include "sqstring.h"
+#include "sqarray.h"
+#include "sqtable.h"
+#include "squserdata.h"
+#include "sqfuncproto.h"
+#include "sqclass.h"
+#include "sqclosure.h"
+
+SQString *SQString::Create(SQSharedState *ss,const SQChar *s,int len)
+{
+ SQString *str=ADD_STRING(ss,s,len);
+ str->_sharedstate=ss;
+ return str;
+}
+
+void SQString::Release()
+{
+ REMOVE_STRING(_sharedstate,this);
+}
+
+unsigned int TranslateIndex(const SQObjectPtr &idx)
+{
+ switch(type(idx)){
+ case OT_NULL:
+ return 0;
+ case OT_INTEGER:
+ return (unsigned int)_integer(idx);
+ default:
+ break;
+ }
+ assert(0);
+ return 0;
+}
+
+bool SQDelegable::GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res) {
+ if(_delegate) {
+ return _delegate->Get((*_ss(this)->_metamethods)[mm],res);
+ }
+ return false;
+}
+
+bool SQGenerator::Yield(SQVM *v)
+{
+ if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator")); return false;}
+ if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }
+ int size = v->_top-v->_stackbase;
+ _ci=*v->ci;
+ _stack.resize(size);
+ for(int n =0; n<size; n++) {
+ _stack._vals[n] = v->_stack[v->_stackbase+n];
+ v->_stack[v->_stackbase+n] = _null_;
+ }
+ int nvargs = v->ci->_vargs.size;
+ int vargsbase = v->ci->_vargs.base;
+ for(int j = nvargs - 1; j >= 0; j--) {
+ _vargsstack.push_back(v->_vargsstack[vargsbase+j]);
+ }
+ _ci._generator=_null_;
+ for(int i=0;i<_ci._etraps;i++) {
+ _etraps.push_back(v->_etraps.top());
+ v->_etraps.pop_back();
+ }
+ _state=eSuspended;
+ return true;
+}
+
+bool SQGenerator::Resume(SQVM *v,int target)
+{
+ int size=_stack.size();
+ if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }
+ if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }
+ int prevtop=v->_top-v->_stackbase;
+ PUSH_CALLINFO(v,_ci);
+ int oldstackbase=v->_stackbase;
+ v->_stackbase=v->_top;
+ v->ci->_target=target;
+ v->ci->_generator=SQObjectPtr(this);
+ v->ci->_vargs.size = _vargsstack.size();
+
+ for(int i=0;i<_ci._etraps;i++) {
+ v->_etraps.push_back(_etraps.top());
+ _etraps.pop_back();
+ }
+ for(int n =0; n<size; n++) {
+ v->_stack[v->_stackbase+n] = _stack._vals[n];
+ _stack._vals[0] = _null_;
+ }
+ while(_vargsstack.size()) {
+ v->_vargsstack.push_back(_vargsstack.back());
+ _vargsstack.pop_back();
+ }
+ v->ci->_vargs.base = v->_vargsstack.size() - v->ci->_vargs.size;
+ v->_top=v->_stackbase+size;
+ v->ci->_prevtop=prevtop;
+ v->ci->_prevstkbase=v->_stackbase-oldstackbase;
+ _state=eRunning;
+ return true;
+}
+
+void SQArray::Extend(const SQArray *a){
+ int xlen;
+ if((xlen=a->Size()))
+ for(int i=0;i<xlen;i++)
+ Append(a->_values[i]);
+}
+
+const SQChar* SQFunctionProto::GetLocal(SQVM *vm,unsigned int stackbase,unsigned int nseq,unsigned int nop)
+{
+ unsigned int nvars=_localvarinfos.size();
+ const SQChar *res=NULL;
+ if(nvars>=nseq){
+ for(unsigned int i=0;i<nvars;i++){
+ if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)
+ {
+ if(nseq==0){
+ vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]);
+ res=_stringval(_localvarinfos[i]._name);
+ break;
+ }
+ nseq--;
+ }
+ }
+ }
+ return res;
+}
+
+int SQFunctionProto::GetLine(SQInstruction *curr)
+{
+ int op=(curr-_instructions._vals);
+ int line=_lineinfos[0]._line;
+ for(unsigned int i=1;i<_lineinfos.size();i++){
+ if(_lineinfos[i]._op>=op)
+ return line;
+ line=_lineinfos[i]._line;
+ }
+ return line;
+}
+
+//#define _ERROR_TRAP() error_trap:
+#define _CHECK_IO(exp) { if(!exp)return false; }
+bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,int size)
+{
+ if(write(up,dest,size) != size) {
+ v->Raise_Error(_SC("io error (write function failure)"));
+ return false;
+ }
+ return true;
+}
+
+bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,int size)
+{
+ if(size && read(up,dest,size) != size) {
+ v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));
+ return false;
+ }
+ return true;
+}
+
+bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,int tag)
+{
+ return SafeWrite(v,write,up,&tag,sizeof(tag));
+}
+
+bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,int tag)
+{
+ int t;
+ _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));
+ if(t != tag){
+ v->Raise_Error(_SC("invalid or corrupted closure stream"));
+ return false;
+ }
+ return true;
+}
+
+bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)
+{
+ _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType)));
+ switch(type(o)){
+ case OT_STRING:
+ _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));
+ _CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len)));
+ break;
+ case OT_INTEGER:
+ _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;
+ case OT_FLOAT:
+ _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break;
+ case OT_NULL:
+ break;
+ default:
+ v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o));
+ return false;
+ }
+ return true;
+}
+
+bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
+{
+ SQObjectType t;
+ _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType)));
+ switch(t){
+ case OT_STRING:{
+ int len;
+ _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger)));
+ _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(rsl(len)),rsl(len)));
+ o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len);
+ }
+ break;
+ case OT_INTEGER:{
+ SQInteger i;
+ _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break;
+ }
+ case OT_FLOAT:{
+ SQFloat f;
+ _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;
+ }
+ case OT_NULL:
+ o=_null_;
+ break;
+ default:
+ v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));
+ return false;
+ }
+ return true;
+}
+
+bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
+{
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));
+ _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));
+ _CHECK_IO(_funcproto(_function)->Save(v,up,write));
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));
+ return true;
+}
+
+bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)
+{
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));
+ _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));
+ _CHECK_IO(_funcproto(_function)->Load(v,up,read));
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));
+ return true;
+}
+
+bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
+{
+ int i,nsize=_literals.size();
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+ _CHECK_IO(WriteObject(v,up,write,_sourcename));
+ _CHECK_IO(WriteObject(v,up,write,_name));
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+ _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
+ for(i=0;i<nsize;i++){
+ _CHECK_IO(WriteObject(v,up,write,_literals[i]));
+ }
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+ nsize=_parameters.size();
+ _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
+ for(i=0;i<nsize;i++){
+ _CHECK_IO(WriteObject(v,up,write,_parameters[i]));
+ }
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+ nsize=_outervalues.size();
+ _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
+ for(i=0;i<nsize;i++){
+ _CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(unsigned int)));
+ _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));
+ _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));
+ }
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+ nsize=_localvarinfos.size();
+ _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
+ for(i=0;i<nsize;i++){
+ SQLocalVarInfo &lvi=_localvarinfos[i];
+ _CHECK_IO(WriteObject(v,up,write,lvi._name));
+ _CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(unsigned int)));
+ _CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(unsigned int)));
+ _CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(unsigned int)));
+ }
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+ nsize=_lineinfos.size();
+ _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
+ _CHECK_IO(SafeWrite(v,write,up,&_lineinfos[0],sizeof(SQLineInfo)*nsize));
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+ nsize=_instructions.size();
+ _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
+ _CHECK_IO(SafeWrite(v,write,up,&_instructions[0],sizeof(SQInstruction)*nsize));
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+ nsize=_functions.size();
+ _CHECK_IO(SafeWrite(v,write,up,&nsize,sizeof(nsize)));
+ for(i=0;i<nsize;i++){
+ _CHECK_IO(_funcproto(_functions[i])->Save(v,up,write));
+ }
+ _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));
+ _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));
+ _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));
+ return true;
+}
+
+bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read)
+{
+ int i, nsize = _literals.size();
+ SQObjectPtr o;
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+ _CHECK_IO(ReadObject(v, up, read, _sourcename));
+ _CHECK_IO(ReadObject(v, up, read, _name));
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+ _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
+ for(i = 0;i < nsize; i++){
+ _CHECK_IO(ReadObject(v, up, read, o));
+ _literals.push_back(o);
+ }
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+ _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
+ for(i = 0; i < nsize; i++){
+ _CHECK_IO(ReadObject(v, up, read, o));
+ _parameters.push_back(o);
+ }
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+ _CHECK_IO(SafeRead(v,read,up,&nsize,sizeof(nsize)));
+ for(i = 0; i < nsize; i++){
+ unsigned int type;
+ SQObjectPtr name;
+ _CHECK_IO(SafeRead(v,read,up, &type, sizeof(unsigned int)));
+ _CHECK_IO(ReadObject(v, up, read, o));
+ _CHECK_IO(ReadObject(v, up, read, name));
+ _outervalues.push_back(SQOuterVar(name,o, (SQOuterType)type));
+ }
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+ _CHECK_IO(SafeRead(v,read,up,&nsize, sizeof(nsize)));
+ for(i = 0; i < nsize; i++){
+ SQLocalVarInfo lvi;
+ _CHECK_IO(ReadObject(v, up, read, lvi._name));
+ _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(unsigned int)));
+ _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(unsigned int)));
+ _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(unsigned int)));
+ _localvarinfos.push_back(lvi);
+ }
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+ _CHECK_IO(SafeRead(v,read,up, &nsize,sizeof(nsize)));
+ _lineinfos.resize(nsize);
+ _CHECK_IO(SafeRead(v,read,up, &_lineinfos[0], sizeof(SQLineInfo)*nsize));
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+ _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
+ _instructions.resize(nsize);
+ _CHECK_IO(SafeRead(v,read,up, &_instructions[0], sizeof(SQInstruction)*nsize));
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+ _CHECK_IO(SafeRead(v,read,up, &nsize, sizeof(nsize)));
+ for(i = 0; i < nsize; i++){
+ o = SQFunctionProto::Create();
+ _CHECK_IO(_funcproto(o)->Load(v, up, read));
+ _functions.push_back(o);
+ }
+ _CHECK_IO(SafeRead(v,read,up, &_stacksize, sizeof(_stacksize)));
+ _CHECK_IO(SafeRead(v,read,up, &_bgenerator, sizeof(_bgenerator)));
+ _CHECK_IO(SafeRead(v,read,up, &_varparams, sizeof(_varparams)));
+ return true;
+}
+
+#ifndef NO_GARBAGE_COLLECTOR
+
+#define START_MARK() if(!(_uiRef&MARK_FLAG)){ \
+ _uiRef|=MARK_FLAG;
+
+#define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \
+ AddToChain(chain, this); }
+
+void SQVM::Mark(SQCollectable **chain)
+{
+ START_MARK()
+ SQSharedState::MarkObject(_lasterror,chain);
+ SQSharedState::MarkObject(_errorhandler,chain);
+ SQSharedState::MarkObject(_debughook,chain);
+ SQSharedState::MarkObject(_roottable, chain);
+ SQSharedState::MarkObject(temp_reg, chain);
+ for(unsigned int i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
+ for(unsigned int j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);
+ END_MARK()
+}
+
+void SQArray::Mark(SQCollectable **chain)
+{
+ START_MARK()
+ int len = _values.size();
+ for(int i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain);
+ END_MARK()
+}
+void SQTable::Mark(SQCollectable **chain)
+{
+ START_MARK()
+ if(_delegate) _delegate->Mark(chain);
+ int len = _numofnodes;
+ for(int i = 0; i < len; i++){
+ SQSharedState::MarkObject(_nodes[i].key, chain);
+ SQSharedState::MarkObject(_nodes[i].val, chain);
+ }
+ END_MARK()
+}
+
+void SQClass::Mark(SQCollectable **chain)
+{
+ START_MARK()
+ _members->Mark(chain);
+ if(_base) _base->Mark(chain);
+ SQSharedState::MarkObject(_attributes, chain);
+ for(unsigned int i =0; i< _defaultvalues.size(); i++) {
+ SQSharedState::MarkObject(_defaultvalues[i].val, chain);
+ SQSharedState::MarkObject(_defaultvalues[i].attrs, chain);
+ }
+ for(unsigned int j =0; j< _methods.size(); j++) {
+ SQSharedState::MarkObject(_methods[j].val, chain);
+ SQSharedState::MarkObject(_methods[j].attrs, chain);
+ }
+ for(unsigned int k =0; k< _metamethods.size(); k++) {
+ SQSharedState::MarkObject(_metamethods[k], chain);
+ }
+ END_MARK()
+}
+
+void SQInstance::Mark(SQCollectable **chain)
+{
+ START_MARK()
+ _class->Mark(chain);
+ for(unsigned int i =0; i< _values.size(); i++) {
+ SQSharedState::MarkObject(_values[i], chain);
+ }
+ END_MARK()
+}
+
+void SQGenerator::Mark(SQCollectable **chain)
+{
+ START_MARK()
+ for(unsigned int i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
+ for(unsigned int j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);
+ SQSharedState::MarkObject(_closure, chain);
+ END_MARK()
+}
+
+void SQClosure::Mark(SQCollectable **chain)
+{
+ START_MARK()
+ for(unsigned int i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);
+ END_MARK()
+}
+
+void SQNativeClosure::Mark(SQCollectable **chain)
+{
+ START_MARK()
+ for(unsigned int i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);
+ END_MARK()
+}
+
+void SQUserData::Mark(SQCollectable **chain){
+ START_MARK()
+ if(_delegate) _delegate->Mark(chain);
+ END_MARK()
+}
+
+void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; }
+
+#endif
+
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQOBJECT_H_\r
-#define _SQOBJECT_H_\r
-\r
-#include "squtils.h"\r
-\r
-#define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R'))\r
-#define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T'))\r
-#define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L'))\r
-\r
-#define SQ_TRY try\r
-#define SQ_CATCH(type, ex) catch(type &ex)\r
-\r
-struct SQSharedState;\r
-\r
-enum SQMetaMethod{\r
- MT_ADD=0,\r
- MT_SUB=1,\r
- MT_MUL=2,\r
- MT_DIV=3,\r
- MT_UNM=4,\r
- MT_MODULO=5,\r
- MT_SET=6,\r
- MT_GET=7,\r
- MT_TYPEOF=8,\r
- MT_NEXTI=9,\r
- MT_CMP=10,\r
- MT_CALL=11,\r
- MT_CLONED=12,\r
- MT_NEWSLOT=13,\r
- MT_DELSLOT=14,\r
- MT_LAST = 15,\r
-};\r
-\r
-#define MM_ADD _SC("_add")\r
-#define MM_SUB _SC("_sub")\r
-#define MM_MUL _SC("_mul")\r
-#define MM_DIV _SC("_div")\r
-#define MM_UNM _SC("_unm")\r
-#define MM_MODULO _SC("_modulo")\r
-#define MM_SET _SC("_set")\r
-#define MM_GET _SC("_get")\r
-#define MM_TYPEOF _SC("_typeof")\r
-#define MM_NEXTI _SC("_nexti")\r
-#define MM_CMP _SC("_cmp")\r
-#define MM_CALL _SC("_call")\r
-#define MM_CLONED _SC("_cloned")\r
-#define MM_NEWSLOT _SC("_newslot")\r
-#define MM_DELSLOT _SC("_delslot")\r
-\r
-#define MINPOWER2 4\r
-\r
-struct SQRefCounted\r
-{\r
- virtual ~SQRefCounted() {}\r
-\r
- unsigned int _uiRef;\r
- virtual void Release()=0;\r
-};\r
-\r
-struct SQObjectPtr;\r
-\r
-#define __AddRef(type,unval) if(ISREFCOUNTED(type)) \\r
- { \\r
- unval.pRefCounted->_uiRef++; \\r
- } \r
-\r
-#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)<=0)) \\r
- { \\r
- unval.pRefCounted->Release(); \\r
- }\r
-\r
-#define __ObjRelease(obj) { \\r
- if((obj)) { \\r
- (obj)->_uiRef--; \\r
- if((obj)->_uiRef == 0) \\r
- (obj)->Release(); \\r
- (obj) = NULL; \\r
- } \\r
-}\r
-\r
-#define __ObjAddRef(obj) { \\r
- (obj)->_uiRef++; \\r
-}\r
-\r
-#define type(obj) ((obj)._type)\r
-#define is_delegable(t) (type(t)&SQOBJECT_DELEGABLE)\r
-#define raw_type(obj) _RAW_TYPE((obj)._type)\r
-\r
-#define _integer(obj) ((obj)._unVal.nInteger)\r
-#define _float(obj) ((obj)._unVal.fFloat)\r
-#define _string(obj) ((obj)._unVal.pString)\r
-#define _table(obj) ((obj)._unVal.pTable)\r
-#define _array(obj) ((obj)._unVal.pArray)\r
-#define _closure(obj) ((obj)._unVal.pClosure)\r
-#define _generator(obj) ((obj)._unVal.pGenerator)\r
-#define _nativeclosure(obj) ((obj)._unVal.pNativeClosure)\r
-#define _userdata(obj) ((obj)._unVal.pUserData)\r
-#define _userpointer(obj) ((obj)._unVal.pUserPointer)\r
-#define _thread(obj) ((obj)._unVal.pThread)\r
-#define _funcproto(obj) ((obj)._unVal.pFunctionProto)\r
-#define _class(obj) ((obj)._unVal.pClass)\r
-#define _instance(obj) ((obj)._unVal.pInstance)\r
-#define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable)\r
-#define _rawval(obj) ((obj)._unVal.pRefCounted)\r
-\r
-#define _stringval(obj) (obj)._unVal.pString->_val\r
-#define _userdataval(obj) (obj)._unVal.pUserData->_val\r
-\r
-#define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num))\r
-#define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num))\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-struct SQObjectPtr : public SQObject\r
-{\r
- SQObjectPtr()\r
- {\r
- _type=OT_NULL;\r
- _unVal.pUserPointer=NULL;\r
- }\r
- SQObjectPtr(const SQObjectPtr &o)\r
- {\r
- _type=o._type;\r
- _unVal=o._unVal;\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(const SQObject &o)\r
- {\r
- _type=o._type;\r
- _unVal=o._unVal;\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(SQTable *pTable)\r
- {\r
- _type=OT_TABLE;\r
- _unVal.pTable=pTable;\r
- assert(_unVal.pTable);\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(SQClass *pClass)\r
- {\r
- _type=OT_CLASS;\r
- _unVal.pClass=pClass;\r
- assert(_unVal.pClass);\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(SQInstance *pInstance)\r
- {\r
- _type=OT_INSTANCE;\r
- _unVal.pInstance=pInstance;\r
- assert(_unVal.pInstance);\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(SQArray *pArray)\r
- {\r
- _type=OT_ARRAY;\r
- _unVal.pArray=pArray;\r
- assert(_unVal.pArray);\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(SQClosure *pClosure)\r
- {\r
- _type=OT_CLOSURE;\r
- _unVal.pClosure=pClosure;\r
- assert(_unVal.pClosure);\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(SQGenerator *pGenerator)\r
- {\r
- _type=OT_GENERATOR;\r
- _unVal.pGenerator=pGenerator;\r
- assert(_unVal.pGenerator);\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(SQNativeClosure *pNativeClosure)\r
- {\r
- _type=OT_NATIVECLOSURE;\r
- _unVal.pNativeClosure=pNativeClosure;\r
- assert(_unVal.pNativeClosure);\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(SQString *pString)\r
- {\r
- _type=OT_STRING;\r
- _unVal.pString=pString;\r
- assert(_unVal.pString);\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(SQUserData *pUserData)\r
- {\r
- _type=OT_USERDATA;\r
- _unVal.pUserData=pUserData;\r
- assert(_unVal.pUserData);\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(SQVM *pThread)\r
- {\r
- _type=OT_THREAD;\r
- _unVal.pThread=pThread;\r
- assert(_unVal.pThread);\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(SQFunctionProto *pFunctionProto)\r
- {\r
- _type=OT_FUNCPROTO;\r
- _unVal.pFunctionProto=pFunctionProto;\r
- assert(_unVal.pFunctionProto);\r
- __AddRef(_type,_unVal);\r
- }\r
- SQObjectPtr(SQInteger nInteger)\r
- {\r
- _type=OT_INTEGER;\r
- _unVal.nInteger=nInteger;\r
- }\r
- SQObjectPtr(SQFloat fFloat)\r
- {\r
- _type=OT_FLOAT;\r
- _unVal.fFloat=fFloat;\r
- }\r
- SQObjectPtr(bool bBool)\r
- {\r
- _type = OT_BOOL;\r
- _unVal.nInteger = bBool?1:0;\r
- }\r
- SQObjectPtr(SQUserPointer pUserPointer)\r
- {\r
- _type=OT_USERPOINTER;\r
- _unVal.pUserPointer=pUserPointer;\r
- }\r
- ~SQObjectPtr()\r
- {\r
- __Release(_type,_unVal);\r
- }\r
- void Null()\r
- {\r
- __Release(_type,_unVal);\r
- _type=OT_NULL;\r
- _unVal.pUserPointer=NULL;\r
- }\r
- SQObjectPtr& operator=(const SQObjectPtr& obj)\r
- { \r
- SQObjectType tOldType;\r
- SQObjectValue unOldVal;\r
- tOldType=_type;\r
- unOldVal=_unVal;\r
- _unVal = obj._unVal;\r
- _type = obj._type;\r
- __AddRef(_type,_unVal);\r
- __Release(tOldType,unOldVal);\r
- return *this;\r
- }\r
- SQObjectPtr& operator=(const SQObject& obj)\r
- { \r
- SQObjectType tOldType;\r
- SQObjectValue unOldVal;\r
- tOldType=_type;\r
- unOldVal=_unVal;\r
- _unVal = obj._unVal;\r
- _type = obj._type;\r
- __AddRef(_type,_unVal);\r
- __Release(tOldType,unOldVal);\r
- return *this;\r
- }\r
- private:\r
- SQObjectPtr(const SQChar *){} //safety\r
-};\r
-/////////////////////////////////////////////////////////////////////////////////////\r
-#ifndef NO_GARBAGE_COLLECTOR\r
-#define MARK_FLAG 0x80000000\r
-struct SQCollectable : public SQRefCounted {\r
- SQCollectable *_next;\r
- SQCollectable *_prev;\r
- SQSharedState *_sharedstate;\r
- virtual void Release()=0;\r
- virtual void Mark(SQCollectable **chain)=0;\r
- void UnMark();\r
- virtual void Finalize()=0;\r
- static void AddToChain(SQCollectable **chain,SQCollectable *c);\r
- static void RemoveFromChain(SQCollectable **chain,SQCollectable *c);\r
-};\r
-\r
-\r
-#define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj)\r
-#define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);}\r
-#define CHAINABLE_OBJ SQCollectable\r
-#define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;}\r
-#else\r
-\r
-#define ADD_TO_CHAIN(chain,obj) ((void)0)\r
-#define REMOVE_FROM_CHAIN(chain,obj) ((void)0)\r
-#define CHAINABLE_OBJ SQRefCounted\r
-#define INIT_CHAIN() ((void)0)\r
-#endif\r
-\r
-struct SQDelegable : public CHAINABLE_OBJ {\r
- virtual bool GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res);\r
- SQTable *_delegate;\r
-};\r
-\r
-unsigned int TranslateIndex(const SQObjectPtr &idx);\r
-typedef sqvector<SQObjectPtr> SQObjectPtrVec;\r
-typedef sqvector<int> SQIntVec;\r
-\r
-#endif //_SQOBJECT_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQOBJECT_H_
+#define _SQOBJECT_H_
+
+#include "squtils.h"
+
+#define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R'))
+#define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T'))
+#define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L'))
+
+#define SQ_TRY try
+#define SQ_CATCH(type, ex) catch(type &ex)
+
+struct SQSharedState;
+
+enum SQMetaMethod{
+ MT_ADD=0,
+ MT_SUB=1,
+ MT_MUL=2,
+ MT_DIV=3,
+ MT_UNM=4,
+ MT_MODULO=5,
+ MT_SET=6,
+ MT_GET=7,
+ MT_TYPEOF=8,
+ MT_NEXTI=9,
+ MT_CMP=10,
+ MT_CALL=11,
+ MT_CLONED=12,
+ MT_NEWSLOT=13,
+ MT_DELSLOT=14,
+ MT_LAST = 15,
+};
+
+#define MM_ADD _SC("_add")
+#define MM_SUB _SC("_sub")
+#define MM_MUL _SC("_mul")
+#define MM_DIV _SC("_div")
+#define MM_UNM _SC("_unm")
+#define MM_MODULO _SC("_modulo")
+#define MM_SET _SC("_set")
+#define MM_GET _SC("_get")
+#define MM_TYPEOF _SC("_typeof")
+#define MM_NEXTI _SC("_nexti")
+#define MM_CMP _SC("_cmp")
+#define MM_CALL _SC("_call")
+#define MM_CLONED _SC("_cloned")
+#define MM_NEWSLOT _SC("_newslot")
+#define MM_DELSLOT _SC("_delslot")
+
+#define MINPOWER2 4
+
+struct SQRefCounted
+{
+ virtual ~SQRefCounted()
+ {}
+ unsigned int _uiRef;
+ virtual void Release()=0;
+};
+
+struct SQObjectPtr;
+
+#define __AddRef(type,unval) if(ISREFCOUNTED(type)) \
+ { \
+ unval.pRefCounted->_uiRef++; \
+ }
+
+#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)<=0)) \
+ { \
+ unval.pRefCounted->Release(); \
+ }
+
+#define __ObjRelease(obj) { \
+ if((obj)) { \
+ (obj)->_uiRef--; \
+ if((obj)->_uiRef == 0) \
+ (obj)->Release(); \
+ (obj) = NULL; \
+ } \
+}
+
+#define __ObjAddRef(obj) { \
+ (obj)->_uiRef++; \
+}
+
+#define type(obj) ((obj)._type)
+#define is_delegable(t) (type(t)&SQOBJECT_DELEGABLE)
+#define raw_type(obj) _RAW_TYPE((obj)._type)
+
+#define _integer(obj) ((obj)._unVal.nInteger)
+#define _float(obj) ((obj)._unVal.fFloat)
+#define _string(obj) ((obj)._unVal.pString)
+#define _table(obj) ((obj)._unVal.pTable)
+#define _array(obj) ((obj)._unVal.pArray)
+#define _closure(obj) ((obj)._unVal.pClosure)
+#define _generator(obj) ((obj)._unVal.pGenerator)
+#define _nativeclosure(obj) ((obj)._unVal.pNativeClosure)
+#define _userdata(obj) ((obj)._unVal.pUserData)
+#define _userpointer(obj) ((obj)._unVal.pUserPointer)
+#define _thread(obj) ((obj)._unVal.pThread)
+#define _funcproto(obj) ((obj)._unVal.pFunctionProto)
+#define _class(obj) ((obj)._unVal.pClass)
+#define _instance(obj) ((obj)._unVal.pInstance)
+#define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable)
+#define _rawval(obj) ((obj)._unVal.pRefCounted)
+
+#define _stringval(obj) (obj)._unVal.pString->_val
+#define _userdataval(obj) (obj)._unVal.pUserData->_val
+
+#define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num))
+#define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num))
+/////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+struct SQObjectPtr : public SQObject
+{
+ SQObjectPtr()
+ {
+ _type=OT_NULL;
+ _unVal.pUserPointer=NULL;
+ }
+ SQObjectPtr(const SQObjectPtr &o)
+ {
+ _type=o._type;
+ _unVal=o._unVal;
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(const SQObject &o)
+ {
+ _type=o._type;
+ _unVal=o._unVal;
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(SQTable *pTable)
+ {
+ _type=OT_TABLE;
+ _unVal.pTable=pTable;
+ assert(_unVal.pTable);
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(SQClass *pClass)
+ {
+ _type=OT_CLASS;
+ _unVal.pClass=pClass;
+ assert(_unVal.pClass);
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(SQInstance *pInstance)
+ {
+ _type=OT_INSTANCE;
+ _unVal.pInstance=pInstance;
+ assert(_unVal.pInstance);
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(SQArray *pArray)
+ {
+ _type=OT_ARRAY;
+ _unVal.pArray=pArray;
+ assert(_unVal.pArray);
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(SQClosure *pClosure)
+ {
+ _type=OT_CLOSURE;
+ _unVal.pClosure=pClosure;
+ assert(_unVal.pClosure);
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(SQGenerator *pGenerator)
+ {
+ _type=OT_GENERATOR;
+ _unVal.pGenerator=pGenerator;
+ assert(_unVal.pGenerator);
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(SQNativeClosure *pNativeClosure)
+ {
+ _type=OT_NATIVECLOSURE;
+ _unVal.pNativeClosure=pNativeClosure;
+ assert(_unVal.pNativeClosure);
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(SQString *pString)
+ {
+ _type=OT_STRING;
+ _unVal.pString=pString;
+ assert(_unVal.pString);
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(SQUserData *pUserData)
+ {
+ _type=OT_USERDATA;
+ _unVal.pUserData=pUserData;
+ assert(_unVal.pUserData);
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(SQVM *pThread)
+ {
+ _type=OT_THREAD;
+ _unVal.pThread=pThread;
+ assert(_unVal.pThread);
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(SQFunctionProto *pFunctionProto)
+ {
+ _type=OT_FUNCPROTO;
+ _unVal.pFunctionProto=pFunctionProto;
+ assert(_unVal.pFunctionProto);
+ __AddRef(_type,_unVal);
+ }
+ SQObjectPtr(SQInteger nInteger)
+ {
+ _type=OT_INTEGER;
+ _unVal.nInteger=nInteger;
+ }
+ SQObjectPtr(SQFloat fFloat)
+ {
+ _type=OT_FLOAT;
+ _unVal.fFloat=fFloat;
+ }
+ SQObjectPtr(bool bBool)
+ {
+ _type = OT_BOOL;
+ _unVal.nInteger = bBool?1:0;
+ }
+ SQObjectPtr(SQUserPointer pUserPointer)
+ {
+ _type=OT_USERPOINTER;
+ _unVal.pUserPointer=pUserPointer;
+ }
+ ~SQObjectPtr()
+ {
+ __Release(_type,_unVal);
+ }
+ void Null()
+ {
+ __Release(_type,_unVal);
+ _type=OT_NULL;
+ _unVal.pUserPointer=NULL;
+ }
+ SQObjectPtr& operator=(const SQObjectPtr& obj)
+ {
+ SQObjectType tOldType;
+ SQObjectValue unOldVal;
+ tOldType=_type;
+ unOldVal=_unVal;
+ _unVal = obj._unVal;
+ _type = obj._type;
+ __AddRef(_type,_unVal);
+ __Release(tOldType,unOldVal);
+ return *this;
+ }
+ SQObjectPtr& operator=(const SQObject& obj)
+ {
+ SQObjectType tOldType;
+ SQObjectValue unOldVal;
+ tOldType=_type;
+ unOldVal=_unVal;
+ _unVal = obj._unVal;
+ _type = obj._type;
+ __AddRef(_type,_unVal);
+ __Release(tOldType,unOldVal);
+ return *this;
+ }
+ private:
+ SQObjectPtr(const SQChar *){} //safety
+};
+/////////////////////////////////////////////////////////////////////////////////////
+#ifndef NO_GARBAGE_COLLECTOR
+#define MARK_FLAG 0x80000000
+struct SQCollectable : public SQRefCounted {
+ SQCollectable *_next;
+ SQCollectable *_prev;
+ SQSharedState *_sharedstate;
+ virtual void Release()=0;
+ virtual void Mark(SQCollectable **chain)=0;
+ void UnMark();
+ virtual void Finalize()=0;
+ static void AddToChain(SQCollectable **chain,SQCollectable *c);
+ static void RemoveFromChain(SQCollectable **chain,SQCollectable *c);
+};
+
+
+#define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj)
+#define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);}
+#define CHAINABLE_OBJ SQCollectable
+#define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;}
+#else
+
+#define ADD_TO_CHAIN(chain,obj) ((void)0)
+#define REMOVE_FROM_CHAIN(chain,obj) ((void)0)
+#define CHAINABLE_OBJ SQRefCounted
+#define INIT_CHAIN() ((void)0)
+#endif
+
+struct SQDelegable : public CHAINABLE_OBJ {
+ virtual bool GetMetaMethod(SQMetaMethod mm,SQObjectPtr &res);
+ SQTable *_delegate;
+};
+
+unsigned int TranslateIndex(const SQObjectPtr &idx);
+typedef sqvector<SQObjectPtr> SQObjectPtrVec;
+typedef sqvector<int> SQIntVec;
+
+#endif //_SQOBJECT_H_
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQOPCODES_H_\r
-#define _SQOPCODES_H_\r
-\r
-#define MAX_FUNC_STACKSIZE 0xFF\r
-#define MAX_LITERALS 0xFFFFFFFF\r
-\r
-enum BitWiseOP {\r
- BW_AND = 0,\r
- BW_OR = 2, //like ADD\r
- BW_XOR = 3,\r
- BW_SHIFTL = 4,\r
- BW_SHIFTR = 5,\r
- BW_USHIFTR = 6\r
-};\r
-\r
-enum CmpOP {\r
- CMP_G = 0,\r
- CMP_GE = 2, //like ADD\r
- CMP_L = 3,\r
- CMP_LE = 4\r
-};\r
-enum SQOpcode\r
-{\r
- _OP_LINE= 0x00, \r
- _OP_LOAD= 0x01, \r
- _OP_TAILCALL= 0x02, \r
- _OP_CALL= 0x03, \r
- _OP_PREPCALL= 0x04, \r
- _OP_PREPCALLK= 0x05, \r
- _OP_GETK= 0x06, \r
- _OP_MOVE= 0x07, \r
- _OP_NEWSLOT= 0x08, \r
- _OP_DELETE= 0x09, \r
- _OP_SET= 0x0A, \r
- _OP_GET= 0x0B,\r
- _OP_EQ= 0x0C,\r
- _OP_NE= 0x0D,\r
- _OP_ARITH= 0x0E,\r
- _OP_BITW= 0x0F,\r
- _OP_RETURN= 0x10, \r
- _OP_LOADNULLS= 0x11, \r
- _OP_LOADROOTTABLE= 0x12, \r
- _OP_DMOVE= 0x13, \r
- _OP_JMP= 0x14, \r
- _OP_JNZ= 0x15, \r
- _OP_JZ= 0x16, \r
- _OP_LOADFREEVAR= 0x17, \r
- _OP_VARGC= 0x18, \r
- _OP_GETVARGV= 0x19, \r
- _OP_NEWTABLE= 0x1A, \r
- _OP_NEWARRAY= 0x1B, \r
- _OP_APPENDARRAY= 0x1C, \r
- _OP_GETPARENT= 0x1D, \r
- _OP_COMPARITH= 0x1E, \r
- _OP_COMPARITHL= 0x1F, \r
- _OP_INC= 0x20, \r
- _OP_INCL= 0x21, \r
- _OP_PINC= 0x22, \r
- _OP_PINCL= 0x23, \r
- _OP_CMP= 0x24,\r
- _OP_EXISTS= 0x25, \r
- _OP_INSTANCEOF= 0x26,\r
- _OP_AND= 0x27,\r
- _OP_OR= 0x28,\r
- _OP_NEG= 0x29,\r
- _OP_NOT= 0x2A,\r
- _OP_BWNOT= 0x2B, \r
- _OP_CLOSURE= 0x2C, \r
- _OP_YIELD= 0x2D, \r
- _OP_RESUME= 0x2E,\r
- _OP_FOREACH= 0x2F,\r
- _OP_DELEGATE= 0x30,\r
- _OP_CLONE= 0x31,\r
- _OP_TYPEOF= 0x32,\r
- _OP_PUSHTRAP= 0x33,\r
- _OP_POPTRAP= 0x34,\r
- _OP_THROW= 0x35,\r
- _OP_CLASS= 0x36,\r
- _OP_NEWSLOTA= 0x37,\r
- _OP_LOADBOOL= 0x38\r
-}; \r
-struct SQInstructionDesc { \r
- const SQChar *name; \r
-}; \r
-\r
-struct SQInstruction \r
-{\r
- SQInstruction(){};\r
- SQInstruction(SQOpcode _op,int a0=0,int a1=0,int a2=0,int a3=0)\r
- { op = _op;\r
- _arg0 = a0;_arg1 = a1;\r
- _arg2 = a2;_arg3 = a3;\r
- }\r
- \r
- \r
- unsigned int _arg1;\r
- unsigned char op;\r
- unsigned char _arg0;\r
- unsigned char _arg2;\r
- unsigned char _arg3;\r
-};\r
-\r
-#include "squtils.h"\r
-typedef sqvector<SQInstruction> SQInstructionVec;\r
-\r
-#endif // _SQOPCODES_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQOPCODES_H_
+#define _SQOPCODES_H_
+
+#include <limits.h>
+
+#define MAX_FUNC_STACKSIZE 0xFF
+#define MAX_LITERALS INT_MAX
+
+enum BitWiseOP {
+ BW_AND = 0,
+ BW_OR = 2, //like ADD
+ BW_XOR = 3,
+ BW_SHIFTL = 4,
+ BW_SHIFTR = 5,
+ BW_USHIFTR = 6
+};
+
+enum CmpOP {
+ CMP_G = 0,
+ CMP_GE = 2, //like ADD
+ CMP_L = 3,
+ CMP_LE = 4
+};
+enum SQOpcode
+{
+ _OP_LINE= 0x00,
+ _OP_LOAD= 0x01,
+ _OP_TAILCALL= 0x02,
+ _OP_CALL= 0x03,
+ _OP_PREPCALL= 0x04,
+ _OP_PREPCALLK= 0x05,
+ _OP_GETK= 0x06,
+ _OP_MOVE= 0x07,
+ _OP_NEWSLOT= 0x08,
+ _OP_DELETE= 0x09,
+ _OP_SET= 0x0A,
+ _OP_GET= 0x0B,
+ _OP_EQ= 0x0C,
+ _OP_NE= 0x0D,
+ _OP_ARITH= 0x0E,
+ _OP_BITW= 0x0F,
+ _OP_RETURN= 0x10,
+ _OP_LOADNULLS= 0x11,
+ _OP_LOADROOTTABLE= 0x12,
+ _OP_DMOVE= 0x13,
+ _OP_JMP= 0x14,
+ _OP_JNZ= 0x15,
+ _OP_JZ= 0x16,
+ _OP_LOADFREEVAR= 0x17,
+ _OP_VARGC= 0x18,
+ _OP_GETVARGV= 0x19,
+ _OP_NEWTABLE= 0x1A,
+ _OP_NEWARRAY= 0x1B,
+ _OP_APPENDARRAY= 0x1C,
+ _OP_GETPARENT= 0x1D,
+ _OP_COMPARITH= 0x1E,
+ _OP_COMPARITHL= 0x1F,
+ _OP_INC= 0x20,
+ _OP_INCL= 0x21,
+ _OP_PINC= 0x22,
+ _OP_PINCL= 0x23,
+ _OP_CMP= 0x24,
+ _OP_EXISTS= 0x25,
+ _OP_INSTANCEOF= 0x26,
+ _OP_AND= 0x27,
+ _OP_OR= 0x28,
+ _OP_NEG= 0x29,
+ _OP_NOT= 0x2A,
+ _OP_BWNOT= 0x2B,
+ _OP_CLOSURE= 0x2C,
+ _OP_YIELD= 0x2D,
+ _OP_RESUME= 0x2E,
+ _OP_FOREACH= 0x2F,
+ _OP_DELEGATE= 0x30,
+ _OP_CLONE= 0x31,
+ _OP_TYPEOF= 0x32,
+ _OP_PUSHTRAP= 0x33,
+ _OP_POPTRAP= 0x34,
+ _OP_THROW= 0x35,
+ _OP_CLASS= 0x36,
+ _OP_NEWSLOTA= 0x37,
+ _OP_LOADBOOL= 0x38
+};
+struct SQInstructionDesc {
+ const SQChar *name;
+};
+
+struct SQInstruction
+{
+ SQInstruction(){};
+ SQInstruction(SQOpcode _op,int a0=0,int a1=0,int a2=0,int a3=0)
+ { op = _op;
+ _arg0 = a0;_arg1 = a1;
+ _arg2 = a2;_arg3 = a3;
+ }
+
+
+ unsigned int _arg1;
+ unsigned char op;
+ unsigned char _arg0;
+ unsigned char _arg2;
+ unsigned char _arg3;
+};
+
+#include "squtils.h"
+typedef sqvector<SQInstruction> SQInstructionVec;
+
+#endif // _SQOPCODES_H_
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQPCHEADER_H_\r
-#define _SQPCHEADER_H_\r
-\r
-#if defined(_MSC_VER) && defined(_DEBUG)\r
-#include <crtdbg.h>\r
-#endif \r
-\r
-#include <stdio.h>\r
-#include <stdlib.h>\r
-#include <string.h>\r
-#include <assert.h>\r
-#include <new>\r
-//squirrel stuff\r
-#include <squirrel.h>\r
-#include "sqobject.h"\r
-#include "sqstate.h"\r
-\r
-#endif //_SQPCHEADER_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQPCHEADER_H_
+#define _SQPCHEADER_H_
+
+#if defined(_MSC_VER) && defined(_DEBUG)
+#include <crtdbg.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <new>
+//squirrel stuff
+#include <squirrel.h>
+#include "sqobject.h"
+#include "sqstate.h"
+
+#endif //_SQPCHEADER_H_
-/*\r
- see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include "sqopcodes.h"\r
-#include "sqvm.h"\r
-#include "sqfuncproto.h"\r
-#include "sqclosure.h"\r
-#include "sqstring.h"\r
-#include "sqtable.h"\r
-#include "sqarray.h"\r
-#include "squserdata.h"\r
-#include "sqclass.h"\r
-\r
-SQObjectPtr _null_;\r
-SQObjectPtr _true_(true);\r
-SQObjectPtr _false_(false);\r
-SQObjectPtr _one_(1);\r
-SQObjectPtr _minusone_(-1);\r
-\r
-SQSharedState::SQSharedState()\r
-{\r
- _compilererrorhandler = NULL;\r
- _printfunc = NULL;\r
- _debuginfo = false;\r
-}\r
-\r
-#define newsysstring(s) { \\r
- _systemstrings->push_back(SQString::Create(this,s)); \\r
- }\r
-\r
-#define newmetamethod(s) { \\r
- _metamethods->push_back(SQString::Create(this,s)); \\r
- _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \\r
- }\r
-\r
-bool CompileTypemask(SQIntVec &res,const SQChar *typemask)\r
-{\r
- int i = 0;\r
- \r
- int mask = 0;\r
- while(typemask[i] != 0) {\r
- \r
- switch(typemask[i]){\r
- case 'i': mask |= _RT_INTEGER; break;\r
- case 'f': mask |= _RT_FLOAT; break;\r
- case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break;\r
- case 's': mask |= _RT_STRING; break;\r
- case 't': mask |= _RT_TABLE; break;\r
- case 'a': mask |= _RT_ARRAY; break;\r
- case 'u': mask |= _RT_USERDATA; break;\r
- case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break;\r
- case 'b': mask |= _RT_BOOL; break;\r
- case 'g': mask |= _RT_GENERATOR; break;\r
- case 'p': mask |= _RT_USERPOINTER; break;\r
- case 'v': mask |= _RT_THREAD; break;\r
- case 'x': mask |= _RT_INSTANCE; break;\r
- case 'y': mask |= _RT_CLASS; break;\r
- case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue;\r
- case ' ': i++; continue; //ignores spaces\r
- default:\r
- return false;\r
- }\r
- i++;\r
- if(typemask[i] == '|') { \r
- i++; \r
- if(typemask[i] == 0)\r
- return false;\r
- continue; \r
- }\r
- res.push_back(mask);\r
- mask = 0;\r
- \r
- }\r
- return true;\r
-}\r
-\r
-SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)\r
-{\r
- int i=0;\r
- SQTable *t=SQTable::Create(ss,0);\r
- while(funcz[i].name!=0){\r
- SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f);\r
- nc->_nparamscheck = funcz[i].nparamscheck;\r
- nc->_name = SQString::Create(ss,funcz[i].name);\r
- if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask))\r
- return NULL;\r
- t->NewSlot(SQString::Create(ss,funcz[i].name),nc);\r
- i++;\r
- }\r
- return t;\r
-}\r
-\r
-void SQSharedState::Init()\r
-{ \r
- _scratchpad=NULL;\r
- _scratchpadsize=0;\r
-#ifndef NO_GARBAGE_COLLECTOR\r
- _gc_chain=NULL;\r
-#endif\r
- sq_new(_stringtable,StringTable);\r
- sq_new(_metamethods,SQObjectPtrVec);\r
- sq_new(_systemstrings,SQObjectPtrVec);\r
- sq_new(_types,SQObjectPtrVec);\r
- _metamethodsmap = SQTable::Create(this,MT_LAST-1);\r
- //adding type strings to avoid memory trashing\r
- //types names\r
- newsysstring(_SC("null"));\r
- newsysstring(_SC("table"));\r
- newsysstring(_SC("array"));\r
- newsysstring(_SC("closure"));\r
- newsysstring(_SC("string"));\r
- newsysstring(_SC("userdata"));\r
- newsysstring(_SC("integer"));\r
- newsysstring(_SC("float"));\r
- newsysstring(_SC("userpointer"));\r
- newsysstring(_SC("function"));\r
- newsysstring(_SC("generator"));\r
- newsysstring(_SC("thread"));\r
- newsysstring(_SC("class"));\r
- newsysstring(_SC("instance"));\r
- newsysstring(_SC("bool"));\r
- //meta methods\r
- newmetamethod(MM_ADD);\r
- newmetamethod(MM_SUB);\r
- newmetamethod(MM_MUL);\r
- newmetamethod(MM_DIV);\r
- newmetamethod(MM_UNM);\r
- newmetamethod(MM_MODULO);\r
- newmetamethod(MM_SET);\r
- newmetamethod(MM_GET);\r
- newmetamethod(MM_TYPEOF);\r
- newmetamethod(MM_NEXTI);\r
- newmetamethod(MM_CMP);\r
- newmetamethod(MM_CALL);\r
- newmetamethod(MM_CLONED);\r
- newmetamethod(MM_NEWSLOT);\r
- newmetamethod(MM_DELSLOT);\r
-\r
- _constructoridx = SQString::Create(this,_SC("constructor"));\r
- _refs_table = SQTable::Create(this,0);\r
- _registry = SQTable::Create(this,0);\r
- _table_default_delegate=CreateDefaultDelegate(this,_table_default_delegate_funcz);\r
- _array_default_delegate=CreateDefaultDelegate(this,_array_default_delegate_funcz);\r
- _string_default_delegate=CreateDefaultDelegate(this,_string_default_delegate_funcz);\r
- _number_default_delegate=CreateDefaultDelegate(this,_number_default_delegate_funcz);\r
- _closure_default_delegate=CreateDefaultDelegate(this,_closure_default_delegate_funcz);\r
- _generator_default_delegate=CreateDefaultDelegate(this,_generator_default_delegate_funcz);\r
- _thread_default_delegate=CreateDefaultDelegate(this,_thread_default_delegate_funcz);\r
- _class_default_delegate=CreateDefaultDelegate(this,_class_default_delegate_funcz);\r
- _instance_default_delegate=CreateDefaultDelegate(this,_instance_default_delegate_funcz);\r
-\r
-}\r
-\r
-SQSharedState::~SQSharedState()\r
-{\r
- _constructoridx = _null_;\r
- _table(_refs_table)->Finalize();\r
- _table(_registry)->Finalize();\r
- _table(_metamethodsmap)->Finalize();\r
- _refs_table = _null_;\r
- _registry = _null_;\r
- _metamethodsmap = _null_;\r
- while(!_systemstrings->empty()){\r
- _systemstrings->back()=_null_;\r
- _systemstrings->pop_back();\r
- }\r
- _thread(_root_vm)->Finalize();\r
- _root_vm = _null_;\r
- _table_default_delegate=_null_;\r
- _array_default_delegate=_null_;\r
- _string_default_delegate=_null_;\r
- _number_default_delegate=_null_;\r
- _closure_default_delegate=_null_;\r
- _generator_default_delegate=_null_;\r
- _thread_default_delegate=_null_;\r
- _class_default_delegate=_null_;\r
- _instance_default_delegate=_null_;\r
- \r
-#ifndef NO_GARBAGE_COLLECTOR\r
- \r
- \r
- SQCollectable *t=_gc_chain;\r
- SQCollectable *nx=NULL;\r
- while(t){\r
- t->_uiRef++;\r
- t->Finalize();\r
- nx=t->_next;\r
- if(--t->_uiRef==0)\r
- t->Release();\r
- t=nx;\r
- }\r
- assert(_gc_chain==NULL); //just to proove a theory\r
- while(_gc_chain){\r
- _gc_chain->_uiRef++;\r
- _gc_chain->Release();\r
- }\r
-#endif\r
- sq_delete(_types,SQObjectPtrVec);\r
- sq_delete(_systemstrings,SQObjectPtrVec);\r
- sq_delete(_metamethods,SQObjectPtrVec);\r
- sq_delete(_stringtable,StringTable);\r
- if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);\r
-}\r
-\r
-\r
-SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name)\r
-{\r
- if(type(name) != OT_STRING)\r
- return -1;\r
- SQObjectPtr ret;\r
- if(_table(_metamethodsmap)->Get(name,ret)) {\r
- return _integer(ret);\r
- }\r
- return -1;\r
-}\r
-\r
-#ifndef NO_GARBAGE_COLLECTOR\r
-\r
-void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)\r
-{\r
- switch(type(o)){\r
- case OT_TABLE:_table(o)->Mark(chain);break;\r
- case OT_ARRAY:_array(o)->Mark(chain);break;\r
- case OT_USERDATA:_userdata(o)->Mark(chain);break;\r
- case OT_CLOSURE:_closure(o)->Mark(chain);break;\r
- case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break;\r
- case OT_GENERATOR:_generator(o)->Mark(chain);break;\r
- case OT_THREAD:_thread(o)->Mark(chain);break;\r
- case OT_CLASS:_class(o)->Mark(chain);break;\r
- case OT_INSTANCE:_instance(o)->Mark(chain);break;\r
- }\r
-}\r
-\r
-\r
-int SQSharedState::CollectGarbage(SQVM *vm)\r
-{\r
- int n=0;\r
- SQCollectable *tchain=NULL;\r
- SQVM *vms=_thread(_root_vm);\r
- \r
- vms->Mark(&tchain);\r
- int x = _table(_thread(_root_vm)->_roottable)->CountUsed();\r
- MarkObject(_refs_table,&tchain);\r
- MarkObject(_registry,&tchain);\r
- MarkObject(_metamethodsmap,&tchain);\r
- MarkObject(_table_default_delegate,&tchain);\r
- MarkObject(_array_default_delegate,&tchain);\r
- MarkObject(_string_default_delegate,&tchain);\r
- MarkObject(_number_default_delegate,&tchain);\r
- MarkObject(_generator_default_delegate,&tchain);\r
- MarkObject(_thread_default_delegate,&tchain);\r
- MarkObject(_closure_default_delegate,&tchain);\r
- MarkObject(_class_default_delegate,&tchain);\r
- MarkObject(_instance_default_delegate,&tchain);\r
- \r
- SQCollectable *t=_gc_chain;\r
- SQCollectable *nx=NULL;\r
- while(t){\r
- t->_uiRef++;\r
- t->Finalize();\r
- nx=t->_next;\r
- if(--t->_uiRef==0)\r
- t->Release();\r
- t=nx;\r
- n++;\r
- }\r
-\r
- t=tchain;\r
- while(t){\r
- t->UnMark();\r
- t=t->_next;\r
- }\r
- _gc_chain=tchain;\r
- int z = _table(_thread(_root_vm)->_roottable)->CountUsed();\r
- assert(z == x);\r
- return n;\r
-}\r
-#endif\r
-\r
-#ifndef NO_GARBAGE_COLLECTOR\r
-void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)\r
-{\r
- c->_prev=NULL;\r
- c->_next=*chain;\r
- if(*chain) (*chain)->_prev=c;\r
- *chain=c;\r
-}\r
-\r
-void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)\r
-{\r
- if(c->_prev) c->_prev->_next=c->_next;\r
- else *chain=c->_next;\r
- if(c->_next)\r
- c->_next->_prev=c->_prev;\r
- c->_next=NULL;\r
- c->_prev=NULL;\r
-}\r
-#endif\r
-\r
-SQChar* SQSharedState::GetScratchPad(int size)\r
-{\r
- int newsize;\r
- if(size>0){\r
- if(_scratchpadsize<size){\r
- newsize=size+(size>>1);\r
- _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);\r
- _scratchpadsize=newsize;\r
-\r
- }else if(_scratchpadsize>=(size<<5)){\r
- newsize=_scratchpadsize>>1;\r
- _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);\r
- _scratchpadsize=newsize;\r
- }\r
- }\r
- return _scratchpad;\r
-}\r
-\r
-//////////////////////////////////////////////////////////////////////////\r
-//StringTable\r
-/*\r
-* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)\r
-* http://www.lua.org/copyright.html#4\r
-* http://www.lua.org/source/4.0.1/src_lstring.c.html\r
-*/\r
-\r
-int SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)\r
-{\r
- int idx = (int)TranslateIndex(refpos);\r
- while(idx < _len){\r
- outkey = (SQInteger)idx;\r
- outval = SQInteger(_val[idx]);\r
- //return idx for the next iteration\r
- return ++idx;\r
- }\r
- //nothing to iterate anymore\r
- return -1;\r
-}\r
-\r
-StringTable::StringTable()\r
-{\r
- AllocNodes(4);\r
- _slotused = 0;\r
-}\r
-\r
-StringTable::~StringTable()\r
-{\r
- SQ_FREE(_strings,sizeof(SQString*)*_numofslots);\r
- _strings=NULL;\r
-}\r
-\r
-void StringTable::AllocNodes(int size)\r
-{\r
- _numofslots=size;\r
- //_slotused=0;\r
- _strings=(SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);\r
- memset(_strings,0,sizeof(SQString*)*_numofslots);\r
-}\r
-\r
-SQString *StringTable::Add(const SQChar *news,int len)\r
-{\r
- if(len<0)\r
- len=scstrlen(news);\r
- unsigned int h=::_hashstr(news,len)&(_numofslots-1);\r
- SQString *s;\r
- for (s = _strings[h]; s; s = s->_next){\r
- if(s->_len == len && (!memcmp(news,s->_val,rsl(len))))\r
- return s; //found\r
- }\r
-\r
- SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString));\r
- new (t) SQString;\r
- memcpy(t->_val,news,rsl(len));\r
- t->_val[len]=_SC('\0');\r
- t->_len=len;\r
- t->_hash=::_hashstr(news,len);\r
- t->_next=_strings[h];\r
- t->_uiRef=0;\r
- _strings[h]=t;\r
- _slotused++;\r
- if (_slotused > _numofslots) /* too crowded? */\r
- Resize(_numofslots*2);\r
- return t;\r
-}\r
-\r
-void StringTable::Resize(int size)\r
-{\r
- int oldsize=_numofslots;\r
- SQString **oldtable=_strings;\r
- AllocNodes(size);\r
- for (int i=0; i<oldsize; i++){\r
- SQString *p = oldtable[i];\r
- while(p){\r
- SQString *next = p->_next;\r
- unsigned int h=p->_hash&(_numofslots-1);\r
- p->_next=_strings[h];\r
- _strings[h] = p;\r
- p=next;\r
- }\r
- }\r
- SQ_FREE(oldtable,oldsize*sizeof(SQString*));\r
-}\r
-\r
-void StringTable::Remove(SQString *bs)\r
-{\r
- SQString *s;\r
- SQString *prev=NULL;\r
- unsigned int h=bs->_hash&(_numofslots-1);\r
- \r
- for (s = _strings[h]; s; ){\r
- if(s == bs){\r
- if(prev)\r
- prev->_next = s->_next;\r
- else\r
- _strings[h] = s->_next;\r
- _slotused--;\r
- int slen=s->_len;\r
- s->~SQString();\r
- SQ_FREE(s,sizeof(SQString)+rsl(slen));\r
- return;\r
- }\r
- prev = s;\r
- s = s->_next;\r
- }\r
- assert(0);//if this fail something is wrong\r
-}\r
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqopcodes.h"
+#include "sqvm.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+#include "sqstring.h"
+#include "sqtable.h"
+#include "sqarray.h"
+#include "squserdata.h"
+#include "sqclass.h"
+
+SQObjectPtr _null_;
+SQObjectPtr _true_(true);
+SQObjectPtr _false_(false);
+SQObjectPtr _one_(1);
+SQObjectPtr _minusone_(-1);
+
+SQSharedState::SQSharedState()
+{
+ _compilererrorhandler = NULL;
+ _printfunc = NULL;
+ _debuginfo = false;
+}
+
+#define newsysstring(s) { \
+ _systemstrings->push_back(SQString::Create(this,s)); \
+ }
+
+#define newmetamethod(s) { \
+ _metamethods->push_back(SQString::Create(this,s)); \
+ _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \
+ }
+
+bool CompileTypemask(SQIntVec &res,const SQChar *typemask)
+{
+ int i = 0;
+
+ int mask = 0;
+ while(typemask[i] != 0) {
+
+ switch(typemask[i]){
+ case 'i': mask |= _RT_INTEGER; break;
+ case 'f': mask |= _RT_FLOAT; break;
+ case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break;
+ case 's': mask |= _RT_STRING; break;
+ case 't': mask |= _RT_TABLE; break;
+ case 'a': mask |= _RT_ARRAY; break;
+ case 'u': mask |= _RT_USERDATA; break;
+ case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break;
+ case 'b': mask |= _RT_BOOL; break;
+ case 'g': mask |= _RT_GENERATOR; break;
+ case 'p': mask |= _RT_USERPOINTER; break;
+ case 'v': mask |= _RT_THREAD; break;
+ case 'x': mask |= _RT_INSTANCE; break;
+ case 'y': mask |= _RT_CLASS; break;
+ case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue;
+ case ' ': i++; continue; //ignores spaces
+ default:
+ return false;
+ }
+ i++;
+ if(typemask[i] == '|') {
+ i++;
+ if(typemask[i] == 0)
+ return false;
+ continue;
+ }
+ res.push_back(mask);
+ mask = 0;
+
+ }
+ return true;
+}
+
+SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)
+{
+ int i=0;
+ SQTable *t=SQTable::Create(ss,0);
+ while(funcz[i].name!=0){
+ SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f);
+ nc->_nparamscheck = funcz[i].nparamscheck;
+ nc->_name = SQString::Create(ss,funcz[i].name);
+ if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask))
+ return NULL;
+ t->NewSlot(SQString::Create(ss,funcz[i].name),nc);
+ i++;
+ }
+ return t;
+}
+
+void SQSharedState::Init()
+{
+ _scratchpad=NULL;
+ _scratchpadsize=0;
+#ifndef NO_GARBAGE_COLLECTOR
+ _gc_chain=NULL;
+#endif
+ sq_new(_stringtable,StringTable);
+ sq_new(_metamethods,SQObjectPtrVec);
+ sq_new(_systemstrings,SQObjectPtrVec);
+ sq_new(_types,SQObjectPtrVec);
+ _metamethodsmap = SQTable::Create(this,MT_LAST-1);
+ //adding type strings to avoid memory trashing
+ //types names
+ newsysstring(_SC("null"));
+ newsysstring(_SC("table"));
+ newsysstring(_SC("array"));
+ newsysstring(_SC("closure"));
+ newsysstring(_SC("string"));
+ newsysstring(_SC("userdata"));
+ newsysstring(_SC("integer"));
+ newsysstring(_SC("float"));
+ newsysstring(_SC("userpointer"));
+ newsysstring(_SC("function"));
+ newsysstring(_SC("generator"));
+ newsysstring(_SC("thread"));
+ newsysstring(_SC("class"));
+ newsysstring(_SC("instance"));
+ newsysstring(_SC("bool"));
+ //meta methods
+ newmetamethod(MM_ADD);
+ newmetamethod(MM_SUB);
+ newmetamethod(MM_MUL);
+ newmetamethod(MM_DIV);
+ newmetamethod(MM_UNM);
+ newmetamethod(MM_MODULO);
+ newmetamethod(MM_SET);
+ newmetamethod(MM_GET);
+ newmetamethod(MM_TYPEOF);
+ newmetamethod(MM_NEXTI);
+ newmetamethod(MM_CMP);
+ newmetamethod(MM_CALL);
+ newmetamethod(MM_CLONED);
+ newmetamethod(MM_NEWSLOT);
+ newmetamethod(MM_DELSLOT);
+
+ _constructoridx = SQString::Create(this,_SC("constructor"));
+ _refs_table = SQTable::Create(this,0);
+ _registry = SQTable::Create(this,0);
+ _table_default_delegate=CreateDefaultDelegate(this,_table_default_delegate_funcz);
+ _array_default_delegate=CreateDefaultDelegate(this,_array_default_delegate_funcz);
+ _string_default_delegate=CreateDefaultDelegate(this,_string_default_delegate_funcz);
+ _number_default_delegate=CreateDefaultDelegate(this,_number_default_delegate_funcz);
+ _closure_default_delegate=CreateDefaultDelegate(this,_closure_default_delegate_funcz);
+ _generator_default_delegate=CreateDefaultDelegate(this,_generator_default_delegate_funcz);
+ _thread_default_delegate=CreateDefaultDelegate(this,_thread_default_delegate_funcz);
+ _class_default_delegate=CreateDefaultDelegate(this,_class_default_delegate_funcz);
+ _instance_default_delegate=CreateDefaultDelegate(this,_instance_default_delegate_funcz);
+
+}
+
+SQSharedState::~SQSharedState()
+{
+ _constructoridx = _null_;
+ _table(_refs_table)->Finalize();
+ _table(_registry)->Finalize();
+ _table(_metamethodsmap)->Finalize();
+ _refs_table = _null_;
+ _registry = _null_;
+ _metamethodsmap = _null_;
+ while(!_systemstrings->empty()){
+ _systemstrings->back()=_null_;
+ _systemstrings->pop_back();
+ }
+ _thread(_root_vm)->Finalize();
+ _root_vm = _null_;
+ _table_default_delegate=_null_;
+ _array_default_delegate=_null_;
+ _string_default_delegate=_null_;
+ _number_default_delegate=_null_;
+ _closure_default_delegate=_null_;
+ _generator_default_delegate=_null_;
+ _thread_default_delegate=_null_;
+ _class_default_delegate=_null_;
+ _instance_default_delegate=_null_;
+
+#ifndef NO_GARBAGE_COLLECTOR
+
+
+ SQCollectable *t=_gc_chain;
+ SQCollectable *nx=NULL;
+ while(t){
+ t->_uiRef++;
+ t->Finalize();
+ nx=t->_next;
+ if(--t->_uiRef==0)
+ t->Release();
+ t=nx;
+ }
+ assert(_gc_chain==NULL); //just to proove a theory
+ while(_gc_chain){
+ _gc_chain->_uiRef++;
+ _gc_chain->Release();
+ }
+#endif
+ sq_delete(_types,SQObjectPtrVec);
+ sq_delete(_systemstrings,SQObjectPtrVec);
+ sq_delete(_metamethods,SQObjectPtrVec);
+ sq_delete(_stringtable,StringTable);
+ if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);
+}
+
+
+SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name)
+{
+ if(type(name) != OT_STRING)
+ return -1;
+ SQObjectPtr ret;
+ if(_table(_metamethodsmap)->Get(name,ret)) {
+ return _integer(ret);
+ }
+ return -1;
+}
+
+#ifndef NO_GARBAGE_COLLECTOR
+
+void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)
+{
+ switch(type(o)){
+ case OT_TABLE:_table(o)->Mark(chain);break;
+ case OT_ARRAY:_array(o)->Mark(chain);break;
+ case OT_USERDATA:_userdata(o)->Mark(chain);break;
+ case OT_CLOSURE:_closure(o)->Mark(chain);break;
+ case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break;
+ case OT_GENERATOR:_generator(o)->Mark(chain);break;
+ case OT_THREAD:_thread(o)->Mark(chain);break;
+ case OT_CLASS:_class(o)->Mark(chain);break;
+ case OT_INSTANCE:_instance(o)->Mark(chain);break;
+ default: break;
+ }
+}
+
+
+int SQSharedState::CollectGarbage(SQVM *vm)
+{
+ (void) vm;
+ int n=0;
+ SQCollectable *tchain=NULL;
+ SQVM *vms=_thread(_root_vm);
+
+ vms->Mark(&tchain);
+ int x = _table(_thread(_root_vm)->_roottable)->CountUsed();
+ MarkObject(_refs_table,&tchain);
+ MarkObject(_registry,&tchain);
+ MarkObject(_metamethodsmap,&tchain);
+ MarkObject(_table_default_delegate,&tchain);
+ MarkObject(_array_default_delegate,&tchain);
+ MarkObject(_string_default_delegate,&tchain);
+ MarkObject(_number_default_delegate,&tchain);
+ MarkObject(_generator_default_delegate,&tchain);
+ MarkObject(_thread_default_delegate,&tchain);
+ MarkObject(_closure_default_delegate,&tchain);
+ MarkObject(_class_default_delegate,&tchain);
+ MarkObject(_instance_default_delegate,&tchain);
+
+ SQCollectable *t=_gc_chain;
+ SQCollectable *nx=NULL;
+ while(t){
+ t->_uiRef++;
+ t->Finalize();
+ nx=t->_next;
+ if(--t->_uiRef==0)
+ t->Release();
+ t=nx;
+ n++;
+ }
+
+ t=tchain;
+ while(t){
+ t->UnMark();
+ t=t->_next;
+ }
+ _gc_chain=tchain;
+ int z = _table(_thread(_root_vm)->_roottable)->CountUsed();
+ assert(z == x);
+ return n;
+}
+#endif
+
+#ifndef NO_GARBAGE_COLLECTOR
+void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)
+{
+ c->_prev=NULL;
+ c->_next=*chain;
+ if(*chain) (*chain)->_prev=c;
+ *chain=c;
+}
+
+void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)
+{
+ if(c->_prev) c->_prev->_next=c->_next;
+ else *chain=c->_next;
+ if(c->_next)
+ c->_next->_prev=c->_prev;
+ c->_next=NULL;
+ c->_prev=NULL;
+}
+#endif
+
+SQChar* SQSharedState::GetScratchPad(int size)
+{
+ int newsize;
+ if(size>0){
+ if(_scratchpadsize<size){
+ newsize=size+(size>>1);
+ _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
+ _scratchpadsize=newsize;
+
+ }else if(_scratchpadsize>=(size<<5)){
+ newsize=_scratchpadsize>>1;
+ _scratchpad=(SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
+ _scratchpadsize=newsize;
+ }
+ }
+ return _scratchpad;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//StringTable
+/*
+* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
+* http://www.lua.org/copyright.html#4
+* http://www.lua.org/source/4.0.1/src_lstring.c.html
+*/
+
+int SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
+{
+ int idx = (int)TranslateIndex(refpos);
+ while(idx < _len){
+ outkey = (SQInteger)idx;
+ outval = SQInteger(_val[idx]);
+ //return idx for the next iteration
+ return ++idx;
+ }
+ //nothing to iterate anymore
+ return -1;
+}
+
+StringTable::StringTable()
+{
+ AllocNodes(4);
+ _slotused = 0;
+}
+
+StringTable::~StringTable()
+{
+ SQ_FREE(_strings,sizeof(SQString*)*_numofslots);
+ _strings=NULL;
+}
+
+void StringTable::AllocNodes(int size)
+{
+ _numofslots=size;
+ //_slotused=0;
+ _strings=(SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
+ memset(_strings,0,sizeof(SQString*)*_numofslots);
+}
+
+SQString *StringTable::Add(const SQChar *news,int len)
+{
+ if(len<0)
+ len=scstrlen(news);
+ unsigned int h=::_hashstr(news,len)&(_numofslots-1);
+ SQString *s;
+ for (s = _strings[h]; s; s = s->_next){
+ if(s->_len == len && (!memcmp(news,s->_val,rsl(len))))
+ return s; //found
+ }
+
+ SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString));
+ new (t) SQString;
+ memcpy(t->_val,news,rsl(len));
+ t->_val[len]=_SC('\0');
+ t->_len=len;
+ t->_hash=::_hashstr(news,len);
+ t->_next=_strings[h];
+ t->_uiRef=0;
+ _strings[h]=t;
+ _slotused++;
+ if (_slotused > _numofslots) /* too crowded? */
+ Resize(_numofslots*2);
+ return t;
+}
+
+void StringTable::Resize(int size)
+{
+ int oldsize=_numofslots;
+ SQString **oldtable=_strings;
+ AllocNodes(size);
+ for (int i=0; i<oldsize; i++){
+ SQString *p = oldtable[i];
+ while(p){
+ SQString *next = p->_next;
+ unsigned int h=p->_hash&(_numofslots-1);
+ p->_next=_strings[h];
+ _strings[h] = p;
+ p=next;
+ }
+ }
+ SQ_FREE(oldtable,oldsize*sizeof(SQString*));
+}
+
+void StringTable::Remove(SQString *bs)
+{
+ SQString *s;
+ SQString *prev=NULL;
+ unsigned int h=bs->_hash&(_numofslots-1);
+
+ for (s = _strings[h]; s; ){
+ if(s == bs){
+ if(prev)
+ prev->_next = s->_next;
+ else
+ _strings[h] = s->_next;
+ _slotused--;
+ int slen=s->_len;
+ s->~SQString();
+ SQ_FREE(s,sizeof(SQString)+rsl(slen));
+ return;
+ }
+ prev = s;
+ s = s->_next;
+ }
+ assert(0);//if this fail something is wrong
+}
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQSTATE_H_\r
-#define _SQSTATE_H_\r
-\r
-#include "squtils.h"\r
-#include "sqobject.h"\r
-struct SQString;\r
-struct SQTable;\r
-//max number of character for a printed number\r
-#define NUMBER_MAX_CHAR 50\r
-\r
-struct StringTable\r
-{\r
- StringTable();\r
- ~StringTable();\r
- //return a string obj if exists\r
- //so when there is a table query, if the string doesn't exists in the global state\r
- //it cannot be in a table so the result will be always null\r
- //SQString *get(const SQChar *news);\r
- SQString *Add(const SQChar *,int len);\r
- void Remove(SQString *);\r
-private:\r
- void Resize(int size);\r
- void AllocNodes(int size);\r
- SQString **_strings;\r
- unsigned int _numofslots;\r
- unsigned int _slotused;\r
-};\r
-\r
-#define ADD_STRING(ss,str,len) ss->_stringtable->Add(str,len)\r
-#define REMOVE_STRING(ss,bstr) ss->_stringtable->Remove(bstr)\r
-\r
-struct SQObjectPtr;\r
-\r
-struct SQSharedState\r
-{\r
- SQSharedState();\r
- ~SQSharedState();\r
- void Init();\r
-public:\r
- SQChar* GetScratchPad(int size);\r
- SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name);\r
-#ifndef NO_GARBAGE_COLLECTOR\r
- int CollectGarbage(SQVM *vm); \r
- static void MarkObject(SQObjectPtr &o,SQCollectable **chain);\r
-#endif\r
- SQObjectPtrVec *_metamethods;\r
- SQObjectPtr _metamethodsmap;\r
- SQObjectPtrVec *_systemstrings;\r
- SQObjectPtrVec *_types;\r
- StringTable *_stringtable;\r
- SQObjectPtr _refs_table;\r
- SQObjectPtr _registry;\r
- SQObjectPtr _constructoridx;\r
-#ifndef NO_GARBAGE_COLLECTOR\r
- SQCollectable *_gc_chain;\r
-#endif\r
- SQObjectPtr _root_vm;\r
- SQObjectPtr _table_default_delegate;\r
- static SQRegFunction _table_default_delegate_funcz[];\r
- SQObjectPtr _array_default_delegate;\r
- static SQRegFunction _array_default_delegate_funcz[];\r
- SQObjectPtr _string_default_delegate;\r
- static SQRegFunction _string_default_delegate_funcz[];\r
- SQObjectPtr _number_default_delegate;\r
- static SQRegFunction _number_default_delegate_funcz[];\r
- SQObjectPtr _generator_default_delegate;\r
- static SQRegFunction _generator_default_delegate_funcz[];\r
- SQObjectPtr _closure_default_delegate;\r
- static SQRegFunction _closure_default_delegate_funcz[];\r
- SQObjectPtr _thread_default_delegate;\r
- static SQRegFunction _thread_default_delegate_funcz[];\r
- SQObjectPtr _class_default_delegate;\r
- static SQRegFunction _class_default_delegate_funcz[];\r
- SQObjectPtr _instance_default_delegate;\r
- static SQRegFunction _instance_default_delegate_funcz[];\r
- \r
- SQCOMPILERERROR _compilererrorhandler;\r
- SQPRINTFUNCTION _printfunc;\r
- bool _debuginfo;\r
-private:\r
- SQChar *_scratchpad;\r
- int _scratchpadsize;\r
-};\r
-\r
-#define _sp(s) (_sharedstate->GetScratchPad(s))\r
-#define _spval (_sharedstate->GetScratchPad(-1))\r
-\r
-#define _table_ddel _table(_sharedstate->_table_default_delegate) \r
-#define _array_ddel _table(_sharedstate->_array_default_delegate) \r
-#define _string_ddel _table(_sharedstate->_string_default_delegate) \r
-#define _number_ddel _table(_sharedstate->_number_default_delegate) \r
-#define _generator_ddel _table(_sharedstate->_generator_default_delegate) \r
-#define _closure_ddel _table(_sharedstate->_closure_default_delegate) \r
-#define _thread_ddel _table(_sharedstate->_thread_default_delegate) \r
-#define _class_ddel _table(_sharedstate->_class_default_delegate) \r
-#define _instance_ddel _table(_sharedstate->_instance_default_delegate) \r
-\r
-#ifdef SQUNICODE //rsl REAL STRING LEN\r
-#define rsl(l) ((l)<<1)\r
-#else\r
-#define rsl(l) (l)\r
-#endif\r
-\r
-extern SQObjectPtr _null_;\r
-extern SQObjectPtr _true_;\r
-extern SQObjectPtr _false_;\r
-extern SQObjectPtr _one_;\r
-extern SQObjectPtr _minusone_;\r
-\r
-bool CompileTypemask(SQIntVec &res,const SQChar *typemask);\r
-\r
-void *sq_vm_malloc(unsigned int size);\r
-void *sq_vm_realloc(void *p,unsigned int oldsize,unsigned int size);\r
-void sq_vm_free(void *p,unsigned int size);\r
-#endif //_SQSTATE_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQSTATE_H_
+#define _SQSTATE_H_
+
+#include "squtils.h"
+#include "sqobject.h"
+struct SQString;
+struct SQTable;
+//max number of character for a printed number
+#define NUMBER_MAX_CHAR 50
+
+struct StringTable
+{
+ StringTable();
+ ~StringTable();
+ //return a string obj if exists
+ //so when there is a table query, if the string doesn't exists in the global state
+ //it cannot be in a table so the result will be always null
+ //SQString *get(const SQChar *news);
+ SQString *Add(const SQChar *,int len);
+ void Remove(SQString *);
+private:
+ void Resize(int size);
+ void AllocNodes(int size);
+ SQString **_strings;
+ unsigned int _numofslots;
+ unsigned int _slotused;
+};
+
+#define ADD_STRING(ss,str,len) ss->_stringtable->Add(str,len)
+#define REMOVE_STRING(ss,bstr) ss->_stringtable->Remove(bstr)
+
+struct SQObjectPtr;
+
+struct SQSharedState
+{
+ SQSharedState();
+ ~SQSharedState();
+ void Init();
+public:
+ SQChar* GetScratchPad(int size);
+ SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name);
+#ifndef NO_GARBAGE_COLLECTOR
+ int CollectGarbage(SQVM *vm);
+ static void MarkObject(SQObjectPtr &o,SQCollectable **chain);
+#endif
+ SQObjectPtrVec *_metamethods;
+ SQObjectPtr _metamethodsmap;
+ SQObjectPtrVec *_systemstrings;
+ SQObjectPtrVec *_types;
+ StringTable *_stringtable;
+ SQObjectPtr _refs_table;
+ SQObjectPtr _registry;
+ SQObjectPtr _constructoridx;
+#ifndef NO_GARBAGE_COLLECTOR
+ SQCollectable *_gc_chain;
+#endif
+ SQObjectPtr _root_vm;
+ SQObjectPtr _table_default_delegate;
+ static SQRegFunction _table_default_delegate_funcz[];
+ SQObjectPtr _array_default_delegate;
+ static SQRegFunction _array_default_delegate_funcz[];
+ SQObjectPtr _string_default_delegate;
+ static SQRegFunction _string_default_delegate_funcz[];
+ SQObjectPtr _number_default_delegate;
+ static SQRegFunction _number_default_delegate_funcz[];
+ SQObjectPtr _generator_default_delegate;
+ static SQRegFunction _generator_default_delegate_funcz[];
+ SQObjectPtr _closure_default_delegate;
+ static SQRegFunction _closure_default_delegate_funcz[];
+ SQObjectPtr _thread_default_delegate;
+ static SQRegFunction _thread_default_delegate_funcz[];
+ SQObjectPtr _class_default_delegate;
+ static SQRegFunction _class_default_delegate_funcz[];
+ SQObjectPtr _instance_default_delegate;
+ static SQRegFunction _instance_default_delegate_funcz[];
+
+ SQCOMPILERERROR _compilererrorhandler;
+ SQPRINTFUNCTION _printfunc;
+ bool _debuginfo;
+private:
+ SQChar *_scratchpad;
+ int _scratchpadsize;
+};
+
+#define _sp(s) (_sharedstate->GetScratchPad(s))
+#define _spval (_sharedstate->GetScratchPad(-1))
+
+#define _table_ddel _table(_sharedstate->_table_default_delegate)
+#define _array_ddel _table(_sharedstate->_array_default_delegate)
+#define _string_ddel _table(_sharedstate->_string_default_delegate)
+#define _number_ddel _table(_sharedstate->_number_default_delegate)
+#define _generator_ddel _table(_sharedstate->_generator_default_delegate)
+#define _closure_ddel _table(_sharedstate->_closure_default_delegate)
+#define _thread_ddel _table(_sharedstate->_thread_default_delegate)
+#define _class_ddel _table(_sharedstate->_class_default_delegate)
+#define _instance_ddel _table(_sharedstate->_instance_default_delegate)
+
+#ifdef SQUNICODE //rsl REAL STRING LEN
+#define rsl(l) ((l)<<1)
+#else
+#define rsl(l) (l)
+#endif
+
+extern SQObjectPtr _null_;
+extern SQObjectPtr _true_;
+extern SQObjectPtr _false_;
+extern SQObjectPtr _one_;
+extern SQObjectPtr _minusone_;
+
+bool CompileTypemask(SQIntVec &res,const SQChar *typemask);
+
+void *sq_vm_malloc(unsigned int size);
+void *sq_vm_realloc(void *p,unsigned int oldsize,unsigned int size);
+void sq_vm_free(void *p,unsigned int size);
+#endif //_SQSTATE_H_
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQSTRING_H_\r
-#define _SQSTRING_H_\r
-\r
-inline unsigned int _hashstr (const SQChar *s, size_t l)\r
-{\r
- unsigned int h = l; /* seed */\r
- size_t step = (l>>5)|1; /* if string is too long, don't hash all its chars */\r
- for (; l>=step; l-=step)\r
- h = h ^ ((h<<5)+(h>>2)+(unsigned short)*(s++));\r
- return h;\r
-}\r
-\r
-struct SQString : public SQRefCounted\r
-{\r
- SQString(){}\r
- ~SQString(){}\r
-public:\r
- static SQString *Create(SQSharedState *ss, const SQChar *, int len = -1 );\r
- int Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);\r
- void Release();\r
- SQSharedState *_sharedstate;\r
- SQString *_next; //chain for the string table\r
- int _len;\r
- int _hash;\r
- SQChar _val[1];\r
-};\r
-\r
-\r
-\r
-#endif //_SQSTRING_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQSTRING_H_
+#define _SQSTRING_H_
+
+inline unsigned int _hashstr (const SQChar *s, size_t l)
+{
+ unsigned int h = l; /* seed */
+ size_t step = (l>>5)|1; /* if string is too long, don't hash all its chars */
+ for (; l>=step; l-=step)
+ h = h ^ ((h<<5)+(h>>2)+(unsigned short)*(s++));
+ return h;
+}
+
+struct SQString : public SQRefCounted
+{
+ SQString(){}
+ ~SQString(){}
+public:
+ static SQString *Create(SQSharedState *ss, const SQChar *, int len = -1 );
+ int Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
+ void Release();
+ SQSharedState *_sharedstate;
+ SQString *_next; //chain for the string table
+ int _len;
+ int _hash;
+ SQChar _val[1];
+};
+
+
+
+#endif //_SQSTRING_H_
-/*\r
-see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include "sqvm.h"\r
-#include "sqtable.h"\r
-#include "sqfuncproto.h"\r
-#include "sqclosure.h"\r
-\r
-SQTable::SQTable(SQSharedState *ss,int nInitialSize)\r
-{\r
- int pow2size=MINPOWER2;\r
- while(nInitialSize>pow2size)pow2size=pow2size<<1;\r
- AllocNodes(pow2size);\r
- _uiRef = 0;\r
- _usednodes = 0;\r
- _delegate = NULL;\r
- INIT_CHAIN();\r
- ADD_TO_CHAIN(&_sharedstate->_gc_chain,this);\r
-}\r
-\r
-void SQTable::Remove(const SQObjectPtr &key)\r
-{\r
- _HashNode *n = _Get(key, HashKey(key) & (_numofnodes - 1));\r
- if (n) {\r
- n->val = n->key = _null_;\r
- _usednodes--;\r
- Rehash(false);\r
- }\r
-}\r
-\r
-void SQTable::AllocNodes(int nSize)\r
-{\r
- _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize);\r
- for(int i=0;i<nSize;i++){\r
- new (&nodes[i]) _HashNode;\r
- nodes[i].next=NULL;\r
- }\r
- _numofnodes=nSize;\r
- _nodes=nodes;\r
- _firstfree=&_nodes[_numofnodes-1];\r
-}\r
-\r
-int SQTable::CountUsed()\r
-{\r
- /*int n=0;\r
- for(int i=0;i<_numofnodes;i++){\r
- if(type(_nodes[i].key)!=OT_NULL) n++;\r
- }*/\r
- return _usednodes;\r
-}\r
-\r
-void SQTable::Rehash(bool force)\r
-{\r
- int oldsize=_numofnodes;\r
- //prevent problems with the integer division\r
- if(oldsize<4)oldsize=4;\r
- _HashNode *nold=_nodes;\r
- int nelems=CountUsed();\r
- if (nelems >= oldsize-oldsize/4) /* using more than 3/4? */\r
- AllocNodes(oldsize*2);\r
- else if (nelems <= oldsize/4 && /* less than 1/4? */\r
- oldsize > MINPOWER2)\r
- AllocNodes(oldsize/2);\r
- else if(force)\r
- AllocNodes(oldsize);\r
- else\r
- return;\r
- _usednodes = 0;\r
- for (int i=0; i<oldsize; i++) {\r
- _HashNode *old = nold+i;\r
- if (type(old->key) != OT_NULL)\r
- NewSlot(old->key,old->val);\r
- }\r
- for(int k=0;k<oldsize;k++) \r
- nold[k].~_HashNode();\r
- SQ_FREE(nold,oldsize*sizeof(_HashNode));\r
-}\r
-\r
-SQTable *SQTable::Clone()\r
-{\r
- SQTable *nt=Create(_opt_ss(this),_numofnodes);\r
- SQInteger ridx=0;\r
- SQObjectPtr key,val;\r
- while((ridx=Next(ridx,key,val))!=-1){\r
- nt->NewSlot(key,val);\r
- }\r
- nt->SetDelegate(_delegate);\r
- return nt;\r
-}\r
-\r
-bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val)\r
-{\r
- _HashNode *n = _Get(key, HashKey(key) & (_numofnodes - 1));\r
- if (n) {\r
- val = n->val;\r
- return true;\r
- }\r
- return false;\r
-}\r
-bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)\r
-{\r
- unsigned long h = HashKey(key) & (_numofnodes - 1);\r
- _HashNode *n = _Get(key, h);\r
- if (n) {\r
- n->val = val;\r
- return false;\r
- }\r
- _HashNode *mp = &_nodes[h];\r
- n = mp;\r
-\r
- //key not found I'll insert it\r
- //main pos is not free\r
-\r
- if(type(mp->key)!=OT_NULL) {\r
-\r
- _HashNode *othern; /* main position of colliding node */\r
- n = _firstfree; /* get a free place */\r
- if (mp > n && (othern = &_nodes[h]) != mp){\r
- /* yes; move colliding node into free position */\r
- while (othern->next != mp)\r
- othern = othern->next; /* find previous */\r
- othern->next = n; /* redo the chain with `n' in place of `mp' */\r
- *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */\r
- mp->next = NULL; /* now `mp' is free */\r
- }\r
- else{\r
- /* new node will go into free position */\r
- n->next = mp->next; /* chain new position */\r
- mp->next = n;\r
- mp = n;\r
- }\r
- }\r
- mp->key = key;\r
-\r
- for (;;) { /* correct `firstfree' */\r
- if (type(_firstfree->key) == OT_NULL) {\r
- mp->val = val;\r
- _usednodes++;\r
- return true; /* OK; table still has a free place */\r
- }\r
- else if (_firstfree == _nodes) break; /* cannot decrement from here */\r
- else (_firstfree)--;\r
- }\r
- Rehash(true);\r
- return NewSlot(key, val);\r
-}\r
-\r
-int SQTable::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)\r
-{\r
- int idx = (int)TranslateIndex(refpos);\r
- while (idx < _numofnodes) {\r
- if(type(_nodes[idx].key) != OT_NULL) {\r
- //first found\r
- outkey = _nodes[idx].key;\r
- outval = _nodes[idx].val;\r
- //return idx for the next iteration\r
- return ++idx;\r
- }\r
- ++idx;\r
- }\r
- //nothing to iterate anymore\r
- return -1;\r
-}\r
-\r
-bool SQTable::SetDelegate(SQTable *mt)\r
-{\r
- SQTable *temp = mt;\r
- while (temp) {\r
- if (temp->_delegate == this) return false; //cycle detected\r
- temp = temp->_delegate;\r
- }\r
- if (mt) __ObjAddRef(mt);\r
- __ObjRelease(_delegate);\r
- _delegate = mt;\r
- return true;\r
-}\r
-\r
-bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val)\r
-{\r
- _HashNode *n = _Get(key, HashKey(key) & (_numofnodes - 1));\r
- if (n) {\r
- n->val = val;\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-void SQTable::Finalize()\r
-{\r
- for(int i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; }\r
- SetDelegate(NULL);\r
-}\r
+/*
+see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqvm.h"
+#include "sqtable.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+
+SQTable::SQTable(SQSharedState *ss,int nInitialSize)
+{
+ int pow2size=MINPOWER2;
+ while(nInitialSize>pow2size)pow2size=pow2size<<1;
+ AllocNodes(pow2size);
+ _uiRef = 0;
+ _usednodes = 0;
+ _delegate = NULL;
+ INIT_CHAIN();
+ ADD_TO_CHAIN(&_sharedstate->_gc_chain,this);
+}
+
+void SQTable::Remove(const SQObjectPtr &key)
+{
+ _HashNode *n = _Get(key, HashKey(key) & (_numofnodes - 1));
+ if (n) {
+ n->val = n->key = _null_;
+ _usednodes--;
+ Rehash(false);
+ }
+}
+
+void SQTable::AllocNodes(int nSize)
+{
+ _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize);
+ for(int i=0;i<nSize;i++){
+ new (&nodes[i]) _HashNode;
+ nodes[i].next=NULL;
+ }
+ _numofnodes=nSize;
+ _nodes=nodes;
+ _firstfree=&_nodes[_numofnodes-1];
+}
+
+int SQTable::CountUsed()
+{
+ /*int n=0;
+ for(int i=0;i<_numofnodes;i++){
+ if(type(_nodes[i].key)!=OT_NULL) n++;
+ }*/
+ return _usednodes;
+}
+
+void SQTable::Rehash(bool force)
+{
+ int oldsize=_numofnodes;
+ //prevent problems with the integer division
+ if(oldsize<4)oldsize=4;
+ _HashNode *nold=_nodes;
+ int nelems=CountUsed();
+ if (nelems >= oldsize-oldsize/4) /* using more than 3/4? */
+ AllocNodes(oldsize*2);
+ else if (nelems <= oldsize/4 && /* less than 1/4? */
+ oldsize > MINPOWER2)
+ AllocNodes(oldsize/2);
+ else if(force)
+ AllocNodes(oldsize);
+ else
+ return;
+ _usednodes = 0;
+ for (int i=0; i<oldsize; i++) {
+ _HashNode *old = nold+i;
+ if (type(old->key) != OT_NULL)
+ NewSlot(old->key,old->val);
+ }
+ for(int k=0;k<oldsize;k++)
+ nold[k].~_HashNode();
+ SQ_FREE(nold,oldsize*sizeof(_HashNode));
+}
+
+SQTable *SQTable::Clone()
+{
+ SQTable *nt=Create(_opt_ss(this),_numofnodes);
+ SQInteger ridx=0;
+ SQObjectPtr key,val;
+ while((ridx=Next(ridx,key,val))!=-1){
+ nt->NewSlot(key,val);
+ }
+ nt->SetDelegate(_delegate);
+ return nt;
+}
+
+bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val)
+{
+ _HashNode *n = _Get(key, HashKey(key) & (_numofnodes - 1));
+ if (n) {
+ val = n->val;
+ return true;
+ }
+ return false;
+}
+bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)
+{
+ unsigned long h = HashKey(key) & (_numofnodes - 1);
+ _HashNode *n = _Get(key, h);
+ if (n) {
+ n->val = val;
+ return false;
+ }
+ _HashNode *mp = &_nodes[h];
+ n = mp;
+
+ //key not found I'll insert it
+ //main pos is not free
+
+ if(type(mp->key)!=OT_NULL) {
+
+ _HashNode *othern; /* main position of colliding node */
+ n = _firstfree; /* get a free place */
+ if (mp > n && (othern = &_nodes[h]) != mp){
+ /* yes; move colliding node into free position */
+ while (othern->next != mp)
+ othern = othern->next; /* find previous */
+ othern->next = n; /* redo the chain with `n' in place of `mp' */
+ *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */
+ mp->next = NULL; /* now `mp' is free */
+ }
+ else{
+ /* new node will go into free position */
+ n->next = mp->next; /* chain new position */
+ mp->next = n;
+ mp = n;
+ }
+ }
+ mp->key = key;
+
+ for (;;) { /* correct `firstfree' */
+ if (type(_firstfree->key) == OT_NULL) {
+ mp->val = val;
+ _usednodes++;
+ return true; /* OK; table still has a free place */
+ }
+ else if (_firstfree == _nodes) break; /* cannot decrement from here */
+ else (_firstfree)--;
+ }
+ Rehash(true);
+ return NewSlot(key, val);
+}
+
+int SQTable::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
+{
+ int idx = (int)TranslateIndex(refpos);
+ while (idx < _numofnodes) {
+ if(type(_nodes[idx].key) != OT_NULL) {
+ //first found
+ outkey = _nodes[idx].key;
+ outval = _nodes[idx].val;
+ //return idx for the next iteration
+ return ++idx;
+ }
+ ++idx;
+ }
+ //nothing to iterate anymore
+ return -1;
+}
+
+bool SQTable::SetDelegate(SQTable *mt)
+{
+ SQTable *temp = mt;
+ while (temp) {
+ if (temp->_delegate == this) return false; //cycle detected
+ temp = temp->_delegate;
+ }
+ if (mt) __ObjAddRef(mt);
+ __ObjRelease(_delegate);
+ _delegate = mt;
+ return true;
+}
+
+bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val)
+{
+ _HashNode *n = _Get(key, HashKey(key) & (_numofnodes - 1));
+ if (n) {
+ n->val = val;
+ return true;
+ }
+ return false;
+}
+
+void SQTable::Finalize()
+{
+ for(int i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; }
+ SetDelegate(NULL);
+}
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQTABLE_H_\r
-#define _SQTABLE_H_\r
-/*\r
-* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)\r
-* http://www.lua.org/copyright.html#4\r
-* http://www.lua.org/source/4.0.1/src_ltable.c.html\r
-*/\r
-\r
-#include "sqstring.h"\r
-\r
-#define hashptr(p) (((unsigned long)(p)) >> 3)\r
-\r
-struct SQTable : public SQDelegable \r
-{\r
-private:\r
- struct _HashNode\r
- {\r
- SQObjectPtr val;\r
- SQObjectPtr key;\r
- _HashNode *next;\r
- };\r
- _HashNode *_firstfree;\r
- _HashNode *_nodes;\r
- int _numofnodes;\r
- int _usednodes;\r
- \r
-///////////////////////////\r
- void AllocNodes(int nSize);\r
- void Rehash(bool force);\r
- SQTable(SQSharedState *ss, int nInitialSize);\r
-public:\r
- static SQTable* Create(SQSharedState *ss,int nInitialSize)\r
- {\r
- SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable));\r
- new (newtable) SQTable(ss, nInitialSize);\r
- newtable->_delegate = NULL;\r
- return newtable;\r
- }\r
- void Finalize();\r
- SQTable *Clone();\r
- ~SQTable()\r
- {\r
- SetDelegate(NULL);\r
- REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);\r
- for (int i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();\r
- SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode));\r
- }\r
-#ifndef NO_GARBAGE_COLLECTOR \r
- void Mark(SQCollectable **chain);\r
-#endif\r
- inline unsigned long HashKey(const SQObjectPtr &key)\r
- {\r
- switch(type(key)){\r
- case OT_STRING: return _string(key)->_hash;\r
- case OT_FLOAT: return (unsigned long)((long)_float(key));\r
- case OT_INTEGER: return (unsigned long)((long)_integer(key));\r
- default: return hashptr(key._unVal.pRefCounted);\r
- }\r
- }\r
- _HashNode *_Get(const SQObjectPtr &key,unsigned long hash)\r
- {\r
- _HashNode *n = &_nodes[hash];\r
- do{\r
- if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){\r
- return n;\r
- }\r
- }while(n = n->next);\r
- return NULL;\r
- }\r
- bool Get(const SQObjectPtr &key,SQObjectPtr &val);\r
- void Remove(const SQObjectPtr &key);\r
- bool Set(const SQObjectPtr &key, const SQObjectPtr &val);\r
- //returns true if a new slot has been created false if it was already present\r
- bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);\r
- int Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);\r
- \r
- int CountUsed();\r
- void Release()\r
- {\r
- sq_delete(this, SQTable);\r
- }\r
- bool SetDelegate(SQTable *mt);\r
- \r
-\r
-};\r
-\r
-#endif //_SQTABLE_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQTABLE_H_
+#define _SQTABLE_H_
+/*
+* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
+* http://www.lua.org/copyright.html#4
+* http://www.lua.org/source/4.0.1/src_ltable.c.html
+*/
+
+#include "sqstring.h"
+
+#define hashptr(p) (((unsigned long)(p)) >> 3)
+
+struct SQTable : public SQDelegable
+{
+private:
+ struct _HashNode
+ {
+ SQObjectPtr val;
+ SQObjectPtr key;
+ _HashNode *next;
+ };
+ _HashNode *_firstfree;
+ _HashNode *_nodes;
+ int _numofnodes;
+ int _usednodes;
+
+///////////////////////////
+ void AllocNodes(int nSize);
+ void Rehash(bool force);
+ SQTable(SQSharedState *ss, int nInitialSize);
+public:
+ static SQTable* Create(SQSharedState *ss,int nInitialSize)
+ {
+ SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable));
+ new (newtable) SQTable(ss, nInitialSize);
+ newtable->_delegate = NULL;
+ return newtable;
+ }
+ void Finalize();
+ SQTable *Clone();
+ ~SQTable()
+ {
+ SetDelegate(NULL);
+ REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
+ for (int i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();
+ SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode));
+ }
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+#endif
+ inline unsigned long HashKey(const SQObjectPtr &key)
+ {
+ switch(type(key)){
+ case OT_STRING: return _string(key)->_hash;
+ case OT_FLOAT: return (unsigned long)((long)_float(key));
+ case OT_INTEGER: return (unsigned long)((long)_integer(key));
+ default: return hashptr(key._unVal.pRefCounted);
+ }
+ }
+ _HashNode *_Get(const SQObjectPtr &key,unsigned long hash)
+ {
+ _HashNode *n = &_nodes[hash];
+ do{
+ if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){
+ return n;
+ }
+ }while( (n = n->next) );
+ return NULL;
+ }
+ bool Get(const SQObjectPtr &key,SQObjectPtr &val);
+ void Remove(const SQObjectPtr &key);
+ bool Set(const SQObjectPtr &key, const SQObjectPtr &val);
+ //returns true if a new slot has been created false if it was already present
+ bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);
+ int Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
+
+ int CountUsed();
+ void Release()
+ {
+ sq_delete(this, SQTable);
+ }
+ bool SetDelegate(SQTable *mt);
+
+
+};
+
+#endif //_SQTABLE_H_
+++ /dev/null
-# Microsoft Developer Studio Project File - Name="squirrel" - Package Owner=<4>\r
-# Microsoft Developer Studio Generated Build File, Format Version 6.00\r
-# ** DO NOT EDIT **\r
-\r
-# TARGTYPE "Win32 (x86) Static Library" 0x0104\r
-\r
-CFG=squirrel - Win32 Debug\r
-!MESSAGE This is not a valid makefile. To build this project using NMAKE,\r
-!MESSAGE use the Export Makefile command and run\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "squirrel.mak".\r
-!MESSAGE \r
-!MESSAGE You can specify a configuration when running NMAKE\r
-!MESSAGE by defining the macro CFG on the command line. For example:\r
-!MESSAGE \r
-!MESSAGE NMAKE /f "squirrel.mak" CFG="squirrel - Win32 Debug"\r
-!MESSAGE \r
-!MESSAGE Possible choices for configuration are:\r
-!MESSAGE \r
-!MESSAGE "squirrel - Win32 Release" (based on "Win32 (x86) Static Library")\r
-!MESSAGE "squirrel - Win32 Debug" (based on "Win32 (x86) Static Library")\r
-!MESSAGE \r
-\r
-# Begin Project\r
-# PROP AllowPerConfigDependencies 0\r
-# PROP Scc_LocalPath ".."\r
-CPP=cl.exe\r
-RSC=rc.exe\r
-\r
-!IF "$(CFG)" == "squirrel - Win32 Release"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 0\r
-# PROP BASE Output_Dir "Release"\r
-# PROP BASE Intermediate_Dir "Release"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 0\r
-# PROP Output_Dir "Release"\r
-# PROP Intermediate_Dir "Release"\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c\r
-# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "GARBAGE_COLLECTOR" /YX /FD /c\r
-# ADD BASE RSC /l 0x410 /d "NDEBUG"\r
-# ADD RSC /l 0x410 /d "NDEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LIB32=link.exe -lib\r
-# ADD BASE LIB32 /nologo\r
-# ADD LIB32 /nologo /out:"..\lib\squirrel.lib"\r
-\r
-!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"\r
-\r
-# PROP BASE Use_MFC 0\r
-# PROP BASE Use_Debug_Libraries 1\r
-# PROP BASE Output_Dir "Debug"\r
-# PROP BASE Intermediate_Dir "Debug"\r
-# PROP BASE Target_Dir ""\r
-# PROP Use_MFC 0\r
-# PROP Use_Debug_Libraries 1\r
-# PROP Output_Dir "Debug"\r
-# PROP Intermediate_Dir "Debug"\r
-# PROP Target_Dir ""\r
-# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c\r
-# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /D "GARBAGE_COLLECTOR" /YX /FD /GZ /c\r
-# ADD BASE RSC /l 0x410 /d "_DEBUG"\r
-# ADD RSC /l 0x410 /d "_DEBUG"\r
-BSC32=bscmake.exe\r
-# ADD BASE BSC32 /nologo\r
-# ADD BSC32 /nologo\r
-LIB32=link.exe -lib\r
-# ADD BASE LIB32 /nologo\r
-# ADD LIB32 /nologo /out:"..\lib\squirrel.lib"\r
-\r
-!ENDIF \r
-\r
-# Begin Target\r
-\r
-# Name "squirrel - Win32 Release"\r
-# Name "squirrel - Win32 Debug"\r
-# Begin Group "Source Files"\r
-\r
-# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"\r
-# Begin Source File\r
-\r
-SOURCE=.\sqapi.cpp\r
-\r
-!IF "$(CFG)" == "squirrel - Win32 Release"\r
-\r
-!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"\r
-\r
-# ADD CPP /YX"stdafx.h"\r
-\r
-!ENDIF \r
-\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqbaselib.cpp\r
-\r
-!IF "$(CFG)" == "squirrel - Win32 Release"\r
-\r
-!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"\r
-\r
-# ADD CPP /YX"stdafx.h"\r
-\r
-!ENDIF \r
-\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqcompiler.cpp\r
-\r
-!IF "$(CFG)" == "squirrel - Win32 Release"\r
-\r
-!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"\r
-\r
-# ADD CPP /YX"stdafx.h"\r
-\r
-!ENDIF \r
-\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqdebug.cpp\r
-\r
-!IF "$(CFG)" == "squirrel - Win32 Release"\r
-\r
-!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"\r
-\r
-# ADD CPP /YX"stdafx.h"\r
-\r
-!ENDIF \r
-\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqfuncstate.cpp\r
-\r
-!IF "$(CFG)" == "squirrel - Win32 Release"\r
-\r
-!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"\r
-\r
-# ADD CPP /YX"stdafx.h"\r
-\r
-!ENDIF \r
-\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqlexer.cpp\r
-\r
-!IF "$(CFG)" == "squirrel - Win32 Release"\r
-\r
-!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"\r
-\r
-# ADD CPP /YX"stdafx.h"\r
-\r
-!ENDIF \r
-\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqmem.cpp\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqobject.cpp\r
-\r
-!IF "$(CFG)" == "squirrel - Win32 Release"\r
-\r
-!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"\r
-\r
-# ADD CPP /YX"stdafx.h"\r
-\r
-!ENDIF \r
-\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstate.cpp\r
-\r
-!IF "$(CFG)" == "squirrel - Win32 Release"\r
-\r
-!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"\r
-\r
-# ADD CPP /YX"stdafx.h"\r
-\r
-!ENDIF \r
-\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqtable.cpp\r
-\r
-!IF "$(CFG)" == "squirrel - Win32 Release"\r
-\r
-!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"\r
-\r
-# ADD CPP /YX"stdafx.h"\r
-\r
-!ENDIF \r
-\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqclass.cpp\r
-\r
-!IF "$(CFG)" == "squirrel - Win32 Release"\r
-\r
-!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"\r
-\r
-# ADD CPP /YX"stdafx.h"\r
-\r
-!ENDIF \r
-\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqvm.cpp\r
-\r
-!IF "$(CFG)" == "squirrel - Win32 Release"\r
-\r
-!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"\r
-\r
-# ADD CPP /YX"stdafx.h"\r
-\r
-!ENDIF \r
-\r
-# End Source File\r
-# End Group\r
-# Begin Group "Header Files"\r
-\r
-# PROP Default_Filter "h;hpp;hxx;hm;inl"\r
-# Begin Source File\r
-\r
-SOURCE=.\sqarray.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqclosure.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqcompiler.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqfuncproto.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqfuncstate.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqlexer.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqobject.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqopcodes.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqpcheader.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstate.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqstring.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqtable.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\squserdata.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\squtils.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqclass.h\r
-# End Source File\r
-# Begin Source File\r
-\r
-SOURCE=.\sqvm.h\r
-# End Source File\r
-# End Group\r
-# End Target\r
-# End Project\r
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQUSERDATA_H_\r
-#define _SQUSERDATA_H_\r
-\r
-struct SQUserData : SQDelegable\r
-{\r
- SQUserData(SQSharedState *ss){ _uiRef = 0; _delegate = 0; _hook = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); }\r
- ~SQUserData()\r
- {\r
- REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain, this);\r
- SetDelegate(NULL);\r
- }\r
- static SQUserData* Create(SQSharedState *ss, int size)\r
- {\r
- SQUserData* ud = (SQUserData*)SQ_MALLOC(sizeof(SQUserData)+(size-1));\r
- new (ud) SQUserData(ss);\r
- ud->_size = size;\r
- ud->_typetag = 0;\r
- return ud;\r
- }\r
-#ifndef NO_GARBAGE_COLLECTOR\r
- void Mark(SQCollectable **chain);\r
- void Finalize(){SetDelegate(NULL);}\r
-#endif\r
- void Release() {\r
- if (_hook) _hook(_val,_size);\r
- int tsize = _size - 1;\r
- this->~SQUserData();\r
- SQ_FREE(this, sizeof(SQUserData) + tsize);\r
- }\r
- void SetDelegate(SQTable *mt)\r
- {\r
- if (mt) __ObjAddRef(mt);\r
- __ObjRelease(_delegate);\r
- _delegate = mt;\r
- }\r
-\r
- \r
- int _size;\r
- SQRELEASEHOOK _hook;\r
- unsigned int _typetag;\r
- SQChar _val[1];\r
-};\r
-\r
-#endif //_SQUSERDATA_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQUSERDATA_H_
+#define _SQUSERDATA_H_
+
+struct SQUserData : SQDelegable
+{
+ SQUserData(SQSharedState *ss){ _uiRef = 0; _delegate = 0; _hook = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); }
+ ~SQUserData()
+ {
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain, this);
+ SetDelegate(NULL);
+ }
+ static SQUserData* Create(SQSharedState *ss, int size)
+ {
+ SQUserData* ud = (SQUserData*)SQ_MALLOC(sizeof(SQUserData)+(size-1));
+ new (ud) SQUserData(ss);
+ ud->_size = size;
+ ud->_typetag = 0;
+ return ud;
+ }
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+ void Finalize(){SetDelegate(NULL);}
+#endif
+ void Release() {
+ if (_hook) _hook(_val,_size);
+ int tsize = _size - 1;
+ this->~SQUserData();
+ SQ_FREE(this, sizeof(SQUserData) + tsize);
+ }
+ void SetDelegate(SQTable *mt)
+ {
+ if (mt) __ObjAddRef(mt);
+ __ObjRelease(_delegate);
+ _delegate = mt;
+ }
+
+
+ int _size;
+ SQRELEASEHOOK _hook;
+ unsigned int _typetag;
+ SQChar _val[1];
+};
+
+#endif //_SQUSERDATA_H_
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQUTILS_H_\r
-#define _SQUTILS_H_\r
-\r
-#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;}\r
-#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));}\r
-#define SQ_MALLOC(__size) sq_vm_malloc(__size);\r
-#define SQ_FREE(__ptr,__size) sq_vm_free(__ptr,__size);\r
-#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc(__ptr,__oldsize,__size);\r
-\r
-//sqvector mini vector class, supports objects by value\r
-template<typename T> class sqvector\r
-{\r
-public:\r
- sqvector()\r
- {\r
- _vals = NULL;\r
- _size = 0;\r
- _allocated = 0;\r
- }\r
- sqvector(const sqvector<T>& v)\r
- {\r
- copy(v);\r
- }\r
- void copy(const sqvector<T>& v)\r
- {\r
- resize(v._size);\r
- for(unsigned int i = 0; i < v._size; i++) {\r
- new ((void *)&_vals[i]) T(v._vals[i]);\r
- }\r
- _size = v._size;\r
- }\r
- ~sqvector()\r
- {\r
- if(_allocated) {\r
- for(unsigned int i = 0; i < _size; i++)\r
- _vals[i].~T();\r
- SQ_FREE(_vals, (_allocated * sizeof(T)));\r
- }\r
- }\r
- void reserve(unsigned int newsize) { _realloc(newsize); }\r
- void resize(unsigned int newsize, const T& fill = T())\r
- {\r
- if(newsize > _allocated)\r
- _realloc(newsize);\r
- if(newsize > _size) {\r
- while(_size < newsize) {\r
- new ((void *)&_vals[_size]) T(fill);\r
- _size++;\r
- }\r
- }\r
- else{\r
- for(unsigned int i = newsize; i < _size; i++) {\r
- _vals[i].~T();\r
- }\r
- _size = newsize;\r
- }\r
- }\r
- void shrinktofit() { if(_size > 4) { _realloc(_size); } }\r
- T& top() const { return _vals[_size - 1]; }\r
- inline unsigned int size() const { return _size; }\r
- bool empty() const { return (_size <= 0); }\r
- inline void push_back(const T& val = T())\r
- {\r
- if(_allocated <= _size)\r
- _realloc(_size * 2);\r
- new ((void *)&_vals[_size++]) T(val);\r
- }\r
- inline void pop_back()\r
- {\r
- _size--; _vals[_size].~T();\r
- }\r
- void insert(unsigned int idx, const T& val)\r
- {\r
- resize(_size + 1);\r
- for(unsigned int i = _size - 1; i > idx; i--) {\r
- _vals[i] = _vals[i - 1];\r
- }\r
- _vals[idx] = val;\r
- }\r
- void remove(unsigned int idx)\r
- {\r
- _vals[idx].~T();\r
- if(idx < (_size - 1)) {\r
- memcpy(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1));\r
- }\r
- _size--;\r
- }\r
- unsigned int capacity() { return _allocated; }\r
- inline T &back() const { return _vals[_size - 1]; }\r
- T& operator[](unsigned int pos) const{ return _vals[pos]; }\r
- T* _vals;\r
-private:\r
- void _realloc(unsigned int newsize)\r
- {\r
- newsize = (newsize > 0)?newsize:4;\r
- _vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T));\r
- _allocated = newsize;\r
- }\r
- unsigned int _size;\r
- unsigned int _allocated;\r
-};\r
-\r
-#endif //_SQUTILS_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQUTILS_H_
+#define _SQUTILS_H_
+
+#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;}
+#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));}
+#define SQ_MALLOC(__size) sq_vm_malloc(__size);
+#define SQ_FREE(__ptr,__size) sq_vm_free(__ptr,__size);
+#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc(__ptr,__oldsize,__size);
+
+//sqvector mini vector class, supports objects by value
+template<typename T> class sqvector
+{
+public:
+ sqvector()
+ {
+ _vals = NULL;
+ _size = 0;
+ _allocated = 0;
+ }
+ sqvector(const sqvector<T>& v)
+ {
+ copy(v);
+ }
+ void copy(const sqvector<T>& v)
+ {
+ resize(v._size);
+ for(unsigned int i = 0; i < v._size; i++) {
+ new ((void *)&_vals[i]) T(v._vals[i]);
+ }
+ _size = v._size;
+ }
+ ~sqvector()
+ {
+ if(_allocated) {
+ for(unsigned int i = 0; i < _size; i++)
+ _vals[i].~T();
+ SQ_FREE(_vals, (_allocated * sizeof(T)));
+ }
+ }
+ void reserve(unsigned int newsize) { _realloc(newsize); }
+ void resize(unsigned int newsize, const T& fill = T())
+ {
+ if(newsize > _allocated)
+ _realloc(newsize);
+ if(newsize > _size) {
+ while(_size < newsize) {
+ new ((void *)&_vals[_size]) T(fill);
+ _size++;
+ }
+ }
+ else{
+ for(unsigned int i = newsize; i < _size; i++) {
+ _vals[i].~T();
+ }
+ _size = newsize;
+ }
+ }
+ void shrinktofit() { if(_size > 4) { _realloc(_size); } }
+ T& top() const { return _vals[_size - 1]; }
+ inline unsigned int size() const { return _size; }
+ bool empty() const { return (_size <= 0); }
+ inline void push_back(const T& val = T())
+ {
+ if(_allocated <= _size)
+ _realloc(_size * 2);
+ new ((void *)&_vals[_size++]) T(val);
+ }
+ inline void pop_back()
+ {
+ _size--; _vals[_size].~T();
+ }
+ void insert(unsigned int idx, const T& val)
+ {
+ resize(_size + 1);
+ for(unsigned int i = _size - 1; i > idx; i--) {
+ _vals[i] = _vals[i - 1];
+ }
+ _vals[idx] = val;
+ }
+ void remove(unsigned int idx)
+ {
+ _vals[idx].~T();
+ if(idx < (_size - 1)) {
+ memcpy(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1));
+ }
+ _size--;
+ }
+ unsigned int capacity() { return _allocated; }
+ inline T &back() const { return _vals[_size - 1]; }
+ T& operator[](unsigned int pos) const{ return _vals[pos]; }
+ T* _vals;
+private:
+ void _realloc(unsigned int newsize)
+ {
+ newsize = (newsize > 0)?newsize:4;
+ _vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T));
+ _allocated = newsize;
+ }
+ unsigned int _size;
+ unsigned int _allocated;
+};
+
+#endif //_SQUTILS_H_
-/*\r
- see copyright notice in squirrel.h\r
-*/\r
-#include "sqpcheader.h"\r
-#include <math.h>\r
-#include <stdlib.h>\r
-#include "sqopcodes.h"\r
-#include "sqfuncproto.h"\r
-#include "sqvm.h"\r
-#include "sqclosure.h"\r
-#include "sqstring.h"\r
-#include "sqtable.h"\r
-#include "squserdata.h"\r
-#include "sqarray.h"\r
-#include "sqclass.h"\r
-\r
-#define TOP() (_stack[_top-1])\r
-\r
-bool SQVM::BW_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)\r
-{\r
- SQInteger res;\r
- SQInteger i1 = _integer(o1), i2 = _integer(o2);\r
- if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER))\r
- {\r
- switch(op) {\r
- case BW_AND: res = i1 & i2; break;\r
- case BW_OR: res = i1 | i2; break;\r
- case BW_XOR: res = i1 ^ i2; break;\r
- case BW_SHIFTL: res = i1 << i2; break;\r
- case BW_SHIFTR: res = i1 >> i2; break;\r
- case BW_USHIFTR:res = (SQInteger)(*((unsigned int*)&i1) >> i2); break;\r
- default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; }\r
- }\r
- } \r
- else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;}\r
- trg = res;\r
- return true;\r
-}\r
-\r
-bool SQVM::ARITH_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)\r
-{\r
- if(sq_isnumeric(o1) && sq_isnumeric(o2)) {\r
- if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) {\r
- switch(op) {\r
- case '+': trg = _integer(o1) + _integer(o2); break;\r
- case '-': trg = _integer(o1) - _integer(o2); break;\r
- case '/': if(_integer(o2) == 0) { Raise_Error(_SC("division by zero")); return false; }\r
- trg = _integer(o1) / _integer(o2); \r
- break;\r
- case '*': trg = _integer(o1) * _integer(o2); break;\r
- case '%': trg = _integer(o1) % _integer(o2); break;\r
- }\r
- }else{\r
- switch(op) {\r
- case '+': trg = tofloat(o1) + tofloat(o2); break;\r
- case '-': trg = tofloat(o1) - tofloat(o2); break;\r
- case '/': trg = tofloat(o1) / tofloat(o2); break;\r
- case '*': trg = tofloat(o1) * tofloat(o2); break;\r
- case '%': trg = SQFloat(fmod((double)tofloat(o1),(double)tofloat(o2))); break;\r
- }\r
- } \r
- } else {\r
- if(op == '+' && (type(o1) == OT_STRING || type(o2) == OT_STRING)){\r
- if(!StringCat(o1, o2, trg)) return false;\r
- }\r
- else if(!ArithMetaMethod(op,o1,o2,trg)) { \r
- Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false; \r
- }\r
- }\r
- return true;\r
-}\r
-\r
-SQObjectPtr &stack_get(HSQUIRRELVM v,int idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}\r
-\r
-SQVM::SQVM(SQSharedState *ss)\r
-{\r
- _sharedstate=ss;\r
- _suspended=false;\r
- _suspended_target=-1;\r
- _suspended_root=false;\r
- _suspended_traps=-1;\r
- _foreignptr=NULL;\r
- _nnativecalls=0;\r
- _uiRef=0;\r
- _lasterror = _null_;\r
- _errorhandler = _null_;\r
- _debughook = _null_;\r
- INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);\r
-}\r
-\r
-void SQVM::Finalize()\r
-{\r
- _roottable = _null_;\r
- _lasterror = _null_;\r
- _errorhandler = _null_;\r
- _debughook = _null_;\r
- temp_reg = _null_;\r
- int size=_stack.size();\r
- for(int i=0;i<size;i++)\r
- _stack[i]=_null_;\r
-}\r
-\r
-SQVM::~SQVM()\r
-{\r
- Finalize();\r
- REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
-}\r
-\r
-bool SQVM::ArithMetaMethod(int op,const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &dest)\r
-{\r
- SQMetaMethod mm;\r
- switch(op){\r
- case _SC('+'): mm=MT_ADD; break;\r
- case _SC('-'): mm=MT_SUB; break;\r
- case _SC('/'): mm=MT_DIV; break;\r
- case _SC('*'): mm=MT_MUL; break;\r
- case _SC('%'): mm=MT_MODULO; break;\r
- }\r
- if(is_delegable(o1) && _delegable(o1)->_delegate) {\r
- Push(o1);Push(o2);\r
- return CallMetaMethod(_delegable(o1),mm,2,dest);\r
- }\r
- return false;\r
-}\r
-\r
-bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o)\r
-{\r
- \r
- switch(type(o)) {\r
- case OT_INTEGER:\r
- trg = -_integer(o);\r
- return true;\r
- case OT_FLOAT:\r
- trg = -_float(o);\r
- return true;\r
- case OT_TABLE:\r
- case OT_USERDATA:\r
- case OT_INSTANCE:\r
- if(_delegable(o)->_delegate) {\r
- Push(o);\r
- if(CallMetaMethod(_delegable(o), MT_UNM, 1, temp_reg)) {\r
- trg = temp_reg;\r
- return true;\r
- }\r
- }\r
- return true;\r
-\r
- }\r
- Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o));\r
- return false;\r
-}\r
-\r
-#define _RET_SUCCEED(exp) { result = (exp); return true; } \r
-bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,int &result)\r
-{\r
- if(type(o1)==type(o2)){\r
- if(_userpointer(o1)==_userpointer(o2))_RET_SUCCEED(0);\r
- SQObjectPtr res;\r
- switch(type(o1)){\r
- case OT_STRING:\r
- _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2)));\r
- case OT_INTEGER:\r
- _RET_SUCCEED(_integer(o1)-_integer(o2));\r
- case OT_FLOAT:\r
- _RET_SUCCEED((_float(o1)<_float(o2))?-1:1);\r
- case OT_TABLE:\r
- case OT_USERDATA:\r
- case OT_INSTANCE:\r
- Push(o1);Push(o2);\r
- if(_delegable(o1)->_delegate)CallMetaMethod(_delegable(o1),MT_CMP,2,res);\r
- break;\r
- }\r
- if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; }\r
- _RET_SUCCEED(_integer(res));\r
- }\r
- else{\r
- if(sq_isnumeric(o1) && sq_isnumeric(o2)){\r
- if((type(o1)==OT_INTEGER) && (type(o2)==OT_FLOAT)) { \r
- if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); }\r
- else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); }\r
- _RET_SUCCEED(1);\r
- }\r
- else{\r
- if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); }\r
- else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); }\r
- _RET_SUCCEED(1);\r
- }\r
- }\r
- else if(type(o1)==OT_NULL) {_RET_SUCCEED(-1);}\r
- else if(type(o2)==OT_NULL) {_RET_SUCCEED(1);}\r
- else { Raise_CompareError(o1,o2); return false; }\r
- \r
- }\r
- assert(0);\r
- _RET_SUCCEED(0); //cannot happen\r
-}\r
-\r
-bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res)\r
-{\r
- int r;\r
- if(ObjCmp(o1,o2,r)) {\r
- switch(op) {\r
- case CMP_G: res = (r > 0)?_true_:_false_; return true;\r
- case CMP_GE: res = (r >= 0)?_true_:_false_; return true;\r
- case CMP_L: res = (r < 0)?_true_:_false_; return true;\r
- case CMP_LE: res = (r <= 0)?_true_:_false_; return true;\r
- \r
- }\r
- assert(0);\r
- }\r
- return false;\r
-}\r
-\r
-bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)\r
-{\r
- switch(type(obj))\r
- {\r
- case OT_STRING:\r
- switch(type(str)){\r
- case OT_STRING: {\r
- int l=_string(str)->_len,ol=_string(obj)->_len;\r
- SQChar *s=_sp(rsl(l+ol+1));\r
- memcpy(s,_stringval(str),rsl(l));memcpy(s+l,_stringval(obj),rsl(ol));s[l+ol]=_SC('\0');\r
- break;\r
- }\r
- case OT_FLOAT:\r
- scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(obj)->_len+1)),_SC("%g%s"),_float(str),_stringval(obj));\r
- break;\r
- case OT_INTEGER:\r
- scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(obj)->_len+1)),_SC("%d%s"),_integer(str),_stringval(obj));\r
- break;\r
- default:\r
- Raise_Error(_SC("string concatenation between '%s' and '%s'"),GetTypeName(str),GetTypeName(obj));\r
- return false;\r
- }\r
- dest=SQString::Create(_ss(this),_spval);\r
- break;\r
- case OT_FLOAT:\r
- scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(str)->_len+1)),_SC("%s%g"),_stringval(str),_float(obj));\r
- dest=SQString::Create(_ss(this),_spval);\r
- break;\r
- case OT_INTEGER:\r
- scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(str)->_len+1)),_SC("%s%d"),_stringval(str),_integer(obj));\r
- dest=SQString::Create(_ss(this),_spval);\r
- break;\r
- default:\r
- Raise_Error(_SC("string concatenation between '%s' and '%s'"),GetTypeName(str),GetTypeName(obj));\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-const SQChar *IdType2Name(SQObjectType type)\r
-{\r
- switch(_RAW_TYPE(type))\r
- {\r
- case _RT_NULL:return _SC("null");\r
- case _RT_INTEGER:return _SC("integer");\r
- case _RT_FLOAT:return _SC("float");\r
- case _RT_BOOL:return _SC("bool");\r
- case _RT_STRING:return _SC("string");\r
- case _RT_TABLE:return _SC("table");\r
- case _RT_ARRAY:return _SC("array");\r
- case _RT_GENERATOR:return _SC("generator");\r
- case _RT_CLOSURE:\r
- case _RT_NATIVECLOSURE:\r
- return _SC("function");\r
- case _RT_USERDATA:\r
- case _RT_USERPOINTER:\r
- return _SC("userdata");\r
- case _RT_THREAD: return _SC("thread");\r
- case _RT_FUNCPROTO: return _SC("function");\r
- case _RT_CLASS: return _SC("class");\r
- case _RT_INSTANCE: return _SC("instance");\r
- default:\r
- return NULL;\r
- }\r
-}\r
-\r
-const SQChar *GetTypeName(const SQObjectPtr &obj1)\r
-{\r
- return IdType2Name(type(obj1)); \r
-}\r
-\r
-void SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest)\r
-{\r
- if(is_delegable(obj1) && _delegable(obj1)->_delegate) {\r
- Push(obj1);\r
- if(CallMetaMethod(_delegable(obj1),MT_TYPEOF,1,dest))\r
- return;\r
- }\r
- dest = SQString::Create(_ss(this),GetTypeName(obj1));\r
-}\r
-\r
-bool SQVM::Init(SQVM *friendvm, int stacksize)\r
-{\r
- _stack.resize(stacksize);\r
- _callsstack.reserve(4);\r
- _stackbase = 0;\r
- _top = 0;\r
- if(!friendvm) \r
- _roottable = SQTable::Create(_ss(this), 0);\r
- else {\r
- _roottable = friendvm->_roottable;\r
- _errorhandler = friendvm->_errorhandler;\r
- _debughook = friendvm->_debughook;\r
- }\r
- \r
- sq_base_register(this);\r
- return true;\r
-}\r
-\r
-extern SQInstructionDesc g_InstrDesc[];\r
-\r
-bool SQVM::StartCall(SQClosure *closure,int target,int nargs,int stackbase,bool tailcall)\r
-{\r
- SQFunctionProto *func = _funcproto(closure->_function);\r
- //const int outerssize = func->_outervalues.size();\r
-\r
- const int paramssize = func->_parameters.size();\r
- const int oldtop = _top;\r
- const int newtop = stackbase + func->_stacksize;\r
- \r
- \r
- if(func->_varparams)\r
- {\r
- if (nargs < paramssize) {\r
- Raise_Error(_SC("wrong number of parameters"));\r
- return false;\r
- }\r
- for(int n = 0; n < nargs - paramssize; n++) {\r
- _vargsstack.push_back(_stack[stackbase+paramssize+n]);\r
- _stack[stackbase+paramssize+n] = _null_;\r
- }\r
- }\r
- else {\r
- if (paramssize != nargs) {\r
- Raise_Error(_SC("wrong number of parameters"));\r
- return false;\r
- }\r
- \r
- }\r
- \r
- if (!tailcall) {\r
- PUSH_CALLINFO(this, CallInfo());\r
- ci->_etraps = 0;\r
- ci->_prevstkbase = stackbase - _stackbase;\r
- ci->_target = target;\r
- ci->_prevtop = _top - _stackbase;\r
- ci->_ncalls = 1;\r
- ci->_root = false;\r
- }\r
- else {\r
- ci->_ncalls++;\r
- }\r
- ci->_vargs.size = (nargs - paramssize);\r
- ci->_vargs.base = _vargsstack.size()-(nargs - paramssize);\r
- ci->_closure._unVal.pClosure = closure;\r
- ci->_closure._type = OT_CLOSURE;\r
- ci->_iv = &func->_instructions;\r
- ci->_literals = &func->_literals;\r
- //grows the stack if needed\r
- if (((unsigned int)newtop + (func->_stacksize<<1)) > _stack.size()) {\r
- _stack.resize(_stack.size() + (func->_stacksize<<1));\r
- }\r
- \r
- _top = newtop;\r
- _stackbase = stackbase;\r
- ci->_ip = ci->_iv->_vals;\r
- return true;\r
-}\r
-\r
-bool SQVM::Return(int _arg0, int _arg1, SQObjectPtr &retval)\r
-{\r
- if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))\r
- for(int i=0;i<ci->_ncalls;i++)\r
- CallDebugHook(_SC('r'));\r
- \r
- bool broot = ci->_root;\r
- int last_top = _top;\r
- int target = ci->_target;\r
- int oldstackbase = _stackbase;\r
- _stackbase -= ci->_prevstkbase;\r
- _top = _stackbase + ci->_prevtop;\r
- PopVarArgs(ci->_vargs);\r
- POP_CALLINFO(this);\r
- if (broot) {\r
- if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack[oldstackbase+_arg1];\r
- else retval = _null_;\r
- }\r
- else {\r
- if (_arg0 != MAX_FUNC_STACKSIZE)\r
- STK(target) = _stack[oldstackbase+_arg1];\r
- else\r
- STK(target) = _null_;\r
- }\r
-\r
- while (last_top >= _top) _stack[last_top--].Null();\r
- assert(oldstackbase >= _stackbase); \r
- return broot;\r
-}\r
-\r
-#define _RET_ON_FAIL(exp) { if(!exp) return false; }\r
-\r
-bool SQVM::LOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)\r
-{\r
- _RET_ON_FAIL(ARITH_OP( op , target, a, incr));\r
- a = target;\r
- return true;\r
-}\r
-\r
-bool SQVM::PLOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)\r
-{\r
- SQObjectPtr trg;\r
- _RET_ON_FAIL(ARITH_OP( op , trg, a, incr));\r
- target = a;\r
- a = trg;\r
- return true;\r
-}\r
-\r
-bool SQVM::DerefInc(int op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix)\r
-{\r
- SQObjectPtr tmp, tself = self, tkey = key;\r
- if (!Get(tself, tkey, tmp, false, true)) { Raise_IdxError(tkey); return false; }\r
- _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr))\r
- Set(tself, tkey, target,true);\r
- if (postfix) target = tmp;\r
- return true;\r
-}\r
-\r
-#define arg0 (_i_._arg0)\r
-#define arg1 (_i_._arg1)\r
-#define sarg1 (*((int *)&_i_._arg1))\r
-#define arg2 (_i_._arg2)\r
-#define arg3 (_i_._arg3)\r
-#define sarg3 (*((char *)&_i_._arg3))\r
-\r
-SQRESULT SQVM::Suspend()\r
-{\r
- if (_suspended)\r
- return sq_throwerror(this, _SC("cannot suspend an already suspended vm"));\r
- if (_nnativecalls!=2)\r
- return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods"));\r
- return SQ_SUSPEND_FLAG;\r
-}\r
-\r
-void SQVM::PopVarArgs(VarArgs &vargs)\r
-{\r
- for(int n = 0; n< vargs.size; n++)\r
- _vargsstack.pop_back();\r
-}\r
-\r
-#define _FINISH(stoploop) {finished = stoploop; return true; }\r
-bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr \r
-&o3,SQObjectPtr &o4,int arg_2,bool &finished)\r
-{\r
- int nrefidx;\r
- switch(type(o1)) {\r
- case OT_TABLE:\r
- if((nrefidx = _table(o1)->Next(o4, o2, o3)) == -1) _FINISH(true);\r
- o4 = (SQInteger)nrefidx; _FINISH(false);\r
- case OT_ARRAY:\r
- if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(true);\r
- o4 = (SQInteger) nrefidx; _FINISH(false);\r
- case OT_STRING:\r
- if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(true);\r
- o4 = (SQInteger)nrefidx; _FINISH(false);\r
- case OT_CLASS:\r
- if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(true);\r
- o4 = (SQInteger)nrefidx; _FINISH(false);\r
- case OT_USERDATA:\r
- case OT_INSTANCE:\r
- if(_delegable(o1)->_delegate) {\r
- SQObjectPtr itr;\r
- Push(o1);\r
- Push(o4);\r
- if(CallMetaMethod(_delegable(o1), MT_NEXTI, 2, itr)){\r
- o4 = o2 = itr;\r
- if(type(itr) == OT_NULL) _FINISH(true);\r
- if(!Get(o1, itr, o3, false,false)) {\r
- Raise_Error(_SC("_nexti returned an invalid idx"));\r
- return false;\r
- }\r
- _FINISH(false);\r
- }\r
- Raise_Error(_SC("_nexti failed"));\r
- return false;\r
- }\r
- break;\r
- case OT_GENERATOR:\r
- if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(true);\r
- if(_generator(o1)->_state == SQGenerator::eSuspended) {\r
- SQInteger idx = 0;\r
- if(type(o4) == OT_INTEGER) {\r
- idx = _integer(o4) + 1;\r
- }\r
- o2 = idx;\r
- o4 = idx;\r
- _generator(o1)->Resume(this, arg_2+1);\r
- _FINISH(false);\r
- }\r
- }\r
- Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));\r
- return false; //cannot be hit(just to avoid warnings)\r
-}\r
-\r
-bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2)\r
-{\r
- if(type(o1) != OT_TABLE) { Raise_Error(_SC("delegating a '%s'"), GetTypeName(o1)); return false; }\r
- switch(type(o2)) {\r
- case OT_TABLE:\r
- if(!_table(o1)->SetDelegate(_table(o2))){\r
- Raise_Error(_SC("delegate cycle detected"));\r
- return false;\r
- }\r
- break;\r
- case OT_NULL:\r
- _table(o1)->SetDelegate(NULL);\r
- break;\r
- default:\r
- Raise_Error(_SC("using '%s' as delegate"), GetTypeName(o2));\r
- return false;\r
- break;\r
- }\r
- trg = o1;\r
- return true;\r
-}\r
-#define COND_LITERAL (arg3!=0?(*ci->_literals)[arg1]:STK(arg1))\r
-\r
-#define _GUARD(exp) { if(!exp) { Raise_Error(_lasterror); SQ_THROW();} }\r
-\r
-#define SQ_THROW() { goto exception_trap; }\r
-\r
-bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)\r
-{\r
- int nouters;\r
- SQClosure *closure = SQClosure::Create(_ss(this), func);\r
- if(nouters = func->_outervalues.size()) {\r
- closure->_outervalues.reserve(nouters);\r
- for(int i = 0; i<nouters; i++) {\r
- SQOuterVar &v = func->_outervalues[i];\r
- switch(v._type){\r
- case otSYMBOL:\r
- closure->_outervalues.push_back(_null_);\r
- if(!Get(_stack._vals[_stackbase]/*STK(0)*/, v._src, closure->_outervalues.top(), false,true))\r
- {Raise_IdxError(v._src); return false; }\r
- break;\r
- case otLOCAL:\r
- closure->_outervalues.push_back(_stack._vals[_stackbase+_integer(v._src)]);\r
- break;\r
- case otOUTER:\r
- closure->_outervalues.push_back(_closure(ci->_closure)->_outervalues[_integer(v._src)]);\r
- break;\r
- }\r
- }\r
- }\r
- target = closure;\r
- return true;\r
-\r
-}\r
-\r
-bool SQVM::GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &index,CallInfo *ci)\r
-{\r
- if(ci->_vargs.size == 0) {\r
- Raise_Error(_SC("the function doesn't have var args"));\r
- return false;\r
- }\r
- if(!sq_isnumeric(index)){\r
- Raise_Error(_SC("indexing 'vargv' with %s"),GetTypeName(index));\r
- return false;\r
- }\r
- int idx = tointeger(index);\r
- if(idx < 0 || idx >= ci->_vargs.size){ Raise_Error(_SC("vargv index out of range")); return false; }\r
- target = _vargsstack[ci->_vargs.base+idx];\r
- return true;\r
-}\r
-\r
-bool SQVM::CLASS_OP(SQObjectPtr &target,int baseclass,int attributes)\r
-{\r
- SQClass *base = NULL;\r
- SQObjectPtr attrs;\r
- if(baseclass != MAX_LITERALS) {\r
- if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; }\r
- base = _class(_stack._vals[_stackbase + baseclass]);\r
- }\r
- if(attributes != MAX_FUNC_STACKSIZE) {\r
- attrs = _stack._vals[_stackbase+attributes];\r
- }\r
- target = SQClass::Create(_ss(this),base);\r
- _class(target)->_attributes = attrs;\r
- return true;\r
-}\r
-\r
-bool SQVM::IsFalse(SQObjectPtr &o)\r
-{\r
- SQObjectType t = type(o);\r
- if((t & SQOBJECT_CANBEFALSE)\r
- && ((t == OT_NULL) || ((t == OT_INTEGER || t == OT_BOOL) && _integer(o) == 0)\r
- || (t == OT_FLOAT && _float(o) == SQFloat(0.0)))) {\r
- return true;\r
- }\r
- return false;\r
-}\r
-\r
-bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res)\r
-{\r
- if(type(o1) == type(o2)) {\r
- res = ((_userpointer(o1) == _userpointer(o2)?true:false));\r
- }\r
- else {\r
- if(sq_isnumeric(o1) && sq_isnumeric(o2)) {\r
- int cmpres;\r
- if(!ObjCmp(o1, o2,cmpres)) return false;\r
- res = (cmpres == 0);\r
- }\r
- else {\r
- res = false;\r
- }\r
- }\r
- return true;\r
-}\r
-\r
-bool SQVM::Execute(SQObjectPtr &closure, int target, int nargs, int stackbase,SQObjectPtr &outres, ExecutionType et)\r
-{\r
- if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }\r
- _nnativecalls++;\r
- AutoDec ad(&_nnativecalls);\r
- int traps = 0;\r
- //temp_reg vars for OP_CALL\r
- int ct_target;\r
- bool ct_tailcall; \r
-\r
- switch(et) {\r
- case ET_CALL: \r
- if(!StartCall(_closure(closure), _top - nargs, nargs, stackbase, false)) { \r
- //call the handler if there are no calls in the stack, if not relies on the previous node\r
- if(ci == NULL) CallErrorHandler(_lasterror);\r
- return false;\r
- }\r
- ci->_root = true;\r
- break;\r
- case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = true; traps += ci->_etraps; break;\r
- case ET_RESUME_VM:\r
- traps = _suspended_traps;\r
- ci->_root = _suspended_root;\r
- _suspended = false;\r
- break;\r
- }\r
- \r
-exception_restore:\r
- //SQ_TRY \r
- {\r
- for(;;)\r
- {\r
- const SQInstruction &_i_ = *ci->_ip++;\r
- //dumpstack(_stackbase);\r
- //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-ci->_iv->_vals,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3);\r
- switch(_i_.op)\r
- {\r
- case _OP_LINE:\r
- if(type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))\r
- CallDebugHook(_SC('l'),arg1);\r
- continue;\r
- case _OP_LOAD: TARGET = (*ci->_literals)[arg1]; continue;\r
- case _OP_TAILCALL:\r
- temp_reg = STK(arg1);\r
- if (type(temp_reg) == OT_CLOSURE){ \r
- ct_tailcall = true;\r
- PopVarArgs(ci->_vargs);\r
- for (int i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);\r
- ct_target = ci->_target;\r
- goto common_call;\r
- }\r
- case _OP_CALL: {\r
- ct_tailcall = false;\r
- ct_target = arg0;\r
- temp_reg = STK(arg1);\r
-common_call:\r
- int last_top = _top;\r
- switch (type(temp_reg)) {\r
- case OT_CLOSURE:{\r
- StartCall(_closure(temp_reg), ct_target, arg3, ct_tailcall?_stackbase:_stackbase+arg2, ct_tailcall);\r
- if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) {\r
- SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg));\r
- _GUARD(gen->Yield(this));\r
- Return(1, ct_target, temp_reg);\r
- STK(ct_target) = gen;\r
- while (last_top >= _top) _stack[last_top--].Null();\r
- continue;\r
- }\r
- if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))\r
- CallDebugHook(_SC('c'));\r
- }\r
- break;\r
- case OT_NATIVECLOSURE: {\r
- bool suspend;\r
- _GUARD(CallNative(_nativeclosure(temp_reg), arg3, _stackbase+arg2, ct_tailcall, temp_reg,suspend));\r
- if(suspend){\r
- _suspended = true;\r
- _suspended_target = ct_target;\r
- _suspended_root = ci->_root;\r
- _suspended_traps = traps;\r
- outres = temp_reg;\r
- return true;\r
- }\r
- STK(ct_target) = temp_reg;\r
- }\r
- break;\r
- case OT_CLASS:{\r
- _GUARD(CreateClassInstance(_class(temp_reg),arg3,_stackbase+arg2,STK(ct_target)));\r
- }\r
- break;\r
- case OT_TABLE:\r
- case OT_USERDATA:\r
- case OT_INSTANCE:\r
- {\r
- Push(temp_reg);\r
- for (int i = 0; i < arg3; i++) Push(STK(arg2 + i));\r
- if (_delegable(temp_reg) && CallMetaMethod(_delegable(temp_reg), MT_CALL, arg3+1, temp_reg)){\r
- STK(ct_target) = temp_reg;\r
- break;\r
- }\r
- Raise_Error(_SC("attempt to call '%s'"), GetTypeName(temp_reg));\r
- SQ_THROW();\r
- }\r
- default:\r
- Raise_Error(_SC("attempt to call '%s'"), GetTypeName(temp_reg));\r
- SQ_THROW();\r
- }\r
- }\r
- continue;\r
- case _OP_PREPCALL:\r
- if (!Get(STK(arg2), STK(arg1), temp_reg, false,true))\r
- { Raise_IdxError(STK(arg1)); SQ_THROW(); }\r
- goto common_prepcall;\r
- case _OP_PREPCALLK:\r
- if (!Get(STK(arg2), (*ci->_literals)[arg1], temp_reg,false,true)) {\r
- if(type(STK(arg2)) == OT_CLASS) { //hack?\r
- if(_class_ddel->Get((*ci->_literals)[arg1],temp_reg)) {\r
- STK(arg3) = STK(arg2);\r
- TARGET = temp_reg;\r
- continue;\r
- }\r
- }\r
- { Raise_IdxError((*ci->_literals)[arg1]); SQ_THROW();}\r
- }\r
-common_prepcall:\r
- if(type(STK(arg2)) == OT_CLASS) {\r
- STK(arg3) = STK(0); // this\r
- }\r
- else {\r
- STK(arg3) = STK(arg2);\r
- }\r
- TARGET = temp_reg;\r
- continue;\r
- case _OP_GETK:\r
- if (!Get(STK(arg2), (*ci->_literals)[arg1], temp_reg, false,true)) { Raise_IdxError((*ci->_literals)[arg1]); SQ_THROW();}\r
- TARGET = temp_reg;\r
- continue;\r
- case _OP_MOVE: TARGET = STK(arg1); continue;\r
- case _OP_NEWSLOT:\r
- _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3)));\r
- if(arg0 != arg3) TARGET = STK(arg3);\r
- continue;\r
- case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue;\r
- case _OP_SET:\r
- if (!Set(STK(arg1), STK(arg2), STK(arg3),true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); }\r
- if (arg0 != arg3) TARGET = STK(arg3);\r
- continue;\r
- case _OP_GET:\r
- if (!Get(STK(arg1), STK(arg2), temp_reg, false,true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); }\r
- TARGET = temp_reg;\r
- continue;\r
- case _OP_EQ:{\r
- bool res;\r
- if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }\r
- TARGET = res?_true_:_false_;\r
- }continue;\r
- case _OP_NE:{ \r
- bool res;\r
- if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }\r
- TARGET = (!res)?_true_:_false_;\r
- } continue;\r
- case _OP_ARITH: _GUARD(ARITH_OP( arg3 , temp_reg, STK(arg2), STK(arg1))); TARGET = temp_reg; continue;\r
- case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue;\r
- case _OP_RETURN:\r
- if(type((ci)->_generator) == OT_GENERATOR) {\r
- _generator((ci)->_generator)->Kill();\r
- }\r
- if(Return(arg0, arg1, temp_reg)){\r
- assert(traps==0);\r
- outres = temp_reg;\r
- return true;\r
- }\r
- continue;\r
- case _OP_LOADNULLS:{ for(unsigned int n=0;n<arg1;n++) STK(arg0+n) = _null_; }continue;\r
- case _OP_LOADROOTTABLE: TARGET = _roottable; continue;\r
- case _OP_LOADBOOL: TARGET = arg1?_true_:_false_; continue;\r
- case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue;\r
- case _OP_JMP: ci->_ip += (sarg1); continue;\r
- case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;\r
- case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;\r
- case _OP_LOADFREEVAR: TARGET = _closure(ci->_closure)->_outervalues[arg1]; continue;\r
- case _OP_VARGC: TARGET = SQInteger(ci->_vargs.size); continue;\r
- case _OP_GETVARGV: \r
- if(!GETVARGV_OP(TARGET,STK(arg1),ci)) { SQ_THROW(); } \r
- continue;\r
- case _OP_NEWTABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;\r
- case _OP_NEWARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;\r
- case _OP_APPENDARRAY: _array(STK(arg0))->Append(COND_LITERAL); continue;\r
- case _OP_GETPARENT:\r
- switch(type(STK(arg1))) {\r
- case OT_TABLE: \r
- TARGET = _table(STK(arg1))->_delegate?SQObjectPtr(_table(STK(arg1))->_delegate):_null_;\r
- continue;\r
- case OT_CLASS: TARGET = _class(STK(arg1))->_base?_class(STK(arg1))->_base:_null_;\r
- continue;\r
- }\r
- Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(STK(arg1)));\r
- SQ_THROW();\r
- continue;\r
- case _OP_COMPARITH: _GUARD(DerefInc(arg3, TARGET, STK((((unsigned int)arg1&0xFFFF0000)>>16)), STK(arg2), STK(arg1&0x0000FFFF), false)); continue;\r
- case _OP_COMPARITHL: _GUARD(LOCAL_INC(arg3, TARGET, STK(arg1), STK(arg2))); continue;\r
- case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false));} continue;\r
- case _OP_INCL: {SQObjectPtr o(sarg3); _GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));} continue;\r
- case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true));} continue;\r
- case _OP_PINCL: {SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));} continue;\r
- case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue;\r
- case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,false)?_true_:_false_;continue;\r
- case _OP_INSTANCEOF: \r
- if(type(STK(arg1)) != OT_CLASS || type(STK(arg2)) != OT_INSTANCE)\r
- {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();}\r
- TARGET = _instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?_true_:_false_;\r
- continue;\r
- case _OP_AND: \r
- if(IsFalse(STK(arg2))) {\r
- TARGET = STK(arg2);\r
- ci->_ip += (sarg1);\r
- }\r
- continue;\r
- case _OP_OR:\r
- if(!IsFalse(STK(arg2))) {\r
- TARGET = STK(arg2);\r
- ci->_ip += (sarg1);\r
- }\r
- continue;\r
- case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue;\r
- case _OP_NOT: TARGET = (IsFalse(STK(arg1))?_true_:_false_); continue;\r
- case _OP_BWNOT:\r
- if(type(STK(arg1)) == OT_INTEGER) {\r
- TARGET = SQInteger(~_integer(STK(arg1)));\r
- continue;\r
- }\r
- Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1)));\r
- SQ_THROW();\r
- case _OP_CLOSURE: {\r
- SQClosure *c = ci->_closure._unVal.pClosure;\r
- SQFunctionProto *fp = c->_function._unVal.pFunctionProto;\r
- if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); }\r
- continue;\r
- }\r
- case _OP_YIELD:{\r
- if(type(ci->_generator) == OT_GENERATOR) {\r
- if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);\r
- _GUARD(_generator(ci->_generator)->Yield(this));\r
- traps -= ci->_etraps;\r
- if(sarg1 != MAX_FUNC_STACKSIZE) STK(arg1) = temp_reg;\r
- }\r
- else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();}\r
- if(Return(arg0, arg1, temp_reg)){\r
- assert(traps==0);\r
- outres = temp_reg;\r
- return true;\r
- }\r
- \r
- }\r
- continue;\r
- case _OP_RESUME:\r
- if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();}\r
- _GUARD(_generator(STK(arg1))->Resume(this, arg0));\r
- traps += ci->_etraps;\r
- continue;\r
- case _OP_FOREACH:{ bool finished;\r
- _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,finished));\r
- if(finished) ci->_ip += sarg1; }\r
- continue;\r
- case _OP_DELEGATE: _GUARD(DELEGATE_OP(TARGET,STK(arg1),STK(arg2))); continue;\r
- case _OP_CLONE:\r
- if(!Clone(STK(arg1), TARGET))\r
- { Raise_Error(_SC("cloning a %s"), GetTypeName(STK(arg1))); SQ_THROW();}\r
- continue;\r
- case _OP_TYPEOF: TypeOf(STK(arg1), TARGET); continue;\r
- case _OP_PUSHTRAP:\r
- _etraps.push_back(SQExceptionTrap(_top,_stackbase, &ci->_iv->_vals[(ci->_ip-ci->_iv->_vals)+arg1], arg0)); traps++;\r
- ci->_etraps++;\r
- continue;\r
- case _OP_POPTRAP:{\r
- for(int i=0; i<arg0; i++) {\r
- _etraps.pop_back(); traps--;\r
- ci->_etraps--;\r
- }}\r
- continue;\r
- case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue;\r
- case _OP_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;\r
- case _OP_NEWSLOTA:\r
- _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3)));\r
- _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1));\r
- if(arg0 != arg3) TARGET = STK(arg3);\r
- continue;\r
- }\r
- \r
- }\r
- }\r
-exception_trap:\r
- {\r
- SQObjectPtr currerror = _lasterror;\r
-// dumpstack(_stackbase);\r
- int n = 0;\r
- int last_top = _top;\r
- if(ci) {\r
- if(traps) {\r
- do {\r
- if(ci->_etraps > 0) {\r
- SQExceptionTrap &et = _etraps.top();\r
- ci->_ip = et._ip;\r
- _top = et._stacksize;\r
- _stackbase = et._stackbase;\r
- _stack[_stackbase+et._extarget] = currerror;\r
- _etraps.pop_back(); traps--; ci->_etraps--;\r
- while(last_top >= _top) _stack[last_top--].Null();\r
- goto exception_restore;\r
- }\r
- //if is a native closure\r
- if(type(ci->_closure) != OT_CLOSURE && n)\r
- break;\r
- if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill();\r
- PopVarArgs(ci->_vargs);\r
- POP_CALLINFO(this);\r
- n++;\r
- }while(_callsstack.size());\r
- }\r
- //call the hook\r
- CallErrorHandler(currerror);\r
- //remove call stack until a C function is found or the cstack is empty\r
- if(ci) do{\r
- bool exitafterthisone = ci->_root;\r
- if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill();\r
- _stackbase -= ci->_prevstkbase;\r
- _top = _stackbase + ci->_prevtop;\r
- PopVarArgs(ci->_vargs);\r
- POP_CALLINFO(this);\r
- if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) break;\r
- }while(_callsstack.size());\r
-\r
- while(last_top >= _top) _stack[last_top--].Null();\r
- }\r
- _lasterror = currerror;\r
- return false;\r
- }\r
- assert(0);\r
-}\r
-\r
-bool SQVM::CreateClassInstance(SQClass *theclass, int nargs, int stackbase, SQObjectPtr &retval)\r
-{\r
- SQObjectPtr constr;\r
- SQObjectPtr inst = theclass->CreateInstance();\r
- _stack[stackbase] = inst;\r
- if(theclass->Get(_ss(this)->_constructoridx,constr)) {\r
- if(!Call(constr,nargs,stackbase,constr))\r
- return false;\r
- }\r
- retval = inst;\r
- return true;\r
-}\r
-\r
-void SQVM::CallErrorHandler(SQObjectPtr &error)\r
-{\r
- if(type(_errorhandler) != OT_NULL) {\r
- SQObjectPtr out;\r
- Push(_roottable); Push(error);\r
- Call(_errorhandler, 2, _top-2, out);\r
- Pop(2);\r
- }\r
-}\r
-\r
-void SQVM::CallDebugHook(int type,int forcedline)\r
-{\r
- SQObjectPtr temp_reg;\r
- int nparams=5;\r
- SQFunctionProto *func=_funcproto(_closure(ci->_closure)->_function);\r
- Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);\r
- Call(_debughook,nparams,_top-nparams,temp_reg);\r
- Pop(nparams);\r
-}\r
-\r
-bool SQVM::CallNative(SQNativeClosure *nclosure,int nargs,int stackbase,bool tailcall,SQObjectPtr &retval,bool &suspend)\r
-{\r
- if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }\r
- int nparamscheck = nclosure->_nparamscheck;\r
- if(((nparamscheck > 0) && (nparamscheck != nargs))\r
- || ((nparamscheck < 0) && (nargs < (-nparamscheck)))) {\r
- Raise_Error(_SC("wrong number of parameters"));\r
- return false;\r
- }\r
-\r
- int tcs;\r
- if(tcs = nclosure->_typecheck.size()) {\r
- for(int i = 0; i < nargs && i < tcs; i++)\r
- if((nclosure->_typecheck[i] != -1) && !(type(_stack[stackbase+i]) & nclosure->_typecheck[i])) {\r
- Raise_ParamTypeError(i,nclosure->_typecheck[i],type(_stack[stackbase+i]));\r
- return false;\r
- }\r
- }\r
- _nnativecalls++;\r
- if ((_top + MIN_STACK_OVERHEAD) > (int)_stack.size()) {\r
- _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD<<1));\r
- }\r
- int oldtop = _top;\r
- int oldstackbase = _stackbase;\r
- _top = stackbase + nargs;\r
- PUSH_CALLINFO(this, CallInfo());\r
- ci->_etraps = 0;\r
- ci->_closure._unVal.pNativeClosure = nclosure;\r
- ci->_closure._type = OT_NATIVECLOSURE;\r
- ci->_prevstkbase = stackbase - _stackbase;\r
- ci->_ncalls = 1;\r
- _stackbase = stackbase;\r
- //push free variables\r
- int outers = nclosure->_outervalues.size();\r
- for (int i = 0; i < outers; i++) {\r
- Push(nclosure->_outervalues[i]);\r
- }\r
- ci->_prevtop = (oldtop - oldstackbase);\r
- int ret = (nclosure->_function)(this);\r
- _nnativecalls--;\r
- suspend = false;\r
- if( ret == SQ_SUSPEND_FLAG) suspend = true;\r
- else if (ret < 0) { \r
- _stackbase = oldstackbase;\r
- _top = oldtop;\r
- POP_CALLINFO(this);\r
- Raise_Error(_lasterror);\r
- return false;\r
- }\r
- \r
- if (ret != 0){ retval = TOP(); }\r
- else { retval = _null_; }\r
- _stackbase = oldstackbase;\r
- _top = oldtop;\r
- POP_CALLINFO(this);\r
- return true;\r
-}\r
-\r
-bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, bool fetchroot)\r
-{\r
- switch(type(self)){\r
- case OT_TABLE:\r
- if(_table(self)->Get(key,dest))return true;\r
- break;\r
- case OT_ARRAY:\r
- if(sq_isnumeric(key)){\r
- return _array(self)->Get(tointeger(key),dest);\r
- }\r
- break;\r
- case OT_INSTANCE:\r
- if(_instance(self)->Get(key,dest)) return true;\r
- break;\r
- }\r
- if(FallBackGet(self,key,dest,raw)) return true;\r
-\r
- if(fetchroot) {\r
- if(_rawval(STK(0)) == _rawval(self) &&\r
- type(STK(0)) == type(self)) {\r
- return _table(_roottable)->Get(key,dest);\r
- }\r
- }\r
- return false;\r
-}\r
-\r
-bool SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw)\r
-{\r
- switch(type(self)){\r
- case OT_CLASS: \r
- return _class(self)->Get(key,dest);\r
- break;\r
- case OT_TABLE:\r
- case OT_USERDATA:\r
- //delegation\r
- if(_delegable(self)->_delegate) {\r
- if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,raw,false))\r
- return true; \r
- if(raw)return false;\r
- Push(self);Push(key);\r
- if(CallMetaMethod(_delegable(self),MT_GET,2,dest))\r
- return true;\r
- }\r
- if(type(self) == OT_TABLE) {\r
- if(raw) return false;\r
- return _table_ddel->Get(key,dest);\r
- }\r
- return false;\r
- break;\r
- case OT_ARRAY:\r
- if(raw)return false;\r
- return _array_ddel->Get(key,dest);\r
- case OT_STRING:\r
- if(sq_isnumeric(key)){\r
- SQInteger n=tointeger(key);\r
- if(abs(n)<_string(self)->_len){\r
- if(n<0)n=_string(self)->_len-n;\r
- dest=SQInteger(_stringval(self)[n]);\r
- return true;\r
- }\r
- return false;\r
- }\r
- else {\r
- if(raw)return false;\r
- return _string_ddel->Get(key,dest);\r
- }\r
- break;\r
- case OT_INSTANCE:\r
- if(raw)return false;\r
- Push(self);Push(key);\r
- if(!CallMetaMethod(_delegable(self),MT_GET,2,dest)) {\r
- return _instance_ddel->Get(key,dest);\r
- }\r
- return true;\r
- case OT_INTEGER:case OT_FLOAT:case OT_BOOL: \r
- if(raw)return false;\r
- return _number_ddel->Get(key,dest);\r
- case OT_GENERATOR: \r
- if(raw)return false;\r
- return _generator_ddel->Get(key,dest);\r
- case OT_CLOSURE: case OT_NATIVECLOSURE: \r
- if(raw)return false;\r
- return _closure_ddel->Get(key,dest);\r
- case OT_THREAD:\r
- if(raw)return false;\r
- return _thread_ddel->Get(key,dest);\r
- default:return false;\r
- }\r
- return false;\r
-}\r
-\r
-bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool fetchroot)\r
-{\r
- switch(type(self)){\r
- case OT_TABLE:\r
- if(_table(self)->Set(key,val))\r
- return true;\r
- if(_table(self)->_delegate) {\r
- if(Set(_table(self)->_delegate,key,val,false)) {\r
- return true;\r
- }\r
- }\r
- //keeps going\r
- case OT_USERDATA:\r
- if(_delegable(self)->_delegate) {\r
- SQObjectPtr t;\r
- Push(self);Push(key);Push(val);\r
- if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true;\r
- }\r
- break;\r
- case OT_INSTANCE:{\r
- if(_instance(self)->Set(key,val))\r
- return true;\r
- SQObjectPtr t;\r
- Push(self);Push(key);Push(val);\r
- if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true;\r
- }\r
- break;\r
- case OT_ARRAY:\r
- if(!sq_isnumeric(key)) {Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; }\r
- return _array(self)->Set(tointeger(key),val);\r
- default:\r
- Raise_Error(_SC("trying to set '%s'"),GetTypeName(self));\r
- return false;\r
- }\r
- if(fetchroot) {\r
- if(_rawval(STK(0)) == _rawval(self) &&\r
- type(STK(0)) == type(self)) {\r
- return _table(_roottable)->Set(key,val);\r
- }\r
- }\r
- return false;\r
-}\r
-\r
-bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target)\r
-{\r
- SQObjectPtr temp_reg;\r
- switch(type(self)){\r
- case OT_TABLE:\r
- target = _table(self)->Clone();\r
- goto cloned_mt;\r
- case OT_INSTANCE:\r
- target = _instance(self)->Clone(_ss(this));\r
-cloned_mt:\r
- if(_delegable(target)->_delegate){\r
- Push(target);\r
- Push(self);\r
- CallMetaMethod(_delegable(target),MT_CLONED,2,temp_reg);\r
- }\r
- return true;\r
- case OT_ARRAY: \r
- target=_array(self)->Clone();\r
- return true;\r
- default: return false;\r
- }\r
-}\r
-\r
-bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val)\r
-{\r
- if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; }\r
- switch(type(self)) {\r
- case OT_TABLE: {\r
- bool rawcall = true;\r
- if(_table(self)->_delegate) {\r
- SQObjectPtr res;\r
- if(!_table(self)->Get(key,res)) {\r
- Push(self);Push(key);Push(val);\r
- rawcall = !CallMetaMethod(_table(self),MT_NEWSLOT,3,res);\r
- }\r
- }\r
- if(rawcall) _table(self)->NewSlot(key,val); //cannot fail\r
- \r
- break;}\r
- case OT_CLASS: \r
- if(!_class(self)->NewSlot(key,val)) {\r
- if(_class(self)->_locked) {\r
- Raise_Error(_SC("trying to modify a class that has already been instantiated"));\r
- return false;\r
- }\r
- else {\r
- SQObjectPtr oval = PrintObjVal(key);\r
- Raise_Error(_SC("the property '%s' already exists"),_stringval(oval));\r
- return false;\r
- }\r
- }\r
- break;\r
- default:\r
- Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key));\r
- return false;\r
- break;\r
- }\r
- return true;\r
-}\r
-\r
-bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res)\r
-{\r
- switch(type(self)) {\r
- case OT_TABLE:\r
- case OT_INSTANCE:\r
- case OT_USERDATA: {\r
- SQObjectPtr t;\r
- bool handled = false;\r
- if(_delegable(self)->_delegate) {\r
- Push(self);Push(key);\r
- handled = CallMetaMethod(_delegable(self),MT_DELSLOT,2,t);\r
- }\r
-\r
- if(!handled) {\r
- if(type(self) == OT_TABLE) {\r
- if(_table(self)->Get(key,t)) {\r
- _table(self)->Remove(key);\r
- }\r
- else {\r
- Raise_IdxError((SQObject &)key);\r
- return false;\r
- }\r
- }\r
- else {\r
- Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self));\r
- return false;\r
- }\r
- }\r
- res = t;\r
- }\r
- break;\r
- default:\r
- Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self));\r
- return false;\r
- }\r
- return true;\r
-}\r
-\r
-bool SQVM::Call(SQObjectPtr &closure,int nparams,int stackbase,SQObjectPtr &outres)\r
-{\r
-#ifdef _DEBUG\r
-int prevstackbase = _stackbase;\r
-#endif\r
- switch(type(closure)) {\r
- case OT_CLOSURE:\r
- return Execute(closure, _top - nparams, nparams, stackbase,outres);\r
- break;\r
- case OT_NATIVECLOSURE:{\r
- bool suspend;\r
- return CallNative(_nativeclosure(closure), nparams, stackbase, false, outres,suspend);\r
- \r
- }\r
- break;\r
- case OT_CLASS:\r
- return CreateClassInstance(_class(closure),nparams,stackbase,outres);\r
- break;\r
- default:\r
- return false;\r
- }\r
-#ifdef _DEBUG\r
- if(!_suspended) {\r
- assert(_stackbase == prevstackbase);\r
- }\r
-#endif\r
- return true;\r
-}\r
-\r
-bool SQVM::CallMetaMethod(SQDelegable *del,SQMetaMethod mm,int nparams,SQObjectPtr &outres)\r
-{\r
- SQObjectPtr closure;\r
- if(del->GetMetaMethod(mm, closure)) {\r
- if(Call(closure, nparams, _top - nparams, outres)) {\r
- Pop(nparams);\r
- return true;\r
- }\r
- }\r
- Pop(nparams);\r
- return false;\r
-}\r
-\r
-void SQVM::Pop() {\r
- _stack[--_top] = _null_;\r
-}\r
-void SQVM::Pop(int n) {\r
- for(int i = 0; i < n; i++){\r
- _stack[--_top] = _null_;\r
- }\r
-}\r
-\r
-void SQVM::Remove(int n) {\r
- n = (n >= 0)?n + _stackbase - 1:_top + n;\r
- for(int i = n; i < _top; i++){\r
- _stack[i] = _stack[i+1];\r
- }\r
- _stack[_top] = _null_;\r
- _top--;\r
-}\r
-\r
-void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; }\r
-SQObjectPtr &SQVM::Top() { return _stack[_top-1]; }\r
-SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; }\r
-SQObjectPtr &SQVM::GetUp(int n) { return _stack[_top+n]; }\r
-SQObjectPtr &SQVM::GetAt(int n) { return _stack[n]; }\r
-\r
-#ifdef _DEBUG_DUMP\r
-void SQVM::dumpstack(int stackbase,bool dumpall)\r
-{\r
- int size=dumpall?_stack.size():_top;\r
- int n=0;\r
- scprintf(_SC("\n>>>>stack dump<<<<\n"));\r
- CallInfo &ci=_callsstack.back();\r
- scprintf(_SC("IP: %d\n"),ci._ip);\r
- scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase);\r
- scprintf(_SC("prev top: %d\n"),ci._prevtop);\r
- for(int i=0;i<size;i++){\r
- SQObjectPtr &obj=_stack[i]; \r
- if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));\r
- scprintf(_SC("[%d]:"),n);\r
- switch(type(obj)){\r
- case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break;\r
- case OT_INTEGER: scprintf(_SC("INTEGER %d"),_integer(obj));break;\r
- case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break;\r
- case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break;\r
- case OT_NULL: scprintf(_SC("NULL")); break;\r
- case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break;\r
- case OT_ARRAY: scprintf(_SC("ARRAY %p"),_array(obj));break;\r
- case OT_CLOSURE: scprintf(_SC("CLOSURE [%p]"),_closure(obj));break;\r
- case OT_NATIVECLOSURE: scprintf(_SC("NATIVECLOSURE"));break;\r
- case OT_USERDATA: scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break;\r
- case OT_GENERATOR: scprintf(_SC("GENERATOR"));break;\r
- case OT_THREAD: scprintf(_SC("THREAD [%p]"),_thread(obj));break;\r
- case OT_USERPOINTER: scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break;\r
- case OT_CLASS: scprintf(_SC("CLASS %p"),_class(obj));break;\r
- case OT_INSTANCE: scprintf(_SC("INSTANCE %p"),_instance(obj));break;\r
- default:\r
- assert(0);\r
- break;\r
- };\r
- scprintf(_SC("\n"));\r
- ++n;\r
- }\r
-}\r
-\r
-#endif\r
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include <math.h>
+#include <stdlib.h>
+#include "sqopcodes.h"
+#include "sqfuncproto.h"
+#include "sqvm.h"
+#include "sqclosure.h"
+#include "sqstring.h"
+#include "sqtable.h"
+#include "squserdata.h"
+#include "sqarray.h"
+#include "sqclass.h"
+
+#define TOP() (_stack[_top-1])
+
+bool SQVM::BW_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)
+{
+ SQInteger res;
+ SQInteger i1 = _integer(o1), i2 = _integer(o2);
+ if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER))
+ {
+ switch(op) {
+ case BW_AND: res = i1 & i2; break;
+ case BW_OR: res = i1 | i2; break;
+ case BW_XOR: res = i1 ^ i2; break;
+ case BW_SHIFTL: res = i1 << i2; break;
+ case BW_SHIFTR: res = i1 >> i2; break;
+ case BW_USHIFTR:res = (SQInteger)(*((unsigned int*)&i1) >> i2); break;
+ default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; }
+ }
+ }
+ else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;}
+ trg = res;
+ return true;
+}
+
+bool SQVM::ARITH_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)
+{
+ if(sq_isnumeric(o1) && sq_isnumeric(o2)) {
+ if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) {
+ switch(op) {
+ case '+': trg = _integer(o1) + _integer(o2); break;
+ case '-': trg = _integer(o1) - _integer(o2); break;
+ case '/': if(_integer(o2) == 0) { Raise_Error(_SC("division by zero")); return false; }
+ trg = _integer(o1) / _integer(o2);
+ break;
+ case '*': trg = _integer(o1) * _integer(o2); break;
+ case '%': trg = _integer(o1) % _integer(o2); break;
+ }
+ }else{
+ switch(op) {
+ case '+': trg = tofloat(o1) + tofloat(o2); break;
+ case '-': trg = tofloat(o1) - tofloat(o2); break;
+ case '/': trg = tofloat(o1) / tofloat(o2); break;
+ case '*': trg = tofloat(o1) * tofloat(o2); break;
+ case '%': trg = SQFloat(fmod((double)tofloat(o1),(double)tofloat(o2))); break;
+ }
+ }
+ } else {
+ if(op == '+' && (type(o1) == OT_STRING || type(o2) == OT_STRING)){
+ if(!StringCat(o1, o2, trg)) return false;
+ }
+ else if(!ArithMetaMethod(op,o1,o2,trg)) {
+ Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false;
+ }
+ }
+ return true;
+}
+
+SQObjectPtr &stack_get(HSQUIRRELVM v,int idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}
+
+SQVM::SQVM(SQSharedState *ss)
+{
+ _sharedstate=ss;
+ _suspended=false;
+ _suspended_target=-1;
+ _suspended_root=false;
+ _suspended_traps=-1;
+ _foreignptr=NULL;
+ _nnativecalls=0;
+ _uiRef=0;
+ _lasterror = _null_;
+ _errorhandler = _null_;
+ _debughook = _null_;
+ INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);
+}
+
+void SQVM::Finalize()
+{
+ _roottable = _null_;
+ _lasterror = _null_;
+ _errorhandler = _null_;
+ _debughook = _null_;
+ temp_reg = _null_;
+ int size=_stack.size();
+ for(int i=0;i<size;i++)
+ _stack[i]=_null_;
+}
+
+SQVM::~SQVM()
+{
+ Finalize();
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+}
+
+bool SQVM::ArithMetaMethod(int op,const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &dest)
+{
+ SQMetaMethod mm;
+ switch(op){
+ case _SC('+'): mm=MT_ADD; break;
+ case _SC('-'): mm=MT_SUB; break;
+ case _SC('/'): mm=MT_DIV; break;
+ case _SC('*'): mm=MT_MUL; break;
+ case _SC('%'): mm=MT_MODULO; break;
+ }
+ if(is_delegable(o1) && _delegable(o1)->_delegate) {
+ Push(o1);Push(o2);
+ return CallMetaMethod(_delegable(o1),mm,2,dest);
+ }
+ return false;
+}
+
+bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o)
+{
+
+ switch(type(o)) {
+ case OT_INTEGER:
+ trg = -_integer(o);
+ return true;
+ case OT_FLOAT:
+ trg = -_float(o);
+ return true;
+ case OT_TABLE:
+ case OT_USERDATA:
+ case OT_INSTANCE:
+ if(_delegable(o)->_delegate) {
+ Push(o);
+ if(CallMetaMethod(_delegable(o), MT_UNM, 1, temp_reg)) {
+ trg = temp_reg;
+ return true;
+ }
+ }
+ return true;
+ default:
+ break;
+ }
+ Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o));
+ return false;
+}
+
+#define _RET_SUCCEED(exp) { result = (exp); return true; }
+bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,int &result)
+{
+ if(type(o1)==type(o2)){
+ if(_userpointer(o1)==_userpointer(o2))_RET_SUCCEED(0);
+ SQObjectPtr res;
+ switch(type(o1)){
+ case OT_STRING:
+ _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2)));
+ case OT_INTEGER:
+ _RET_SUCCEED(_integer(o1)-_integer(o2));
+ case OT_FLOAT:
+ _RET_SUCCEED((_float(o1)<_float(o2))?-1:1);
+ case OT_TABLE:
+ case OT_USERDATA:
+ case OT_INSTANCE:
+ Push(o1);Push(o2);
+ if(_delegable(o1)->_delegate)CallMetaMethod(_delegable(o1),MT_CMP,2,res);
+ break;
+ default:
+ break;
+ }
+ if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; }
+ _RET_SUCCEED(_integer(res));
+ }
+ else{
+ if(sq_isnumeric(o1) && sq_isnumeric(o2)){
+ if((type(o1)==OT_INTEGER) && (type(o2)==OT_FLOAT)) {
+ if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); }
+ else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); }
+ _RET_SUCCEED(1);
+ }
+ else{
+ if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); }
+ else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); }
+ _RET_SUCCEED(1);
+ }
+ }
+ else if(type(o1)==OT_NULL) {_RET_SUCCEED(-1);}
+ else if(type(o2)==OT_NULL) {_RET_SUCCEED(1);}
+ else { Raise_CompareError(o1,o2); return false; }
+
+ }
+ assert(0);
+ _RET_SUCCEED(0); //cannot happen
+}
+
+bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res)
+{
+ int r;
+ if(ObjCmp(o1,o2,r)) {
+ switch(op) {
+ case CMP_G: res = (r > 0)?_true_:_false_; return true;
+ case CMP_GE: res = (r >= 0)?_true_:_false_; return true;
+ case CMP_L: res = (r < 0)?_true_:_false_; return true;
+ case CMP_LE: res = (r <= 0)?_true_:_false_; return true;
+
+ }
+ assert(0);
+ }
+ return false;
+}
+
+bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)
+{
+ switch(type(obj))
+ {
+ case OT_STRING:
+ switch(type(str)){
+ case OT_STRING: {
+ int l=_string(str)->_len,ol=_string(obj)->_len;
+ SQChar *s=_sp(rsl(l+ol+1));
+ memcpy(s,_stringval(str),rsl(l));memcpy(s+l,_stringval(obj),rsl(ol));s[l+ol]=_SC('\0');
+ break;
+ }
+ case OT_FLOAT:
+ scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(obj)->_len+1)),_SC("%g%s"),_float(str),_stringval(obj));
+ break;
+ case OT_INTEGER:
+ scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(obj)->_len+1)),_SC("%d%s"),_integer(str),_stringval(obj));
+ break;
+ default:
+ Raise_Error(_SC("string concatenation between '%s' and '%s'"),GetTypeName(str),GetTypeName(obj));
+ return false;
+ }
+ dest=SQString::Create(_ss(this),_spval);
+ break;
+ case OT_FLOAT:
+ scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(str)->_len+1)),_SC("%s%g"),_stringval(str),_float(obj));
+ dest=SQString::Create(_ss(this),_spval);
+ break;
+ case OT_INTEGER:
+ scsprintf(_sp(rsl(NUMBER_MAX_CHAR+_string(str)->_len+1)),_SC("%s%d"),_stringval(str),_integer(obj));
+ dest=SQString::Create(_ss(this),_spval);
+ break;
+ default:
+ Raise_Error(_SC("string concatenation between '%s' and '%s'"),GetTypeName(str),GetTypeName(obj));
+ return false;
+ }
+ return true;
+}
+
+const SQChar *IdType2Name(SQObjectType type)
+{
+ switch(_RAW_TYPE(type))
+ {
+ case _RT_NULL:return _SC("null");
+ case _RT_INTEGER:return _SC("integer");
+ case _RT_FLOAT:return _SC("float");
+ case _RT_BOOL:return _SC("bool");
+ case _RT_STRING:return _SC("string");
+ case _RT_TABLE:return _SC("table");
+ case _RT_ARRAY:return _SC("array");
+ case _RT_GENERATOR:return _SC("generator");
+ case _RT_CLOSURE:
+ case _RT_NATIVECLOSURE:
+ return _SC("function");
+ case _RT_USERDATA:
+ case _RT_USERPOINTER:
+ return _SC("userdata");
+ case _RT_THREAD: return _SC("thread");
+ case _RT_FUNCPROTO: return _SC("function");
+ case _RT_CLASS: return _SC("class");
+ case _RT_INSTANCE: return _SC("instance");
+ default:
+ return NULL;
+ }
+}
+
+const SQChar *GetTypeName(const SQObjectPtr &obj1)
+{
+ return IdType2Name(type(obj1));
+}
+
+void SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest)
+{
+ if(is_delegable(obj1) && _delegable(obj1)->_delegate) {
+ Push(obj1);
+ if(CallMetaMethod(_delegable(obj1),MT_TYPEOF,1,dest))
+ return;
+ }
+ dest = SQString::Create(_ss(this),GetTypeName(obj1));
+}
+
+bool SQVM::Init(SQVM *friendvm, int stacksize)
+{
+ _stack.resize(stacksize);
+ _callsstack.reserve(4);
+ _stackbase = 0;
+ _top = 0;
+ if(!friendvm)
+ _roottable = SQTable::Create(_ss(this), 0);
+ else {
+ _roottable = friendvm->_roottable;
+ _errorhandler = friendvm->_errorhandler;
+ _debughook = friendvm->_debughook;
+ }
+
+ sq_base_register(this);
+ return true;
+}
+
+extern SQInstructionDesc g_InstrDesc[];
+
+bool SQVM::StartCall(SQClosure *closure,int target,int nargs,int stackbase,bool tailcall)
+{
+ SQFunctionProto *func = _funcproto(closure->_function);
+ //const int outerssize = func->_outervalues.size();
+
+ const int paramssize = func->_parameters.size();
+ // const int oldtop = _top;
+ const int newtop = stackbase + func->_stacksize;
+
+
+ if(func->_varparams)
+ {
+ if (nargs < paramssize) {
+ Raise_Error(_SC("wrong number of parameters"));
+ return false;
+ }
+ for(int n = 0; n < nargs - paramssize; n++) {
+ _vargsstack.push_back(_stack[stackbase+paramssize+n]);
+ _stack[stackbase+paramssize+n] = _null_;
+ }
+ }
+ else {
+ if (paramssize != nargs) {
+ Raise_Error(_SC("wrong number of parameters"));
+ return false;
+ }
+
+ }
+
+ if (!tailcall) {
+ PUSH_CALLINFO(this, CallInfo());
+ ci->_etraps = 0;
+ ci->_prevstkbase = stackbase - _stackbase;
+ ci->_target = target;
+ ci->_prevtop = _top - _stackbase;
+ ci->_ncalls = 1;
+ ci->_root = false;
+ }
+ else {
+ ci->_ncalls++;
+ }
+ ci->_vargs.size = (nargs - paramssize);
+ ci->_vargs.base = _vargsstack.size()-(nargs - paramssize);
+ ci->_closure._unVal.pClosure = closure;
+ ci->_closure._type = OT_CLOSURE;
+ ci->_iv = &func->_instructions;
+ ci->_literals = &func->_literals;
+ //grows the stack if needed
+ if (((unsigned int)newtop + (func->_stacksize<<1)) > _stack.size()) {
+ _stack.resize(_stack.size() + (func->_stacksize<<1));
+ }
+
+ _top = newtop;
+ _stackbase = stackbase;
+ ci->_ip = ci->_iv->_vals;
+ return true;
+}
+
+bool SQVM::Return(int _arg0, int _arg1, SQObjectPtr &retval)
+{
+ if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
+ for(int i=0;i<ci->_ncalls;i++)
+ CallDebugHook(_SC('r'));
+
+ bool broot = ci->_root;
+ int last_top = _top;
+ int target = ci->_target;
+ int oldstackbase = _stackbase;
+ _stackbase -= ci->_prevstkbase;
+ _top = _stackbase + ci->_prevtop;
+ PopVarArgs(ci->_vargs);
+ POP_CALLINFO(this);
+ if (broot) {
+ if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack[oldstackbase+_arg1];
+ else retval = _null_;
+ }
+ else {
+ if (_arg0 != MAX_FUNC_STACKSIZE)
+ STK(target) = _stack[oldstackbase+_arg1];
+ else
+ STK(target) = _null_;
+ }
+
+ while (last_top >= _top) _stack[last_top--].Null();
+ assert(oldstackbase >= _stackbase);
+ return broot;
+}
+
+#define _RET_ON_FAIL(exp) { if(!exp) return false; }
+
+bool SQVM::LOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)
+{
+ _RET_ON_FAIL(ARITH_OP( op , target, a, incr));
+ a = target;
+ return true;
+}
+
+bool SQVM::PLOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)
+{
+ SQObjectPtr trg;
+ _RET_ON_FAIL(ARITH_OP( op , trg, a, incr));
+ target = a;
+ a = trg;
+ return true;
+}
+
+bool SQVM::DerefInc(int op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix)
+{
+ SQObjectPtr tmp, tself = self, tkey = key;
+ if (!Get(tself, tkey, tmp, false, true)) { Raise_IdxError(tkey); return false; }
+ _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr))
+ Set(tself, tkey, target,true);
+ if (postfix) target = tmp;
+ return true;
+}
+
+#define arg0 (_i_._arg0)
+#define arg1 (_i_._arg1)
+#define sarg1 (*((int *)&_i_._arg1))
+#define arg2 (_i_._arg2)
+#define arg3 (_i_._arg3)
+#define sarg3 (*((char *)&_i_._arg3))
+
+SQRESULT SQVM::Suspend()
+{
+ if (_suspended)
+ return sq_throwerror(this, _SC("cannot suspend an already suspended vm"));
+ if (_nnativecalls!=2)
+ return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods"));
+ return SQ_SUSPEND_FLAG;
+}
+
+void SQVM::PopVarArgs(VarArgs &vargs)
+{
+ for(int n = 0; n< vargs.size; n++)
+ _vargsstack.pop_back();
+}
+
+#define _FINISH(stoploop) {finished = stoploop; return true; }
+bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
+&o3,SQObjectPtr &o4,int arg_2,bool &finished)
+{
+ int nrefidx;
+ switch(type(o1)) {
+ case OT_TABLE:
+ if((nrefidx = _table(o1)->Next(o4, o2, o3)) == -1) _FINISH(true);
+ o4 = (SQInteger)nrefidx; _FINISH(false);
+ case OT_ARRAY:
+ if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(true);
+ o4 = (SQInteger) nrefidx; _FINISH(false);
+ case OT_STRING:
+ if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(true);
+ o4 = (SQInteger)nrefidx; _FINISH(false);
+ case OT_CLASS:
+ if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(true);
+ o4 = (SQInteger)nrefidx; _FINISH(false);
+ case OT_USERDATA:
+ case OT_INSTANCE:
+ if(_delegable(o1)->_delegate) {
+ SQObjectPtr itr;
+ Push(o1);
+ Push(o4);
+ if(CallMetaMethod(_delegable(o1), MT_NEXTI, 2, itr)){
+ o4 = o2 = itr;
+ if(type(itr) == OT_NULL) _FINISH(true);
+ if(!Get(o1, itr, o3, false,false)) {
+ Raise_Error(_SC("_nexti returned an invalid idx"));
+ return false;
+ }
+ _FINISH(false);
+ }
+ Raise_Error(_SC("_nexti failed"));
+ return false;
+ }
+ break;
+ case OT_GENERATOR:
+ if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(true);
+ if(_generator(o1)->_state == SQGenerator::eSuspended) {
+ SQInteger idx = 0;
+ if(type(o4) == OT_INTEGER) {
+ idx = _integer(o4) + 1;
+ }
+ o2 = idx;
+ o4 = idx;
+ _generator(o1)->Resume(this, arg_2+1);
+ _FINISH(false);
+ }
+ default:
+ break;
+ }
+ Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));
+ return false; //cannot be hit(just to avoid warnings)
+}
+
+bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2)
+{
+ if(type(o1) != OT_TABLE) { Raise_Error(_SC("delegating a '%s'"), GetTypeName(o1)); return false; }
+ switch(type(o2)) {
+ case OT_TABLE:
+ if(!_table(o1)->SetDelegate(_table(o2))){
+ Raise_Error(_SC("delegate cycle detected"));
+ return false;
+ }
+ break;
+ case OT_NULL:
+ _table(o1)->SetDelegate(NULL);
+ break;
+ default:
+ Raise_Error(_SC("using '%s' as delegate"), GetTypeName(o2));
+ return false;
+ break;
+ }
+ trg = o1;
+ return true;
+}
+#define COND_LITERAL (arg3!=0?(*ci->_literals)[arg1]:STK(arg1))
+
+#define _GUARD(exp) { if(!exp) { Raise_Error(_lasterror); SQ_THROW();} }
+
+#define SQ_THROW() { goto exception_trap; }
+
+bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)
+{
+ int nouters;
+ SQClosure *closure = SQClosure::Create(_ss(this), func);
+ if( (nouters = func->_outervalues.size()) ) {
+ closure->_outervalues.reserve(nouters);
+ for(int i = 0; i<nouters; i++) {
+ SQOuterVar &v = func->_outervalues[i];
+ switch(v._type){
+ case otSYMBOL:
+ closure->_outervalues.push_back(_null_);
+ if(!Get(_stack._vals[_stackbase]/*STK(0)*/, v._src, closure->_outervalues.top(), false,true))
+ {Raise_IdxError(v._src); return false; }
+ break;
+ case otLOCAL:
+ closure->_outervalues.push_back(_stack._vals[_stackbase+_integer(v._src)]);
+ break;
+ case otOUTER:
+ closure->_outervalues.push_back(_closure(ci->_closure)->_outervalues[_integer(v._src)]);
+ break;
+ }
+ }
+ }
+ target = closure;
+ return true;
+
+}
+
+bool SQVM::GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &index,CallInfo *ci)
+{
+ if(ci->_vargs.size == 0) {
+ Raise_Error(_SC("the function doesn't have var args"));
+ return false;
+ }
+ if(!sq_isnumeric(index)){
+ Raise_Error(_SC("indexing 'vargv' with %s"),GetTypeName(index));
+ return false;
+ }
+ int idx = tointeger(index);
+ if(idx < 0 || idx >= ci->_vargs.size){ Raise_Error(_SC("vargv index out of range")); return false; }
+ target = _vargsstack[ci->_vargs.base+idx];
+ return true;
+}
+
+bool SQVM::CLASS_OP(SQObjectPtr &target,int baseclass,int attributes)
+{
+ SQClass *base = NULL;
+ SQObjectPtr attrs;
+ if(baseclass != MAX_LITERALS) {
+ if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; }
+ base = _class(_stack._vals[_stackbase + baseclass]);
+ }
+ if(attributes != MAX_FUNC_STACKSIZE) {
+ attrs = _stack._vals[_stackbase+attributes];
+ }
+ target = SQClass::Create(_ss(this),base);
+ _class(target)->_attributes = attrs;
+ return true;
+}
+
+bool SQVM::IsFalse(SQObjectPtr &o)
+{
+ SQObjectType t = type(o);
+ if((t & SQOBJECT_CANBEFALSE)
+ && ((t == OT_NULL) || ((t == OT_INTEGER || t == OT_BOOL) && _integer(o) == 0)
+ || (t == OT_FLOAT && _float(o) == SQFloat(0.0)))) {
+ return true;
+ }
+ return false;
+}
+
+bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res)
+{
+ if(type(o1) == type(o2)) {
+ res = ((_userpointer(o1) == _userpointer(o2)?true:false));
+ }
+ else {
+ if(sq_isnumeric(o1) && sq_isnumeric(o2)) {
+ int cmpres;
+ if(!ObjCmp(o1, o2,cmpres)) return false;
+ res = (cmpres == 0);
+ }
+ else {
+ res = false;
+ }
+ }
+ return true;
+}
+
+bool SQVM::Execute(SQObjectPtr &closure, int target, int nargs, int stackbase,SQObjectPtr &outres, ExecutionType et)
+{
+ if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }
+ _nnativecalls++;
+ AutoDec ad(&_nnativecalls);
+ int traps = 0;
+ //temp_reg vars for OP_CALL
+ int ct_target;
+ bool ct_tailcall;
+
+ switch(et) {
+ case ET_CALL:
+ if(!StartCall(_closure(closure), _top - nargs, nargs, stackbase, false)) {
+ //call the handler if there are no calls in the stack, if not relies on the previous node
+ if(ci == NULL) CallErrorHandler(_lasterror);
+ return false;
+ }
+ ci->_root = true;
+ break;
+ case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = true; traps += ci->_etraps; break;
+ case ET_RESUME_VM:
+ traps = _suspended_traps;
+ ci->_root = _suspended_root;
+ _suspended = false;
+ break;
+ }
+
+exception_restore:
+ //SQ_TRY
+ {
+ for(;;)
+ {
+ const SQInstruction &_i_ = *ci->_ip++;
+ //dumpstack(_stackbase);
+ //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-ci->_iv->_vals,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3);
+ switch(_i_.op)
+ {
+ case _OP_LINE:
+ if(type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
+ CallDebugHook(_SC('l'),arg1);
+ continue;
+ case _OP_LOAD: TARGET = (*ci->_literals)[arg1]; continue;
+ case _OP_TAILCALL:
+ temp_reg = STK(arg1);
+ if (type(temp_reg) == OT_CLOSURE){
+ ct_tailcall = true;
+ PopVarArgs(ci->_vargs);
+ for (int i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);
+ ct_target = ci->_target;
+ goto common_call;
+ }
+ case _OP_CALL: {
+ ct_tailcall = false;
+ ct_target = arg0;
+ temp_reg = STK(arg1);
+common_call:
+ int last_top = _top;
+ switch (type(temp_reg)) {
+ case OT_CLOSURE:{
+ StartCall(_closure(temp_reg), ct_target, arg3, ct_tailcall?_stackbase:_stackbase+arg2, ct_tailcall);
+ if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) {
+ SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg));
+ _GUARD(gen->Yield(this));
+ Return(1, ct_target, temp_reg);
+ STK(ct_target) = gen;
+ while (last_top >= _top) _stack[last_top--].Null();
+ continue;
+ }
+ if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
+ CallDebugHook(_SC('c'));
+ }
+ break;
+ case OT_NATIVECLOSURE: {
+ bool suspend;
+ _GUARD(CallNative(_nativeclosure(temp_reg), arg3, _stackbase+arg2, ct_tailcall, temp_reg,suspend));
+ if(suspend){
+ _suspended = true;
+ _suspended_target = ct_target;
+ _suspended_root = ci->_root;
+ _suspended_traps = traps;
+ outres = temp_reg;
+ return true;
+ }
+ STK(ct_target) = temp_reg;
+ }
+ break;
+ case OT_CLASS:{
+ _GUARD(CreateClassInstance(_class(temp_reg),arg3,_stackbase+arg2,STK(ct_target)));
+ }
+ break;
+ case OT_TABLE:
+ case OT_USERDATA:
+ case OT_INSTANCE:
+ {
+ Push(temp_reg);
+ for (int i = 0; i < arg3; i++) Push(STK(arg2 + i));
+ if (_delegable(temp_reg) && CallMetaMethod(_delegable(temp_reg), MT_CALL, arg3+1, temp_reg)){
+ STK(ct_target) = temp_reg;
+ break;
+ }
+ Raise_Error(_SC("attempt to call '%s'"), GetTypeName(temp_reg));
+ SQ_THROW();
+ }
+ default:
+ Raise_Error(_SC("attempt to call '%s'"), GetTypeName(temp_reg));
+ SQ_THROW();
+ }
+ }
+ continue;
+ case _OP_PREPCALL:
+ if (!Get(STK(arg2), STK(arg1), temp_reg, false,true))
+ { Raise_IdxError(STK(arg1)); SQ_THROW(); }
+ goto common_prepcall;
+ case _OP_PREPCALLK:
+ if (!Get(STK(arg2), (*ci->_literals)[arg1], temp_reg,false,true)) {
+ if(type(STK(arg2)) == OT_CLASS) { //hack?
+ if(_class_ddel->Get((*ci->_literals)[arg1],temp_reg)) {
+ STK(arg3) = STK(arg2);
+ TARGET = temp_reg;
+ continue;
+ }
+ }
+ { Raise_IdxError((*ci->_literals)[arg1]); SQ_THROW();}
+ }
+common_prepcall:
+ if(type(STK(arg2)) == OT_CLASS) {
+ STK(arg3) = STK(0); // this
+ }
+ else {
+ STK(arg3) = STK(arg2);
+ }
+ TARGET = temp_reg;
+ continue;
+ case _OP_GETK:
+ if (!Get(STK(arg2), (*ci->_literals)[arg1], temp_reg, false,true)) { Raise_IdxError((*ci->_literals)[arg1]); SQ_THROW();}
+ TARGET = temp_reg;
+ continue;
+ case _OP_MOVE: TARGET = STK(arg1); continue;
+ case _OP_NEWSLOT:
+ _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3)));
+ if(arg0 != arg3) TARGET = STK(arg3);
+ continue;
+ case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue;
+ case _OP_SET:
+ if (!Set(STK(arg1), STK(arg2), STK(arg3),true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); }
+ if (arg0 != arg3) TARGET = STK(arg3);
+ continue;
+ case _OP_GET:
+ if (!Get(STK(arg1), STK(arg2), temp_reg, false,true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); }
+ TARGET = temp_reg;
+ continue;
+ case _OP_EQ:{
+ bool res;
+ if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }
+ TARGET = res?_true_:_false_;
+ }continue;
+ case _OP_NE:{
+ bool res;
+ if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }
+ TARGET = (!res)?_true_:_false_;
+ } continue;
+ case _OP_ARITH: _GUARD(ARITH_OP( arg3 , temp_reg, STK(arg2), STK(arg1))); TARGET = temp_reg; continue;
+ case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue;
+ case _OP_RETURN:
+ if(type((ci)->_generator) == OT_GENERATOR) {
+ _generator((ci)->_generator)->Kill();
+ }
+ if(Return(arg0, arg1, temp_reg)){
+ assert(traps==0);
+ outres = temp_reg;
+ return true;
+ }
+ continue;
+ case _OP_LOADNULLS:{ for(unsigned int n=0;n<arg1;n++) STK(arg0+n) = _null_; }continue;
+ case _OP_LOADROOTTABLE: TARGET = _roottable; continue;
+ case _OP_LOADBOOL: TARGET = arg1?_true_:_false_; continue;
+ case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue;
+ case _OP_JMP: ci->_ip += (sarg1); continue;
+ case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
+ case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
+ case _OP_LOADFREEVAR: TARGET = _closure(ci->_closure)->_outervalues[arg1]; continue;
+ case _OP_VARGC: TARGET = SQInteger(ci->_vargs.size); continue;
+ case _OP_GETVARGV:
+ if(!GETVARGV_OP(TARGET,STK(arg1),ci)) { SQ_THROW(); }
+ continue;
+ case _OP_NEWTABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;
+ case _OP_NEWARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;
+ case _OP_APPENDARRAY: _array(STK(arg0))->Append(COND_LITERAL); continue;
+ case _OP_GETPARENT:
+ switch(type(STK(arg1))) {
+ case OT_TABLE:
+ TARGET = _table(STK(arg1))->_delegate?SQObjectPtr(_table(STK(arg1))->_delegate):_null_;
+ continue;
+ case OT_CLASS: TARGET = _class(STK(arg1))->_base?_class(STK(arg1))->_base:_null_;
+ continue;
+ default:
+ break;
+ }
+ Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(STK(arg1)));
+ SQ_THROW();
+ continue;
+ case _OP_COMPARITH: _GUARD(DerefInc(arg3, TARGET, STK((((unsigned int)arg1&0xFFFF0000)>>16)), STK(arg2), STK(arg1&0x0000FFFF), false)); continue;
+ case _OP_COMPARITHL: _GUARD(LOCAL_INC(arg3, TARGET, STK(arg1), STK(arg2))); continue;
+ case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false));} continue;
+ case _OP_INCL: {SQObjectPtr o(sarg3); _GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));} continue;
+ case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true));} continue;
+ case _OP_PINCL: {SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));} continue;
+ case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue;
+ case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,false)?_true_:_false_;continue;
+ case _OP_INSTANCEOF:
+ if(type(STK(arg1)) != OT_CLASS || type(STK(arg2)) != OT_INSTANCE)
+ {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();}
+ TARGET = _instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?_true_:_false_;
+ continue;
+ case _OP_AND:
+ if(IsFalse(STK(arg2))) {
+ TARGET = STK(arg2);
+ ci->_ip += (sarg1);
+ }
+ continue;
+ case _OP_OR:
+ if(!IsFalse(STK(arg2))) {
+ TARGET = STK(arg2);
+ ci->_ip += (sarg1);
+ }
+ continue;
+ case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue;
+ case _OP_NOT: TARGET = (IsFalse(STK(arg1))?_true_:_false_); continue;
+ case _OP_BWNOT:
+ if(type(STK(arg1)) == OT_INTEGER) {
+ TARGET = SQInteger(~_integer(STK(arg1)));
+ continue;
+ }
+ Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1)));
+ SQ_THROW();
+ case _OP_CLOSURE: {
+ SQClosure *c = ci->_closure._unVal.pClosure;
+ SQFunctionProto *fp = c->_function._unVal.pFunctionProto;
+ if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); }
+ continue;
+ }
+ case _OP_YIELD:{
+ if(type(ci->_generator) == OT_GENERATOR) {
+ if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);
+ _GUARD(_generator(ci->_generator)->Yield(this));
+ traps -= ci->_etraps;
+ if(sarg1 != MAX_FUNC_STACKSIZE) STK(arg1) = temp_reg;
+ }
+ else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();}
+ if(Return(arg0, arg1, temp_reg)){
+ assert(traps==0);
+ outres = temp_reg;
+ return true;
+ }
+
+ }
+ continue;
+ case _OP_RESUME:
+ if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();}
+ _GUARD(_generator(STK(arg1))->Resume(this, arg0));
+ traps += ci->_etraps;
+ continue;
+ case _OP_FOREACH:{ bool finished;
+ _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,finished));
+ if(finished) ci->_ip += sarg1; }
+ continue;
+ case _OP_DELEGATE: _GUARD(DELEGATE_OP(TARGET,STK(arg1),STK(arg2))); continue;
+ case _OP_CLONE:
+ if(!Clone(STK(arg1), TARGET))
+ { Raise_Error(_SC("cloning a %s"), GetTypeName(STK(arg1))); SQ_THROW();}
+ continue;
+ case _OP_TYPEOF: TypeOf(STK(arg1), TARGET); continue;
+ case _OP_PUSHTRAP:
+ _etraps.push_back(SQExceptionTrap(_top,_stackbase, &ci->_iv->_vals[(ci->_ip-ci->_iv->_vals)+arg1], arg0)); traps++;
+ ci->_etraps++;
+ continue;
+ case _OP_POPTRAP:{
+ for(int i=0; i<arg0; i++) {
+ _etraps.pop_back(); traps--;
+ ci->_etraps--;
+ }}
+ continue;
+ case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue;
+ case _OP_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;
+ case _OP_NEWSLOTA:
+ _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3)));
+ _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1));
+ if(arg0 != arg3) TARGET = STK(arg3);
+ continue;
+ }
+
+ }
+ }
+exception_trap:
+ {
+ SQObjectPtr currerror = _lasterror;
+// dumpstack(_stackbase);
+ int n = 0;
+ int last_top = _top;
+ if(ci) {
+ if(traps) {
+ do {
+ if(ci->_etraps > 0) {
+ SQExceptionTrap &et = _etraps.top();
+ ci->_ip = et._ip;
+ _top = et._stacksize;
+ _stackbase = et._stackbase;
+ _stack[_stackbase+et._extarget] = currerror;
+ _etraps.pop_back(); traps--; ci->_etraps--;
+ while(last_top >= _top) _stack[last_top--].Null();
+ goto exception_restore;
+ }
+ //if is a native closure
+ if(type(ci->_closure) != OT_CLOSURE && n)
+ break;
+ if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill();
+ PopVarArgs(ci->_vargs);
+ POP_CALLINFO(this);
+ n++;
+ }while(_callsstack.size());
+ }
+ //call the hook
+ CallErrorHandler(currerror);
+ //remove call stack until a C function is found or the cstack is empty
+ if(ci) do{
+ bool exitafterthisone = ci->_root;
+ if(type(ci->_generator) == OT_GENERATOR) _generator(ci->_generator)->Kill();
+ _stackbase -= ci->_prevstkbase;
+ _top = _stackbase + ci->_prevtop;
+ PopVarArgs(ci->_vargs);
+ POP_CALLINFO(this);
+ if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) break;
+ }while(_callsstack.size());
+
+ while(last_top >= _top) _stack[last_top--].Null();
+ }
+ _lasterror = currerror;
+ return false;
+ }
+ assert(0);
+}
+
+bool SQVM::CreateClassInstance(SQClass *theclass, int nargs, int stackbase, SQObjectPtr &retval)
+{
+ SQObjectPtr constr;
+ SQObjectPtr inst = theclass->CreateInstance();
+ _stack[stackbase] = inst;
+ if(theclass->Get(_ss(this)->_constructoridx,constr)) {
+ if(!Call(constr,nargs,stackbase,constr))
+ return false;
+ }
+ retval = inst;
+ return true;
+}
+
+void SQVM::CallErrorHandler(SQObjectPtr &error)
+{
+ if(type(_errorhandler) != OT_NULL) {
+ SQObjectPtr out;
+ Push(_roottable); Push(error);
+ Call(_errorhandler, 2, _top-2, out);
+ Pop(2);
+ }
+}
+
+void SQVM::CallDebugHook(int type,int forcedline)
+{
+ SQObjectPtr temp_reg;
+ int nparams=5;
+ SQFunctionProto *func=_funcproto(_closure(ci->_closure)->_function);
+ Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);
+ Call(_debughook,nparams,_top-nparams,temp_reg);
+ Pop(nparams);
+}
+
+bool SQVM::CallNative(SQNativeClosure *nclosure,int nargs,int stackbase,bool tailcall,SQObjectPtr &retval,bool &suspend)
+{
+ (void) tailcall;
+ if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }
+ int nparamscheck = nclosure->_nparamscheck;
+ if(((nparamscheck > 0) && (nparamscheck != nargs))
+ || ((nparamscheck < 0) && (nargs < (-nparamscheck)))) {
+ Raise_Error(_SC("wrong number of parameters"));
+ return false;
+ }
+
+ int tcs;
+ if( (tcs = nclosure->_typecheck.size()) ) {
+ for(int i = 0; i < nargs && i < tcs; i++)
+ if((nclosure->_typecheck[i] != -1) && !(type(_stack[stackbase+i]) & nclosure->_typecheck[i])) {
+ Raise_ParamTypeError(i,nclosure->_typecheck[i],type(_stack[stackbase+i]));
+ return false;
+ }
+ }
+ _nnativecalls++;
+ if ((_top + MIN_STACK_OVERHEAD) > (int)_stack.size()) {
+ _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD<<1));
+ }
+ int oldtop = _top;
+ int oldstackbase = _stackbase;
+ _top = stackbase + nargs;
+ PUSH_CALLINFO(this, CallInfo());
+ ci->_etraps = 0;
+ ci->_closure._unVal.pNativeClosure = nclosure;
+ ci->_closure._type = OT_NATIVECLOSURE;
+ ci->_prevstkbase = stackbase - _stackbase;
+ ci->_ncalls = 1;
+ _stackbase = stackbase;
+ //push free variables
+ int outers = nclosure->_outervalues.size();
+ for (int i = 0; i < outers; i++) {
+ Push(nclosure->_outervalues[i]);
+ }
+ ci->_prevtop = (oldtop - oldstackbase);
+ int ret = (nclosure->_function)(this);
+ _nnativecalls--;
+ suspend = false;
+ if( ret == SQ_SUSPEND_FLAG) suspend = true;
+ else if (ret < 0) {
+ _stackbase = oldstackbase;
+ _top = oldtop;
+ POP_CALLINFO(this);
+ Raise_Error(_lasterror);
+ return false;
+ }
+
+ if (ret != 0){ retval = TOP(); }
+ else { retval = _null_; }
+ _stackbase = oldstackbase;
+ _top = oldtop;
+ POP_CALLINFO(this);
+ return true;
+}
+
+bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, bool fetchroot)
+{
+ switch(type(self)){
+ case OT_TABLE:
+ if(_table(self)->Get(key,dest))return true;
+ break;
+ case OT_ARRAY:
+ if(sq_isnumeric(key)){
+ return _array(self)->Get(tointeger(key),dest);
+ }
+ break;
+ case OT_INSTANCE:
+ if(_instance(self)->Get(key,dest)) return true;
+ break;
+ default:
+ break;
+ }
+ if(FallBackGet(self,key,dest,raw)) return true;
+
+ if(fetchroot) {
+ if(_rawval(STK(0)) == _rawval(self) &&
+ type(STK(0)) == type(self)) {
+ return _table(_roottable)->Get(key,dest);
+ }
+ }
+ return false;
+}
+
+bool SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw)
+{
+ switch(type(self)){
+ case OT_CLASS:
+ return _class(self)->Get(key,dest);
+ break;
+ case OT_TABLE:
+ case OT_USERDATA:
+ //delegation
+ if(_delegable(self)->_delegate) {
+ if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,raw,false))
+ return true;
+ if(raw)return false;
+ Push(self);Push(key);
+ if(CallMetaMethod(_delegable(self),MT_GET,2,dest))
+ return true;
+ }
+ if(type(self) == OT_TABLE) {
+ if(raw) return false;
+ return _table_ddel->Get(key,dest);
+ }
+ return false;
+ break;
+ case OT_ARRAY:
+ if(raw)return false;
+ return _array_ddel->Get(key,dest);
+ case OT_STRING:
+ if(sq_isnumeric(key)){
+ SQInteger n=tointeger(key);
+ if(abs(n)<_string(self)->_len){
+ if(n<0)n=_string(self)->_len-n;
+ dest=SQInteger(_stringval(self)[n]);
+ return true;
+ }
+ return false;
+ }
+ else {
+ if(raw)return false;
+ return _string_ddel->Get(key,dest);
+ }
+ break;
+ case OT_INSTANCE:
+ if(raw)return false;
+ Push(self);Push(key);
+ if(!CallMetaMethod(_delegable(self),MT_GET,2,dest)) {
+ return _instance_ddel->Get(key,dest);
+ }
+ return true;
+ case OT_INTEGER:case OT_FLOAT:case OT_BOOL:
+ if(raw)return false;
+ return _number_ddel->Get(key,dest);
+ case OT_GENERATOR:
+ if(raw)return false;
+ return _generator_ddel->Get(key,dest);
+ case OT_CLOSURE: case OT_NATIVECLOSURE:
+ if(raw)return false;
+ return _closure_ddel->Get(key,dest);
+ case OT_THREAD:
+ if(raw)return false;
+ return _thread_ddel->Get(key,dest);
+ default:return false;
+ }
+ return false;
+}
+
+bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool fetchroot)
+{
+ switch(type(self)){
+ case OT_TABLE:
+ if(_table(self)->Set(key,val))
+ return true;
+ if(_table(self)->_delegate) {
+ if(Set(_table(self)->_delegate,key,val,false)) {
+ return true;
+ }
+ }
+ //keeps going
+ case OT_USERDATA:
+ if(_delegable(self)->_delegate) {
+ SQObjectPtr t;
+ Push(self);Push(key);Push(val);
+ if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true;
+ }
+ break;
+ case OT_INSTANCE:{
+ if(_instance(self)->Set(key,val))
+ return true;
+ SQObjectPtr t;
+ Push(self);Push(key);Push(val);
+ if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true;
+ }
+ break;
+ case OT_ARRAY:
+ if(!sq_isnumeric(key)) {Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; }
+ return _array(self)->Set(tointeger(key),val);
+ default:
+ Raise_Error(_SC("trying to set '%s'"),GetTypeName(self));
+ return false;
+ }
+ if(fetchroot) {
+ if(_rawval(STK(0)) == _rawval(self) &&
+ type(STK(0)) == type(self)) {
+ return _table(_roottable)->Set(key,val);
+ }
+ }
+ return false;
+}
+
+bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target)
+{
+ SQObjectPtr temp_reg;
+ switch(type(self)){
+ case OT_TABLE:
+ target = _table(self)->Clone();
+ goto cloned_mt;
+ case OT_INSTANCE:
+ target = _instance(self)->Clone(_ss(this));
+cloned_mt:
+ if(_delegable(target)->_delegate){
+ Push(target);
+ Push(self);
+ CallMetaMethod(_delegable(target),MT_CLONED,2,temp_reg);
+ }
+ return true;
+ case OT_ARRAY:
+ target=_array(self)->Clone();
+ return true;
+ default: return false;
+ }
+}
+
+bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val)
+{
+ if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; }
+ switch(type(self)) {
+ case OT_TABLE: {
+ bool rawcall = true;
+ if(_table(self)->_delegate) {
+ SQObjectPtr res;
+ if(!_table(self)->Get(key,res)) {
+ Push(self);Push(key);Push(val);
+ rawcall = !CallMetaMethod(_table(self),MT_NEWSLOT,3,res);
+ }
+ }
+ if(rawcall) _table(self)->NewSlot(key,val); //cannot fail
+
+ break;}
+ case OT_CLASS:
+ if(!_class(self)->NewSlot(key,val)) {
+ if(_class(self)->_locked) {
+ Raise_Error(_SC("trying to modify a class that has already been instantiated"));
+ return false;
+ }
+ else {
+ SQObjectPtr oval = PrintObjVal(key);
+ Raise_Error(_SC("the property '%s' already exists"),_stringval(oval));
+ return false;
+ }
+ }
+ break;
+ default:
+ Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key));
+ return false;
+ break;
+ }
+ return true;
+}
+
+bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res)
+{
+ switch(type(self)) {
+ case OT_TABLE:
+ case OT_INSTANCE:
+ case OT_USERDATA: {
+ SQObjectPtr t;
+ bool handled = false;
+ if(_delegable(self)->_delegate) {
+ Push(self);Push(key);
+ handled = CallMetaMethod(_delegable(self),MT_DELSLOT,2,t);
+ }
+
+ if(!handled) {
+ if(type(self) == OT_TABLE) {
+ if(_table(self)->Get(key,t)) {
+ _table(self)->Remove(key);
+ }
+ else {
+ Raise_IdxError((SQObject &)key);
+ return false;
+ }
+ }
+ else {
+ Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self));
+ return false;
+ }
+ }
+ res = t;
+ }
+ break;
+ default:
+ Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self));
+ return false;
+ }
+ return true;
+}
+
+bool SQVM::Call(SQObjectPtr &closure,int nparams,int stackbase,SQObjectPtr &outres)
+{
+#ifdef _DEBUG
+int prevstackbase = _stackbase;
+#endif
+ switch(type(closure)) {
+ case OT_CLOSURE:
+ return Execute(closure, _top - nparams, nparams, stackbase,outres);
+ break;
+ case OT_NATIVECLOSURE:{
+ bool suspend;
+ return CallNative(_nativeclosure(closure), nparams, stackbase, false, outres,suspend);
+
+ }
+ break;
+ case OT_CLASS:
+ return CreateClassInstance(_class(closure),nparams,stackbase,outres);
+ break;
+ default:
+ return false;
+ }
+#ifdef _DEBUG
+ if(!_suspended) {
+ assert(_stackbase == prevstackbase);
+ }
+#endif
+ return true;
+}
+
+bool SQVM::CallMetaMethod(SQDelegable *del,SQMetaMethod mm,int nparams,SQObjectPtr &outres)
+{
+ SQObjectPtr closure;
+ if(del->GetMetaMethod(mm, closure)) {
+ if(Call(closure, nparams, _top - nparams, outres)) {
+ Pop(nparams);
+ return true;
+ }
+ }
+ Pop(nparams);
+ return false;
+}
+
+void SQVM::Pop() {
+ _stack[--_top] = _null_;
+}
+void SQVM::Pop(int n) {
+ for(int i = 0; i < n; i++){
+ _stack[--_top] = _null_;
+ }
+}
+
+void SQVM::Remove(int n) {
+ n = (n >= 0)?n + _stackbase - 1:_top + n;
+ for(int i = n; i < _top; i++){
+ _stack[i] = _stack[i+1];
+ }
+ _stack[_top] = _null_;
+ _top--;
+}
+
+void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; }
+SQObjectPtr &SQVM::Top() { return _stack[_top-1]; }
+SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; }
+SQObjectPtr &SQVM::GetUp(int n) { return _stack[_top+n]; }
+SQObjectPtr &SQVM::GetAt(int n) { return _stack[n]; }
+
+#ifdef _DEBUG_DUMP
+void SQVM::dumpstack(int stackbase,bool dumpall)
+{
+ int size=dumpall?_stack.size():_top;
+ int n=0;
+ scprintf(_SC("\n>>>>stack dump<<<<\n"));
+ CallInfo &ci=_callsstack.back();
+ scprintf(_SC("IP: %d\n"),ci._ip);
+ scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase);
+ scprintf(_SC("prev top: %d\n"),ci._prevtop);
+ for(int i=0;i<size;i++){
+ SQObjectPtr &obj=_stack[i];
+ if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));
+ scprintf(_SC("[%d]:"),n);
+ switch(type(obj)){
+ case OT_FLOAT: scprintf(_SC("FLOAT %.3f"),_float(obj));break;
+ case OT_INTEGER: scprintf(_SC("INTEGER %d"),_integer(obj));break;
+ case OT_BOOL: scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break;
+ case OT_STRING: scprintf(_SC("STRING %s"),_stringval(obj));break;
+ case OT_NULL: scprintf(_SC("NULL")); break;
+ case OT_TABLE: scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break;
+ case OT_ARRAY: scprintf(_SC("ARRAY %p"),_array(obj));break;
+ case OT_CLOSURE: scprintf(_SC("CLOSURE [%p]"),_closure(obj));break;
+ case OT_NATIVECLOSURE: scprintf(_SC("NATIVECLOSURE"));break;
+ case OT_USERDATA: scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break;
+ case OT_GENERATOR: scprintf(_SC("GENERATOR"));break;
+ case OT_THREAD: scprintf(_SC("THREAD [%p]"),_thread(obj));break;
+ case OT_USERPOINTER: scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break;
+ case OT_CLASS: scprintf(_SC("CLASS %p"),_class(obj));break;
+ case OT_INSTANCE: scprintf(_SC("INSTANCE %p"),_instance(obj));break;
+ default:
+ assert(0);
+ break;
+ };
+ scprintf(_SC("\n"));
+ ++n;
+ }
+}
+
+#endif
-/* see copyright notice in squirrel.h */\r
-#ifndef _SQVM_H_\r
-#define _SQVM_H_\r
-\r
-#include "sqopcodes.h"\r
-#include "sqobject.h"\r
-#define MAX_NATIVE_CALLS 100\r
-#define MIN_STACK_OVERHEAD 10\r
-\r
-#define SQ_SUSPEND_FLAG -666\r
-//base lib\r
-void sq_base_register(HSQUIRRELVM v);\r
-\r
-struct SQExceptionTrap{\r
- SQExceptionTrap() {}\r
- SQExceptionTrap(int ss, int stackbase,SQInstruction *ip, int ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}\r
- SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; }\r
- int _stackbase;\r
- int _stacksize;\r
- SQInstruction *_ip;\r
- int _extarget;\r
-};\r
-\r
-\r
-#define STK(a) _stack._vals[_stackbase+(a)]\r
-#define TARGET _stack._vals[_stackbase+arg0]\r
-\r
-typedef sqvector<SQExceptionTrap> ExceptionsTraps;\r
-\r
-struct SQVM : public CHAINABLE_OBJ\r
-{\r
- struct VarArgs {\r
- VarArgs() { size = 0; base = 0; }\r
- int size;\r
- int base;\r
- };\r
-\r
- struct CallInfo{\r
- //CallInfo() {}\r
- //CallInfo(const CallInfo& ci) { }\r
- SQInstructionVec *_iv;\r
- SQObjectPtrVec *_literals;\r
- SQObject _closure;\r
- SQObject _generator;\r
- int _etraps;\r
- int _prevstkbase;\r
- int _prevtop;\r
- int _target;\r
- SQInstruction *_ip;\r
- int _ncalls;\r
- bool _root;\r
- VarArgs _vargs;\r
- };\r
-\r
-typedef sqvector<CallInfo> CallInfoVec;\r
-public:\r
- enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM };\r
- SQVM(SQSharedState *ss);\r
- ~SQVM();\r
- bool Init(SQVM *friendvm, int stacksize);\r
- bool Execute(SQObjectPtr &func, int target, int nargs, int stackbase, SQObjectPtr &outres, ExecutionType et = ET_CALL);\r
- //start a native call return when the NATIVE closure returns(returns true if the vm has been suspended)\r
- bool CallNative(SQNativeClosure *nclosure, int nargs, int stackbase, bool tailcall, SQObjectPtr &retval,bool &suspend);\r
- //start a SQUIRREL call in the same "Execution loop"\r
- bool StartCall(SQClosure *closure, int target, int nargs, int stackbase, bool tailcall);\r
- bool CreateClassInstance(SQClass *theclass, int nargs, int stackbase, SQObjectPtr &retval);\r
- //call a generic closure pure SQUIRREL or NATIVE\r
- bool Call(SQObjectPtr &closure, int nparams, int stackbase, SQObjectPtr &outres);\r
- SQRESULT Suspend();\r
-\r
- void CallDebugHook(int type,int forcedline=0);\r
- void CallErrorHandler(SQObjectPtr &e);\r
- bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, bool fetchroot);\r
- bool FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw);\r
- bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, bool fetchroot);\r
- bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val);\r
- bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res);\r
- bool Clone(const SQObjectPtr &self, SQObjectPtr &target);\r
- bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,int &res);\r
- bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);\r
- bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res);\r
- bool IsFalse(SQObjectPtr &o);\r
- SQString *PrintObjVal(const SQObject &o);\r
-\r
- \r
- void Raise_Error(const SQChar *s, ...);\r
- void Raise_Error(SQObjectPtr &desc);\r
- void Raise_IdxError(SQObject &o);\r
- void Raise_CompareError(const SQObject &o1, const SQObject &o2);\r
- void Raise_ParamTypeError(int nparam,int typemask,int type);\r
-\r
- void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);\r
- bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, int nparams, SQObjectPtr &outres);\r
- bool ArithMetaMethod(int op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);\r
- //void Modulo(const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);\r
- bool Return(int _arg0, int _arg1, SQObjectPtr &retval);\r
- //new stuff\r
- bool ARITH_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);\r
- bool BW_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);\r
- bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);\r
- bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);\r
- bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);\r
- bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci);\r
- bool CLASS_OP(SQObjectPtr &target,int base,int attrs);\r
- //return true if the loop is finished\r
- bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,int arg_2,bool &finished);\r
- bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2);\r
- bool LOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);\r
- bool PLOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);\r
- bool DerefInc(int op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix);\r
- void PopVarArgs(VarArgs &vargs);\r
-#ifdef _DEBUG_DUMP\r
- void dumpstack(int stackbase=-1, bool dumpall = false);\r
-#endif\r
-\r
-#ifndef NO_GARBAGE_COLLECTOR\r
- void Mark(SQCollectable **chain);\r
-#endif\r
- void Finalize();\r
-\r
- void Release(){ sq_delete(this,SQVM); } //does nothing\r
-////////////////////////////////////////////////////////////////////////////\r
- //stack functions for the api\r
- void Pop();\r
- void Pop(int n);\r
- void Remove(int n);\r
-\r
- void Push(const SQObjectPtr &o);\r
- SQObjectPtr &Top();\r
- SQObjectPtr &PopGet();\r
- SQObjectPtr &GetUp(int n);\r
- SQObjectPtr &GetAt(int n);\r
-\r
- SQObjectPtrVec _stack;\r
- SQObjectPtrVec _vargsstack;\r
- int _top;\r
- int _stackbase;\r
- SQObjectPtr _roottable;\r
- //SQObjectPtr _thrownerror;\r
- SQObjectPtr _lasterror;\r
- SQObjectPtr _errorhandler;\r
- SQObjectPtr _debughook;\r
-\r
- SQObjectPtr temp_reg;\r
- CallInfoVec _callsstack;\r
- ExceptionsTraps _etraps;\r
- CallInfo *ci;\r
- void *_foreignptr;\r
- //VMs sharing the same state\r
- SQSharedState *_sharedstate;\r
- int _nnativecalls;\r
- //suspend infos\r
- bool _suspended;\r
- bool _suspended_root;\r
- int _suspended_target;\r
- int _suspended_traps;\r
-};\r
-\r
-struct AutoDec{\r
- AutoDec(int *n) { _n = n; }\r
- ~AutoDec() { (*_n)--; }\r
- int *_n;\r
-};\r
-\r
-SQObjectPtr &stack_get(HSQUIRRELVM v, int idx);\r
-const SQChar *GetTypeName(const SQObjectPtr &obj1);\r
-const SQChar *IdType2Name(SQObjectType type);\r
-\r
-#define _ss(_vm_) (_vm_)->_sharedstate\r
-\r
-#ifndef NO_GARBAGE_COLLECTOR\r
-#define _opt_ss(_vm_) (_vm_)->_sharedstate\r
-#else\r
-#define _opt_ss(_vm_) NULL\r
-#endif\r
-\r
-#define PUSH_CALLINFO(v,nci){ \\r
- v->_callsstack.push_back(nci); \\r
- v->ci = &v->_callsstack.back(); \\r
-}\r
-\r
-#define POP_CALLINFO(v){ \\r
- v->_callsstack.pop_back(); \\r
- if(v->_callsstack.size()) \\r
- v->ci = &v->_callsstack.back() ; \\r
- else \\r
- v->ci = NULL; \\r
-}\r
-#endif //_SQVM_H_\r
+/* see copyright notice in squirrel.h */
+#ifndef _SQVM_H_
+#define _SQVM_H_
+
+#include "sqopcodes.h"
+#include "sqobject.h"
+#define MAX_NATIVE_CALLS 100
+#define MIN_STACK_OVERHEAD 10
+
+#define SQ_SUSPEND_FLAG -666
+//base lib
+void sq_base_register(HSQUIRRELVM v);
+
+struct SQExceptionTrap{
+ SQExceptionTrap() {}
+ SQExceptionTrap(int ss, int stackbase,SQInstruction *ip, int ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}
+ SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; }
+ int _stackbase;
+ int _stacksize;
+ SQInstruction *_ip;
+ int _extarget;
+};
+
+
+#define STK(a) _stack._vals[_stackbase+(a)]
+#define TARGET _stack._vals[_stackbase+arg0]
+
+typedef sqvector<SQExceptionTrap> ExceptionsTraps;
+
+struct SQVM : public CHAINABLE_OBJ
+{
+ struct VarArgs {
+ VarArgs() { size = 0; base = 0; }
+ int size;
+ int base;
+ };
+
+ struct CallInfo{
+ //CallInfo() {}
+ //CallInfo(const CallInfo& ci) { }
+ SQInstructionVec *_iv;
+ SQObjectPtrVec *_literals;
+ SQObject _closure;
+ SQObject _generator;
+ int _etraps;
+ int _prevstkbase;
+ int _prevtop;
+ int _target;
+ SQInstruction *_ip;
+ int _ncalls;
+ bool _root;
+ VarArgs _vargs;
+ };
+
+typedef sqvector<CallInfo> CallInfoVec;
+public:
+ enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM };
+ SQVM(SQSharedState *ss);
+ ~SQVM();
+ bool Init(SQVM *friendvm, int stacksize);
+ bool Execute(SQObjectPtr &func, int target, int nargs, int stackbase, SQObjectPtr &outres, ExecutionType et = ET_CALL);
+ //start a native call return when the NATIVE closure returns(returns true if the vm has been suspended)
+ bool CallNative(SQNativeClosure *nclosure, int nargs, int stackbase, bool tailcall, SQObjectPtr &retval,bool &suspend);
+ //start a SQUIRREL call in the same "Execution loop"
+ bool StartCall(SQClosure *closure, int target, int nargs, int stackbase, bool tailcall);
+ bool CreateClassInstance(SQClass *theclass, int nargs, int stackbase, SQObjectPtr &retval);
+ //call a generic closure pure SQUIRREL or NATIVE
+ bool Call(SQObjectPtr &closure, int nparams, int stackbase, SQObjectPtr &outres);
+ SQRESULT Suspend();
+
+ void CallDebugHook(int type,int forcedline=0);
+ void CallErrorHandler(SQObjectPtr &e);
+ bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, bool fetchroot);
+ bool FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw);
+ bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, bool fetchroot);
+ bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val);
+ bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res);
+ bool Clone(const SQObjectPtr &self, SQObjectPtr &target);
+ bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,int &res);
+ bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);
+ bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res);
+ bool IsFalse(SQObjectPtr &o);
+ SQString *PrintObjVal(const SQObject &o);
+
+
+ void Raise_Error(const SQChar *s, ...);
+ void Raise_Error(SQObjectPtr &desc);
+ void Raise_IdxError(SQObject &o);
+ void Raise_CompareError(const SQObject &o1, const SQObject &o2);
+ void Raise_ParamTypeError(int nparam,int typemask,int type);
+
+ void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);
+ bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, int nparams, SQObjectPtr &outres);
+ bool ArithMetaMethod(int op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
+ //void Modulo(const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
+ bool Return(int _arg0, int _arg1, SQObjectPtr &retval);
+ //new stuff
+ bool ARITH_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
+ bool BW_OP(unsigned int op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
+ bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);
+ bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);
+ bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);
+ bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci);
+ bool CLASS_OP(SQObjectPtr &target,int base,int attrs);
+ //return true if the loop is finished
+ bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,int arg_2,bool &finished);
+ bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2);
+ bool LOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
+ bool PLOCAL_INC(int op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
+ bool DerefInc(int op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix);
+ void PopVarArgs(VarArgs &vargs);
+#ifdef _DEBUG_DUMP
+ void dumpstack(int stackbase=-1, bool dumpall = false);
+#endif
+
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+#endif
+ void Finalize();
+
+ void Release(){ sq_delete(this,SQVM); } //does nothing
+////////////////////////////////////////////////////////////////////////////
+ //stack functions for the api
+ void Pop();
+ void Pop(int n);
+ void Remove(int n);
+
+ void Push(const SQObjectPtr &o);
+ SQObjectPtr &Top();
+ SQObjectPtr &PopGet();
+ SQObjectPtr &GetUp(int n);
+ SQObjectPtr &GetAt(int n);
+
+ SQObjectPtrVec _stack;
+ SQObjectPtrVec _vargsstack;
+ int _top;
+ int _stackbase;
+ SQObjectPtr _roottable;
+ //SQObjectPtr _thrownerror;
+ SQObjectPtr _lasterror;
+ SQObjectPtr _errorhandler;
+ SQObjectPtr _debughook;
+
+ SQObjectPtr temp_reg;
+ CallInfoVec _callsstack;
+ ExceptionsTraps _etraps;
+ CallInfo *ci;
+ void *_foreignptr;
+ //VMs sharing the same state
+ SQSharedState *_sharedstate;
+ int _nnativecalls;
+ //suspend infos
+ bool _suspended;
+ bool _suspended_root;
+ int _suspended_target;
+ int _suspended_traps;
+};
+
+struct AutoDec{
+ AutoDec(int *n) { _n = n; }
+ ~AutoDec() { (*_n)--; }
+ int *_n;
+};
+
+SQObjectPtr &stack_get(HSQUIRRELVM v, int idx);
+const SQChar *GetTypeName(const SQObjectPtr &obj1);
+const SQChar *IdType2Name(SQObjectType type);
+
+#define _ss(_vm_) (_vm_)->_sharedstate
+
+#ifndef NO_GARBAGE_COLLECTOR
+#define _opt_ss(_vm_) (_vm_)->_sharedstate
+#else
+#define _opt_ss(_vm_) NULL
+#endif
+
+#define PUSH_CALLINFO(v,nci){ \
+ v->_callsstack.push_back(nci); \
+ v->ci = &v->_callsstack.back(); \
+}
+
+#define POP_CALLINFO(v){ \
+ v->_callsstack.pop_back(); \
+ if(v->_callsstack.size()) \
+ v->ci = &v->_callsstack.back() ; \
+ else \
+ v->ci = NULL; \
+}
+#endif //_SQVM_H_