-Copyright (c) 2003-2009 Alberto Demichelis\r
+Copyright (c) 2003-2011 Alberto Demichelis\r
\r
This software is provided 'as-is', without any \r
express or implied warranty. In no event will the \r
+***version 2.2.5 stable***\r
+-sq_getsize() now returns userdatasize for classes and instances\r
+-added parameter 'isstatic' to _newmember metamethod(thx G.Meyer)\r
+-now array.sort() is implemented with heapsort\r
+-added SQUIRREL_VERSION_NUMBER preprocessor definition\r
+-now floats in scientific notation also accept numbers with no '.' (eg. 1e+6 or 1e6)\r
+-fixed some compiler warning\r
+-fixed a minor compiler bug\r
+-fixed some bugs when SQUSEDOUBLE is used in 32bits systems\r
+-fixed bug in GC\r
+\r
+***2009-11-15 ***\r
***version 2.2.4 stable***\r
-fixed bug in functions with default parameters\r
\r
-The programming language SQUIRREL 2.2.4 stable\r
+The programming language SQUIRREL 2.2.5 stable\r
\r
--------------------------------------------------\r
The project has been compiled and run on Windows(Windows XP/2000 on Intel x86 Windows XP Pro on AMD x64) and\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 _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 _SQSTDBLOB_H_
-#define _SQSTDBLOB_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-SQUIRREL_API SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size);
-SQUIRREL_API SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr);
-SQUIRREL_API SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger 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 _SQSTDBLOB_H_\r
+#define _SQSTDBLOB_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+SQUIRREL_API SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size);\r
+SQUIRREL_API SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr);\r
+SQUIRREL_API SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger 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 _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 SQInteger Flush() = 0;
- virtual SQInteger Tell() = 0;
- virtual SQInteger Len() = 0;
- virtual SQInteger Seek(SQInteger offset, SQInteger 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 , SQInteger , SQInteger);
-SQUIRREL_API SQInteger 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, SQInteger 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 _SQSTDIO_H_\r
+#define _SQSTDIO_H_\r
+\r
+#ifdef __cplusplus\r
+\r
+#define SQSTD_STREAM_TYPE_TAG 0x80000000\r
+\r
+struct SQStream {\r
+ virtual ~SQStream() {}\r
+ virtual SQInteger Read(void *buffer, SQInteger size) = 0;\r
+ virtual SQInteger Write(void *buffer, SQInteger size) = 0;\r
+ virtual SQInteger Flush() = 0;\r
+ virtual SQInteger Tell() = 0;\r
+ virtual SQInteger Len() = 0;\r
+ virtual SQInteger Seek(SQInteger offset, SQInteger 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 , SQInteger , SQInteger);\r
+SQUIRREL_API SQInteger 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, SQInteger 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 _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_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_STRING_H_
-#define _SQSTD_STRING_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef unsigned int SQRexBool;
-typedef struct SQRex SQRex;
-
-typedef struct {
- const SQChar *begin;
- SQInteger 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 SQInteger sqstd_rex_getsubexpcount(SQRex* exp);
-SQUIRREL_API SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp);
-
-SQUIRREL_API SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output);
-
-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_STRING_H_\r
+#define _SQSTD_STRING_H_\r
+\r
+#ifdef __cplusplus\r
+extern "C" {\r
+#endif\r
+\r
+typedef unsigned int SQRexBool;\r
+typedef struct SQRex SQRex;\r
+\r
+typedef struct {\r
+ const SQChar *begin;\r
+ SQInteger 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 SQInteger sqstd_rex_getsubexpcount(SQRex* exp);\r
+SQUIRREL_API SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp);\r
+\r
+SQUIRREL_API SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output);\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_SYSTEMLIB_H_
-#define _SQSTD_SYSTEMLIB_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-SQUIRREL_API SQInteger sqstd_register_systemlib(HSQUIRRELVM v);
-
-#ifdef __cplusplus
-} /*extern "C"*/
-#endif
-
-#endif /* _SQSTD_SYSTEMLIB_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 SQInteger sqstd_register_systemlib(HSQUIRRELVM v);\r
+\r
+#ifdef __cplusplus\r
+} /*extern "C"*/\r
+#endif\r
+\r
+#endif /* _SQSTD_SYSTEMLIB_H_ */\r
-/*
-Copyright (c) 2003-2009 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
-
-/* Get uintptr_t from a non standard or standard location */
-#ifdef _MSC_VER
-#include <stddef.h>
-
-typedef __int32 SQInt32;
-typedef __int64 SQInt64;
-#else /* _MSC_VER */
-#include <stdint.h>
-
-typedef int32_t SQInt32;
-typedef int64_t SQInt64;
-#endif /* _MSC_VER */
-
-typedef intptr_t SQInteger;
-typedef uintptr_t SQUnsignedInteger;
-typedef uintptr_t SQHash;
-
-#ifdef SQUSEDOUBLE
-typedef double SQFloat;
-#else
-typedef float SQFloat;
-#endif
-
-#if defined(SQUSEDOUBLE)
-typedef SQInt64 SQRawObjectVal; /* must be 64 bits */
-#define SQ_OBJECT_RAWINIT() { _unVal.raw = 0; }
-#else
-typedef SQUnsignedInteger SQRawObjectVal; //is 32 bits on 32 bits builds and 64 bits otherwise
-#define SQ_OBJECT_RAWINIT()
-#endif
-
-typedef void* SQUserPointer;
-typedef SQUnsignedInteger SQBool;
-typedef SQInteger 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
-#if (defined(_MSC_VER) && _MSC_VER >= 1400) // 1400 = VS8
-
-#if defined(wchar_t) //this is if the compiler considers wchar_t as native type
-#define wchar_t unsigned short
-#endif
-
-#else
-typedef unsigned short wchar_t;
-#endif
-
-typedef wchar_t SQChar;
-#define _SC(a) L##a
-#define scstrcmp wcscmp
-#define scsprintf swprintf
-#define scstrlen wcslen
-#define scstrtod wcstod
-#define scstrtol wcstol
-#define scatoi _wtoi
-#define scstrtoul wcstoul
-#define scvsprintf vswprintf
-#define scstrstr wcsstr
-#define scisspace iswspace
-#define scisdigit iswdigit
-#define scisxdigit iswxdigit
-#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 scstrtol strtol
-#define scatoi atoi
-#define scstrtoul strtoul
-#define scvsprintf vsprintf
-#define scstrstr strstr
-#define scisspace isspace
-#define scisdigit isdigit
-#define scisxdigit isxdigit
-#define sciscntrl iscntrl
-#define scisalpha isalpha
-#define scisalnum isalnum
-#define scprintf printf
-#define MAX_CHAR 0xFF
-#endif
-
-#define SQUIRREL_VERSION _SC("Squirrel 2.2.4 stable")
-#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2009 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 0x08000000
-#define SQOBJECT_NUMERIC 0x04000000
-#define SQOBJECT_DELEGABLE 0x02000000
-#define SQOBJECT_CANBEFALSE 0x01000000
-
-#define SQ_MATCHTYPEMASKSTRING (-99999)
-
-#define _RT_MASK 0x00FFFFFF
-#define _RAW_TYPE(type) (type&_RT_MASK)
-
-#define _RT_NULL 0x00000001
-#define _RT_INTEGER 0x00000002
-#define _RT_FLOAT 0x00000004
-#define _RT_BOOL 0x00000008
-#define _RT_STRING 0x00000010
-#define _RT_TABLE 0x00000020
-#define _RT_ARRAY 0x00000040
-#define _RT_USERDATA 0x00000080
-#define _RT_CLOSURE 0x00000100
-#define _RT_NATIVECLOSURE 0x00000200
-#define _RT_GENERATOR 0x00000400
-#define _RT_USERPOINTER 0x00000800
-#define _RT_THREAD 0x00001000
-#define _RT_FUNCPROTO 0x00002000
-#define _RT_CLASS 0x00004000
-#define _RT_INSTANCE 0x00008000
-#define _RT_WEAKREF 0x00010000
-
-typedef enum tagSQObjectType{
- 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),
- OT_WEAKREF = (_RT_WEAKREF|SQOBJECT_REF_COUNTED)
-}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;
- struct SQWeakRef *pWeakRef;
- SQRawObjectVal raw;
-}SQObjectValue;
-
-
-typedef struct tagSQObject
-{
- SQObjectType _type;
- SQObjectValue _unVal;
-}SQObject;
-
-typedef struct tagSQStackInfos{
- const SQChar* funcname;
- const SQChar* source;
- SQInteger line;
-}SQStackInfos;
-
-typedef struct SQVM* HSQUIRRELVM;
-typedef SQObject HSQOBJECT;
-typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM);
-typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size);
-typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/);
-typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...);
-
-typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger);
-typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger);
-
-typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer);
-
-typedef struct tagSQRegFunction{
- const SQChar *name;
- SQFUNCTION f;
- SQInteger nparamscheck;
- const SQChar *typemask;
-}SQRegFunction;
-
-typedef struct tagSQFunctionInfo {
- SQUserPointer funcid;
- const SQChar *name;
- const SQChar *source;
-}SQFunctionInfo;
-
-
-/*vm*/
-SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize);
-SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger 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,SQBool raiseerror,SQBool throwerror);
-SQUIRREL_API SQInteger 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,SQInteger size,const SQChar *sourcename,SQBool raiseerror);
-SQUIRREL_API void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable);
-SQUIRREL_API void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable);
-SQUIRREL_API void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f);
-
-/*stack operations*/
-SQUIRREL_API void sq_push(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API void sq_pop(HSQUIRRELVM v,SQInteger nelemstopop);
-SQUIRREL_API void sq_poptop(HSQUIRRELVM v);
-SQUIRREL_API void sq_remove(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQInteger sq_gettop(HSQUIRRELVM v);
-SQUIRREL_API void sq_settop(HSQUIRRELVM v,SQInteger newtop);
-SQUIRREL_API void sq_reservestack(HSQUIRRELVM v,SQInteger nsize);
-SQUIRREL_API SQInteger sq_cmp(HSQUIRRELVM v);
-SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx);
-
-/*object creation handling*/
-SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size);
-SQUIRREL_API void sq_newtable(HSQUIRRELVM v);
-SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size);
-SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars);
-SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask);
-SQUIRREL_API SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger 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,SQInteger idx);
-SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQBool sq_instanceof(HSQUIRRELVM v);
-SQUIRREL_API void sq_tostring(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b);
-SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c);
-SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i);
-SQUIRREL_API SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f);
-SQUIRREL_API SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b);
-SQUIRREL_API SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread);
-SQUIRREL_API SQRESULT sq_getuserpointer(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p);
-SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag);
-SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag);
-SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag);
-SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook);
-SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize);
-SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger idx,SQFunctionInfo *fi);
-SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars);
-SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name);
-SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p);
-SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag);
-SQUIRREL_API SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize);
-SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase);
-SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API void sq_weakref(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t);
-
-/*object manipulation*/
-SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v);
-SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v);
-SQUIRREL_API void sq_pushconsttable(HSQUIRRELVM v);
-SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v);
-SQUIRREL_API SQRESULT sq_setconsttable(HSQUIRRELVM v);
-SQUIRREL_API SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);
-SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
-SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
-SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
-SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize);
-SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx);
-SQUIRREL_API SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos);
-SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
-SQUIRREL_API SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx);
-
-/*calls*/
-SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror);
-SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror);
-SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx);
-SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
-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,SQInteger 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 SQBool sq_objtobool(HSQOBJECT *o);
-SQUIRREL_API SQInteger sq_objtointeger(HSQOBJECT *o);
-SQUIRREL_API SQFloat sq_objtofloat(HSQOBJECT *o);
-SQUIRREL_API SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag);
-
-/*GC*/
-SQUIRREL_API SQInteger 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(SQUnsignedInteger size);
-SQUIRREL_API void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize);
-SQUIRREL_API void sq_free(void *p,SQUnsignedInteger size);
-
-/*debug*/
-SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,SQInteger 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_isweakref(o) ((o)._type==OT_WEAKREF)
-#define sq_type(o) ((o)._type)
-
-/* deprecated */
-#define sq_createslot(v,n) sq_newslot(v,n,SQFalse)
-
-#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
-
-/*
- define for code which depend on squirrel to
- determine bitiness. IMO, this should be discouraged.
- --ohnobinki
-*/
-#if (defined(_WIN64) || defined(_LP64))
-#define _SQ64
-#endif
-
-#endif /*_SQUIRREL_H_*/
+/*\r
+Copyright (c) 2003-2011 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
+#if (defined(_WIN64) || defined(_LP64))\r
+#ifndef _SQ64\r
+#define _SQ64\r
+#endif\r
+#endif\r
+\r
+\r
+#ifdef _SQ64\r
+#ifdef _MSC_VER\r
+typedef __int64 SQInteger;\r
+typedef unsigned __int64 SQUnsignedInteger;\r
+typedef unsigned __int64 SQHash; /*should be the same size of a pointer*/\r
+#else\r
+typedef long SQInteger;\r
+typedef unsigned long SQUnsignedInteger;\r
+typedef unsigned long SQHash; /*should be the same size of a pointer*/\r
+#endif\r
+typedef int SQInt32; \r
+#else \r
+typedef int SQInteger;\r
+typedef int SQInt32; /*must be 32 bits(also on 64bits processors)*/\r
+typedef unsigned int SQUnsignedInteger;\r
+typedef unsigned int SQHash; /*should be the same size of a pointer*/\r
+#endif\r
+\r
+\r
+#ifdef SQUSEDOUBLE\r
+typedef double SQFloat;\r
+#else\r
+typedef float SQFloat;\r
+#endif\r
+\r
+#if defined(SQUSEDOUBLE) && !defined(_SQ64) || !defined(SQUSEDOUBLE) && defined(_SQ64)\r
+#ifdef _MSC_VER\r
+typedef __int64 SQRawObjectVal; //must be 64bits\r
+#else\r
+typedef long long SQRawObjectVal; //must be 64bits\r
+#endif\r
+#define SQ_OBJECT_RAWINIT() { _unVal.raw = 0; }\r
+#else\r
+typedef SQUnsignedInteger SQRawObjectVal; //is 32 bits on 32 bits builds and 64 bits otherwise\r
+#define SQ_OBJECT_RAWINIT()\r
+#endif\r
+\r
+typedef void* SQUserPointer;\r
+typedef SQUnsignedInteger SQBool;\r
+typedef SQInteger SQRESULT;\r
+\r
+#define SQTrue (1)\r
+#define SQFalse (0)\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
+#if (defined(_MSC_VER) && _MSC_VER >= 1400) // 1400 = VS8\r
+\r
+#if defined(wchar_t) //this is if the compiler considers wchar_t as native type\r
+#define wchar_t unsigned short\r
+#endif\r
+\r
+#else\r
+typedef unsigned short wchar_t;\r
+#endif\r
+\r
+typedef wchar_t 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 scstrtol wcstol\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 scisxdigit iswxdigit\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 scstrtol strtol\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 scisxdigit isxdigit\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.2.5 stable")\r
+#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2010 Alberto Demichelis")\r
+#define SQUIRREL_AUTHOR _SC("Alberto Demichelis")\r
+#define SQUIRREL_VERSION_NUMBER 225\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 0x08000000\r
+#define SQOBJECT_NUMERIC 0x04000000\r
+#define SQOBJECT_DELEGABLE 0x02000000\r
+#define SQOBJECT_CANBEFALSE 0x01000000\r
+\r
+#define SQ_MATCHTYPEMASKSTRING (-99999)\r
+\r
+#define _RT_MASK 0x00FFFFFF\r
+#define _RAW_TYPE(type) (type&_RT_MASK)\r
+\r
+#define _RT_NULL 0x00000001\r
+#define _RT_INTEGER 0x00000002\r
+#define _RT_FLOAT 0x00000004\r
+#define _RT_BOOL 0x00000008\r
+#define _RT_STRING 0x00000010\r
+#define _RT_TABLE 0x00000020\r
+#define _RT_ARRAY 0x00000040\r
+#define _RT_USERDATA 0x00000080\r
+#define _RT_CLOSURE 0x00000100\r
+#define _RT_NATIVECLOSURE 0x00000200\r
+#define _RT_GENERATOR 0x00000400\r
+#define _RT_USERPOINTER 0x00000800\r
+#define _RT_THREAD 0x00001000\r
+#define _RT_FUNCPROTO 0x00002000\r
+#define _RT_CLASS 0x00004000\r
+#define _RT_INSTANCE 0x00008000\r
+#define _RT_WEAKREF 0x00010000\r
+\r
+typedef enum tagSQObjectType{\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
+ OT_WEAKREF = (_RT_WEAKREF|SQOBJECT_REF_COUNTED)\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
+ struct SQWeakRef *pWeakRef;\r
+ SQRawObjectVal raw;\r
+}SQObjectValue;\r
+\r
+\r
+typedef struct tagSQObject\r
+{\r
+ SQObjectType _type;\r
+ SQObjectValue _unVal;\r
+}SQObject;\r
+\r
+typedef struct tagSQStackInfos{\r
+ const SQChar* funcname;\r
+ const SQChar* source;\r
+ SQInteger line;\r
+}SQStackInfos;\r
+\r
+typedef struct SQVM* HSQUIRRELVM;\r
+typedef SQObject HSQOBJECT;\r
+typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM);\r
+typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size);\r
+typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/);\r
+typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...);\r
+\r
+typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger);\r
+typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger);\r
+\r
+typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer);\r
+\r
+typedef struct tagSQRegFunction{\r
+ const SQChar *name;\r
+ SQFUNCTION f;\r
+ SQInteger nparamscheck;\r
+ const SQChar *typemask;\r
+}SQRegFunction;\r
+\r
+typedef struct tagSQFunctionInfo {\r
+ SQUserPointer funcid;\r
+ const SQChar *name;\r
+ const SQChar *source;\r
+}SQFunctionInfo;\r
+\r
+\r
+/*vm*/\r
+SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize);\r
+SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger 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,SQBool raiseerror,SQBool throwerror);\r
+SQUIRREL_API SQInteger 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,SQInteger size,const SQChar *sourcename,SQBool raiseerror);\r
+SQUIRREL_API void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable);\r
+SQUIRREL_API void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable);\r
+SQUIRREL_API void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f);\r
+\r
+/*stack operations*/\r
+SQUIRREL_API void sq_push(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API void sq_pop(HSQUIRRELVM v,SQInteger nelemstopop);\r
+SQUIRREL_API void sq_poptop(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_remove(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQInteger sq_gettop(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_settop(HSQUIRRELVM v,SQInteger newtop);\r
+SQUIRREL_API void sq_reservestack(HSQUIRRELVM v,SQInteger nsize);\r
+SQUIRREL_API SQInteger sq_cmp(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx);\r
+\r
+/*object creation handling*/\r
+SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size);\r
+SQUIRREL_API void sq_newtable(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size);\r
+SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars);\r
+SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask);\r
+SQUIRREL_API SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger 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,SQInteger idx);\r
+SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQBool sq_instanceof(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_tostring(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b);\r
+SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c);\r
+SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i);\r
+SQUIRREL_API SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f);\r
+SQUIRREL_API SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b);\r
+SQUIRREL_API SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread);\r
+SQUIRREL_API SQRESULT sq_getuserpointer(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p);\r
+SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag);\r
+SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag);\r
+SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag);\r
+SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook);\r
+SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize);\r
+SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger idx,SQFunctionInfo *fi);\r
+SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars);\r
+SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name);\r
+SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p);\r
+SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag);\r
+SQUIRREL_API SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize);\r
+SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase);\r
+SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API void sq_weakref(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t);\r
+\r
+/*object manipulation*/\r
+SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v);\r
+SQUIRREL_API void sq_pushconsttable(HSQUIRRELVM v);\r
+SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v);\r
+SQUIRREL_API SQRESULT sq_setconsttable(HSQUIRRELVM v);\r
+SQUIRREL_API SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);\r
+SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);\r
+SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);\r
+SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval); \r
+SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize); \r
+SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx); \r
+SQUIRREL_API SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx);\r
+SQUIRREL_API SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos);\r
+SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);\r
+SQUIRREL_API SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx);\r
+SQUIRREL_API SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx);\r
+\r
+/*calls*/\r
+SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror);\r
+SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror);\r
+SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx);\r
+SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);\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,SQInteger 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 SQBool sq_objtobool(HSQOBJECT *o);\r
+SQUIRREL_API SQInteger sq_objtointeger(HSQOBJECT *o);\r
+SQUIRREL_API SQFloat sq_objtofloat(HSQOBJECT *o);\r
+SQUIRREL_API SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag);\r
+\r
+/*GC*/\r
+SQUIRREL_API SQInteger 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(SQUnsignedInteger size);\r
+SQUIRREL_API void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize);\r
+SQUIRREL_API void sq_free(void *p,SQUnsignedInteger size);\r
+\r
+/*debug*/\r
+SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,SQInteger 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_isweakref(o) ((o)._type==OT_WEAKREF)\r
+#define sq_type(o) ((o)._type)\r
+\r
+/* deprecated */\r
+#define sq_createslot(v,n) sq_newslot(v,n,SQFalse)\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
-/* see copyright notice in squirrel.h */
-#include <squirrel.h>
-#include <sqstdaux.h>
-#include <assert.h>
-
-void sqstd_printcallstack(HSQUIRRELVM v)
-{
- SQPRINTFUNCTION pf = sq_getprintfunc(v);
- if(pf) {
- SQStackInfos si;
- SQInteger i;
- SQBool b;
- SQFloat f;
- const SQChar *s;
- SQInteger level=1; //1 is to skip this function that is level 0
- const SQChar *name=0;
- SQInteger 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_GENERATOR:
- pf(v,_SC("[%s] GENERATOR\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;
- case OT_WEAKREF:
- pf(v,_SC("[%s] WEAKREF\n"),name);
- break;
- case OT_BOOL:{
- sq_getbool(v,-1,&b);
- pf(v,_SC("[%s] %s\n"),name,b?_SC("true"):_SC("false"));
- }
- break;
- default: assert(0); break;
- }
- sq_pop(v,1);
- }
- }
- }
-}
-
-static SQInteger _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,SQInteger line,SQInteger column)
-{
- SQPRINTFUNCTION pf = sq_getprintfunc(v);
- if(pf) {
- pf(v,_SC("%s line = (%d) column = (%d) : error %s\n"),sSource,line,column,sErr);
- }
-}
-
-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 <squirrel.h>\r
+#include <sqstdaux.h>\r
+#include <assert.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
+ SQBool b;\r
+ SQFloat f;\r
+ const SQChar *s;\r
+ SQInteger level=1; //1 is to skip this function that is level 0\r
+ const SQChar *name=0; \r
+ SQInteger 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_GENERATOR:\r
+ pf(v,_SC("[%s] GENERATOR\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
+ case OT_WEAKREF:\r
+ pf(v,_SC("[%s] WEAKREF\n"),name);\r
+ break;\r
+ case OT_BOOL:{\r
+ sq_getbool(v,-1,&b);\r
+ pf(v,_SC("[%s] %s\n"),name,b?_SC("true"):_SC("false"));\r
+ }\r
+ break;\r
+ default: assert(0); break;\r
+ }\r
+ sq_pop(v,1);\r
+ }\r
+ }\r
+ }\r
+}\r
+\r
+static SQInteger _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,SQInteger line,SQInteger column)\r
+{\r
+ SQPRINTFUNCTION pf = sq_getprintfunc(v);\r
+ if(pf) {\r
+ pf(v,_SC("%s line = (%d) column = (%d) : error %s\n"),sSource,line,column,sErr);\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 <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,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \
- return SQ_ERROR; }
-
-
-static SQInteger _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 SQInteger _blob_swap4(HSQUIRRELVM v)
-{
- SETUP_BLOB(v);
- SQInteger num=(self->Len()-(self->Len()%4))>>2;
- unsigned int *t=(unsigned int *)self->GetBuf();
- for(SQInteger i = 0; i < num; i++) {
- __swap_dword(&t[i]);
- }
- return 0;
-}
-
-static SQInteger _blob_swap2(HSQUIRRELVM v)
-{
- SETUP_BLOB(v);
- SQInteger num=(self->Len()-(self->Len()%2))>>1;
- unsigned short *t = (unsigned short *)self->GetBuf();
- for(SQInteger i = 0; i < num; i++) {
- __swap_word(&t[i]);
- }
- return 0;
-}
-
-static SQInteger _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 SQInteger _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 SQInteger _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 SQInteger _blob__typeof(HSQUIRRELVM v)
-{
- sq_pushstring(v,_SC("blob"),-1);
- return 1;
-}
-
-static SQInteger _blob_releasehook(SQUserPointer p, SQInteger size)
-{
- SQBlob *self = (SQBlob*)p;
- delete self;
- return 1;
-}
-
-static SQInteger _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 SQInteger _g_blob_casti2f(HSQUIRRELVM v)
-{
- SQInteger i;
- sq_getinteger(v,2,&i);
- sq_pushfloat(v,*((SQFloat *)&i));
- return 1;
-}
-
-static SQInteger _g_blob_castf2i(HSQUIRRELVM v)
-{
- SQFloat f;
- sq_getfloat(v,2,&f);
- sq_pushinteger(v,*((SQInteger *)&f));
- return 1;
-}
-
-static SQInteger _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 SQInteger _g_blob_swap4(HSQUIRRELVM v)
-{
- SQInteger i;
- sq_getinteger(v,2,&i);
- unsigned int t4 = (unsigned int)i;
- __swap_dword(&t4);
- sq_pushinteger(v,(SQInteger)t4);
- return 1;
-}
-
-static SQInteger _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}
-};
-
-SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr)
-{
- SQBlob *blob;
- if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
- return -1;
- *ptr = blob->GetBuf();
- return SQ_OK;
-}
-
-SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx)
-{
- SQBlob *blob;
- if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
- return -1;
- return blob->Len();
-}
-
-SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size)
-{
- SQInteger top = sq_gettop(v);
- 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,SQFalse))
- && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) {
- 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"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);
-}
-
+/* 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,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \\r
+ return SQ_ERROR; }\r
+\r
+\r
+static SQInteger _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 SQInteger _blob_swap4(HSQUIRRELVM v)\r
+{\r
+ SETUP_BLOB(v);\r
+ SQInteger num=(self->Len()-(self->Len()%4))>>2;\r
+ unsigned int *t=(unsigned int *)self->GetBuf();\r
+ for(SQInteger i = 0; i < num; i++) {\r
+ __swap_dword(&t[i]);\r
+ }\r
+ return 0;\r
+}\r
+\r
+static SQInteger _blob_swap2(HSQUIRRELVM v)\r
+{\r
+ SETUP_BLOB(v);\r
+ SQInteger num=(self->Len()-(self->Len()%2))>>1;\r
+ unsigned short *t = (unsigned short *)self->GetBuf();\r
+ for(SQInteger i = 0; i < num; i++) {\r
+ __swap_word(&t[i]);\r
+ }\r
+ return 0;\r
+}\r
+\r
+static SQInteger _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 SQInteger _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 SQInteger _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 SQInteger _blob__typeof(HSQUIRRELVM v)\r
+{\r
+ sq_pushstring(v,_SC("blob"),-1);\r
+ return 1;\r
+}\r
+\r
+static SQInteger _blob_releasehook(SQUserPointer p, SQInteger size)\r
+{\r
+ SQBlob *self = (SQBlob*)p;\r
+ delete self;\r
+ return 1;\r
+}\r
+\r
+static SQInteger _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 SQInteger _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 SQInteger _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 SQInteger _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 SQInteger _g_blob_swap4(HSQUIRRELVM v)\r
+{\r
+ SQInteger i;\r
+ sq_getinteger(v,2,&i);\r
+ unsigned int t4 = (unsigned int)i;\r
+ __swap_dword(&t4);\r
+ sq_pushinteger(v,(SQInteger)t4);\r
+ return 1;\r
+}\r
+\r
+static SQInteger _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,SQInteger idx,SQUserPointer *ptr)\r
+{\r
+ SQBlob *blob;\r
+ if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))\r
+ return -1;\r
+ *ptr = blob->GetBuf();\r
+ return SQ_OK;\r
+}\r
+\r
+SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx)\r
+{\r
+ SQBlob *blob;\r
+ if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))\r
+ return -1;\r
+ return blob->Len();\r
+}\r
+\r
+SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size)\r
+{\r
+ SQInteger top = sq_gettop(v);\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,SQFalse))\r
+ && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) {\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"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);\r
+}\r
+\r
-/* see copyright notice in squirrel.h */
-#ifndef _SQSTD_BLOBIMPL_H_
-#define _SQSTD_BLOBIMPL_H_
-
-struct SQBlob : public SQStream
-{
- SQBlob(SQInteger size) {
- _size = size;
- _allocated = size;
- _buf = (unsigned char *)sq_malloc(size);
- memset(_buf, 0, _size);
- _ptr = 0;
- _owns = true;
- }
- virtual ~SQBlob() {
- sq_free(_buf, _allocated);
- }
- 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) {
- SQInteger 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(SQInteger 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(SQInteger 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(SQInteger n) {
- if(_ptr+n>_size)return false;
- return true;
- }
- SQInteger Seek(SQInteger offset, SQInteger 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;
- }
- SQInteger Flush() { return 0; }
- SQInteger Tell() { return _ptr; }
- SQInteger Len() { return _size; }
- SQUserPointer GetBuf(){ return _buf; }
-private:
- SQInteger _size;
- SQInteger _allocated;
- SQInteger _ptr;
- unsigned char *_buf;
- bool _owns;
-};
-
-#endif //_SQSTD_BLOBIMPL_H_
+/* 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(SQInteger 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
+ virtual ~SQBlob() {\r
+ sq_free(_buf, _allocated);\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
+ SQInteger 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(SQInteger 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(SQInteger 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(SQInteger n) {\r
+ if(_ptr+n>_size)return false;\r
+ return true;\r
+ }\r
+ SQInteger Seek(SQInteger offset, SQInteger 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
+ SQInteger Flush() { return 0; }\r
+ SQInteger Tell() { return _ptr; }\r
+ SQInteger Len() { return _size; }\r
+ SQUserPointer GetBuf(){ return _buf; }\r
+private:\r
+ SQInteger _size;\r
+ SQInteger _allocated;\r
+ SQInteger _ptr;\r
+ unsigned char *_buf;\r
+ bool _owns;\r
+};\r
+\r
+#endif //_SQSTD_BLOBIMPL_H_\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 SQUNICODE
- 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, SQInteger offset, SQInteger origin)
-{
- SQInteger 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,(long)offset,(int)realorigin);
-}
-
-SQInteger 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);
- }
- SQInteger Flush() {
- return sqstd_fflush(_handle);
- }
- SQInteger Tell() {
- return sqstd_ftell(_handle);
- }
- SQInteger Len() {
- SQInteger prevpos=Tell();
- Seek(0,SQ_SEEK_END);
- SQInteger size=Tell();
- Seek(prevpos,SQ_SEEK_SET);
- return size;
- }
- SQInteger Seek(SQInteger offset, SQInteger 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 SQInteger _file__typeof(HSQUIRRELVM v)
-{
- sq_pushstring(v,_SC("file"),-1);
- return 1;
-}
-
-static SQInteger _file_releasehook(SQUserPointer p, SQInteger size)
-{
- SQFile *self = (SQFile*)p;
- delete self;
- return 1;
-}
-
-static SQInteger _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)
-{
- SQInteger 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,SQFalse) )) {
- sq_remove(v,-2);
- return SQ_OK;
- }
- }
- sq_settop(v,top);
- return SQ_OK;
-}
-
-SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file)
-{
- SQFile *fileobj = NULL;
- if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)SQSTD_FILE_TYPE_TAG))) {
- *file = fileobj->GetHandle();
- return SQ_OK;
- }
- return sq_throwerror(v,_SC("not a file"));
-}
-
-
-
-static SQInteger _io_file_lexfeed_ASCII(SQUserPointer file)
-{
- SQInteger ret;
- char c;
- if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )
- return c;
- return 0;
-}
-
-static SQInteger _io_file_lexfeed_UTF8(SQUserPointer file)
-{
-#define READ() \
- if(sqstd_fread(&inchar,sizeof(inchar),1,(FILE *)file) != 1) \
- return 0;
-
- static const SQInteger utf8_lengths[16] =
- {
- 1,1,1,1,1,1,1,1, /* 0000 to 0111 : 1 byte (plain ASCII) */
- 0,0,0,0, /* 1000 to 1011 : not valid */
- 2,2, /* 1100, 1101 : 2 bytes */
- 3, /* 1110 : 3 bytes */
- 4 /* 1111 :4 bytes */
- };
- static unsigned char byte_masks[5] = {0,0,0x1f,0x0f,0x07};
- unsigned char inchar;
- SQInteger c = 0;
- READ();
- c = inchar;
- //
- if(c >= 0x80) {
- SQInteger tmp;
- SQInteger codelen = utf8_lengths[c>>4];
- if(codelen == 0)
- return 0;
- //"invalid UTF-8 stream";
- tmp = c&byte_masks[codelen];
- for(SQInteger n = 0; n < codelen-1; n++) {
- tmp<<=6;
- READ();
- tmp |= inchar & 0x3F;
- }
- c = tmp;
- }
- return c;
-}
-
-static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer file)
-{
- SQInteger ret;
- wchar_t c;
- if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )
- return (SQChar)c;
- return 0;
-}
-
-static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer file)
-{
- SQInteger ret;
- unsigned short c;
- if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) ) {
- c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00);
- return (SQChar)c;
- }
- return 0;
-}
-
-SQInteger file_read(SQUserPointer file,SQUserPointer buf,SQInteger size)
-{
- SQInteger ret;
- if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;
- return -1;
-}
-
-SQInteger file_write(SQUserPointer file,SQUserPointer p,SQInteger 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"));
- SQInteger ret;
- unsigned short us;
- unsigned char uc;
- SQLEXREADFUNC func = _io_file_lexfeed_ASCII;
- if(file){
- ret = sqstd_fread(&us,1,2,file);
- if(ret != 2) {
- //probably an empty file
- us = 0;
- }
- if(us == 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
- switch(us)
- {
- //gotta swap the next 2 lines on BIG endian machines
- case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian;
- case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian;
- case 0xBBEF:
- if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) {
- sqstd_fclose(file);
- return sq_throwerror(v,_SC("io error"));
- }
- if(uc != 0xBF) {
- sqstd_fclose(file);
- return sq_throwerror(v,_SC("Unrecognozed ecoding"));
- }
- func = _io_file_lexfeed_UTF8;
- break;//UTF-8 ;
- default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii
- }
-
- 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);
- if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) {
- 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
-}
-
-SQInteger _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
-}
-
-SQInteger _g_io_writeclosuretofile(HSQUIRRELVM v)
-{
- const SQChar *filename;
- sq_getstring(v,2,&filename);
- if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,filename)))
- return 1;
- return SQ_ERROR; //propagates the error
-}
-
-SQInteger _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")),
- _DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")),
- {0,0}
-};
-
-SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
-{
- SQInteger top = sq_gettop(v);
- //create delegate
- declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);
- sq_pushstring(v,_SC("stdout"),-1);
- sqstd_createfile(v,stdout,SQFalse);
- sq_createslot(v,-3);
- sq_pushstring(v,_SC("stdin"),-1);
- sqstd_createfile(v,stdin,SQFalse);
- sq_createslot(v,-3);
- sq_pushstring(v,_SC("stderr"),-1);
- sqstd_createfile(v,stderr,SQFalse);
- sq_createslot(v,-3);
- sq_settop(v,top);
- return SQ_OK;
-}
+/* 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 SQUNICODE\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, SQInteger offset, SQInteger origin)\r
+{\r
+ SQInteger 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,(long)offset,(int)realorigin);\r
+}\r
+\r
+SQInteger 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
+ virtual ~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
+ SQInteger Flush() {\r
+ return sqstd_fflush(_handle);\r
+ }\r
+ SQInteger Tell() {\r
+ return sqstd_ftell(_handle);\r
+ }\r
+ SQInteger Len() {\r
+ SQInteger prevpos=Tell();\r
+ Seek(0,SQ_SEEK_END);\r
+ SQInteger size=Tell();\r
+ Seek(prevpos,SQ_SEEK_SET);\r
+ return size;\r
+ }\r
+ SQInteger Seek(SQInteger offset, SQInteger 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 SQInteger _file__typeof(HSQUIRRELVM v)\r
+{\r
+ sq_pushstring(v,_SC("file"),-1);\r
+ return 1;\r
+}\r
+\r
+static SQInteger _file_releasehook(SQUserPointer p, SQInteger size)\r
+{\r
+ SQFile *self = (SQFile*)p;\r
+ delete self;\r
+ return 1;\r
+}\r
+\r
+static SQInteger _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
+ SQInteger 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,SQFalse) )) {\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, SQInteger idx, SQFILE *file)\r
+{\r
+ SQFile *fileobj = NULL;\r
+ if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)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
+\r
+static SQInteger _io_file_lexfeed_ASCII(SQUserPointer file)\r
+{\r
+ SQInteger 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_lexfeed_UTF8(SQUserPointer file)\r
+{\r
+#define READ() \\r
+ if(sqstd_fread(&inchar,sizeof(inchar),1,(FILE *)file) != 1) \\r
+ return 0;\r
+\r
+ static const SQInteger utf8_lengths[16] =\r
+ {\r
+ 1,1,1,1,1,1,1,1, /* 0000 to 0111 : 1 byte (plain ASCII) */\r
+ 0,0,0,0, /* 1000 to 1011 : not valid */\r
+ 2,2, /* 1100, 1101 : 2 bytes */\r
+ 3, /* 1110 : 3 bytes */\r
+ 4 /* 1111 :4 bytes */\r
+ };\r
+ static unsigned char byte_masks[5] = {0,0,0x1f,0x0f,0x07};\r
+ unsigned char inchar;\r
+ SQInteger c = 0;\r
+ READ();\r
+ c = inchar;\r
+ //\r
+ if(c >= 0x80) {\r
+ SQInteger tmp;\r
+ SQInteger codelen = utf8_lengths[c>>4];\r
+ if(codelen == 0) \r
+ return 0;\r
+ //"invalid UTF-8 stream";\r
+ tmp = c&byte_masks[codelen];\r
+ for(SQInteger n = 0; n < codelen-1; n++) {\r
+ tmp<<=6;\r
+ READ();\r
+ tmp |= inchar & 0x3F;\r
+ }\r
+ c = tmp;\r
+ }\r
+ return c;\r
+}\r
+\r
+static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer file)\r
+{\r
+ SQInteger 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
+static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer file)\r
+{\r
+ SQInteger ret;\r
+ unsigned short c;\r
+ if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) ) {\r
+ c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00);\r
+ return (SQChar)c;\r
+ }\r
+ return 0;\r
+}\r
+\r
+SQInteger file_read(SQUserPointer file,SQUserPointer buf,SQInteger size)\r
+{\r
+ SQInteger ret;\r
+ if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;\r
+ return -1;\r
+}\r
+\r
+SQInteger file_write(SQUserPointer file,SQUserPointer p,SQInteger 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
+ SQInteger ret;\r
+ unsigned short us;\r
+ unsigned char uc;\r
+ SQLEXREADFUNC func = _io_file_lexfeed_ASCII;\r
+ if(file){\r
+ ret = sqstd_fread(&us,1,2,file);\r
+ if(ret != 2) {\r
+ //probably an empty file\r
+ us = 0;\r
+ }\r
+ if(us == 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
+ switch(us)\r
+ {\r
+ //gotta swap the next 2 lines on BIG endian machines\r
+ case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian;\r
+ case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian;\r
+ case 0xBBEF: \r
+ if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) { \r
+ sqstd_fclose(file); \r
+ return sq_throwerror(v,_SC("io error")); \r
+ }\r
+ if(uc != 0xBF) { \r
+ sqstd_fclose(file); \r
+ return sq_throwerror(v,_SC("Unrecognozed ecoding")); \r
+ }\r
+ func = _io_file_lexfeed_UTF8;\r
+ break;//UTF-8 ;\r
+ default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii\r
+ }\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
+ if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) {\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
+SQInteger _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
+SQInteger _g_io_writeclosuretofile(HSQUIRRELVM v)\r
+{\r
+ const SQChar *filename;\r
+ sq_getstring(v,2,&filename);\r
+ if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,filename)))\r
+ return 1;\r
+ return SQ_ERROR; //propagates the error\r
+}\r
+\r
+SQInteger _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
+ _DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")),\r
+ {0,0}\r
+};\r
+\r
+SQRESULT sqstd_register_iolib(HSQUIRRELVM v)\r
+{\r
+ SQInteger top = sq_gettop(v);\r
+ //create delegate\r
+ declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);\r
+ sq_pushstring(v,_SC("stdout"),-1);\r
+ sqstd_createfile(v,stdout,SQFalse);\r
+ sq_createslot(v,-3);\r
+ sq_pushstring(v,_SC("stdin"),-1);\r
+ sqstd_createfile(v,stdin,SQFalse);\r
+ sq_createslot(v,-3);\r
+ sq_pushstring(v,_SC("stderr"),-1);\r
+ sqstd_createfile(v,stderr,SQFalse);\r
+ sq_createslot(v,-3);\r
+ sq_settop(v,top);\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 SQInteger 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 SQInteger 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 SQInteger math_srand(HSQUIRRELVM v)
-{
- SQInteger i;
- if(SQ_FAILED(sq_getinteger(v,2,&i)))
- return sq_throwerror(v,_SC("invalid param"));
- srand((unsigned int)i);
- return 0;
-}
-
-static SQInteger math_rand(HSQUIRRELVM v)
-{
- sq_pushinteger(v,rand());
- return 1;
-}
-
-static SQInteger math_abs(HSQUIRRELVM v)
-{
- SQInteger n;
- sq_getinteger(v,2,&n);
- sq_pushinteger(v,(SQInteger)abs((int)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},
-};
-
-#ifndef M_PI
-#define M_PI (3.14159265358979323846)
-#endif
-
-SQRESULT sqstd_register_mathlib(HSQUIRRELVM v)
-{
- SQInteger 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 <math.h>\r
+#include <stdlib.h>\r
+#include <sqstdmath.h>\r
+\r
+#define SINGLE_ARG_FUNC(_funcname) static SQInteger 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 SQInteger 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 SQInteger math_srand(HSQUIRRELVM v)\r
+{\r
+ SQInteger i;\r
+ if(SQ_FAILED(sq_getinteger(v,2,&i)))\r
+ return sq_throwerror(v,_SC("invalid param"));\r
+ srand((unsigned int)i);\r
+ return 0;\r
+}\r
+\r
+static SQInteger math_rand(HSQUIRRELVM v)\r
+{\r
+ sq_pushinteger(v,rand());\r
+ return 1;\r
+}\r
+\r
+static SQInteger math_abs(HSQUIRRELVM v)\r
+{\r
+ SQInteger n;\r
+ sq_getinteger(v,2,&n);\r
+ sq_pushinteger(v,(SQInteger)abs((int)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
+ SQInteger 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 <string.h>
-#include <ctype.h>
-#include <setjmp.h>
-#include "sqstdstring.h"
-
-#ifdef _UINCODE
-#define scisprint iswprint
-#else
-#define scisprint isprint
-#endif
-
-#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;
- SQInteger left;
- SQInteger right;
- SQInteger next;
-}SQRexNode;
-
-struct SQRex{
- const SQChar *_eol;
- const SQChar *_bol;
- const SQChar *_p;
- SQInteger _first;
- SQInteger _op;
- SQRexNode *_nodes;
- SQInteger _nallocated;
- SQInteger _nsize;
- SQInteger _nsubexpr;
- SQRexMatch *_matches;
- SQInteger _currsubexp;
- void *_jmpbuf;
- const SQChar **_error;
-};
-
-static SQInteger sqstd_rex_list(SQRex *exp);
-
-static SQInteger 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)) {
- SQInteger 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;
- SQInteger newid = exp->_nsize - 1;
- return (SQInteger)newid;
-}
-
-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, SQInteger n){
- if((*exp->_p) != n)
- sqstd_rex_error(exp, _SC("expected paren"));
- exp->_p++;
-}
-
-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(!scisprint(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected"));
- return (*exp->_p++);
-}
-
-static SQInteger sqstd_rex_charclass(SQRex *exp,SQInteger classid)
-{
- SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS);
- exp->_nodes[n].left = classid;
- return n;
-}
-
-static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass)
-{
- SQChar t;
- 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':
- {
- t = *exp->_p; exp->_p++;
- return sqstd_rex_charclass(exp,t);
- }
- case 'b':
- case 'B':
- if(!isclass) {
- SQInteger node = sqstd_rex_newnode(exp,OP_WB);
- exp->_nodes[node].left = *exp->_p;
- exp->_p++;
- return node;
- } //else default
- default:
- t = *exp->_p; exp->_p++;
- return sqstd_rex_newnode(exp,t);
- }
- }
- else if(!scisprint(*exp->_p)) {
-
- sqstd_rex_error(exp,_SC("letter expected"));
- }
- t = *exp->_p; exp->_p++;
- return sqstd_rex_newnode(exp,t);
-}
-static SQInteger sqstd_rex_class(SQRex *exp)
-{
- SQInteger ret = -1;
- SQInteger 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 == ']') sqstd_rex_error(exp,_SC("empty class"));
- chain = ret;
- while(*exp->_p != ']' && exp->_p != exp->_eol) {
- if(*exp->_p == '-' && first != -1){
- SQInteger 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;
- SQInteger t = sqstd_rex_escapechar(exp);
- exp->_nodes[r].right = t;
- exp->_nodes[chain].next = r;
- chain = r;
- first = -1;
- }
- else{
- if(first!=-1){
- SQInteger 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){
- SQInteger 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 SQInteger sqstd_rex_parsenumber(SQRex *exp)
-{
- SQInteger ret = *exp->_p-'0';
- SQInteger 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 SQInteger sqstd_rex_element(SQRex *exp)
-{
- SQInteger ret = -1;
- switch(*exp->_p)
- {
- case '(': {
- SQInteger 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);
- SQInteger newn = sqstd_rex_list(exp);
- exp->_nodes[expr].left = newn;
- 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;
- }
-
-
- SQInteger op;
- SQBool isgreedy = SQFalse;
- unsigned short p0 = 0, p1 = 0;
- switch(*exp->_p){
- case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
- case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
- case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = SQTrue; break;
- case '{':
- exp->_p++;
- if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected"));
- p0 = (unsigned short)sqstd_rex_parsenumber(exp);
- /*******************************/
- switch(*exp->_p) {
- case '}':
- p1 = p0; exp->_p++;
- break;
- case ',':
- exp->_p++;
- p1 = 0xFFFF;
- if(isdigit(*exp->_p)){
- p1 = (unsigned short)sqstd_rex_parsenumber(exp);
- }
- sqstd_rex_expect(exp,'}');
- break;
- default:
- sqstd_rex_error(exp,_SC(", or } expected"));
- }
- /*******************************/
- isgreedy = SQTrue;
- break;
-
- }
- if(isgreedy) {
- SQInteger 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')) {
- SQInteger nnode = sqstd_rex_element(exp);
- exp->_nodes[ret].next = nnode;
- }
-
- return ret;
-}
-
-static SQInteger sqstd_rex_list(SQRex *exp)
-{
- SQInteger 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) {
- SQInteger temp,tright;
- exp->_p++;
- temp = sqstd_rex_newnode(exp,OP_OR);
- exp->_nodes[temp].left = ret;
- tright = sqstd_rex_list(exp);
- exp->_nodes[temp].right = tright;
- ret = temp;
- }
- return ret;
-}
-
-static SQBool sqstd_rex_matchcclass(SQInteger 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,SQRexNode *next)
-{
-
- SQRexNodeType type = node->type;
- switch(type) {
- case OP_GREEDY: {
- //SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL;
- SQRexNode *greedystop = NULL;
- SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
- const SQChar *s=str, *good = str;
-
- if(node->next != -1) {
- greedystop = &exp->_nodes[node->next];
- }
- else {
- greedystop = next;
- }
-
- while((nmaches == 0xFFFF || nmaches < p1)) {
-
- const SQChar *stop;
- if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop)))
- break;
- nmaches++;
- good=s;
- if(greedystop) {
- //checks that 0 matches satisfy the expression(if so skips)
- //if not would always stop(for instance if is a '?')
- if(greedystop->type != OP_GREEDY ||
- (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0))
- {
- SQRexNode *gnext = NULL;
- if(greedystop->next != -1) {
- gnext = &exp->_nodes[greedystop->next];
- }else if(next && next->next != -1){
- gnext = &exp->_nodes[next->next];
- }
- stop = sqstd_rex_matchnode(exp,greedystop,s,gnext);
- if(stop) {
- //if satisfied stop it
- if(p0 == p1 && p0 == nmaches) break;
- else if(nmaches >= p0 && p1 == 0xFFFF) break;
- else if(nmaches >= p0 && nmaches <= p1) break;
- }
- }
- }
-
- 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,NULL)) ) {
- 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,NULL)) ) {
- 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;
- SQInteger capture = -1;
- if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
- capture = exp->_currsubexp;
- exp->_matches[capture].begin = cur;
- exp->_currsubexp++;
- }
-
- do {
- SQRexNode *subnext = NULL;
- if(n->next != -1) {
- subnext = &exp->_nodes[n->next];
- }else {
- subnext = next;
- }
- if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) {
- 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->_eol = exp->_bol = NULL;
- exp->_p = pattern;
- exp->_nallocated = (SQInteger)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) {
- SQInteger res = sqstd_rex_list(exp);
- exp->_nodes[exp->_first].left = res;
- if(*exp->_p!='\0')
- sqstd_rex_error(exp,_SC("unexpected character"));
-#ifdef _DEBUG
- {
- SQInteger 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,NULL);
- 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;
- SQInteger 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,NULL);
- 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);
-}
-
-SQInteger sqstd_rex_getsubexpcount(SQRex* exp)
-{
- return exp->_nsubexpr;
-}
-
-SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger 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 <squirrel.h>\r
+#include <string.h>\r
+#include <ctype.h>\r
+#include <setjmp.h>\r
+#include "sqstdstring.h"\r
+\r
+#ifdef _UINCODE\r
+#define scisprint iswprint\r
+#else\r
+#define scisprint isprint\r
+#endif\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
+ SQInteger left;\r
+ SQInteger right;\r
+ SQInteger next;\r
+}SQRexNode;\r
+\r
+struct SQRex{\r
+ const SQChar *_eol;\r
+ const SQChar *_bol;\r
+ const SQChar *_p;\r
+ SQInteger _first;\r
+ SQInteger _op;\r
+ SQRexNode *_nodes;\r
+ SQInteger _nallocated;\r
+ SQInteger _nsize;\r
+ SQInteger _nsubexpr;\r
+ SQRexMatch *_matches;\r
+ SQInteger _currsubexp;\r
+ void *_jmpbuf;\r
+ const SQChar **_error;\r
+};\r
+\r
+static SQInteger sqstd_rex_list(SQRex *exp);\r
+\r
+static SQInteger 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
+ SQInteger 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
+ SQInteger newid = exp->_nsize - 1;\r
+ return (SQInteger)newid;\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, SQInteger n){\r
+ if((*exp->_p) != n) \r
+ sqstd_rex_error(exp, _SC("expected paren"));\r
+ exp->_p++;\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(!scisprint(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected"));\r
+ return (*exp->_p++);\r
+}\r
+\r
+static SQInteger sqstd_rex_charclass(SQRex *exp,SQInteger classid)\r
+{\r
+ SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS);\r
+ exp->_nodes[n].left = classid;\r
+ return n;\r
+}\r
+\r
+static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass)\r
+{\r
+ SQChar t;\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
+ t = *exp->_p; exp->_p++; \r
+ return sqstd_rex_charclass(exp,t);\r
+ }\r
+ case 'b': \r
+ case 'B':\r
+ if(!isclass) {\r
+ SQInteger 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: \r
+ t = *exp->_p; exp->_p++; \r
+ return sqstd_rex_newnode(exp,t);\r
+ }\r
+ }\r
+ else if(!scisprint(*exp->_p)) {\r
+ \r
+ sqstd_rex_error(exp,_SC("letter expected"));\r
+ }\r
+ t = *exp->_p; exp->_p++; \r
+ return sqstd_rex_newnode(exp,t);\r
+}\r
+static SQInteger sqstd_rex_class(SQRex *exp)\r
+{\r
+ SQInteger ret = -1;\r
+ SQInteger 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 == ']') sqstd_rex_error(exp,_SC("empty class"));\r
+ chain = ret;\r
+ while(*exp->_p != ']' && exp->_p != exp->_eol) {\r
+ if(*exp->_p == '-' && first != -1){ \r
+ SQInteger r;\r
+ if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range"));\r
+ r = sqstd_rex_newnode(exp,OP_RANGE);\r
+ if(exp->_nodes[first].type>*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
+ SQInteger t = sqstd_rex_escapechar(exp);\r
+ exp->_nodes[r].right = t;\r
+ exp->_nodes[chain].next = r;\r
+ chain = r;\r
+ first = -1;\r
+ }\r
+ else{\r
+ if(first!=-1){\r
+ SQInteger 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
+ SQInteger 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 SQInteger sqstd_rex_parsenumber(SQRex *exp)\r
+{\r
+ SQInteger ret = *exp->_p-'0';\r
+ SQInteger 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 SQInteger sqstd_rex_element(SQRex *exp)\r
+{\r
+ SQInteger ret = -1;\r
+ switch(*exp->_p)\r
+ {\r
+ case '(': {\r
+ SQInteger 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
+ SQInteger newn = sqstd_rex_list(exp);\r
+ exp->_nodes[expr].left = newn;\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
+\r
+\r
+ SQInteger op;\r
+ SQBool isgreedy = SQFalse;\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++; isgreedy = SQTrue; break;\r
+ case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;\r
+ case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = SQTrue; break;\r
+ case '{':\r
+ exp->_p++;\r
+ if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected"));\r
+ p0 = (unsigned short)sqstd_rex_parsenumber(exp);\r
+ /*******************************/\r
+ switch(*exp->_p) {\r
+ case '}':\r
+ p1 = p0; exp->_p++;\r
+ break;\r
+ case ',':\r
+ exp->_p++;\r
+ p1 = 0xFFFF;\r
+ if(isdigit(*exp->_p)){\r
+ p1 = (unsigned short)sqstd_rex_parsenumber(exp);\r
+ }\r
+ sqstd_rex_expect(exp,'}');\r
+ break;\r
+ default:\r
+ sqstd_rex_error(exp,_SC(", or } expected"));\r
+ }\r
+ /*******************************/\r
+ isgreedy = SQTrue; \r
+ break;\r
+\r
+ }\r
+ if(isgreedy) {\r
+ SQInteger 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
+ 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
+ SQInteger nnode = sqstd_rex_element(exp);\r
+ exp->_nodes[ret].next = nnode;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+static SQInteger sqstd_rex_list(SQRex *exp)\r
+{\r
+ SQInteger 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
+ SQInteger temp,tright;\r
+ exp->_p++;\r
+ temp = sqstd_rex_newnode(exp,OP_OR);\r
+ exp->_nodes[temp].left = ret;\r
+ tright = sqstd_rex_list(exp);\r
+ exp->_nodes[temp].right = tright;\r
+ ret = temp;\r
+ }\r
+ return ret;\r
+}\r
+\r
+static SQBool sqstd_rex_matchcclass(SQInteger 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,SQRexNode *next)\r
+{\r
+ \r
+ SQRexNodeType type = node->type;\r
+ switch(type) {\r
+ case OP_GREEDY: {\r
+ //SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL;\r
+ SQRexNode *greedystop = NULL;\r
+ SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;\r
+ const SQChar *s=str, *good = str;\r
+\r
+ if(node->next != -1) {\r
+ greedystop = &exp->_nodes[node->next];\r
+ }\r
+ else {\r
+ greedystop = next;\r
+ }\r
+\r
+ while((nmaches == 0xFFFF || nmaches < p1)) {\r
+\r
+ const SQChar *stop;\r
+ if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop)))\r
+ break;\r
+ nmaches++;\r
+ good=s;\r
+ if(greedystop) {\r
+ //checks that 0 matches satisfy the expression(if so skips)\r
+ //if not would always stop(for instance if is a '?')\r
+ if(greedystop->type != OP_GREEDY ||\r
+ (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0))\r
+ {\r
+ SQRexNode *gnext = NULL;\r
+ if(greedystop->next != -1) {\r
+ gnext = &exp->_nodes[greedystop->next];\r
+ }else if(next && next->next != -1){\r
+ gnext = &exp->_nodes[next->next];\r
+ }\r
+ stop = sqstd_rex_matchnode(exp,greedystop,s,gnext);\r
+ if(stop) {\r
+ //if satisfied stop it\r
+ if(p0 == p1 && p0 == nmaches) break;\r
+ else if(nmaches >= p0 && p1 == 0xFFFF) break;\r
+ else if(nmaches >= p0 && nmaches <= p1) break;\r
+ }\r
+ }\r
+ }\r
+ \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,NULL)) ) {\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,NULL)) ) {\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
+ SQInteger 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
+ SQRexNode *subnext = NULL;\r
+ if(n->next != -1) {\r
+ subnext = &exp->_nodes[n->next];\r
+ }else {\r
+ subnext = next;\r
+ }\r
+ if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) {\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
+ }\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->_eol = exp->_bol = NULL;\r
+ exp->_p = pattern;\r
+ exp->_nallocated = (SQInteger)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
+ SQInteger res = sqstd_rex_list(exp);\r
+ exp->_nodes[exp->_first].left = res;\r
+ if(*exp->_p!='\0')\r
+ sqstd_rex_error(exp,_SC("unexpected character"));\r
+#ifdef _DEBUG\r
+ {\r
+ SQInteger 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,NULL);\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
+ SQInteger 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,NULL);\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
+SQInteger sqstd_rex_getsubexpcount(SQRex* exp)\r
+{\r
+ return exp->_nsubexpr;\r
+}\r
+\r
+SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger 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 <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,(SQUserPointer)SQSTD_STREAM_TYPE_TAG))) \
- return sq_throwerror(v,_SC("invalid type tag")); \
- if(!self->IsValid()) \
- return sq_throwerror(v,_SC("the stream is invalid"));
-
-SQInteger _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")); \
- }
-SQInteger _stream_readn(HSQUIRRELVM v)
-{
- SETUP_STREAM(v);
- SQInteger format;
- sq_getinteger(v, 2, &format);
- switch(format) {
- case 'l': {
- SQInteger i;
- SAFE_READN(&i, sizeof(i));
- sq_pushinteger(v, i);
- }
- break;
- case 'i': {
- SQInt32 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;
-}
-
-SQInteger _stream_writeblob(HSQUIRRELVM v)
-{
- SQUserPointer data;
- SQInteger 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;
-}
-
-SQInteger _stream_writen(HSQUIRRELVM v)
-{
- SETUP_STREAM(v);
- SQInteger format, ti;
- SQFloat tf;
- sq_getinteger(v, 3, &format);
- switch(format) {
- case 'l': {
- SQInteger i;
- sq_getinteger(v, 2, &ti);
- i = ti;
- self->Write(&i, sizeof(SQInteger));
- }
- break;
- case 'i': {
- SQInt32 i;
- sq_getinteger(v, 2, &ti);
- i = (SQInt32)ti;
- self->Write(&i, sizeof(SQInt32));
- }
- break;
- case 's': {
- short s;
- sq_getinteger(v, 2, &ti);
- s = (short)ti;
- self->Write(&s, sizeof(short));
- }
- break;
- case 'w': {
- unsigned short w;
- sq_getinteger(v, 2, &ti);
- w = (unsigned short)ti;
- self->Write(&w, sizeof(unsigned short));
- }
- break;
- case 'c': {
- char c;
- sq_getinteger(v, 2, &ti);
- c = (char)ti;
- self->Write(&c, sizeof(char));
- }
- break;
- case 'b': {
- unsigned char b;
- sq_getinteger(v, 2, &ti);
- b = (unsigned char)ti;
- self->Write(&b, sizeof(unsigned char));
- }
- break;
- case 'f': {
- float f;
- sq_getfloat(v, 2, &tf);
- f = (float)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;
-}
-
-SQInteger _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;
-}
-
-SQInteger _stream_tell(HSQUIRRELVM v)
-{
- SETUP_STREAM(v);
- sq_pushinteger(v, self->Tell());
- return 1;
-}
-
-SQInteger _stream_len(HSQUIRRELVM v)
-{
- SETUP_STREAM(v);
- sq_pushinteger(v, self->Len());
- return 1;
-}
-
-SQInteger _stream_flush(HSQUIRRELVM v)
-{
- SETUP_STREAM(v);
- if(!self->Flush())
- sq_pushinteger(v, 1);
- else
- sq_pushnull(v);
- return 1;
-}
-
-SQInteger _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(readblob,2,_SC("xn")),
- _DECL_STREAM_FUNC(readn,2,_SC("xn")),
- _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}
-};
-
-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,(SQUserPointer)SQSTD_STREAM_TYPE_TAG);
- SQInteger 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);
- sq_pushroottable(v);
- sq_pushstring(v,_SC("stream"),-1);
- sq_pushstring(v,_SC("std_stream"),-1);
- sq_get(v,-4);
- sq_createslot(v,-3);
- sq_pop(v,1);
- }
- else {
- sq_pop(v,1); //result
- }
- sq_pop(v,1);
-}
-
-SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals)
-{
- if(sq_gettype(v,-1) != OT_TABLE)
- return sq_throwerror(v,_SC("table expected"));
- SQInteger 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);
- SQInteger 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
+#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,(SQUserPointer)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
+SQInteger _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
+SQInteger _stream_readn(HSQUIRRELVM v)\r
+{\r
+ SETUP_STREAM(v);\r
+ SQInteger format;\r
+ sq_getinteger(v, 2, &format);\r
+ switch(format) {\r
+ case 'l': {\r
+ SQInteger i;\r
+ SAFE_READN(&i, sizeof(i));\r
+ sq_pushinteger(v, i);\r
+ }\r
+ break;\r
+ case 'i': {\r
+ SQInt32 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
+SQInteger _stream_writeblob(HSQUIRRELVM v)\r
+{\r
+ SQUserPointer data;\r
+ SQInteger 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
+SQInteger _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 'l': {\r
+ SQInteger i;\r
+ sq_getinteger(v, 2, &ti);\r
+ i = ti;\r
+ self->Write(&i, sizeof(SQInteger));\r
+ }\r
+ break;\r
+ case 'i': {\r
+ SQInt32 i;\r
+ sq_getinteger(v, 2, &ti);\r
+ i = (SQInt32)ti;\r
+ self->Write(&i, sizeof(SQInt32));\r
+ }\r
+ break;\r
+ case 's': {\r
+ short s;\r
+ sq_getinteger(v, 2, &ti);\r
+ s = (short)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 = (unsigned short)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 = (char)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 = (unsigned char)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 = (float)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
+SQInteger _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
+SQInteger _stream_tell(HSQUIRRELVM v)\r
+{\r
+ SETUP_STREAM(v);\r
+ sq_pushinteger(v, self->Tell());\r
+ return 1;\r
+}\r
+\r
+SQInteger _stream_len(HSQUIRRELVM v)\r
+{\r
+ SETUP_STREAM(v);\r
+ sq_pushinteger(v, self->Len());\r
+ return 1;\r
+}\r
+\r
+SQInteger _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
+SQInteger _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(readblob,2,_SC("xn")),\r
+ _DECL_STREAM_FUNC(readn,2,_SC("xn")),\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,(SQUserPointer)SQSTD_STREAM_TYPE_TAG);\r
+ SQInteger 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
+ sq_pushroottable(v);\r
+ sq_pushstring(v,_SC("stream"),-1);\r
+ sq_pushstring(v,_SC("std_stream"),-1);\r
+ sq_get(v,-4);\r
+ sq_createslot(v,-3);\r
+ sq_pop(v,1);\r
+ }\r
+ else {\r
+ sq_pop(v,1); //result\r
+ }\r
+ sq_pop(v,1);\r
+}\r
+\r
+SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const 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
+ SQInteger 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
+ SQInteger 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 */
-#ifndef _SQSTD_STREAM_H_
-#define _SQSTD_STREAM_H_
-
-SQInteger _stream_readblob(HSQUIRRELVM v);
-SQInteger _stream_readline(HSQUIRRELVM v);
-SQInteger _stream_readn(HSQUIRRELVM v);
-SQInteger _stream_writeblob(HSQUIRRELVM v);
-SQInteger _stream_writen(HSQUIRRELVM v);
-SQInteger _stream_seek(HSQUIRRELVM v);
-SQInteger _stream_tell(HSQUIRRELVM v);
-SQInteger _stream_len(HSQUIRRELVM v);
-SQInteger _stream_eos(HSQUIRRELVM v);
-SQInteger _stream_flush(HSQUIRRELVM v);
-
-#define _DECL_STREAM_FUNC(name,nparams,typecheck) {_SC(#name),_stream_##name,nparams,typecheck}
-SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals);
-#endif /*_SQSTD_STREAM_H_*/
+/* see copyright notice in squirrel.h */\r
+#ifndef _SQSTD_STREAM_H_\r
+#define _SQSTD_STREAM_H_\r
+\r
+SQInteger _stream_readblob(HSQUIRRELVM v);\r
+SQInteger _stream_readline(HSQUIRRELVM v);\r
+SQInteger _stream_readn(HSQUIRRELVM v);\r
+SQInteger _stream_writeblob(HSQUIRRELVM v);\r
+SQInteger _stream_writen(HSQUIRRELVM v);\r
+SQInteger _stream_seek(HSQUIRRELVM v);\r
+SQInteger _stream_tell(HSQUIRRELVM v);\r
+SQInteger _stream_len(HSQUIRRELVM v);\r
+SQInteger _stream_eos(HSQUIRRELVM v);\r
+SQInteger _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,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals);\r
+#endif /*_SQSTD_STREAM_H_*/\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>
-#include <assert.h>
-
-#ifdef SQUNICODE
-#define scstrchr wcschr
-#define scsnprintf wsnprintf
-#define scatoi _wtoi
-#define scstrtok wcstok
-#else
-#define scstrchr strchr
-#define scsnprintf snprintf
-#define scatoi atoi
-#define scstrtok strtok
-#endif
-#define MAX_FORMAT_LEN 20
-#define MAX_WFORMAT_LEN 3
-#define ADDITIONAL_FORMAT_SPACE (100*sizeof(SQChar))
-
-static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, SQInteger n,SQInteger &width)
-{
- SQChar swidth[MAX_WFORMAT_LEN];
- SQInteger wc = 0;
- SQInteger 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;
-}
-
-
-SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output)
-{
- const SQChar *format;
- SQChar *dest;
- SQChar fmt[MAX_FORMAT_LEN];
- sq_getstring(v,nformatstringidx,&format);
- SQInteger allocated = (sq_getsize(v,nformatstringidx)+2)*sizeof(SQChar);
- dest = sq_getscratchpad(v,allocated);
- SQInteger n = 0,i = 0, nparam = nformatstringidx+1, w = 0;
- while(format[n] != '\0') {
- if(format[n] != '%') {
- assert(i < allocated);
- dest[i++] = format[n];
- n++;
- }
- else if(format[n+1] == '%') { //handles %%
- dest[i++] = '%';
- n += 2;
- }
- else {
- n++;
- 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;
- SQInteger addlen = 0;
- SQInteger 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++;
- allocated += addlen + sizeof(SQChar);
- 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 ++;
- }
- }
- *outlen = i;
- dest[i] = '\0';
- *output = dest;
- return SQ_OK;
-}
-
-static SQInteger _string_format(HSQUIRRELVM v)
-{
- SQChar *dest = NULL;
- SQInteger length = 0;
- if(SQ_FAILED(sqstd_format(v,2,&length,&dest)))
- return -1;
- sq_pushstring(v,dest,length);
- return 1;
-}
-
-static void __strip_l(const SQChar *str,const SQChar **start)
-{
- const SQChar *t = str;
- while(((*t) != '\0') && scisspace(*t)){ t++; }
- *start = t;
-}
-
-static void __strip_r(const SQChar *str,SQInteger len,const SQChar **end)
-{
- if(len == 0) {
- *end = str;
- return;
- }
- const SQChar *t = &str[len-1];
- while(t != str && scisspace(*t)) { t--; }
- *end = t+1;
-}
-
-static SQInteger _string_strip(HSQUIRRELVM v)
-{
- const SQChar *str,*start,*end;
- sq_getstring(v,2,&str);
- SQInteger len = sq_getsize(v,2);
- __strip_l(str,&start);
- __strip_r(str,len,&end);
- sq_pushstring(v,start,end - start);
- return 1;
-}
-
-static SQInteger _string_lstrip(HSQUIRRELVM v)
-{
- const SQChar *str,*start;
- sq_getstring(v,2,&str);
- __strip_l(str,&start);
- sq_pushstring(v,start,-1);
- return 1;
-}
-
-static SQInteger _string_rstrip(HSQUIRRELVM v)
-{
- const SQChar *str,*end;
- sq_getstring(v,2,&str);
- SQInteger len = sq_getsize(v,2);
- __strip_r(str,len,&end);
- sq_pushstring(v,str,end - str);
- return 1;
-}
-
-static SQInteger _string_split(HSQUIRRELVM v)
-{
- const SQChar *str,*seps;
- SQChar *stemp,*tok;
- sq_getstring(v,2,&str);
- sq_getstring(v,3,&seps);
- if(sq_getsize(v,3) == 0) return sq_throwerror(v,_SC("empty separators string"));
- SQInteger memsize = (sq_getsize(v,2)+1)*sizeof(SQChar);
- stemp = sq_getscratchpad(v,memsize);
- memcpy(stemp,str,memsize);
- tok = scstrtok(stemp,seps);
- sq_newarray(v,0);
- while( tok != NULL ) {
- sq_pushstring(v,tok,-1);
- sq_arrayappend(v,-2);
- tok = scstrtok( NULL, seps );
- }
- return 1;
-}
-
-#define SETUP_REX(v) \
- SQRex *self = NULL; \
- sq_getinstanceup(v,1,(SQUserPointer *)&self,0);
-
-static SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger size)
-{
- SQRex *self = ((SQRex *)p);
- sqstd_rex_free(self);
- return 1;
-}
-
-static SQInteger _regexp_match(HSQUIRRELVM v)
-{
- SETUP_REX(v);
- const SQChar *str;
- sq_getstring(v,2,&str);
- if(sqstd_rex_match(self,str) == SQTrue)
- {
- sq_pushbool(v,SQTrue);
- return 1;
- }
- sq_pushbool(v,SQFalse);
- return 1;
-}
-
-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 SQInteger _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 SQInteger _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 SQInteger _regexp_subexpcount(HSQUIRRELVM v)
-{
- SETUP_REX(v);
- sq_pushinteger(v,sqstd_rex_getsubexpcount(self));
- return 1;
-}
-
-static SQInteger _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 SQInteger _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}
-};
-
-#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask}
-static SQRegFunction stringlib_funcs[]={
- _DECL_FUNC(format,-2,_SC(".s")),
- _DECL_FUNC(strip,2,_SC(".s")),
- _DECL_FUNC(lstrip,2,_SC(".s")),
- _DECL_FUNC(rstrip,2,_SC(".s")),
- _DECL_FUNC(split,3,_SC(".ss")),
- {0,0}
-};
-
-
-SQInteger sqstd_register_stringlib(HSQUIRRELVM v)
-{
- sq_pushstring(v,_SC("regexp"),-1);
- sq_newclass(v,SQFalse);
- SQInteger 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 <sqstdstring.h>\r
+#include <string.h>\r
+#include <stdlib.h>\r
+#include <stdio.h>\r
+#include <ctype.h>\r
+#include <assert.h>\r
+\r
+#ifdef SQUNICODE\r
+#define scstrchr wcschr\r
+#define scsnprintf wsnprintf\r
+#define scatoi _wtoi\r
+#define scstrtok wcstok\r
+#else\r
+#define scstrchr strchr\r
+#define scsnprintf snprintf\r
+#define scatoi atoi\r
+#define scstrtok strtok\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 SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, SQInteger n,SQInteger &width)\r
+{\r
+ SQChar swidth[MAX_WFORMAT_LEN];\r
+ SQInteger wc = 0;\r
+ SQInteger 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
+\r
+SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output)\r
+{\r
+ const SQChar *format;\r
+ SQChar *dest;\r
+ SQChar fmt[MAX_FORMAT_LEN];\r
+ sq_getstring(v,nformatstringidx,&format);\r
+ SQInteger allocated = (sq_getsize(v,nformatstringidx)+2)*sizeof(SQChar);\r
+ dest = sq_getscratchpad(v,allocated);\r
+ SQInteger n = 0,i = 0, nparam = nformatstringidx+1, w = 0;\r
+ while(format[n] != '\0') {\r
+ if(format[n] != '%') {\r
+ assert(i < allocated);\r
+ dest[i++] = format[n];\r
+ n++;\r
+ }\r
+ else if(format[n+1] == '%') { //handles %%\r
+ dest[i++] = '%';\r
+ n += 2; \r
+ }\r
+ else {\r
+ n++;\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
+ SQInteger addlen = 0;\r
+ SQInteger 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
+ allocated += addlen + sizeof(SQChar);\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
+ *outlen = i;\r
+ dest[i] = '\0';\r
+ *output = dest;\r
+ return SQ_OK;\r
+}\r
+\r
+static SQInteger _string_format(HSQUIRRELVM v)\r
+{\r
+ SQChar *dest = NULL;\r
+ SQInteger length = 0;\r
+ if(SQ_FAILED(sqstd_format(v,2,&length,&dest)))\r
+ return -1;\r
+ sq_pushstring(v,dest,length);\r
+ return 1;\r
+}\r
+\r
+static void __strip_l(const SQChar *str,const SQChar **start)\r
+{\r
+ const SQChar *t = str;\r
+ while(((*t) != '\0') && scisspace(*t)){ t++; }\r
+ *start = t;\r
+}\r
+\r
+static void __strip_r(const SQChar *str,SQInteger len,const SQChar **end)\r
+{\r
+ if(len == 0) {\r
+ *end = str;\r
+ return;\r
+ }\r
+ const SQChar *t = &str[len-1];\r
+ while(t != str && scisspace(*t)) { t--; }\r
+ *end = t+1;\r
+}\r
+\r
+static SQInteger _string_strip(HSQUIRRELVM v)\r
+{\r
+ const SQChar *str,*start,*end;\r
+ sq_getstring(v,2,&str);\r
+ SQInteger len = sq_getsize(v,2);\r
+ __strip_l(str,&start);\r
+ __strip_r(str,len,&end);\r
+ sq_pushstring(v,start,end - start);\r
+ return 1;\r
+}\r
+\r
+static SQInteger _string_lstrip(HSQUIRRELVM v)\r
+{\r
+ const SQChar *str,*start;\r
+ sq_getstring(v,2,&str);\r
+ __strip_l(str,&start);\r
+ sq_pushstring(v,start,-1);\r
+ return 1;\r
+}\r
+\r
+static SQInteger _string_rstrip(HSQUIRRELVM v)\r
+{\r
+ const SQChar *str,*end;\r
+ sq_getstring(v,2,&str);\r
+ SQInteger len = sq_getsize(v,2);\r
+ __strip_r(str,len,&end);\r
+ sq_pushstring(v,str,end - str);\r
+ return 1;\r
+}\r
+\r
+static SQInteger _string_split(HSQUIRRELVM v)\r
+{\r
+ const SQChar *str,*seps;\r
+ SQChar *stemp,*tok;\r
+ sq_getstring(v,2,&str);\r
+ sq_getstring(v,3,&seps);\r
+ if(sq_getsize(v,3) == 0) return sq_throwerror(v,_SC("empty separators string"));\r
+ SQInteger memsize = (sq_getsize(v,2)+1)*sizeof(SQChar);\r
+ stemp = sq_getscratchpad(v,memsize);\r
+ memcpy(stemp,str,memsize);\r
+ tok = scstrtok(stemp,seps);\r
+ sq_newarray(v,0);\r
+ while( tok != NULL ) {\r
+ sq_pushstring(v,tok,-1);\r
+ sq_arrayappend(v,-2);\r
+ tok = scstrtok( NULL, seps );\r
+ }\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 SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger size)\r
+{\r
+ SQRex *self = ((SQRex *)p);\r
+ sqstd_rex_free(self);\r
+ return 1;\r
+}\r
+\r
+static SQInteger _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_pushbool(v,SQTrue);\r
+ return 1;\r
+ }\r
+ sq_pushbool(v,SQFalse);\r
+ return 1;\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 SQInteger _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 SQInteger _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 SQInteger _regexp_subexpcount(HSQUIRRELVM v)\r
+{\r
+ SETUP_REX(v);\r
+ sq_pushinteger(v,sqstd_rex_getsubexpcount(self));\r
+ return 1;\r
+}\r
+\r
+static SQInteger _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 SQInteger _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
+ _DECL_FUNC(strip,2,_SC(".s")),\r
+ _DECL_FUNC(lstrip,2,_SC(".s")),\r
+ _DECL_FUNC(rstrip,2,_SC(".s")),\r
+ _DECL_FUNC(split,3,_SC(".ss")),\r
+ {0,0}\r
+};\r
+\r
+\r
+SQInteger sqstd_register_stringlib(HSQUIRRELVM v)\r
+{\r
+ sq_pushstring(v,_SC("regexp"),-1);\r
+ sq_newclass(v,SQFalse);\r
+ SQInteger 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 <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 SQInteger _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 SQInteger _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 SQInteger _system_clock(HSQUIRRELVM v)
-{
- sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC);
- return 1;
-}
-
-static SQInteger _system_time(HSQUIRRELVM v)
-{
- time_t t;
- time(&t);
- sq_pushinteger(v,*((SQInteger *)&t));
- return 1;
-}
-
-static SQInteger _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 SQInteger _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 SQInteger _system_date(HSQUIRRELVM v)
-{
- time_t t;
- SQInteger it;
- SQInteger format = 'l';
- if(sq_gettop(v) > 1) {
- sq_getinteger(v,2,&it);
- t = it;
- 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}
-};
-
-
-SQInteger sqstd_register_systemlib(HSQUIRRELVM v)
-{
- SQInteger 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;
-}
+/* 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 SQInteger _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 SQInteger _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 SQInteger _system_clock(HSQUIRRELVM v)\r
+{\r
+ sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC);\r
+ return 1;\r
+}\r
+\r
+static SQInteger _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 SQInteger _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 SQInteger _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 SQInteger _system_date(HSQUIRRELVM v)\r
+{\r
+ time_t t;\r
+ SQInteger it;\r
+ SQInteger format = 'l';\r
+ if(sq_gettop(v) > 1) {\r
+ sq_getinteger(v,2,&it);\r
+ t = it;\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
+SQInteger sqstd_register_systemlib(HSQUIRRELVM v)\r
+{\r
+ SQInteger 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 "sqpcheader.h"
-#include "sqvm.h"
-#include "sqstring.h"
-#include "sqtable.h"
-#include "sqarray.h"
-#include "sqfuncproto.h"
-#include "sqclosure.h"
-#include "squserdata.h"
-#include "sqcompiler.h"
-#include "sqfuncstate.h"
-#include "sqclass.h"
-
-bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger 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; }\
-}
-
-SQInteger sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e)
-{
- v->_lasterror = e;
- return SQ_ERROR;
-}
-
-SQInteger 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(SQInteger 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, SQInteger 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;
- }
-}
-
-SQInteger sq_getvmstate(HSQUIRRELVM v)
-{
- if(v->_suspended)
- return SQ_VMSTATE_SUSPENDED;
- else {
- if(v->_callsstacksize != 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 enable)
-{
- _ss(v)->_debuginfo = enable?true:false;
-}
-
-void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable)
-{
- _ss(v)->_notifyallexceptions = enable?true:false;
-}
-
-void sq_addref(HSQUIRRELVM v,HSQOBJECT *po)
-{
- if(!ISREFCOUNTED(type(*po))) return;
-#ifdef NO_GARBAGE_COLLECTOR
- __AddRef(po->_type,po->_unVal);
-#else
- _ss(v)->_refs_table.AddRef(*po);
-#endif
-}
-
-SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)
-{
- if(!ISREFCOUNTED(type(*po))) return SQTrue;
-#ifdef NO_GARBAGE_COLLECTOR
- __Release(po->_type,po->_unVal);
- return SQFalse; //the ret val doesn't work(and cannot be fixed)
-#else
- return _ss(v)->_refs_table.Release(*po);
-#endif
-}
-
-const SQChar *sq_objtostring(HSQOBJECT *o)
-{
- if(sq_type(*o) == OT_STRING) {
- return _stringval(*o);
- }
- 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;
-}
-
-SQBool sq_objtobool(HSQOBJECT *o)
-{
- if(sq_isbool(*o)) {
- return _integer(*o);
- }
- return SQFalse;
-}
-
-void sq_pushnull(HSQUIRRELVM v)
-{
- v->Push(_null_);
-}
-
-void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger 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,SQUnsignedInteger 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,SQInteger 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;
-}
-
-SQBool 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))?SQTrue:SQFalse;
-}
-
-SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger 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,SQInteger 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,SQInteger idx,SQInteger newsize)
-{
- sq_aux_paramscheck(v,1);
- SQObjectPtr *arr;
- _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
- if(newsize >= 0) {
- _array(*arr)->Resize(newsize);
- return SQ_OK;
- }
- return sq_throwerror(v,_SC("negative size"));
-}
-
-
-SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger 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;
- SQInteger size = arr->Size();
- SQInteger n = size >> 1; size -= 1;
- for(SQInteger 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_OK;
-}
-
-SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx)
-{
- sq_aux_paramscheck(v, 1);
- SQObjectPtr *arr;
- _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
- return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));
-}
-
-SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos)
-{
- sq_aux_paramscheck(v, 1);
- SQObjectPtr *arr;
- _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
- SQRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));
- v->Pop();
- return ret;
-}
-
-
-void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars)
-{
- SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func);
- nc->_nparamscheck = 0;
- for(SQUnsignedInteger i = 0; i < nfreevars; i++) {
- nc->_outervalues.push_back(v->Top());
- v->Pop();
- }
- v->Push(SQObjectPtr(nc));
-}
-
-SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars)
-{
- SQObject o = stack_get(v, idx);
- if(sq_isclosure(o)) {
- SQClosure *c = _closure(o);
- SQFunctionProto *proto = _funcproto(c->_function);
- *nparams = (SQUnsignedInteger)proto->_nparameters;
- *nfreevars = (SQUnsignedInteger)c->_outervalues.size();
- return SQ_OK;
- }
- return sq_throwerror(v,_SC("the object is not a closure"));
-}
-
-SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger 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,SQInteger 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);
- }
- if(nparamscheck == SQ_MATCHTYPEMASKSTRING) {
- nc->_nparamscheck = nc->_typecheck.size();
- }
- return SQ_OK;
-}
-
-SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)
-{
- SQObjectPtr &o = stack_get(v,idx);
- if(!sq_isnativeclosure(o) &&
- !sq_isclosure(o))
- return sq_throwerror(v,_SC("the target is not a closure"));
- SQObjectPtr &env = stack_get(v,-1);
- if(!sq_istable(env) &&
- !sq_isclass(env) &&
- !sq_isinstance(env))
- return sq_throwerror(v,_SC("invalid environment"));
- SQObjectPtr w = _refcounted(env)->GetWeakRef(type(env));
- SQObjectPtr ret;
- if(sq_isclosure(o)) {
- SQClosure *c = _closure(o)->Clone();
- c->_env = w;
- ret = c;
- }
- else { //then must be a native closure
- SQNativeClosure *c = _nativeclosure(o)->Clone();
- c->_env = w;
- ret = c;
- }
- v->Pop();
- v->Push(ret);
- return SQ_OK;
-}
-
-SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx)
-{
- SQObject &o=stack_get(v,idx);
- switch(type(o)) {
- case OT_TABLE: _table(o)->Clear(); break;
- case OT_ARRAY: _array(o)->Resize(0); break;
- default:
- return sq_throwerror(v, _SC("clear only works on table and array"));
- break;
-
- }
- return SQ_OK;
-}
-
-void sq_pushroottable(HSQUIRRELVM v)
-{
- v->Push(v->_roottable);
-}
-
-void sq_pushregistrytable(HSQUIRRELVM v)
-{
- v->Push(_ss(v)->_registry);
-}
-
-void sq_pushconsttable(HSQUIRRELVM v)
-{
- v->Push(_ss(v)->_consts);
-}
-
-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"));
-}
-
-SQRESULT sq_setconsttable(HSQUIRRELVM v)
-{
- SQObject o = stack_get(v, -1);
- if(sq_istable(o)) {
- _ss(v)->_consts = o;
- v->Pop();
- return SQ_OK;
- }
- return sq_throwerror(v, _SC("ivalid type, expected table"));
-}
-
-void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p)
-{
- v->_foreignptr = p;
-}
-
-SQUserPointer sq_getforeignptr(HSQUIRRELVM v)
-{
- return v->_foreignptr;
-}
-
-void sq_push(HSQUIRRELVM v,SQInteger idx)
-{
- v->Push(stack_get(v, idx));
-}
-
-SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx)
-{
- return type(stack_get(v, idx));
-}
-
-
-void sq_tostring(HSQUIRRELVM v,SQInteger idx)
-{
- SQObjectPtr &o = stack_get(v, idx);
- SQObjectPtr res;
- v->ToString(o,res);
- v->Push(res);
-}
-
-void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b)
-{
- SQObjectPtr &o = stack_get(v, idx);
- *b = v->IsFalse(o)?SQFalse:SQTrue;
-}
-
-SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger 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,SQInteger 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,SQInteger 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,SQInteger 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,SQInteger idx,HSQUIRRELVM *thread)
-{
- SQObjectPtr *o = NULL;
- _GETSAFE_OBJ(v, idx, OT_THREAD,o);
- *thread = _thread(*o);
- return SQ_OK;
-}
-
-SQRESULT sq_clone(HSQUIRRELVM v,SQInteger 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, SQInteger 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,SQInteger idx,SQUserPointer *p,SQUserPointer *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,SQInteger idx,SQUserPointer 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_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag)
-{
- switch(type(*o)) {
- case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break;
- case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break;
- case OT_CLASS: *typetag = _class(*o)->_typetag; break;
- default: return SQ_ERROR;
- }
- return SQ_OK;
-}
-
-SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag)
-{
- SQObjectPtr &o = stack_get(v,idx);
- if(SQ_FAILED(sq_getobjtypetag(&o,typetag)))
- return sq_throwerror(v,_SC("invalid object type"));
- return SQ_OK;
-}
-
-SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p)
-{
- SQObjectPtr *o = NULL;
- _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o);
- (*p) = _userpointer(*o);
- return SQ_OK;
-}
-
-SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger 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_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize)
-{
- SQObjectPtr &o = stack_get(v,idx);
- if(type(o) != OT_CLASS) return sq_throwerror(v,_SC("the object is not a class"));
- if(_class(o)->_locked) return sq_throwerror(v,_SC("the class is locked"));
- _class(o)->_udsize = udsize;
- return SQ_OK;
-}
-
-
-SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer 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;
-}
-
-SQInteger sq_gettop(HSQUIRRELVM v)
-{
- return (v->_top) - v->_stackbase;
-}
-
-void sq_settop(HSQUIRRELVM v, SQInteger newtop)
-{
- SQInteger top = sq_gettop(v);
- if(top > newtop)
- sq_pop(v, top - newtop);
- else
- while(top++ < newtop) sq_pushnull(v);
-}
-
-void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop)
-{
- assert(v->_top >= nelemstopop);
- v->Pop(nelemstopop);
-}
-
-void sq_poptop(HSQUIRRELVM v)
-{
- assert(v->_top >= 1);
- v->Pop();
-}
-
-
-void sq_remove(HSQUIRRELVM v, SQInteger idx)
-{
- v->Remove(idx);
-}
-
-SQInteger sq_cmp(HSQUIRRELVM v)
-{
- SQInteger res;
- v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res);
- return res;
-}
-
-SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic)
-{
- 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),bstatic?true:false);
- v->Pop(2);
- }
- return SQ_OK;
-}
-
-SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger 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,SQInteger 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,SQInteger 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(_ss(v), v->GetUp(-2), v->GetUp(-1),false);
- 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 array/table/class and instance"));
- }
- v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;
-}
-
-SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger 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,SQInteger 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,SQInteger idx)
-{
- SQObjectPtr &self=stack_get(v,idx);
- switch(type(self)){
- case OT_TABLE:
- case OT_USERDATA:
- if(!_delegable(self)->_delegate){
- v->Push(_null_);
- break;
- }
- v->Push(SQObjectPtr(_delegable(self)->_delegate));
- break;
- default: return sq_throwerror(v,_SC("wrong type")); break;
- }
- return SQ_OK;
-
-}
-
-SQRESULT sq_get(HSQUIRRELVM v,SQInteger 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,SQInteger 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 array/table/instance and class"));
- }
- v->Pop(1);
- return sq_throwerror(v,_SC("the index doesn't exist"));
-}
-
-SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po)
-{
- *po=stack_get(v,idx);
- return SQ_OK;
-}
-
-const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx)
-{
- SQUnsignedInteger cstksize=v->_callsstacksize;
- SQUnsignedInteger lvl=(cstksize-level)-1;
- SQInteger stackbase=v->_stackbase;
- if(lvl<cstksize){
- for(SQUnsignedInteger 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);
- if(func->_noutervalues > (SQInteger)idx) {
- v->Push(c->_outervalues[idx]);
- return _stringval(func->_outervalues[idx]._name);
- }
- idx -= func->_noutervalues;
- return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-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,SQInteger nsize)
-{
- if (((SQUnsignedInteger)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,SQBool raiseerror)
-{
- 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),raiseerror,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,SQInteger params,SQBool retval,SQBool raiseerror)
-{
- SQObjectPtr res;
- if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){
- if(!v->_suspended) {
- 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,SQBool raiseerror,SQBool throwerror)
-{
- 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,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : 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,SQInteger 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;
- case OT_CLASS: _class(ud)->_hook = hook; break;
- default: break; //shutup compiler
- }
- }
-}
-
-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);
- 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 closure;
-
- 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(!SQClosure::Load(v,up,r,closure))
- return SQ_ERROR;
- v->Push(closure);
- return SQ_OK;
-}
-
-SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)
-{
- return _ss(v)->GetScratchPad(minsize);
-}
-
-SQInteger sq_collectgarbage(HSQUIRRELVM v)
-{
-#ifndef NO_GARBAGE_COLLECTOR
- return _ss(v)->CollectGarbage(v);
-#else
- return -1;
-#endif
-}
-
-const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
-{
- SQObjectPtr &self = stack_get(v,idx);
- const SQChar *name = NULL;
- if(type(self) == OT_CLOSURE) {
- if(_closure(self)->_outervalues.size()>nval) {
- v->Push(_closure(self)->_outervalues[nval]);
- SQFunctionProto *fp = _funcproto(_closure(self)->_function);
- SQOuterVar &ov = fp->_outervalues[nval];
- name = _stringval(ov._name);
- }
- }
- return name;
-}
-
-SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger 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,SQInteger 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,SQInteger 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_getbase(HSQUIRRELVM v,SQInteger idx)
-{
- SQObjectPtr *o = NULL;
- _GETSAFE_OBJ(v, idx, OT_CLASS,o);
- if(_class(*o)->_base)
- v->Push(SQObjectPtr(_class(*o)->_base));
- else
- v->Push(_null_);
- return SQ_OK;
-}
-
-SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger 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,SQInteger idx)
-{
- SQObjectPtr *o = NULL;
- _GETSAFE_OBJ(v, idx, OT_CLASS,o);
- v->Push(_class(*o)->CreateInstance());
- return SQ_OK;
-}
-
-void sq_weakref(HSQUIRRELVM v,SQInteger idx)
-{
- SQObject &o=stack_get(v,idx);
- if(ISREFCOUNTED(type(o))) {
- v->Push(_refcounted(o)->GetWeakRef(type(o)));
- return;
- }
- v->Push(o);
-}
-
-SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx)
-{
- SQObjectPtr &o = stack_get(v,idx);
- if(type(o) != OT_WEAKREF) {
- return sq_throwerror(v,_SC("the object must be a weakref"));
- }
- v->Push(_weakref(o)->_obj);
- return SQ_OK;
-}
-
-SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t)
-{
- SQSharedState *ss = _ss(v);
- switch(t) {
- case OT_TABLE: v->Push(ss->_table_default_delegate); break;
- case OT_ARRAY: v->Push(ss->_array_default_delegate); break;
- case OT_STRING: v->Push(ss->_string_default_delegate); break;
- case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break;
- case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break;
- case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break;
- case OT_THREAD: v->Push(ss->_thread_default_delegate); break;
- case OT_CLASS: v->Push(ss->_class_default_delegate); break;
- case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break;
- case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break;
- default: return sq_throwerror(v,_SC("the type doesn't have a default delegate"));
- }
- return SQ_OK;
-}
-
-SQRESULT sq_next(HSQUIRRELVM v,SQInteger 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"));
- }
- int faketojump;
- if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump))
- return SQ_ERROR;
- if(faketojump != 666) {
- v->Push(realkey);
- v->Push(val);
- return SQ_OK;
- }
- return SQ_ERROR;
-}
-
-struct BufState{
- const SQChar *buf;
- SQInteger ptr;
- SQInteger 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,SQInteger 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,SQInteger 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(SQUnsignedInteger size)
-{
- return SQ_MALLOC(size);
-}
-
-void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize)
-{
- return SQ_REALLOC(p,oldsize,newsize);
-}
-
-void sq_free(void *p,SQUnsignedInteger size)
-{
- SQ_FREE(p,size);
-}
+/*\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 "sqcompiler.h"\r
+#include "sqfuncstate.h"\r
+#include "sqclass.h"\r
+\r
+bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger 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
+SQInteger sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e)\r
+{\r
+ v->_lasterror = e;\r
+ return SQ_ERROR;\r
+}\r
+\r
+SQInteger 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(SQInteger 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, SQInteger 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
+SQInteger sq_getvmstate(HSQUIRRELVM v)\r
+{\r
+ if(v->_suspended)\r
+ return SQ_VMSTATE_SUSPENDED;\r
+ else { \r
+ if(v->_callsstacksize != 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 enable)\r
+{\r
+ _ss(v)->_debuginfo = enable?true:false;\r
+}\r
+\r
+void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable)\r
+{\r
+ _ss(v)->_notifyallexceptions = enable?true:false;\r
+}\r
+\r
+void sq_addref(HSQUIRRELVM v,HSQOBJECT *po)\r
+{\r
+ if(!ISREFCOUNTED(type(*po))) return;\r
+#ifdef NO_GARBAGE_COLLECTOR\r
+ __AddRef(po->_type,po->_unVal);\r
+#else\r
+ _ss(v)->_refs_table.AddRef(*po);\r
+#endif\r
+}\r
+\r
+SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)\r
+{\r
+ if(!ISREFCOUNTED(type(*po))) return SQTrue;\r
+#ifdef NO_GARBAGE_COLLECTOR\r
+ __Release(po->_type,po->_unVal);\r
+ return SQFalse; //the ret val doesn't work(and cannot be fixed)\r
+#else\r
+ return _ss(v)->_refs_table.Release(*po);\r
+#endif\r
+}\r
+\r
+const SQChar *sq_objtostring(HSQOBJECT *o) \r
+{\r
+ if(sq_type(*o) == OT_STRING) {\r
+ return _stringval(*o);\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
+SQBool sq_objtobool(HSQOBJECT *o) \r
+{\r
+ if(sq_isbool(*o)) {\r
+ return _integer(*o);\r
+ }\r
+ return SQFalse;\r
+}\r
+\r
+void sq_pushnull(HSQUIRRELVM v)\r
+{\r
+ v->Push(_null_);\r
+}\r
+\r
+void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger 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,SQUnsignedInteger 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,SQInteger 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
+SQBool 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))?SQTrue:SQFalse;\r
+}\r
+\r
+SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger 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,SQInteger 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,SQInteger idx,SQInteger newsize)\r
+{\r
+ sq_aux_paramscheck(v,1);\r
+ SQObjectPtr *arr;\r
+ _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
+ if(newsize >= 0) {\r
+ _array(*arr)->Resize(newsize);\r
+ return SQ_OK;\r
+ }\r
+ return sq_throwerror(v,_SC("negative size"));\r
+}\r
+\r
+\r
+SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger 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
+ SQInteger size = arr->Size();\r
+ SQInteger n = size >> 1; size -= 1;\r
+ for(SQInteger 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_OK;\r
+}\r
+\r
+SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx)\r
+{\r
+ sq_aux_paramscheck(v, 1); \r
+ SQObjectPtr *arr;\r
+ _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); \r
+ return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range")); \r
+}\r
+\r
+SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos)\r
+{\r
+ sq_aux_paramscheck(v, 1); \r
+ SQObjectPtr *arr;\r
+ _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);\r
+ SQRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));\r
+ v->Pop();\r
+ return ret;\r
+}\r
+\r
+\r
+void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars)\r
+{\r
+ SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func);\r
+ nc->_nparamscheck = 0;\r
+ for(SQUnsignedInteger 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,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *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 = (SQUnsignedInteger)proto->_nparameters;\r
+ *nfreevars = (SQUnsignedInteger)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,SQInteger 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,SQInteger 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
+ if(nparamscheck == SQ_MATCHTYPEMASKSTRING) {\r
+ nc->_nparamscheck = nc->_typecheck.size();\r
+ }\r
+ return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)\r
+{\r
+ SQObjectPtr &o = stack_get(v,idx);\r
+ if(!sq_isnativeclosure(o) &&\r
+ !sq_isclosure(o))\r
+ return sq_throwerror(v,_SC("the target is not a closure"));\r
+ SQObjectPtr &env = stack_get(v,-1);\r
+ if(!sq_istable(env) &&\r
+ !sq_isclass(env) &&\r
+ !sq_isinstance(env))\r
+ return sq_throwerror(v,_SC("invalid environment"));\r
+ SQObjectPtr w = _refcounted(env)->GetWeakRef(type(env));\r
+ SQObjectPtr ret;\r
+ if(sq_isclosure(o)) {\r
+ SQClosure *c = _closure(o)->Clone();\r
+ c->_env = w;\r
+ ret = c;\r
+ }\r
+ else { //then must be a native closure\r
+ SQNativeClosure *c = _nativeclosure(o)->Clone();\r
+ c->_env = w;\r
+ ret = c;\r
+ }\r
+ v->Pop();\r
+ v->Push(ret);\r
+ return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx)\r
+{\r
+ SQObject &o=stack_get(v,idx);\r
+ switch(type(o)) {\r
+ case OT_TABLE: _table(o)->Clear(); break;\r
+ case OT_ARRAY: _array(o)->Resize(0); break;\r
+ default:\r
+ return sq_throwerror(v, _SC("clear only works on table and array"));\r
+ break;\r
+\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
+void sq_pushconsttable(HSQUIRRELVM v)\r
+{\r
+ v->Push(_ss(v)->_consts);\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
+SQRESULT sq_setconsttable(HSQUIRRELVM v)\r
+{\r
+ SQObject o = stack_get(v, -1);\r
+ if(sq_istable(o)) {\r
+ _ss(v)->_consts = o;\r
+ v->Pop();\r
+ return SQ_OK;\r
+ }\r
+ return sq_throwerror(v, _SC("ivalid type, expected table"));\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,SQInteger idx)\r
+{\r
+ v->Push(stack_get(v, idx));\r
+}\r
+\r
+SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx)\r
+{\r
+ return type(stack_get(v, idx));\r
+}\r
+\r
+\r
+void sq_tostring(HSQUIRRELVM v,SQInteger idx)\r
+{\r
+ SQObjectPtr &o = stack_get(v, idx);\r
+ SQObjectPtr res;\r
+ v->ToString(o,res);\r
+ v->Push(res);\r
+}\r
+\r
+void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b)\r
+{\r
+ SQObjectPtr &o = stack_get(v, idx);\r
+ *b = v->IsFalse(o)?SQFalse:SQTrue;\r
+}\r
+\r
+SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger 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,SQInteger 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,SQInteger 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,SQInteger 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,SQInteger 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,SQInteger 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, SQInteger 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
+ case OT_INSTANCE: return _instance(o)->_class->_udsize;\r
+ case OT_CLASS: return _class(o)->_udsize;\r
+ default:\r
+ return sq_aux_invalidtype(v, type);\r
+ }\r
+}\r
+\r
+SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *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,SQInteger idx,SQUserPointer 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_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag)\r
+{\r
+ switch(type(*o)) {\r
+ case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break;\r
+ case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break;\r
+ case OT_CLASS: *typetag = _class(*o)->_typetag; break;\r
+ default: return SQ_ERROR;\r
+ }\r
+ return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag)\r
+{\r
+ SQObjectPtr &o = stack_get(v,idx);\r
+ if(SQ_FAILED(sq_getobjtypetag(&o,typetag)))\r
+ return sq_throwerror(v,_SC("invalid object type"));\r
+ return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger 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, SQInteger 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_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize)\r
+{\r
+ SQObjectPtr &o = stack_get(v,idx);\r
+ if(type(o) != OT_CLASS) return sq_throwerror(v,_SC("the object is not a class"));\r
+ if(_class(o)->_locked) return sq_throwerror(v,_SC("the class is locked"));\r
+ _class(o)->_udsize = udsize;\r
+ return SQ_OK;\r
+}\r
+\r
+\r
+SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer 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
+SQInteger sq_gettop(HSQUIRRELVM v)\r
+{\r
+ return (v->_top) - v->_stackbase;\r
+}\r
+\r
+void sq_settop(HSQUIRRELVM v, SQInteger newtop)\r
+{\r
+ SQInteger 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, SQInteger nelemstopop)\r
+{\r
+ assert(v->_top >= nelemstopop);\r
+ v->Pop(nelemstopop);\r
+}\r
+\r
+void sq_poptop(HSQUIRRELVM v)\r
+{\r
+ assert(v->_top >= 1);\r
+ v->Pop();\r
+}\r
+\r
+\r
+void sq_remove(HSQUIRRELVM v, SQInteger idx)\r
+{\r
+ v->Remove(idx);\r
+}\r
+\r
+SQInteger sq_cmp(HSQUIRRELVM v)\r
+{\r
+ SQInteger res;\r
+ v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res);\r
+ return res;\r
+}\r
+\r
+SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic)\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),bstatic?true:false);\r
+ v->Pop(2);\r
+ }\r
+ return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger 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,SQInteger 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,SQInteger 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(_ss(v), v->GetUp(-2), v->GetUp(-1),false);\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 array/table/class and instance"));\r
+ }\r
+ v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR;\r
+}\r
+\r
+SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger 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,SQInteger 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,SQInteger idx)\r
+{\r
+ SQObjectPtr &self=stack_get(v,idx);\r
+ switch(type(self)){\r
+ case OT_TABLE:\r
+ case OT_USERDATA:\r
+ if(!_delegable(self)->_delegate){\r
+ v->Push(_null_);\r
+ break;\r
+ }\r
+ v->Push(SQObjectPtr(_delegable(self)->_delegate));\r
+ break;\r
+ default: return sq_throwerror(v,_SC("wrong type")); break;\r
+ }\r
+ return SQ_OK;\r
+ \r
+}\r
+\r
+SQRESULT sq_get(HSQUIRRELVM v,SQInteger 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,SQInteger 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 array/table/instance and class"));\r
+ } \r
+ v->Pop(1);\r
+ return sq_throwerror(v,_SC("the index doesn't exist"));\r
+}\r
+\r
+SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po)\r
+{\r
+ *po=stack_get(v,idx);\r
+ return SQ_OK;\r
+}\r
+\r
+const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx)\r
+{\r
+ SQUnsignedInteger cstksize=v->_callsstacksize;\r
+ SQUnsignedInteger lvl=(cstksize-level)-1;\r
+ SQInteger stackbase=v->_stackbase;\r
+ if(lvl<cstksize){\r
+ for(SQUnsignedInteger 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
+ if(func->_noutervalues > (SQInteger)idx) {\r
+ v->Push(c->_outervalues[idx]);\r
+ return _stringval(func->_outervalues[idx]._name);\r
+ }\r
+ idx -= func->_noutervalues;\r
+ return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-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,SQInteger nsize)\r
+{\r
+ if (((SQUnsignedInteger)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,SQBool raiseerror)\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),raiseerror,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,SQInteger params,SQBool retval,SQBool raiseerror)\r
+{\r
+ SQObjectPtr res;\r
+ if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){\r
+ if(!v->_suspended) {\r
+ v->Pop(params);//pop closure and args\r
+ }\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,SQBool raiseerror,SQBool throwerror)\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,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : 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,SQInteger 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: _userdata(ud)->_hook = hook; break;\r
+ case OT_INSTANCE: _instance(ud)->_hook = hook; break;\r
+ case OT_CLASS: _class(ud)->_hook = hook; break;\r
+ default: break; //shutup compiler\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
+ 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 closure;\r
+ \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(!SQClosure::Load(v,up,r,closure))\r
+ return SQ_ERROR;\r
+ v->Push(closure);\r
+ return SQ_OK;\r
+}\r
+\r
+SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)\r
+{\r
+ return _ss(v)->GetScratchPad(minsize);\r
+}\r
+\r
+SQInteger 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
+const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)\r
+{\r
+ SQObjectPtr &self = stack_get(v,idx);\r
+ const SQChar *name = NULL;\r
+ if(type(self) == OT_CLOSURE) {\r
+ if(_closure(self)->_outervalues.size()>nval) {\r
+ v->Push(_closure(self)->_outervalues[nval]);\r
+ SQFunctionProto *fp = _funcproto(_closure(self)->_function);\r
+ SQOuterVar &ov = fp->_outervalues[nval];\r
+ name = _stringval(ov._name);\r
+ }\r
+ }\r
+ return name;\r
+}\r
+\r
+SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger 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,SQInteger 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,SQInteger 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_getbase(HSQUIRRELVM v,SQInteger idx)\r
+{\r
+ SQObjectPtr *o = NULL;\r
+ _GETSAFE_OBJ(v, idx, OT_CLASS,o);\r
+ if(_class(*o)->_base)\r
+ v->Push(SQObjectPtr(_class(*o)->_base));\r
+ else\r
+ v->Push(_null_);\r
+ return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger 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,SQInteger 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
+void sq_weakref(HSQUIRRELVM v,SQInteger idx)\r
+{\r
+ SQObject &o=stack_get(v,idx);\r
+ if(ISREFCOUNTED(type(o))) {\r
+ v->Push(_refcounted(o)->GetWeakRef(type(o)));\r
+ return;\r
+ }\r
+ v->Push(o);\r
+}\r
+\r
+SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx)\r
+{\r
+ SQObjectPtr &o = stack_get(v,idx);\r
+ if(type(o) != OT_WEAKREF) {\r
+ return sq_throwerror(v,_SC("the object must be a weakref"));\r
+ }\r
+ v->Push(_weakref(o)->_obj);\r
+ return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t)\r
+{\r
+ SQSharedState *ss = _ss(v);\r
+ switch(t) {\r
+ case OT_TABLE: v->Push(ss->_table_default_delegate); break;\r
+ case OT_ARRAY: v->Push(ss->_array_default_delegate); break;\r
+ case OT_STRING: v->Push(ss->_string_default_delegate); break;\r
+ case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break;\r
+ case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break;\r
+ case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break;\r
+ case OT_THREAD: v->Push(ss->_thread_default_delegate); break;\r
+ case OT_CLASS: v->Push(ss->_class_default_delegate); break;\r
+ case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break;\r
+ case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break;\r
+ default: return sq_throwerror(v,_SC("the type doesn't have a default delegate"));\r
+ }\r
+ return SQ_OK;\r
+}\r
+\r
+SQRESULT sq_next(HSQUIRRELVM v,SQInteger 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
+ int faketojump;\r
+ if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump))\r
+ return SQ_ERROR;\r
+ if(faketojump != 666) {\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
+ SQInteger ptr;\r
+ SQInteger 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,SQInteger 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,SQInteger 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(SQUnsignedInteger size)\r
+{\r
+ return SQ_MALLOC(size);\r
+}\r
+\r
+void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize)\r
+{\r
+ return SQ_REALLOC(p,oldsize,newsize);\r
+}\r
+\r
+void sq_free(void *p,SQUnsignedInteger size)\r
+{\r
+ SQ_FREE(p,size);\r
+}\r
-/* see copyright notice in squirrel.h */
-#ifndef _SQARRAY_H_
-#define _SQARRAY_H_
-
-struct SQArray : public CHAINABLE_OBJ
-{
-private:
- SQArray(SQSharedState *ss,SQInteger nsize){_values.resize(nsize); 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,SQInteger 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 SQInteger nidx,SQObjectPtr &val)
- {
- if(nidx>=0 && nidx<(SQInteger)_values.size()){
- SQObjectPtr &o = _values[nidx];
- val = _realval(o);
- return true;
- }
- else return false;
- }
- bool Set(const SQInteger nidx,const SQObjectPtr &val)
- {
- if(nidx>=0 && nidx<(SQInteger)_values.size()){
- _values[nidx]=val;
- return true;
- }
- else return false;
- }
- SQInteger Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval)
- {
- SQUnsignedInteger idx=TranslateIndex(refpos);
- while(idx<_values.size()){
- //first found
- outkey=(SQInteger)idx;
- SQObjectPtr &o = _values[idx];
- outval = _realval(o);
- //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; }
- SQInteger Size() const {return _values.size();}
- void Resize(SQInteger size,SQObjectPtr &fill = _null_) { _values.resize(size,fill); ShrinkIfNeeded(); }
- void Reserve(SQInteger 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(); }
- bool Insert(SQInteger idx,const SQObject &val){
- if(idx < 0 || idx > (SQInteger)_values.size())
- return false;
- _values.insert(idx,val);
- return true;
- }
- void ShrinkIfNeeded() {
- if(_values.size() <= _values.capacity()>>2) //shrink the array
- _values.shrinktofit();
- }
- bool Remove(SQInteger idx){
- if(idx < 0 || idx >= (SQInteger)_values.size())
- return false;
- _values.remove(idx);
- ShrinkIfNeeded();
- return true;
- }
- void Release()
- {
- sq_delete(this,SQArray);
- }
- SQObjectPtrVec _values;
-};
-#endif //_SQARRAY_H_
+/* 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,SQInteger nsize){_values.resize(nsize); 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,SQInteger 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 SQInteger nidx,SQObjectPtr &val)\r
+ {\r
+ if(nidx>=0 && nidx<(SQInteger)_values.size()){\r
+ SQObjectPtr &o = _values[nidx];\r
+ val = _realval(o);\r
+ return true;\r
+ }\r
+ else return false;\r
+ }\r
+ bool Set(const SQInteger nidx,const SQObjectPtr &val)\r
+ {\r
+ if(nidx>=0 && nidx<(SQInteger)_values.size()){\r
+ _values[nidx]=val;\r
+ return true;\r
+ }\r
+ else return false;\r
+ }\r
+ SQInteger Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval)\r
+ {\r
+ SQUnsignedInteger idx=TranslateIndex(refpos);\r
+ while(idx<_values.size()){\r
+ //first found\r
+ outkey=(SQInteger)idx;\r
+ SQObjectPtr &o = _values[idx];\r
+ outval = _realval(o);\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
+ SQInteger Size() const {return _values.size();}\r
+ void Resize(SQInteger size,SQObjectPtr &fill = _null_) { _values.resize(size,fill); ShrinkIfNeeded(); }\r
+ void Reserve(SQInteger 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
+ bool Insert(SQInteger idx,const SQObject &val){\r
+ if(idx < 0 || idx > (SQInteger)_values.size())\r
+ return false;\r
+ _values.insert(idx,val);\r
+ return true;\r
+ }\r
+ void ShrinkIfNeeded() {\r
+ if(_values.size() <= _values.capacity()>>2) //shrink the array\r
+ _values.shrinktofit();\r
+ }\r
+ bool Remove(SQInteger idx){\r
+ if(idx < 0 || idx >= (SQInteger)_values.size())\r
+ return false;\r
+ _values.remove(idx);\r
+ ShrinkIfNeeded();\r
+ return true;\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
-*/
-#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;
- res = r;
- return true;
- }
- else{
- SQInteger r = SQInteger(scstrtol(s,&end,10));
- if(s == end) return false;
- res = r;
- return true;
- }
-}
-
-static SQInteger base_dummy(HSQUIRRELVM v)
-{
- return 0;
-}
-
-#ifndef NO_GARBAGE_COLLECTOR
-static SQInteger base_collectgarbage(HSQUIRRELVM v)
-{
- sq_pushinteger(v, sq_collectgarbage(v));
- return 1;
-}
-#endif
-
-static SQInteger base_getroottable(HSQUIRRELVM v)
-{
- v->Push(v->_roottable);
- return 1;
-}
-
-static SQInteger base_getconsttable(HSQUIRRELVM v)
-{
- v->Push(_ss(v)->_consts);
- return 1;
-}
-
-
-static SQInteger 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 SQInteger base_setconsttable(HSQUIRRELVM v)
-{
- SQObjectPtr &o=stack_get(v,2);
- if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR;
- v->Push(o);
- return 1;
-}
-
-static SQInteger base_seterrorhandler(HSQUIRRELVM v)
-{
- sq_seterrorhandler(v);
- return 0;
-}
-
-static SQInteger base_setdebughook(HSQUIRRELVM v)
-{
- sq_setdebughook(v);
- return 0;
-}
-
-static SQInteger base_enabledebuginfo(HSQUIRRELVM v)
-{
- SQObjectPtr &o=stack_get(v,2);
- sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0);
- return 0;
-}
-
-static SQInteger base_getstackinfos(HSQUIRRELVM v)
-{
- SQInteger level;
- SQStackInfos si;
- SQInteger 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 SQInteger base_assert(HSQUIRRELVM v)
-{
- if(v->IsFalse(stack_get(v,2))){
- return sq_throwerror(v,_SC("assertion failed"));
- }
- return 0;
-}
-
-static SQInteger get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,SQObjectPtr &o)
-{
- SQInteger 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 SQInteger base_print(HSQUIRRELVM v)
-{
- const SQChar *str;
- sq_tostring(v,2);
- sq_getstring(v,-1,&str);
- if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str);
- return 0;
-}
-
-static SQInteger base_compilestring(HSQUIRRELVM v)
-{
- SQInteger 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 SQInteger base_newthread(HSQUIRRELVM v)
-{
- SQObjectPtr &func = stack_get(v,2);
- SQInteger 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 SQInteger base_suspend(HSQUIRRELVM v)
-{
- return sq_suspendvm(v);
-}
-
-static SQInteger 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 SQInteger 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("getconsttable"),base_getconsttable,1, NULL},
- {_SC("setconsttable"),base_setconsttable,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},
- {_SC("dummy"),base_dummy,0,NULL},
-#ifndef NO_GARBAGE_COLLECTOR
- {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")},
-#endif
- {0,0}
-};
-
-void sq_base_register(HSQUIRRELVM v)
-{
- SQInteger 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("_version_"),-1);
- sq_pushstring(v,SQUIRREL_VERSION,-1);
- sq_createslot(v,-3);
- sq_pushstring(v,_SC("_charsize_"),-1);
- sq_pushinteger(v,sizeof(SQChar));
- sq_createslot(v,-3);
- sq_pushstring(v,_SC("_intsize_"),-1);
- sq_pushinteger(v,sizeof(SQInteger));
- sq_createslot(v,-3);
- sq_pushstring(v,_SC("_floatsize_"),-1);
- sq_pushinteger(v,sizeof(SQFloat));
- sq_createslot(v,-3);
- sq_pop(v,1);
-}
-
-static SQInteger default_delegate_len(HSQUIRRELVM v)
-{
- v->Push(SQInteger(sq_getsize(v,1)));
- return 1;
-}
-
-static SQInteger 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;
- }}
- return sq_throwerror(v, _SC("cannot convert the string"));
- 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 SQInteger 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;
- }}
- return sq_throwerror(v, _SC("cannot convert the string"));
- break;
- case OT_INTEGER:case OT_FLOAT:
- v->Push(SQObjectPtr(tointeger(o)));
- break;
- case OT_BOOL:
- v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0));
- break;
- default:
- v->Push(_null_);
- break;
- }
- return 1;
-}
-
-static SQInteger default_delegate_tostring(HSQUIRRELVM v)
-{
- sq_tostring(v,1);
- return 1;
-}
-
-static SQInteger obj_delegate_weakref(HSQUIRRELVM v)
-{
- sq_weakref(v,1);
- return 1;
-}
-
-static SQInteger obj_clear(HSQUIRRELVM v)
-{
- return sq_clear(v,-1);
-}
-
-
-static SQInteger number_delegate_tochar(HSQUIRRELVM v)
-{
- SQObject &o=stack_get(v,1);
- SQChar c = (SQChar)tointeger(o);
- v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1));
- return 1;
-}
-
-
-/////////////////////////////////////////////////////////////////
-//TABLE DEFAULT DELEGATE
-
-static SQInteger table_rawdelete(HSQUIRRELVM v)
-{
- if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue)))
- return SQ_ERROR;
- return 1;
-}
-
-
-static SQInteger container_rawexists(HSQUIRRELVM v)
-{
- if(SQ_SUCCEEDED(sq_rawget(v,-2))) {
- sq_pushbool(v,SQTrue);
- return 1;
- }
- sq_pushbool(v,SQFalse);
- return 1;
-}
-
-static SQInteger table_rawset(HSQUIRRELVM v)
-{
- return sq_rawset(v,-3);
-}
-
-
-static SQInteger 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")},
- {_SC("weakref"),obj_delegate_weakref,1, NULL },
- {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
- {_SC("clear"),obj_clear,1, _SC(".")},
- {0,0}
-};
-
-//ARRAY DEFAULT DELEGATE///////////////////////////////////////
-
-static SQInteger array_append(HSQUIRRELVM v)
-{
- return sq_arrayappend(v,-2);
-}
-
-static SQInteger array_extend(HSQUIRRELVM v)
-{
- _array(stack_get(v,1))->Extend(_array(stack_get(v,2)));
- return 0;
-}
-
-static SQInteger array_reverse(HSQUIRRELVM v)
-{
- return sq_arrayreverse(v,-1);
-}
-
-static SQInteger array_pop(HSQUIRRELVM v)
-{
- return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR;
-}
-
-static SQInteger 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 SQInteger array_insert(HSQUIRRELVM v)
-{
- SQObject &o=stack_get(v,1);
- SQObject &idx=stack_get(v,2);
- SQObject &val=stack_get(v,3);
- if(!_array(o)->Insert(tointeger(idx),val))
- return sq_throwerror(v,_SC("index out of range"));
- return 0;
-}
-
-static SQInteger 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 SQInteger 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,SQInteger func,SQInteger &ret)
-{
- if(func < 0) {
- if(!v->ObjCmp(a,b,ret)) return false;
- }
- else {
- SQInteger 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, SQFalse))) {
- if(!sq_isstring( v->_lasterror))
- 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, SQInteger l, SQInteger r,SQInteger func)
-{
- SQInteger i, j;
- SQArray *a=_array(arr);
- SQObjectPtr pivot,t;
- if( l < r ){
- pivot = a->_values[l];
- i = l; j = r+1;
- while(1){
- SQInteger 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 ( j < 0 ) {
- v->Raise_Error( _SC("Invalid qsort, probably compare function defect") );
- return false;
- }
- 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 SQInteger array_sort(HSQUIRRELVM v)
-{
- SQInteger 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 SQInteger array_slice(HSQUIRRELVM v)
-{
- SQInteger sidx,eidx;
- SQObjectPtr o;
- if(get_slice_params(v,sidx,eidx,o)==-1)return -1;
- SQInteger alen = _array(o)->Size();
- if(sidx < 0)sidx = alen + sidx;
- if(eidx < 0)eidx = alen + eidx;
- if(eidx < sidx)return sq_throwerror(v,_SC("wrong indexes"));
- if(eidx > alen)return sq_throwerror(v,_SC("slice out of range"));
- SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);
- SQObjectPtr t;
- SQInteger count=0;
- for(SQInteger 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")},
- {_SC("weakref"),obj_delegate_weakref,1, NULL },
- {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
- {_SC("clear"),obj_clear,1, _SC(".")},
- {0,0}
-};
-
-//STRING DEFAULT DELEGATE//////////////////////////
-static SQInteger string_slice(HSQUIRRELVM v)
-{
- SQInteger sidx,eidx;
- SQObjectPtr o;
- if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;
- SQInteger slen = _string(o)->_len;
- if(sidx < 0)sidx = slen + sidx;
- if(eidx < 0)eidx = slen + eidx;
- if(eidx < sidx) return sq_throwerror(v,_SC("wrong indexes"));
- if(eidx > slen) return sq_throwerror(v,_SC("slice out of range"));
- v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));
- return 1;
-}
-
-static SQInteger string_find(HSQUIRRELVM v)
-{
- SQInteger 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,(SQInteger)(ret-str));
- return 1;
- }
- }
- return 0;
- }
- return sq_throwerror(v,_SC("invalid param"));
-}
-
-#define STRING_TOFUNCZ(func) static SQInteger string_##func(HSQUIRRELVM v) \
-{ \
- SQObject str=stack_get(v,1); \
- SQInteger len=_string(str)->_len; \
- const SQChar *sThis=_stringval(str); \
- SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \
- for(SQInteger 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(".")},
- {_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")},
- {_SC("weakref"),obj_delegate_weakref,1, NULL },
- {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(".")},
- {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},
- {_SC("weakref"),obj_delegate_weakref,1, NULL },
- {0,0}
-};
-
-//CLOSURE DEFAULT DELEGATE//////////////////////////
-static SQInteger closure_pcall(HSQUIRRELVM v)
-{
- return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQFalse))?1:SQ_ERROR;
-}
-
-static SQInteger closure_call(HSQUIRRELVM v)
-{
- return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQTrue))?1:SQ_ERROR;
-}
-
-static SQInteger _closure_acall(HSQUIRRELVM v,SQBool raiseerror)
-{
- SQArray *aparams=_array(stack_get(v,2));
- SQInteger nparams=aparams->Size();
- v->Push(stack_get(v,1));
- for(SQInteger i=0;i<nparams;i++)v->Push(aparams->_values[i]);
- return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue,raiseerror))?1:SQ_ERROR;
-}
-
-static SQInteger closure_acall(HSQUIRRELVM v)
-{
- return _closure_acall(v,SQTrue);
-}
-
-static SQInteger closure_pacall(HSQUIRRELVM v)
-{
- return _closure_acall(v,SQFalse);
-}
-
-static SQInteger closure_bindenv(HSQUIRRELVM v)
-{
- if(SQ_FAILED(sq_bindenv(v,1)))
- return SQ_ERROR;
- return 1;
-}
-
-static SQInteger closure_getinfos(HSQUIRRELVM v) {
- SQObject o = stack_get(v,1);
- SQTable *res = SQTable::Create(_ss(v),4);
- if(type(o) == OT_CLOSURE) {
- SQFunctionProto *f = _funcproto(_closure(o)->_function);
- SQInteger nparams = f->_nparameters + (f->_varparams?1:0);
- SQObjectPtr params = SQArray::Create(_ss(v),nparams);
- for(SQInteger n = 0; n<f->_nparameters; n++) {
- _array(params)->Set((SQInteger)n,f->_parameters[n]);
- }
- if(f->_varparams) {
- _array(params)->Set(nparams-1,SQString::Create(_ss(v),_SC("..."),-1));
- }
- res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),false);
- res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),f->_name);
- res->NewSlot(SQString::Create(_ss(v),_SC("src"),-1),f->_sourcename);
- res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params);
- res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams);
- }
- else { //OT_NATIVECLOSURE
- SQNativeClosure *nc = _nativeclosure(o);
- res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),true);
- res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),nc->_name);
- res->NewSlot(SQString::Create(_ss(v),_SC("paramscheck"),-1),nc->_nparamscheck);
- SQObjectPtr typecheck;
- if(nc->_typecheck.size() > 0) {
- typecheck =
- SQArray::Create(_ss(v), nc->_typecheck.size());
- for(SQUnsignedInteger n = 0; n<nc->_typecheck.size(); n++) {
- _array(typecheck)->Set((SQInteger)n,nc->_typecheck[n]);
- }
- }
- res->NewSlot(SQString::Create(_ss(v),_SC("typecheck"),-1),typecheck);
- }
- v->Push(res);
- return 1;
-}
-
-
-SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={
- {_SC("call"),closure_call,-1, _SC("c")},
- {_SC("pcall"),closure_pcall,-1, _SC("c")},
- {_SC("acall"),closure_acall,2, _SC("ca")},
- {_SC("pacall"),closure_pacall,2, _SC("ca")},
- {_SC("weakref"),obj_delegate_weakref,1, NULL },
- {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
- {_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")},
- {_SC("getinfos"),closure_getinfos,1, _SC("c")},
- {0,0}
-};
-
-//GENERATOR DEFAULT DELEGATE
-static SQInteger 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")},
- {_SC("weakref"),obj_delegate_weakref,1, NULL },
- {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
- {0,0}
-};
-
-//THREAD DEFAULT DELEGATE
-
-static SQInteger thread_call(HSQUIRRELVM v)
-{
-
- SQObjectPtr o = stack_get(v,1);
- if(type(o) == OT_THREAD) {
- SQInteger nparams = sq_gettop(v);
- _thread(o)->Push(_thread(o)->_roottable);
- for(SQInteger i = 2; i<(nparams+1); i++)
- sq_move(_thread(o),v,i);
- if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQFalse))) {
- sq_move(v,_thread(o),-1);
- sq_pop(_thread(o),1);
- return 1;
- }
- v->_lasterror = _thread(o)->_lasterror;
- return SQ_ERROR;
- }
- return sq_throwerror(v,_SC("wrong parameter"));
-}
-
-static SQInteger thread_wakeup(HSQUIRRELVM v)
-{
- SQObjectPtr o = stack_get(v,1);
- if(type(o) == OT_THREAD) {
- SQVM *thread = _thread(o);
- SQInteger 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;
- }
- }
-
- SQInteger wakeupret = sq_gettop(v)>1?1:0;
- if(wakeupret) {
- sq_move(thread,v,2);
- }
- if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,SQTrue,SQTrue,SQFalse))) {
- sq_move(v,thread,-1);
- sq_pop(thread,1); //pop retval
- if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {
- sq_settop(thread,1); //pop roottable
- }
- return 1;
- }
- sq_settop(thread,1);
- v->_lasterror = thread->_lasterror;
- return SQ_ERROR;
- }
- return sq_throwerror(v,_SC("wrong parameter"));
-}
-
-static SQInteger 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")},
- {_SC("weakref"),obj_delegate_weakref,1, NULL },
- {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
- {0,0},
-};
-
-static SQInteger class_getattributes(HSQUIRRELVM v)
-{
- if(SQ_SUCCEEDED(sq_getattributes(v,-2)))
- return 1;
- return SQ_ERROR;
-}
-
-static SQInteger class_setattributes(HSQUIRRELVM v)
-{
- if(SQ_SUCCEEDED(sq_setattributes(v,-3)))
- return 1;
- return SQ_ERROR;
-}
-
-static SQInteger class_instance(HSQUIRRELVM v)
-{
- if(SQ_SUCCEEDED(sq_createinstance(v,-1)))
- 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")},
- {_SC("weakref"),obj_delegate_weakref,1, NULL },
- {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
- {_SC("instance"),class_instance,1, _SC("y")},
- {0,0}
-};
-
-static SQInteger 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")},
- {_SC("weakref"),obj_delegate_weakref,1, NULL },
- {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
- {0,0}
-};
-
-static SQInteger weakref_ref(HSQUIRRELVM v)
-{
- if(SQ_FAILED(sq_getweakrefval(v,1)))
- return SQ_ERROR;
- return 1;
-}
-
-SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = {
- {_SC("ref"),weakref_ref,1, _SC("r")},
- {_SC("weakref"),obj_delegate_weakref,1, NULL },
- {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
- {0,0}
-};
-
-
+/*\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
+ res = r;\r
+ return true;\r
+ }\r
+ else{\r
+ SQInteger r = SQInteger(scstrtol(s,&end,10));\r
+ if(s == end) return false;\r
+ res = r;\r
+ return true;\r
+ }\r
+}\r
+\r
+static SQInteger base_dummy(HSQUIRRELVM v)\r
+{\r
+ return 0;\r
+}\r
+\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+static SQInteger base_collectgarbage(HSQUIRRELVM v)\r
+{\r
+ sq_pushinteger(v, sq_collectgarbage(v));\r
+ return 1;\r
+}\r
+#endif\r
+\r
+static SQInteger base_getroottable(HSQUIRRELVM v)\r
+{\r
+ v->Push(v->_roottable);\r
+ return 1;\r
+}\r
+\r
+static SQInteger base_getconsttable(HSQUIRRELVM v)\r
+{\r
+ v->Push(_ss(v)->_consts);\r
+ return 1;\r
+}\r
+\r
+\r
+static SQInteger 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 SQInteger base_setconsttable(HSQUIRRELVM v)\r
+{\r
+ SQObjectPtr &o=stack_get(v,2);\r
+ if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR;\r
+ v->Push(o);\r
+ return 1;\r
+}\r
+\r
+static SQInteger base_seterrorhandler(HSQUIRRELVM v)\r
+{\r
+ sq_seterrorhandler(v);\r
+ return 0;\r
+}\r
+\r
+static SQInteger base_setdebughook(HSQUIRRELVM v)\r
+{\r
+ sq_setdebughook(v);\r
+ return 0;\r
+}\r
+\r
+static SQInteger 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 SQInteger base_getstackinfos(HSQUIRRELVM v)\r
+{\r
+ SQInteger level;\r
+ SQStackInfos si;\r
+ SQInteger 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 SQInteger 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 SQInteger get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,SQObjectPtr &o)\r
+{\r
+ SQInteger 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 SQInteger base_print(HSQUIRRELVM v)\r
+{\r
+ const SQChar *str;\r
+ sq_tostring(v,2);\r
+ sq_getstring(v,-1,&str);\r
+ if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str);\r
+ return 0;\r
+}\r
+\r
+static SQInteger base_compilestring(HSQUIRRELVM v)\r
+{\r
+ SQInteger 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 SQInteger base_newthread(HSQUIRRELVM v)\r
+{\r
+ SQObjectPtr &func = stack_get(v,2);\r
+ SQInteger 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 SQInteger base_suspend(HSQUIRRELVM v)\r
+{\r
+ return sq_suspendvm(v);\r
+}\r
+\r
+static SQInteger 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 SQInteger 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("getconsttable"),base_getconsttable,1, NULL},\r
+ {_SC("setconsttable"),base_setconsttable,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
+ {_SC("dummy"),base_dummy,0,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
+ SQInteger 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("_version_"),-1);\r
+ sq_pushstring(v,SQUIRREL_VERSION,-1);\r
+ sq_createslot(v,-3);\r
+ sq_pushstring(v,_SC("_charsize_"),-1);\r
+ sq_pushinteger(v,sizeof(SQChar));\r
+ sq_createslot(v,-3);\r
+ sq_pushstring(v,_SC("_intsize_"),-1);\r
+ sq_pushinteger(v,sizeof(SQInteger));\r
+ sq_createslot(v,-3);\r
+ sq_pushstring(v,_SC("_floatsize_"),-1);\r
+ sq_pushinteger(v,sizeof(SQFloat));\r
+ sq_createslot(v,-3);\r
+ sq_pop(v,1);\r
+}\r
+\r
+static SQInteger default_delegate_len(HSQUIRRELVM v)\r
+{\r
+ v->Push(SQInteger(sq_getsize(v,1)));\r
+ return 1;\r
+}\r
+\r
+static SQInteger 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
+ return sq_throwerror(v, _SC("cannot convert the string"));\r
+ break;\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 SQInteger 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
+ return sq_throwerror(v, _SC("cannot convert the string"));\r
+ break;\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)?(SQInteger)1:(SQInteger)0));\r
+ break;\r
+ default:\r
+ v->Push(_null_);\r
+ break;\r
+ }\r
+ return 1;\r
+}\r
+\r
+static SQInteger default_delegate_tostring(HSQUIRRELVM v)\r
+{\r
+ sq_tostring(v,1);\r
+ return 1;\r
+}\r
+\r
+static SQInteger obj_delegate_weakref(HSQUIRRELVM v)\r
+{\r
+ sq_weakref(v,1);\r
+ return 1;\r
+}\r
+\r
+static SQInteger obj_clear(HSQUIRRELVM v)\r
+{\r
+ return sq_clear(v,-1);\r
+}\r
+\r
+\r
+static SQInteger number_delegate_tochar(HSQUIRRELVM v)\r
+{\r
+ SQObject &o=stack_get(v,1);\r
+ SQChar c = (SQChar)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 SQInteger 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 SQInteger 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 SQInteger table_rawset(HSQUIRRELVM v)\r
+{\r
+ return sq_rawset(v,-3);\r
+}\r
+\r
+\r
+static SQInteger table_rawget(HSQUIRRELVM v)\r
+{\r
+ return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;\r
+}\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
+ {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
+ {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
+ {_SC("clear"),obj_clear,1, _SC(".")},\r
+ {0,0}\r
+};\r
+\r
+//ARRAY DEFAULT DELEGATE///////////////////////////////////////\r
+\r
+static SQInteger array_append(HSQUIRRELVM v)\r
+{\r
+ return sq_arrayappend(v,-2);\r
+}\r
+\r
+static SQInteger array_extend(HSQUIRRELVM v)\r
+{\r
+ _array(stack_get(v,1))->Extend(_array(stack_get(v,2)));\r
+ return 0;\r
+}\r
+\r
+static SQInteger array_reverse(HSQUIRRELVM v)\r
+{\r
+ return sq_arrayreverse(v,-1);\r
+}\r
+\r
+static SQInteger array_pop(HSQUIRRELVM v)\r
+{\r
+ return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR;\r
+}\r
+\r
+static SQInteger 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 SQInteger 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
+ if(!_array(o)->Insert(tointeger(idx),val))\r
+ return sq_throwerror(v,_SC("index out of range"));\r
+ return 0;\r
+}\r
+\r
+static SQInteger 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 SQInteger 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
+bool _sort_compare(HSQUIRRELVM v,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret)\r
+{\r
+ if(func < 0) {\r
+ if(!v->ObjCmp(a,b,ret)) return false;\r
+ }\r
+ else {\r
+ SQInteger 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, SQFalse))) {\r
+ if(!sq_isstring( v->_lasterror)) \r
+ v->Raise_Error(_SC("compare func failed"));\r
+ return false;\r
+ }\r
+ if(SQ_FAILED(sq_getinteger(v, -1, &ret))) {\r
+ v->Raise_Error(_SC("numeric value expected as return value of the compare function"));\r
+ return false;\r
+ }\r
+ sq_settop(v, top);\r
+ return true;\r
+ }\r
+ return true;\r
+}\r
+\r
+bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, int root, int bottom, SQInteger func)\r
+{\r
+ SQInteger maxChild;\r
+ SQInteger done = 0;\r
+ SQInteger ret;\r
+ SQInteger root2;\r
+ while (((root2 = root * 2) <= bottom) && (!done))\r
+ {\r
+ if (root2 == bottom) {\r
+ maxChild = root2;\r
+ }\r
+ else {\r
+ if(!_sort_compare(v,arr->_values[root2],arr->_values[root2 + 1],func,ret))\r
+ return false;\r
+ if (ret > 0) {\r
+ maxChild = root2;\r
+ }\r
+ else {\r
+ maxChild = root2 + 1;\r
+ }\r
+ }\r
+\r
+ if(!_sort_compare(v,arr->_values[root],arr->_values[maxChild],func,ret))\r
+ return false;\r
+ if (ret < 0) {\r
+ _Swap(arr->_values[root],arr->_values[maxChild]);\r
+ root = maxChild;\r
+ }\r
+ else {\r
+ done = 1;\r
+ }\r
+ }\r
+ return true;\r
+}\r
+\r
+bool _hsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger l, SQInteger r,SQInteger func)\r
+{\r
+ SQArray *a = _array(arr);\r
+ SQInteger i;\r
+ SQInteger array_size = a->Size();\r
+ for (i = (array_size / 2); i >= 0; i--) {\r
+ if(!_hsort_sift_down(v,a, i, array_size - 1,func)) return false;\r
+ }\r
+\r
+ for (i = array_size-1; i >= 1; i--)\r
+ {\r
+ _Swap(a->_values[0],a->_values[i]);\r
+ if(!_hsort_sift_down(v,a, 0, i-1,func)) return false;\r
+ }\r
+ return true;\r
+}\r
+\r
+static SQInteger array_sort(HSQUIRRELVM v)\r
+{\r
+ SQInteger func = -1;\r
+ SQObjectPtr &o = stack_get(v,1);\r
+ if(_array(o)->Size() > 1) {\r
+ if(sq_gettop(v) == 2) func = 2;\r
+ if(!_hsort(v, o, 0, _array(o)->Size()-1, func))\r
+ return SQ_ERROR;\r
+\r
+ }\r
+ return 0;\r
+}\r
+\r
+static SQInteger array_slice(HSQUIRRELVM v)\r
+{\r
+ SQInteger sidx,eidx;\r
+ SQObjectPtr o;\r
+ if(get_slice_params(v,sidx,eidx,o)==-1)return -1;\r
+ SQInteger alen = _array(o)->Size();\r
+ if(sidx < 0)sidx = alen + sidx;\r
+ if(eidx < 0)eidx = alen + eidx;\r
+ if(eidx < sidx)return sq_throwerror(v,_SC("wrong indexes"));\r
+ if(eidx > alen)return sq_throwerror(v,_SC("slice out of range"));\r
+ SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);\r
+ SQObjectPtr t;\r
+ SQInteger count=0;\r
+ for(SQInteger 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
+ {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
+ {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
+ {_SC("clear"),obj_clear,1, _SC(".")},\r
+ {0,0}\r
+};\r
+\r
+//STRING DEFAULT DELEGATE//////////////////////////\r
+static SQInteger string_slice(HSQUIRRELVM v)\r
+{\r
+ SQInteger sidx,eidx;\r
+ SQObjectPtr o;\r
+ if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;\r
+ SQInteger slen = _string(o)->_len;\r
+ if(sidx < 0)sidx = slen + sidx;\r
+ if(eidx < 0)eidx = slen + eidx;\r
+ if(eidx < sidx) return sq_throwerror(v,_SC("wrong indexes"));\r
+ if(eidx > slen) return sq_throwerror(v,_SC("slice out of range"));\r
+ v->Push(SQString::Create(_ss(v),&_stringval(o)[sidx],eidx-sidx));\r
+ return 1;\r
+}\r
+\r
+static SQInteger string_find(HSQUIRRELVM v)\r
+{\r
+ SQInteger 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,(SQInteger)(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 SQInteger string_##func(HSQUIRRELVM v) \\r
+{ \\r
+ SQObject str=stack_get(v,1); \\r
+ SQInteger len=_string(str)->_len; \\r
+ const SQChar *sThis=_stringval(str); \\r
+ SQChar *sNew=(_ss(v)->GetScratchPad(rsl(len))); \\r
+ for(SQInteger 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(".")},\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
+ {_SC("weakref"),obj_delegate_weakref,1, NULL },\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(".")},\r
+ {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},\r
+ {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
+ {0,0}\r
+};\r
+\r
+//CLOSURE DEFAULT DELEGATE//////////////////////////\r
+static SQInteger closure_pcall(HSQUIRRELVM v)\r
+{\r
+ return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQFalse))?1:SQ_ERROR;\r
+}\r
+\r
+static SQInteger closure_call(HSQUIRRELVM v)\r
+{\r
+ return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQTrue))?1:SQ_ERROR;\r
+}\r
+\r
+static SQInteger _closure_acall(HSQUIRRELVM v,SQBool raiseerror)\r
+{\r
+ SQArray *aparams=_array(stack_get(v,2));\r
+ SQInteger nparams=aparams->Size();\r
+ v->Push(stack_get(v,1));\r
+ for(SQInteger i=0;i<nparams;i++)v->Push(aparams->_values[i]);\r
+ return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue,raiseerror))?1:SQ_ERROR;\r
+}\r
+\r
+static SQInteger closure_acall(HSQUIRRELVM v)\r
+{\r
+ return _closure_acall(v,SQTrue);\r
+}\r
+\r
+static SQInteger closure_pacall(HSQUIRRELVM v)\r
+{\r
+ return _closure_acall(v,SQFalse);\r
+}\r
+\r
+static SQInteger closure_bindenv(HSQUIRRELVM v)\r
+{\r
+ if(SQ_FAILED(sq_bindenv(v,1)))\r
+ return SQ_ERROR;\r
+ return 1;\r
+}\r
+\r
+static SQInteger closure_getinfos(HSQUIRRELVM v) {\r
+ SQObject o = stack_get(v,1);\r
+ SQTable *res = SQTable::Create(_ss(v),4);\r
+ if(type(o) == OT_CLOSURE) {\r
+ SQFunctionProto *f = _funcproto(_closure(o)->_function);\r
+ SQInteger nparams = f->_nparameters + (f->_varparams?1:0);\r
+ SQObjectPtr params = SQArray::Create(_ss(v),nparams);\r
+ for(SQInteger n = 0; n<f->_nparameters; n++) {\r
+ _array(params)->Set((SQInteger)n,f->_parameters[n]);\r
+ }\r
+ if(f->_varparams) {\r
+ _array(params)->Set(nparams-1,SQString::Create(_ss(v),_SC("..."),-1));\r
+ }\r
+ res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),false);\r
+ res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),f->_name);\r
+ res->NewSlot(SQString::Create(_ss(v),_SC("src"),-1),f->_sourcename);\r
+ res->NewSlot(SQString::Create(_ss(v),_SC("parameters"),-1),params);\r
+ res->NewSlot(SQString::Create(_ss(v),_SC("varargs"),-1),f->_varparams);\r
+ }\r
+ else { //OT_NATIVECLOSURE \r
+ SQNativeClosure *nc = _nativeclosure(o);\r
+ res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),true);\r
+ res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),nc->_name);\r
+ res->NewSlot(SQString::Create(_ss(v),_SC("paramscheck"),-1),nc->_nparamscheck);\r
+ SQObjectPtr typecheck;\r
+ if(nc->_typecheck.size() > 0) {\r
+ typecheck =\r
+ SQArray::Create(_ss(v), nc->_typecheck.size());\r
+ for(SQUnsignedInteger n = 0; n<nc->_typecheck.size(); n++) {\r
+ _array(typecheck)->Set((SQInteger)n,nc->_typecheck[n]);\r
+ }\r
+ }\r
+ res->NewSlot(SQString::Create(_ss(v),_SC("typecheck"),-1),typecheck);\r
+ }\r
+ v->Push(res);\r
+ return 1;\r
+}\r
+\r
+\r
+SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={\r
+ {_SC("call"),closure_call,-1, _SC("c")},\r
+ {_SC("pcall"),closure_pcall,-1, _SC("c")},\r
+ {_SC("acall"),closure_acall,2, _SC("ca")},\r
+ {_SC("pacall"),closure_pacall,2, _SC("ca")},\r
+ {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
+ {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
+ {_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")},\r
+ {_SC("getinfos"),closure_getinfos,1, _SC("c")},\r
+ {0,0}\r
+};\r
+\r
+//GENERATOR DEFAULT DELEGATE\r
+static SQInteger 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
+ {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
+ {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
+ {0,0}\r
+};\r
+\r
+//THREAD DEFAULT DELEGATE\r
+\r
+static SQInteger thread_call(HSQUIRRELVM v)\r
+{\r
+ \r
+ SQObjectPtr o = stack_get(v,1);\r
+ if(type(o) == OT_THREAD) {\r
+ SQInteger nparams = sq_gettop(v);\r
+ _thread(o)->Push(_thread(o)->_roottable);\r
+ for(SQInteger i = 2; i<(nparams+1); i++)\r
+ sq_move(_thread(o),v,i);\r
+ if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQFalse))) {\r
+ sq_move(v,_thread(o),-1);\r
+ sq_pop(_thread(o),1);\r
+ return 1;\r
+ }\r
+ v->_lasterror = _thread(o)->_lasterror;\r
+ return SQ_ERROR;\r
+ }\r
+ return sq_throwerror(v,_SC("wrong parameter"));\r
+}\r
+\r
+static SQInteger thread_wakeup(HSQUIRRELVM v)\r
+{\r
+ SQObjectPtr o = stack_get(v,1);\r
+ if(type(o) == OT_THREAD) {\r
+ SQVM *thread = _thread(o);\r
+ SQInteger 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
+ SQInteger 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,SQTrue,SQTrue,SQFalse))) {\r
+ sq_move(v,thread,-1);\r
+ sq_pop(thread,1); //pop retval\r
+ if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {\r
+ sq_settop(thread,1); //pop roottable\r
+ }\r
+ return 1;\r
+ }\r
+ sq_settop(thread,1);\r
+ v->_lasterror = thread->_lasterror;\r
+ return SQ_ERROR;\r
+ }\r
+ return sq_throwerror(v,_SC("wrong parameter"));\r
+}\r
+\r
+static SQInteger 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
+ {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
+ {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
+ {0,0},\r
+};\r
+\r
+static SQInteger class_getattributes(HSQUIRRELVM v)\r
+{\r
+ if(SQ_SUCCEEDED(sq_getattributes(v,-2)))\r
+ return 1;\r
+ return SQ_ERROR;\r
+}\r
+\r
+static SQInteger class_setattributes(HSQUIRRELVM v)\r
+{\r
+ if(SQ_SUCCEEDED(sq_setattributes(v,-3)))\r
+ return 1;\r
+ return SQ_ERROR;\r
+}\r
+\r
+static SQInteger class_instance(HSQUIRRELVM v)\r
+{\r
+ if(SQ_SUCCEEDED(sq_createinstance(v,-1)))\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
+ {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
+ {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
+ {_SC("instance"),class_instance,1, _SC("y")},\r
+ {0,0}\r
+};\r
+\r
+static SQInteger 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
+ {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
+ {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
+ {0,0}\r
+};\r
+\r
+static SQInteger weakref_ref(HSQUIRRELVM v)\r
+{\r
+ if(SQ_FAILED(sq_getweakrefval(v,1)))\r
+ return SQ_ERROR;\r
+ return 1;\r
+}\r
+\r
+SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = {\r
+ {_SC("ref"),weakref_ref,1, _SC("r")},\r
+ {_SC("weakref"),obj_delegate_weakref,1, NULL },\r
+ {_SC("tostring"),default_delegate_tostring,1, _SC(".")},\r
+ {0,0}\r
+};\r
+\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)
-{
- _base = base;
- _typetag = 0;
- _hook = NULL;
- _udsize = 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(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
-{
- SQObjectPtr temp;
- if(_locked)
- return false; //the class already has an instance so cannot be modified
- if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value
- {
- _defaultvalues[_member_idx(temp)].val = val;
- return true;
- }
- if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic) {
- SQInteger mmidx;
- if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) &&
- (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
- _metamethods[mmidx] = val;
- }
- else {
- if(type(temp) == OT_NULL) {
- SQClassMember m;
- m.val = val;
- _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));
- _methods.push_back(m);
- }
- else {
- _methods[_member_idx(temp)].val = val;
- }
- }
- return true;
- }
- SQClassMember m;
- m.val = val;
- _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size())));
- _defaultvalues.push_back(m);
- return true;
-}
-
-SQInstance *SQClass::CreateInstance()
-{
- if(!_locked) Lock();
- return SQInstance::Create(_opt_ss(this),this);
-}
-
-SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
-{
- SQObjectPtr oval;
- SQInteger idx = _members->Next(false,refpos,outkey,oval);
- if(idx != -1) {
- if(_ismethod(oval)) {
- outval = _methods[_member_idx(oval)].val;
- }
- else {
- SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
- outval = _realval(o);
- }
- }
- return idx;
-}
-
-bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)
-{
- SQObjectPtr idx;
- if(_members->Get(key,idx)) {
- if(_isfield(idx))
- _defaultvalues[_member_idx(idx)].attrs = val;
- else
- _methods[_member_idx(idx)].attrs = val;
- return true;
- }
- return false;
-}
-
-bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)
-{
- SQObjectPtr idx;
- if(_members->Get(key,idx)) {
- outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
- return true;
- }
- return false;
-}
-
-///////////////////////////////////////////////////////////////////////
-void SQInstance::Init(SQSharedState *ss)
-{
- _userpointer = NULL;
- _hook = NULL;
- __ObjAddRef(_class);
- _delegate = _class->_members;
- INIT_CHAIN();
- ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
-}
-
-SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)
-{
- _memsize = memsize;
- _class = c;
- SQUnsignedInteger nvalues = _class->_defaultvalues.size();
- for(SQUnsignedInteger n = 0; n < nvalues; n++) {
- new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val);
- }
- Init(ss);
-}
-
-SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)
-{
- _memsize = memsize;
- _class = i->_class;
- SQUnsignedInteger nvalues = _class->_defaultvalues.size();
- for(SQUnsignedInteger n = 0; n < nvalues; n++) {
- new (&_values[n]) SQObjectPtr(i->_values[n]);
- }
- Init(ss);
-}
-
-void SQInstance::Finalize()
-{
- SQUnsignedInteger nvalues = _class->_defaultvalues.size();
- __ObjRelease(_class);
- for(SQUnsignedInteger i = 0; i < nvalues; i++) {
- _values[i] = _null_;
- }
-}
-
-SQInstance::~SQInstance()
-{
- REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
- if(_class){ Finalize(); } //if _class is null it was already finalized by the GC
-}
-
-bool SQInstance::GetMetaMethod(SQVM *v,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;
-}
+/*\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
+ _base = base;\r
+ _typetag = 0;\r
+ _hook = NULL;\r
+ _udsize = 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(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)\r
+{\r
+ SQObjectPtr temp;\r
+ if(_locked) \r
+ return false; //the class already has an instance so cannot be modified\r
+ if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value\r
+ {\r
+ _defaultvalues[_member_idx(temp)].val = val;\r
+ return true;\r
+ }\r
+ if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic) {\r
+ SQInteger mmidx;\r
+ if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) && \r
+ (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {\r
+ _metamethods[mmidx] = val;\r
+ } \r
+ else {\r
+ if(type(temp) == OT_NULL) {\r
+ SQClassMember m;\r
+ m.val = val;\r
+ _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));\r
+ _methods.push_back(m);\r
+ }\r
+ else {\r
+ _methods[_member_idx(temp)].val = val;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+ SQClassMember m;\r
+ m.val = val;\r
+ _members->NewSlot(key,SQObjectPtr(_make_field_idx(_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
+SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)\r
+{\r
+ SQObjectPtr oval;\r
+ SQInteger idx = _members->Next(false,refpos,outkey,oval);\r
+ if(idx != -1) {\r
+ if(_ismethod(oval)) {\r
+ outval = _methods[_member_idx(oval)].val;\r
+ }\r
+ else {\r
+ SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val;\r
+ outval = _realval(o);\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(_isfield(idx))\r
+ _defaultvalues[_member_idx(idx)].attrs = val;\r
+ else\r
+ _methods[_member_idx(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 = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);\r
+ return true;\r
+ }\r
+ return false;\r
+}\r
+\r
+///////////////////////////////////////////////////////////////////////\r
+void SQInstance::Init(SQSharedState *ss)\r
+{\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, SQInteger memsize)\r
+{\r
+ _memsize = memsize;\r
+ _class = c;\r
+ SQUnsignedInteger nvalues = _class->_defaultvalues.size();\r
+ for(SQUnsignedInteger n = 0; n < nvalues; n++) {\r
+ new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val);\r
+ }\r
+ Init(ss);\r
+}\r
+\r
+SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)\r
+{\r
+ _memsize = memsize;\r
+ _class = i->_class;\r
+ SQUnsignedInteger nvalues = _class->_defaultvalues.size();\r
+ for(SQUnsignedInteger n = 0; n < nvalues; n++) {\r
+ new (&_values[n]) SQObjectPtr(i->_values[n]);\r
+ }\r
+ Init(ss);\r
+}\r
+\r
+void SQInstance::Finalize() \r
+{\r
+ SQUnsignedInteger nvalues = _class->_defaultvalues.size();\r
+ __ObjRelease(_class);\r
+ for(SQUnsignedInteger i = 0; i < nvalues; i++) {\r
+ _values[i] = _null_;\r
+ }\r
+}\r
+\r
+SQInstance::~SQInstance()\r
+{\r
+ REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);\r
+ if(_class){ Finalize(); } //if _class is null it was already finalized by the GC\r
+}\r
+\r
+bool SQInstance::GetMetaMethod(SQVM *v,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 */
-#ifndef _SQCLASS_H_
-#define _SQCLASS_H_
-
-struct SQInstance;
-
-struct SQClassMember {
- SQClassMember(){}
- SQClassMember(const SQClassMember &o) {
- val = o.val;
- attrs = o.attrs;
- }
- SQObjectPtr val;
- SQObjectPtr attrs;
-};
-
-typedef sqvector<SQClassMember> SQClassMemberVec;
-
-#define MEMBER_TYPE_METHOD 0x01000000
-#define MEMBER_TYPE_FIELD 0x02000000
-
-#define _ismethod(o) (_integer(o)&MEMBER_TYPE_METHOD)
-#define _isfield(o) (_integer(o)&MEMBER_TYPE_FIELD)
-#define _make_method_idx(i) ((SQInteger)(MEMBER_TYPE_METHOD|i))
-#define _make_field_idx(i) ((SQInteger)(MEMBER_TYPE_FIELD|i))
-#define _member_type(o) (_integer(o)&0xFF000000)
-#define _member_idx(o) (_integer(o)&0x00FFFFFF)
-
-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(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic);
- bool Get(const SQObjectPtr &key,SQObjectPtr &val) {
- if(_members->Get(key,val)) {
- if(_isfield(val)) {
- SQObjectPtr &o = _defaultvalues[_member_idx(val)].val;
- val = _realval(o);
- }
- else {
- val = _methods[_member_idx(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() {
- if (_hook) { _hook(_typetag,0);}
- sq_delete(this, SQClass);
- }
- void Finalize();
-#ifndef NO_GARBAGE_COLLECTOR
- void Mark(SQCollectable ** );
-#endif
- SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
- SQInstance *CreateInstance();
- SQTable *_members;
- SQClass *_base;
- SQClassMemberVec _defaultvalues;
- SQClassMemberVec _methods;
- SQObjectPtrVec _metamethods;
- SQObjectPtr _attributes;
- SQUserPointer _typetag;
- SQRELEASEHOOK _hook;
- bool _locked;
- SQInteger _udsize;
-};
-
-#define calcinstancesize(_theclass_) \
- (_theclass_->_udsize + sizeof(SQInstance) + (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0)))
-
-struct SQInstance : public SQDelegable
-{
- void Init(SQSharedState *ss);
- SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize);
- SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize);
-public:
- static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {
-
- SQInteger size = calcinstancesize(theclass);
- SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
- new (newinst) SQInstance(ss, theclass,size);
- if(theclass->_udsize) {
- newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize);
- }
- return newinst;
- }
- SQInstance *Clone(SQSharedState *ss)
- {
- SQInteger size = calcinstancesize(_class);
- SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
- new (newinst) SQInstance(ss, this,size);
- if(_class->_udsize) {
- newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize);
- }
- return newinst;
- }
- ~SQInstance();
- bool Get(const SQObjectPtr &key,SQObjectPtr &val) {
- if(_class->_members->Get(key,val)) {
- if(_isfield(val)) {
- SQObjectPtr &o = _values[_member_idx(val)];
- val = _realval(o);
- }
- else {
- val = _class->_methods[_member_idx(val)].val;
- }
- return true;
- }
- return false;
- }
- bool Set(const SQObjectPtr &key,const SQObjectPtr &val) {
- SQObjectPtr idx;
- if(_class->_members->Get(key,idx) && _isfield(idx)) {
- _values[_member_idx(idx)] = val;
- return true;
- }
- return false;
- }
- void Release() {
- _uiRef++;
- if (_hook) { _hook(_userpointer,0);}
- _uiRef--;
- if(_uiRef > 0) return;
- SQInteger size = _memsize;
- this->~SQInstance();
- SQ_FREE(this, size);
- }
- void Finalize();
-#ifndef NO_GARBAGE_COLLECTOR
- void Mark(SQCollectable ** );
-#endif
- bool InstanceOf(SQClass *trg);
- bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);
-
- SQClass *_class;
- SQUserPointer _userpointer;
- SQRELEASEHOOK _hook;
- SQInteger _memsize;
- SQObjectPtr _values[1];
-};
-
-#endif //_SQCLASS_H_
+/* see copyright notice in squirrel.h */\r
+#ifndef _SQCLASS_H_\r
+#define _SQCLASS_H_\r
+\r
+struct SQInstance;\r
+\r
+struct SQClassMember {\r
+ SQClassMember(){}\r
+ SQClassMember(const SQClassMember &o) {\r
+ val = o.val;\r
+ attrs = o.attrs;\r
+ }\r
+ SQObjectPtr val;\r
+ SQObjectPtr attrs;\r
+};\r
+\r
+typedef sqvector<SQClassMember> SQClassMemberVec;\r
+\r
+#define MEMBER_TYPE_METHOD 0x01000000\r
+#define MEMBER_TYPE_FIELD 0x02000000\r
+\r
+#define _ismethod(o) (_integer(o)&MEMBER_TYPE_METHOD)\r
+#define _isfield(o) (_integer(o)&MEMBER_TYPE_FIELD)\r
+#define _make_method_idx(i) ((SQInteger)(MEMBER_TYPE_METHOD|i))\r
+#define _make_field_idx(i) ((SQInteger)(MEMBER_TYPE_FIELD|i))\r
+#define _member_type(o) (_integer(o)&0xFF000000)\r
+#define _member_idx(o) (_integer(o)&0x00FFFFFF)\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(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic);\r
+ bool Get(const SQObjectPtr &key,SQObjectPtr &val) {\r
+ if(_members->Get(key,val)) {\r
+ if(_isfield(val)) {\r
+ SQObjectPtr &o = _defaultvalues[_member_idx(val)].val;\r
+ val = _realval(o);\r
+ }\r
+ else {\r
+ val = _methods[_member_idx(val)].val;\r
+ }\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() { \r
+ if (_hook) { _hook(_typetag,0);}\r
+ sq_delete(this, SQClass); \r
+ }\r
+ void Finalize();\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+ void Mark(SQCollectable ** );\r
+#endif\r
+ SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);\r
+ SQInstance *CreateInstance();\r
+ SQTable *_members;\r
+ SQClass *_base;\r
+ SQClassMemberVec _defaultvalues;\r
+ SQClassMemberVec _methods;\r
+ SQObjectPtrVec _metamethods;\r
+ SQObjectPtr _attributes;\r
+ SQUserPointer _typetag;\r
+ SQRELEASEHOOK _hook;\r
+ bool _locked;\r
+ SQInteger _udsize;\r
+};\r
+\r
+#define calcinstancesize(_theclass_) \\r
+ (_theclass_->_udsize + sizeof(SQInstance) + (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0)))\r
+\r
+struct SQInstance : public SQDelegable \r
+{\r
+ void Init(SQSharedState *ss);\r
+ SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize);\r
+ SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize);\r
+public:\r
+ static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {\r
+ \r
+ SQInteger size = calcinstancesize(theclass);\r
+ SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);\r
+ new (newinst) SQInstance(ss, theclass,size);\r
+ if(theclass->_udsize) {\r
+ newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize);\r
+ }\r
+ return newinst;\r
+ }\r
+ SQInstance *Clone(SQSharedState *ss)\r
+ {\r
+ SQInteger size = calcinstancesize(_class);\r
+ SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);\r
+ new (newinst) SQInstance(ss, this,size);\r
+ if(_class->_udsize) {\r
+ newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize);\r
+ }\r
+ return newinst;\r
+ }\r
+ ~SQInstance();\r
+ bool Get(const SQObjectPtr &key,SQObjectPtr &val) {\r
+ if(_class->_members->Get(key,val)) {\r
+ if(_isfield(val)) {\r
+ SQObjectPtr &o = _values[_member_idx(val)];\r
+ val = _realval(o);\r
+ }\r
+ else {\r
+ val = _class->_methods[_member_idx(val)].val;\r
+ }\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) && _isfield(idx)) {\r
+ _values[_member_idx(idx)] = val;\r
+ return true;\r
+ }\r
+ return false;\r
+ }\r
+ void Release() {\r
+ _uiRef++;\r
+ if (_hook) { _hook(_userpointer,0);}\r
+ _uiRef--;\r
+ if(_uiRef > 0) return;\r
+ SQInteger size = _memsize;\r
+ this->~SQInstance();\r
+ SQ_FREE(this, size);\r
+ }\r
+ void Finalize();\r
+#ifndef NO_GARBAGE_COLLECTOR \r
+ void Mark(SQCollectable ** );\r
+#endif\r
+ bool InstanceOf(SQClass *trg);\r
+ bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);\r
+\r
+ SQClass *_class;\r
+ SQUserPointer _userpointer;\r
+ SQRELEASEHOOK _hook;\r
+ SQInteger _memsize;\r
+ SQObjectPtr _values[1];\r
+};\r
+\r
+#endif //_SQCLASS_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){_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 *Clone()
- {
- SQClosure * ret = SQClosure::Create(_opt_ss(this),_funcproto(_function));
- ret->_env = _env;
- ret->_outervalues.copy(_outervalues);
- ret->_defaultparams.copy(_defaultparams);
- return ret;
- }
- ~SQClosure()
- {
- REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
- }
- bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
- static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
-#ifndef NO_GARBAGE_COLLECTOR
- void Mark(SQCollectable **chain);
- void Finalize(){_outervalues.resize(0); }
-#endif
- SQObjectPtr _env;
- SQObjectPtr _function;
- SQObjectPtrVec _outervalues;
- SQObjectPtrVec _defaultparams;
-};
-//////////////////////////////////////////////
-struct SQGenerator : public CHAINABLE_OBJ
-{
- enum SQGeneratorState{eRunning,eSuspended,eDead};
-private:
- SQGenerator(SQSharedState *ss,SQClosure *closure){_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,SQInteger 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){_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 *Clone()
- {
- SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function);
- ret->_env = _env;
- ret->_name = _name;
- ret->_outervalues.copy(_outervalues);
- ret->_typecheck.copy(_typecheck);
- ret->_nparamscheck = _nparamscheck;
- return ret;
- }
- ~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
- SQInteger _nparamscheck;
- SQIntVec _typecheck;
- SQObjectPtrVec _outervalues;
- SQObjectPtr _env;
- SQFUNCTION _function;
- SQObjectPtr _name;
-};
-
-
-
-#endif //_SQCLOSURE_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){_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 *Clone()\r
+ {\r
+ SQClosure * ret = SQClosure::Create(_opt_ss(this),_funcproto(_function));\r
+ ret->_env = _env;\r
+ ret->_outervalues.copy(_outervalues);\r
+ ret->_defaultparams.copy(_defaultparams);\r
+ return ret;\r
+ }\r
+ ~SQClosure()\r
+ {\r
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+ }\r
+ bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);\r
+ static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+ void Mark(SQCollectable **chain);\r
+ void Finalize(){_outervalues.resize(0); }\r
+#endif\r
+ SQObjectPtr _env;\r
+ SQObjectPtr _function;\r
+ SQObjectPtrVec _outervalues;\r
+ SQObjectPtrVec _defaultparams;\r
+};\r
+//////////////////////////////////////////////\r
+struct SQGenerator : public CHAINABLE_OBJ \r
+{\r
+ enum SQGeneratorState{eRunning,eSuspended,eDead};\r
+private:\r
+ SQGenerator(SQSharedState *ss,SQClosure *closure){_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,SQInteger 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){_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 *Clone()\r
+ {\r
+ SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function);\r
+ ret->_env = _env;\r
+ ret->_name = _name;\r
+ ret->_outervalues.copy(_outervalues);\r
+ ret->_typecheck.copy(_typecheck);\r
+ ret->_nparamscheck = _nparamscheck;\r
+ return ret;\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
+ SQInteger _nparamscheck;\r
+ SQIntVec _typecheck;\r
+ SQObjectPtrVec _outervalues;\r
+ SQObjectPtr _env;\r
+ SQFUNCTION _function;\r
+ SQObjectPtr _name;\r
+};\r
+\r
+\r
+\r
+#endif //_SQCLOSURE_H_\r
-/*
- see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include <stdarg.h>
-#include <setjmp.h>
-#include "sqopcodes.h"
-#include "sqstring.h"
-#include "sqfuncproto.h"
-#include "sqcompiler.h"
-#include "sqfuncstate.h"
-#include "sqlexer.h"
-#include "sqvm.h"
-#include "sqtable.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;
- SQInteger _deref;
-};
-
-typedef sqvector<ExpState> ExpStateVec;
-
-#define _exst (_expstates.top())
-
-#define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \
- SQInteger __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,ThrowError,this);
- _sourcename = SQString::Create(_ss(v), sourcename);
- _lineinfo = lineinfo;_raiseerror = raiseerror;
- compilererror = NULL;
- }
- static void ThrowError(void *ud, const SQChar *s) {
- SQCompiler *c = (SQCompiler *)ud;
- c->Error(s);
- }
- void Error(const SQChar *s, ...)
- {
- static SQChar temp[256];
- va_list vl;
- va_start(vl, s);
- scvsprintf(temp, s, vl);
- va_end(vl);
- compilererror = temp;
- longjmp(_errorjmp,1);
- }
- void Lex(){ _token = _lex.Lex();}
- void PushExpState(){ _expstates.push_back(ExpState()); }
- bool IsDerefToken(SQInteger 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;
- }
- SQObject Expect(SQInteger tok)
- {
-
- if(_token != tok) {
- if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {
- //ret = SQString::Create(_ss(_vm),_SC("constructor"));
- //do nothing
- }
- else {
- const SQChar *etypename;
- if(tok > 255) {
- switch(tok)
- {
- case TK_IDENTIFIER:
- etypename = _SC("IDENTIFIER");
- break;
- case TK_STRING_LITERAL:
- etypename = _SC("STRING_LITERAL");
- break;
- case TK_INTEGER:
- etypename = _SC("INTEGER");
- break;
- case TK_FLOAT:
- etypename = _SC("FLOAT");
- break;
- default:
- etypename = _lex.Tok2Str(tok);
- }
- Error(_SC("expected '%s'"), etypename);
- }
- Error(_SC("expected '%c'"), tok);
- }
- }
- SQObjectPtr ret;
- switch(tok)
- {
- case TK_IDENTIFIER:
- ret = _fs->CreateString(_lex._svalue);
- break;
- case TK_STRING_LITERAL:
- ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
- break;
- case TK_INTEGER:
- ret = SQObjectPtr(_lex._nvalue);
- break;
- case TK_FLOAT:
- ret = SQObjectPtr(_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() {
- SQInteger 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)
- {
- _debugline = 1;
- _debugop = 0;
-
- SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this);
- funcstate._name = SQString::Create(_ss(_vm), _SC("main"));
- _fs = &funcstate;
- _fs->AddParameter(_fs->CreateString(_SC("this")));
- _fs->_sourcename = _sourcename;
- SQInteger stacksize = _fs->GetStackSize();
- if(setjmp(_errorjmp) == 0) {
- Lex();
- while(_token > 0){
- Statement();
- if(_lex._prevtoken != _SC('}')) OptionalSemicolon();
- }
- CleanStack(stacksize);
- _fs->AddLineInfos(_lex._currentline, _lineinfo, true);
- _fs->AddInstruction(_OP_RETURN, 0xFF);
- _fs->SetStackSize(0);
- o =_fs->BuildProto();
-#ifdef _DEBUG_DUMP
- _fs->Dump(_funcproto(o));
-#endif
- }
- else {
- if(_raiseerror && _ss(_vm)->_compilererrorhandler) {
- _ss(_vm)->_compilererrorhandler(_vm, compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),
- _lex._currentline, _lex._currentcolumn);
- }
- _vm->_lasterror = SQString::Create(_ss(_vm), compilererror, -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;
- _fs->_bgenerator = true;
- }
- Lex();
- if(!IsEndOfStatement()) {
- SQInteger 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 TK_ENUM:
- EnumStatement();
- break;
- case _SC('{'):{
- SQInteger 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;
- case TK_CONST:
- {
- Lex();
- SQObject id = Expect(TK_IDENTIFIER);
- Expect('=');
- SQObject val = ExpectScalar();
- OptionalSemicolon();
- SQTable *enums = _table(_ss(_vm)->_consts);
- SQObjectPtr strongid = id;
- enums->NewSlot(strongid,SQObjectPtr(val));
- strongid.Null();
- }
- break;
- default:
- CommaExpr();
- _fs->PopTarget();
- break;
- }
- _fs->SnoozeOpt();
- }
- void EmitDerefOp(SQOpcode op)
- {
- SQInteger val = _fs->PopTarget();
- SQInteger key = _fs->PopTarget();
- SQInteger src = _fs->PopTarget();
- _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);
- }
- void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0)
- {
- SQInteger p2 = _fs->PopTarget(); //src in OP_GET
- SQInteger p1 = _fs->PopTarget(); //key in OP_GET
- _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);
- }
- void EmitCompoundArith(SQInteger tok,bool deref)
- {
- SQInteger 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: oper = 0; //shut up compiler
- assert(0); break;
- };
- if(deref) {
- SQInteger val = _fs->PopTarget();
- SQInteger key = _fs->PopTarget();
- SQInteger 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:
- {
- SQInteger op = _token;
- SQInteger 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
- SQInteger p2 = _fs->PopTarget(); //src in OP_GET
- SQInteger 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());
- SQInteger jzpos = _fs->GetCurrentPos();
- SQInteger trg = _fs->PushTarget();
- Expression();
- SQInteger first_exp = _fs->PopTarget();
- if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
- SQInteger endfirstexp = _fs->GetCurrentPos();
- _fs->AddInstruction(_OP_JMP, 0, 0);
- Expect(_SC(':'));
- SQInteger jmppos = _fs->GetCurrentPos();
- Expression();
- SQInteger 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),SQInteger op3 = 0)
- {
- Lex(); (this->*f)();
- SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget();
- _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3);
- }
- void LogicalOrExp()
- {
- LogicalAndExp();
- for(;;) if(_token == TK_OR) {
- SQInteger first_exp = _fs->PopTarget();
- SQInteger trg = _fs->PushTarget();
- _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);
- SQInteger jpos = _fs->GetCurrentPos();
- if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
- Lex(); LogicalOrExp();
- _fs->SnoozeOpt();
- SQInteger 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: {
- SQInteger first_exp = _fs->PopTarget();
- SQInteger trg = _fs->PushTarget();
- _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);
- SQInteger jpos = _fs->GetCurrentPos();
- if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
- Lex(); LogicalAndExp();
- _fs->SnoozeOpt();
- SQInteger 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()
- {
- SQInteger pos = Factor();
- for(;;) {
- switch(_token) {
- case _SC('.'): {
- pos = -1;
- Lex();
- if(_token == TK_PARENT) {
- Lex();
- if(!NeedGet())
- Error(_SC("parent cannot be set"));
- SQInteger src = _fs->PopTarget();
- _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src);
- }
- else {
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
- 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()) {
- SQInteger 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
- SQInteger 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) {
- SQInteger key = _fs->PopTarget(); //key
- SQInteger table = _fs->PopTarget(); //table etc...
- SQInteger closure = _fs->PushTarget();
- SQInteger 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;
- }
- }
- }
- SQInteger 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->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
- Lex();
- }
- break;
- case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break;
- case TK_VARGV: { Lex();
- Expect(_SC('['));
- Expression();
- Expect(_SC(']'));
- SQInteger src = _fs->PopTarget();
- _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src);
- }
- break;
- case TK_IDENTIFIER:
- case TK_CONSTRUCTOR:
- case TK_THIS:{
- _exst._freevar = false;
- SQObject id;
- SQObject constant;
- switch(_token) {
- case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break;
- case TK_THIS: id = _fs->CreateString(_SC("this")); break;
- case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor")); break;
- }
- SQInteger 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 if(_fs->IsConstant(id,constant)) { //line 634
- SQObjectPtr constval;
- SQObject constid;
- if(type(constant) == OT_TABLE) {
- Expect('.'); constid = Expect(TK_IDENTIFIER);
- if(!_table(constant)->Get(constid,constval)) {
- constval.Null();
- Error(_SC("invalid constant [%s.%s]"), _stringval(id),_stringval(constid));
- }
- }
- else {
- constval = constant;
- }
- _exst._deref = _fs->PushTarget();
- SQObjectType ctype = type(constval);
- if(ctype == OT_INTEGER && (_integer(constval) & (~0x7FFFFFFF)) == 0) {
- _fs->AddInstruction(_OP_LOADINT, _exst._deref,_integer(constval));
- }
- else if(ctype == OT_FLOAT && sizeof(SQFloat) == sizeof(SQInt32)) {
- SQFloat f = _float(constval);
- _fs->AddInstruction(_OP_LOADFLOAT, _exst._deref,*((SQInt32 *)&f));
- }
- else {
- _fs->AddInstruction(_OP_LOAD, _exst._deref, _fs->GetConstant(constval));
- }
-
- _exst._freevar = true;
- }
- else {
- _fs->PushTarget(0);
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(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: {
- if((_lex._nvalue & (~0x7FFFFFFF)) == 0) { //does it fit in 32 bits?
- _fs->AddInstruction(_OP_LOADINT, _fs->PushTarget(),_lex._nvalue);
- }
- else {
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue));
- }
- Lex();
- }
- break;
- case TK_FLOAT:
- if(sizeof(SQFloat) == sizeof(SQInt32)) {
- _fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(),*((SQInt32 *)&_lex._fvalue));
- }
- else {
- _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());
- SQInteger apos = _fs->GetCurrentPos(),key = 0;
- Lex();
- while(_token != _SC(']')) {
- Expression();
- if(_token == _SC(',')) Lex();
- SQInteger val = _fs->PopTarget();
- SQInteger 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();
- SQInteger 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()
- {
- SQInteger nargs = 1;//this
- while(_token != _SC(')')) {
- Expression(true);
- MoveIfCurrentTargetIsLocal();
- nargs++;
- if(_token == _SC(',')){
- Lex();
- if(_token == ')') Error(_SC("expression expected, found ')'"));
- }
- }
- Lex();
- for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget();
- SQInteger stackbase = _fs->PopTarget();
- SQInteger closure = _fs->PopTarget();
- _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);
- }
- void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}')
- {
- SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;
-
- while(_token != terminator) {
- bool hasattrs = false;
- bool isstatic = false;
- //check if is an attribute
- if(separator == ';') {
- if(_token == TK_ATTR_OPEN) {
- _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex();
- ParseTableOrClass(',',TK_ATTR_CLOSE);
- hasattrs = true;
- }
- if(_token == TK_STATIC) {
- isstatic = true;
- Lex();
- }
- }
- switch(_token) {
- case TK_FUNCTION:
- case TK_CONSTRUCTOR:{
- SQInteger tk = _token;
- Lex();
- SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor"));
- Expect(_SC('('));
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(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->GetConstant(Expect(TK_IDENTIFIER)));
- Expect(_SC('=')); Expression();
- }
-
- if(_token == separator) Lex();//optional comma/semicolon
- nkeys++;
- SQInteger val = _fs->PopTarget();
- SQInteger key = _fs->PopTarget();
- SQInteger attrs = hasattrs ? _fs->PopTarget():-1;
- assert(hasattrs && attrs == key-1 || !hasattrs);
- unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);
- SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
- _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val);
- //_fs->PopTarget();
- }
- if(separator == _SC(',')) //hack recognizes a table from the separator
- _fs->SetIntructionParam(tpos, 1, nkeys);
- Lex();
- }
- void LocalDeclStatement()
- {
- SQObject varname;
- do {
- Lex(); varname = Expect(TK_IDENTIFIER);
- if(_token == _SC('=')) {
- Lex(); Expression();
- SQInteger src = _fs->PopTarget();
- SQInteger 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()
- {
- SQInteger jmppos;
- bool haselse = false;
- Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
- _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
- SQInteger jnepos = _fs->GetCurrentPos();
- SQInteger stacksize = _fs->GetStackSize();
-
- Statement();
- //
- if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();
-
- CleanStack(stacksize);
- SQInteger 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()
- {
- SQInteger jzpos, jmppos;
- SQInteger 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();
- SQInteger jzpos = _fs->GetCurrentPos();
- SQInteger stacksize = _fs->GetStackSize();
- BEGIN_BREAKBLE_BLOCK()
- Statement();
- CleanStack(stacksize);
- Expect(TK_WHILE);
- SQInteger 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();
- SQInteger stacksize = _fs->GetStackSize();
- Expect(_SC('('));
- if(_token == TK_LOCAL) LocalDeclStatement();
- else if(_token != _SC(';')){
- CommaExpr();
- _fs->PopTarget();
- }
- Expect(_SC(';'));
- _fs->SnoozeOpt();
- SQInteger jmppos = _fs->GetCurrentPos();
- SQInteger jzpos = -1;
- if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }
- Expect(_SC(';'));
- _fs->SnoozeOpt();
- SQInteger expstart = _fs->GetCurrentPos() + 1;
- if(_token != _SC(')')) {
- CommaExpr();
- _fs->PopTarget();
- }
- Expect(_SC(')'));
- _fs->SnoozeOpt();
- SQInteger expend = _fs->GetCurrentPos();
- SQInteger expsize = (expend - expstart) + 1;
- SQInstructionVec exp;
- if(expsize > 0) {
- for(SQInteger i = 0; i < expsize; i++)
- exp.push_back(_fs->GetInstruction(expstart + i));
- _fs->PopInstructions(expsize);
- }
- BEGIN_BREAKBLE_BLOCK()
- Statement();
- SQInteger continuetrg = _fs->GetCurrentPos();
- if(expsize > 0) {
- for(SQInteger 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()
- {
- SQObject idxname, valname;
- Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);
- if(_token == _SC(',')) {
- idxname = valname;
- Lex(); valname = Expect(TK_IDENTIFIER);
- }
- else{
- idxname = _fs->CreateString(_SC("@INDEX@"));
- }
- Expect(TK_IN);
-
- //save the stack size
- SQInteger stacksize = _fs->GetStackSize();
- //put the table in the stack(evaluate the table expression)
- Expression(); Expect(_SC(')'));
- SQInteger container = _fs->TopTarget();
- //push the index local var
- SQInteger indexpos = _fs->PushLocalVariable(idxname);
- _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);
- //push the value local var
- SQInteger valuepos = _fs->PushLocalVariable(valname);
- _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);
- //push reference index
- SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible
- _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);
- SQInteger jmppos = _fs->GetCurrentPos();
- _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);
- SQInteger foreachpos = _fs->GetCurrentPos();
- _fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos);
- //generate the statement code
- BEGIN_BREAKBLE_BLOCK()
- Statement();
- _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
- _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);
- _fs->SetIntructionParam(foreachpos + 1, 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('{'));
- SQInteger expr = _fs->TopTarget();
- bool bfirst = true;
- SQInteger tonextcondjmp = -1;
- SQInteger skipcondjmp = -1;
- SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size();
- _fs->_breaktargets.push_back(0);
- while(_token == TK_CASE) {
- //_fs->AddLineInfos(_lex._currentline, _lineinfo); think about this one
- if(!bfirst) {
- _fs->AddInstruction(_OP_JMP, 0, 0);
- skipcondjmp = _fs->GetCurrentPos();
- _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
- }
- //condition
- Lex(); Expression(); Expect(_SC(':'));
- SQInteger 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();
- SQInteger stacksize = _fs->GetStackSize();
- Statements();
- _fs->SetStackSize(stacksize);
- bfirst = false;
- }
- if(tonextcondjmp != -1)
- _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
- if(_token == TK_DEFAULT) {
- // _fs->AddLineInfos(_lex._currentline, _lineinfo);
- Lex(); Expect(_SC(':'));
- SQInteger 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()
- {
- SQObject id;
- Lex(); id = Expect(TK_IDENTIFIER);
- _fs->PushTarget(0);
- _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(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->GetConstant(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>)"));
- }
- SQObject ExpectScalar()
- {
- SQObject val;
- switch(_token) {
- case TK_INTEGER:
- val._type = OT_INTEGER;
- val._unVal.nInteger = _lex._nvalue;
- break;
- case TK_FLOAT:
- val._type = OT_FLOAT;
- val._unVal.fFloat = _lex._fvalue;
- break;
- case TK_STRING_LITERAL:
- val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
- break;
- case '-':
- Lex();
- switch(_token)
- {
- case TK_INTEGER:
- val._type = OT_INTEGER;
- val._unVal.nInteger = -_lex._nvalue;
- break;
- case TK_FLOAT:
- val._type = OT_FLOAT;
- val._unVal.fFloat = -_lex._fvalue;
- break;
- default:
- Error(_SC("scalar expected : integer,float"));
- }
- break;
- default:
- Error(_SC("scalar expected : integer,float or string"));
- }
- Lex();
- return val;
- }
- void EnumStatement()
- {
-
- Lex();
- SQObject id = Expect(TK_IDENTIFIER);
- Expect(_SC('{'));
-
- SQObject table = _fs->CreateTable();
- SQInteger nval = 0;
- while(_token != _SC('}')) {
- SQObject key = Expect(TK_IDENTIFIER);
- SQObject val;
- if(_token == _SC('=')) {
- Lex();
- val = ExpectScalar();
- }
- else {
- val._type = OT_INTEGER;
- val._unVal.nInteger = nval++;
- }
- _table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val));
- if(_token == ',') Lex();
- }
- SQTable *enums = _table(_ss(_vm)->_consts);
- SQObjectPtr strongid = id;
- /*SQObjectPtr dummy;
- if(enums->Get(strongid,dummy)) {
- dummy.Null(); strongid.Null();
- Error(_SC("enumeration already exists"));
- }*/
- enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table));
- strongid.Null();
- Lex();
-
- }
- void TryCatchStatement()
- {
- SQObject exid;
- Lex();
- _fs->AddInstruction(_OP_PUSHTRAP,0,0);
- _fs->_traps++;
- if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;
- if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;
- SQInteger 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);
- SQInteger jmppos = _fs->GetCurrentPos();
- _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));
- Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));
- SQInteger stacksize = _fs->GetStackSize();
- SQInteger ex_target = _fs->PushLocalVariable(exid);
- _fs->SetIntructionParam(trappos, 0, ex_target);
- Statement();
- _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);
- CleanStack(stacksize);
- }
- void FunctionExp(SQInteger ftype)
- {
- Lex(); Expect(_SC('('));
- CreateFunction(_null_);
- _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);
- }
- void ClassExp()
- {
- SQInteger base = -1;
- SQInteger 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();
- SQInteger 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(SQInteger 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 {
- SQInteger src = _fs->PopTarget();
- _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1);
- }
- }
- void CreateFunction(SQObject &name)
- {
-
- SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));
- funcstate->_name = name;
- SQObject paramname;
- funcstate->AddParameter(_fs->CreateString(_SC("this")));
- funcstate->_sourcename = _sourcename;
- SQInteger defparams = 0;
- while(_token!=_SC(')')) {
- if(_token == TK_VARPARAMS) {
- if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters"));
- funcstate->_varparams = true;
- Lex();
- if(_token != _SC(')')) Error(_SC("expected ')'"));
- break;
- }
- else {
- paramname = Expect(TK_IDENTIFIER);
- funcstate->AddParameter(paramname);
- if(_token == _SC('=')) {
- Lex();
- Expression();
- funcstate->AddDefaultParam(_fs->TopTarget());
- defparams++;
- }
- else {
- if(defparams > 0) Error(_SC("expected '='"));
- }
- if(_token == _SC(',')) Lex();
- else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
- }
- }
- Expect(_SC(')'));
- for(SQInteger n = 0; n < defparams; n++) {
- _fs->PopTarget();
- }
- //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);
- //_fs->->_stacksize = _fs->_stacksize;
- SQFunctionProto *func = funcstate->BuildProto();
-#ifdef _DEBUG_DUMP
- funcstate->Dump(func);
-#endif
- _fs = currchunk;
- _fs->_functions.push_back(func);
- _fs->PopChildState();
- }
- void CleanStack(SQInteger stacksize)
- {
- if(_fs->GetStackSize() != stacksize)
- _fs->SetStackSize(stacksize);
- }
- void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
- {
- while(ntoresolve > 0) {
- SQInteger 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, SQInteger ntoresolve, SQInteger targetpos)
- {
- while(ntoresolve > 0) {
- SQInteger pos = funcstate->_unresolvedcontinues.back();
- funcstate->_unresolvedcontinues.pop_back();
- //set the jmp instruction
- funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);
- ntoresolve--;
- }
- }
-private:
- SQInteger _token;
- SQFuncState *_fs;
- SQObjectPtr _sourcename;
- SQLexer _lex;
- bool _lineinfo;
- bool _raiseerror;
- SQInteger _debugline;
- SQInteger _debugop;
- ExpStateVec _expstates;
- SQChar *compilererror;
- jmp_buf _errorjmp;
- 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);
-}
+/*\r
+ see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+#include <stdarg.h>\r
+#include <setjmp.h>\r
+#include "sqopcodes.h"\r
+#include "sqstring.h"\r
+#include "sqfuncproto.h"\r
+#include "sqcompiler.h"\r
+#include "sqfuncstate.h"\r
+#include "sqlexer.h"\r
+#include "sqvm.h"\r
+#include "sqtable.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
+ SQInteger _deref;\r
+};\r
+\r
+typedef sqvector<ExpState> ExpStateVec;\r
+\r
+#define _exst (_expstates.top())\r
+\r
+#define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \\r
+ SQInteger __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,ThrowError,this);\r
+ _sourcename = SQString::Create(_ss(v), sourcename);\r
+ _lineinfo = lineinfo;_raiseerror = raiseerror;\r
+ compilererror = NULL;\r
+ }\r
+ static void ThrowError(void *ud, const SQChar *s) {\r
+ SQCompiler *c = (SQCompiler *)ud;\r
+ c->Error(s);\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
+ compilererror = temp;\r
+ longjmp(_errorjmp,1);\r
+ }\r
+ void Lex(){ _token = _lex.Lex();}\r
+ void PushExpState(){ _expstates.push_back(ExpState()); }\r
+ bool IsDerefToken(SQInteger 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
+ SQObject Expect(SQInteger tok)\r
+ {\r
+ \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
+ const SQChar *etypename;\r
+ if(tok > 255) {\r
+ switch(tok)\r
+ {\r
+ case TK_IDENTIFIER:\r
+ etypename = _SC("IDENTIFIER");\r
+ break;\r
+ case TK_STRING_LITERAL:\r
+ etypename = _SC("STRING_LITERAL");\r
+ break;\r
+ case TK_INTEGER:\r
+ etypename = _SC("INTEGER");\r
+ break;\r
+ case TK_FLOAT:\r
+ etypename = _SC("FLOAT");\r
+ break;\r
+ default:\r
+ etypename = _lex.Tok2Str(tok);\r
+ }\r
+ Error(_SC("expected '%s'"), etypename);\r
+ }\r
+ Error(_SC("expected '%c'"), tok);\r
+ }\r
+ }\r
+ SQObjectPtr ret;\r
+ switch(tok)\r
+ {\r
+ case TK_IDENTIFIER:\r
+ ret = _fs->CreateString(_lex._svalue);\r
+ break;\r
+ case TK_STRING_LITERAL:\r
+ ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);\r
+ break;\r
+ case TK_INTEGER:\r
+ ret = SQObjectPtr(_lex._nvalue);\r
+ break;\r
+ case TK_FLOAT:\r
+ ret = SQObjectPtr(_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
+ SQInteger 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
+ _debugline = 1;\r
+ _debugop = 0;\r
+\r
+ SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this);\r
+ funcstate._name = SQString::Create(_ss(_vm), _SC("main"));\r
+ _fs = &funcstate;\r
+ _fs->AddParameter(_fs->CreateString(_SC("this")));\r
+ _fs->_sourcename = _sourcename;\r
+ SQInteger stacksize = _fs->GetStackSize();\r
+ if(setjmp(_errorjmp) == 0) {\r
+ Lex();\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
+ _fs->SetStackSize(0);\r
+ o =_fs->BuildProto();\r
+#ifdef _DEBUG_DUMP\r
+ _fs->Dump(_funcproto(o));\r
+#endif\r
+ }\r
+ else {\r
+ if(_raiseerror && _ss(_vm)->_compilererrorhandler) {\r
+ _ss(_vm)->_compilererrorhandler(_vm, compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),\r
+ _lex._currentline, _lex._currentcolumn);\r
+ }\r
+ _vm->_lasterror = SQString::Create(_ss(_vm), compilererror, -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
+ _fs->_bgenerator = true;\r
+ }\r
+ Lex();\r
+ if(!IsEndOfStatement()) {\r
+ SQInteger 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 TK_ENUM:\r
+ EnumStatement();\r
+ break;\r
+ case _SC('{'):{\r
+ SQInteger 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
+ case TK_CONST:\r
+ {\r
+ Lex();\r
+ SQObject id = Expect(TK_IDENTIFIER);\r
+ Expect('=');\r
+ SQObject val = ExpectScalar();\r
+ OptionalSemicolon();\r
+ SQTable *enums = _table(_ss(_vm)->_consts);\r
+ SQObjectPtr strongid = id; \r
+ enums->NewSlot(strongid,SQObjectPtr(val));\r
+ strongid.Null();\r
+ }\r
+ break;\r
+ default:\r
+ CommaExpr();\r
+ _fs->PopTarget();\r
+ break;\r
+ }\r
+ _fs->SnoozeOpt();\r
+ }\r
+ void EmitDerefOp(SQOpcode op)\r
+ {\r
+ SQInteger val = _fs->PopTarget();\r
+ SQInteger key = _fs->PopTarget();\r
+ SQInteger src = _fs->PopTarget();\r
+ _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);\r
+ }\r
+ void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0)\r
+ {\r
+ SQInteger p2 = _fs->PopTarget(); //src in OP_GET\r
+ SQInteger p1 = _fs->PopTarget(); //key in OP_GET\r
+ _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);\r
+ }\r
+ void EmitCompoundArith(SQInteger tok,bool deref)\r
+ {\r
+ SQInteger 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: oper = 0; //shut up compiler\r
+ assert(0); break;\r
+ };\r
+ if(deref) {\r
+ SQInteger val = _fs->PopTarget();\r
+ SQInteger key = _fs->PopTarget();\r
+ SQInteger 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
+ SQInteger op = _token;\r
+ SQInteger 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
+ SQInteger p2 = _fs->PopTarget(); //src in OP_GET\r
+ SQInteger 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
+ SQInteger jzpos = _fs->GetCurrentPos();\r
+ SQInteger trg = _fs->PushTarget();\r
+ Expression();\r
+ SQInteger first_exp = _fs->PopTarget();\r
+ if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
+ SQInteger endfirstexp = _fs->GetCurrentPos();\r
+ _fs->AddInstruction(_OP_JMP, 0, 0);\r
+ Expect(_SC(':'));\r
+ SQInteger jmppos = _fs->GetCurrentPos();\r
+ Expression();\r
+ SQInteger 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),SQInteger op3 = 0)\r
+ {\r
+ Lex(); (this->*f)();\r
+ SQInteger op1 = _fs->PopTarget();SQInteger 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
+ SQInteger first_exp = _fs->PopTarget();\r
+ SQInteger trg = _fs->PushTarget();\r
+ _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0);\r
+ SQInteger jpos = _fs->GetCurrentPos();\r
+ if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
+ Lex(); LogicalOrExp();\r
+ _fs->SnoozeOpt();\r
+ SQInteger 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
+ SQInteger first_exp = _fs->PopTarget();\r
+ SQInteger trg = _fs->PushTarget();\r
+ _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0);\r
+ SQInteger jpos = _fs->GetCurrentPos();\r
+ if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);\r
+ Lex(); LogicalAndExp();\r
+ _fs->SnoozeOpt();\r
+ SQInteger 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
+ SQInteger pos = Factor();\r
+ \r
+ for(;;) {\r
+ switch(_token) {\r
+ case _SC('.'): {\r
+ pos = -1;\r
+ Lex(); \r
+ if(_token == TK_PARENT) {\r
+ Lex();\r
+ if(!NeedGet())\r
+ Error(_SC("parent cannot be set"));\r
+ SQInteger src = _fs->PopTarget();\r
+ _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src);\r
+ }\r
+ else {\r
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));\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
+ SQInteger 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
+ SQInteger 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
+ SQInteger key = _fs->PopTarget(); //key\r
+ SQInteger table = _fs->PopTarget(); //table etc...\r
+ SQInteger closure = _fs->PushTarget();\r
+ SQInteger 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
+ SQInteger Factor()\r
+ {\r
+ _exst._deref = DEREF_NO_DEREF;\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->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));\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
+ SQInteger 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
+ SQObject id;\r
+ SQObject constant;\r
+ switch(_token) {\r
+ case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break;\r
+ case TK_THIS: id = _fs->CreateString(_SC("this")); break;\r
+ case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor")); break;\r
+ }\r
+ SQInteger 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
+ }\r
+ else if(_fs->IsConstant(id,constant)) { //line 634\r
+ SQObjectPtr constval;\r
+ SQObject constid;\r
+ if(type(constant) == OT_TABLE) {\r
+ Expect('.'); constid = Expect(TK_IDENTIFIER);\r
+ if(!_table(constant)->Get(constid,constval)) {\r
+ constval.Null();\r
+ Error(_SC("invalid constant [%s.%s]"), _stringval(id),_stringval(constid));\r
+ }\r
+ }\r
+ else {\r
+ constval = constant;\r
+ }\r
+ _exst._deref = _fs->PushTarget();\r
+ SQObjectType ctype = type(constval);\r
+ if(ctype == OT_INTEGER && (_integer(constval) & (~0x7FFFFFFF)) == 0) {\r
+ _fs->AddInstruction(_OP_LOADINT, _exst._deref,_integer(constval));\r
+ }\r
+ else if(ctype == OT_FLOAT && sizeof(SQFloat) == sizeof(SQInt32)) {\r
+ SQFloat f = _float(constval);\r
+ _fs->AddInstruction(_OP_LOADFLOAT, _exst._deref,*((SQInt32 *)&f));\r
+ }\r
+ else {\r
+ _fs->AddInstruction(_OP_LOAD, _exst._deref, _fs->GetConstant(constval));\r
+ }\r
+\r
+ _exst._freevar = true;\r
+ }\r
+ else {\r
+ _fs->PushTarget(0);\r
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));\r
+ if(NeedGet()) Emit2ArgsOP(_OP_GET);\r
+ _exst._deref = DEREF_FIELD;\r
+ }\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
+ if((_lex._nvalue & (~0x7FFFFFFF)) == 0) { //does it fit in 32 bits?\r
+ _fs->AddInstruction(_OP_LOADINT, _fs->PushTarget(),_lex._nvalue);\r
+ }\r
+ else {\r
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue));\r
+ }\r
+ Lex();\r
+ }\r
+ break;\r
+ case TK_FLOAT:\r
+ if(sizeof(SQFloat) == sizeof(SQInt32)) {\r
+ _fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(),*((SQInt32 *)&_lex._fvalue));\r
+ }\r
+ else {\r
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue));\r
+ }\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
+ SQInteger apos = _fs->GetCurrentPos(),key = 0;\r
+ Lex();\r
+ while(_token != _SC(']')) {\r
+ Expression(); \r
+ if(_token == _SC(',')) Lex();\r
+ SQInteger val = _fs->PopTarget();\r
+ SQInteger 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
+ SQInteger 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
+ SQInteger 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(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget();\r
+ SQInteger stackbase = _fs->PopTarget();\r
+ SQInteger closure = _fs->PopTarget();\r
+ _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);\r
+ }\r
+ void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}')\r
+ {\r
+ SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;\r
+ \r
+ while(_token != terminator) {\r
+ bool hasattrs = false;\r
+ bool isstatic = false;\r
+ //check if is an attribute\r
+ if(separator == ';') {\r
+ if(_token == TK_ATTR_OPEN) {\r
+ _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex();\r
+ ParseTableOrClass(',',TK_ATTR_CLOSE);\r
+ hasattrs = true;\r
+ }\r
+ if(_token == TK_STATIC) {\r
+ isstatic = true;\r
+ Lex();\r
+ }\r
+ }\r
+ switch(_token) {\r
+ case TK_FUNCTION:\r
+ case TK_CONSTRUCTOR:{\r
+ SQInteger tk = _token;\r
+ Lex();\r
+ SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor"));\r
+ Expect(_SC('('));\r
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(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->GetConstant(Expect(TK_IDENTIFIER)));\r
+ Expect(_SC('=')); Expression();\r
+ }\r
+\r
+ if(_token == separator) Lex();//optional comma/semicolon\r
+ nkeys++;\r
+ SQInteger val = _fs->PopTarget();\r
+ SQInteger key = _fs->PopTarget();\r
+ SQInteger attrs = hasattrs ? _fs->PopTarget():-1;\r
+ assert(hasattrs && attrs == key-1 || !hasattrs);\r
+ unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);\r
+ SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE\r
+ _fs->AddInstruction(_OP_NEWSLOTA, flags, 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
+ SQObject varname;\r
+ do {\r
+ Lex(); varname = Expect(TK_IDENTIFIER);\r
+ if(_token == _SC('=')) {\r
+ Lex(); Expression();\r
+ SQInteger src = _fs->PopTarget();\r
+ SQInteger 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
+ SQInteger jmppos;\r
+ bool haselse = false;\r
+ Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));\r
+ _fs->AddInstruction(_OP_JZ, _fs->PopTarget());\r
+ SQInteger jnepos = _fs->GetCurrentPos();\r
+ SQInteger stacksize = _fs->GetStackSize();\r
+ \r
+ Statement();\r
+ //\r
+ if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();\r
+ \r
+ CleanStack(stacksize);\r
+ SQInteger 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
+ SQInteger jzpos, jmppos;\r
+ SQInteger 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
+ SQInteger jzpos = _fs->GetCurrentPos();\r
+ SQInteger stacksize = _fs->GetStackSize();\r
+ BEGIN_BREAKBLE_BLOCK()\r
+ Statement();\r
+ CleanStack(stacksize);\r
+ Expect(TK_WHILE);\r
+ SQInteger 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
+ SQInteger 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
+ SQInteger jmppos = _fs->GetCurrentPos();\r
+ SQInteger jzpos = -1;\r
+ if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }\r
+ Expect(_SC(';'));\r
+ _fs->SnoozeOpt();\r
+ SQInteger expstart = _fs->GetCurrentPos() + 1;\r
+ if(_token != _SC(')')) {\r
+ CommaExpr();\r
+ _fs->PopTarget();\r
+ }\r
+ Expect(_SC(')'));\r
+ _fs->SnoozeOpt();\r
+ SQInteger expend = _fs->GetCurrentPos();\r
+ SQInteger expsize = (expend - expstart) + 1;\r
+ SQInstructionVec exp;\r
+ if(expsize > 0) {\r
+ for(SQInteger 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
+ SQInteger continuetrg = _fs->GetCurrentPos();\r
+ if(expsize > 0) {\r
+ for(SQInteger 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
+ SQObject 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 = _fs->CreateString(_SC("@INDEX@"));\r
+ }\r
+ Expect(TK_IN);\r
+ \r
+ //save the stack size\r
+ SQInteger stacksize = _fs->GetStackSize();\r
+ //put the table in the stack(evaluate the table expression)\r
+ Expression(); Expect(_SC(')'));\r
+ SQInteger container = _fs->TopTarget();\r
+ //push the index local var\r
+ SQInteger indexpos = _fs->PushLocalVariable(idxname);\r
+ _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);\r
+ //push the value local var\r
+ SQInteger valuepos = _fs->PushLocalVariable(valname);\r
+ _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);\r
+ //push reference index\r
+ SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible\r
+ _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);\r
+ SQInteger jmppos = _fs->GetCurrentPos();\r
+ _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);\r
+ SQInteger foreachpos = _fs->GetCurrentPos();\r
+ _fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos);\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
+ _fs->SetIntructionParam(foreachpos + 1, 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
+ SQInteger expr = _fs->TopTarget();\r
+ bool bfirst = true;\r
+ SQInteger tonextcondjmp = -1;\r
+ SQInteger skipcondjmp = -1;\r
+ SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size();\r
+ _fs->_breaktargets.push_back(0);\r
+ while(_token == TK_CASE) {\r
+ //_fs->AddLineInfos(_lex._currentline, _lineinfo); think about this one\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
+ SQInteger 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
+ SQInteger 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
+ // _fs->AddLineInfos(_lex._currentline, _lineinfo);\r
+ Lex(); Expect(_SC(':'));\r
+ SQInteger 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
+ SQObject id;\r
+ Lex(); id = Expect(TK_IDENTIFIER);\r
+ _fs->PushTarget(0);\r
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(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->GetConstant(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
+ SQObject ExpectScalar()\r
+ {\r
+ SQObject val;\r
+ switch(_token) {\r
+ case TK_INTEGER:\r
+ val._type = OT_INTEGER;\r
+ val._unVal.nInteger = _lex._nvalue;\r
+ break;\r
+ case TK_FLOAT:\r
+ val._type = OT_FLOAT;\r
+ val._unVal.fFloat = _lex._fvalue;\r
+ break;\r
+ case TK_STRING_LITERAL:\r
+ val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);\r
+ break;\r
+ case '-':\r
+ Lex();\r
+ switch(_token)\r
+ {\r
+ case TK_INTEGER:\r
+ val._type = OT_INTEGER;\r
+ val._unVal.nInteger = -_lex._nvalue;\r
+ break;\r
+ case TK_FLOAT:\r
+ val._type = OT_FLOAT;\r
+ val._unVal.fFloat = -_lex._fvalue;\r
+ break;\r
+ default:\r
+ Error(_SC("scalar expected : integer,float"));\r
+ }\r
+ break;\r
+ default:\r
+ Error(_SC("scalar expected : integer,float or string"));\r
+ }\r
+ Lex();\r
+ return val;\r
+ }\r
+ void EnumStatement()\r
+ {\r
+ \r
+ Lex(); \r
+ SQObject id = Expect(TK_IDENTIFIER);\r
+ Expect(_SC('{'));\r
+ \r
+ SQObject table = _fs->CreateTable();\r
+ SQInteger nval = 0;\r
+ while(_token != _SC('}')) {\r
+ SQObject key = Expect(TK_IDENTIFIER);\r
+ SQObject val;\r
+ if(_token == _SC('=')) {\r
+ Lex();\r
+ val = ExpectScalar();\r
+ }\r
+ else {\r
+ val._type = OT_INTEGER;\r
+ val._unVal.nInteger = nval++;\r
+ }\r
+ _table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val));\r
+ if(_token == ',') Lex();\r
+ }\r
+ SQTable *enums = _table(_ss(_vm)->_consts);\r
+ SQObjectPtr strongid = id; \r
+ /*SQObjectPtr dummy;\r
+ if(enums->Get(strongid,dummy)) {\r
+ dummy.Null(); strongid.Null();\r
+ Error(_SC("enumeration already exists"));\r
+ }*/\r
+ enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table));\r
+ strongid.Null();\r
+ Lex();\r
+ \r
+ }\r
+ void TryCatchStatement()\r
+ {\r
+ SQObject 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
+ SQInteger 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
+ SQInteger jmppos = _fs->GetCurrentPos();\r
+ _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));\r
+ Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));\r
+ SQInteger stacksize = _fs->GetStackSize();\r
+ SQInteger 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(SQInteger 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
+ SQInteger base = -1;\r
+ SQInteger 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
+ SQInteger 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(SQInteger 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
+ SQInteger src = _fs->PopTarget();\r
+ _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1);\r
+ }\r
+ }\r
+ void CreateFunction(SQObject &name)\r
+ {\r
+ \r
+ SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));\r
+ funcstate->_name = name;\r
+ SQObject paramname;\r
+ funcstate->AddParameter(_fs->CreateString(_SC("this")));\r
+ funcstate->_sourcename = _sourcename;\r
+ SQInteger defparams = 0;\r
+ while(_token!=_SC(')')) {\r
+ if(_token == TK_VARPARAMS) {\r
+ if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters"));\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('=')) { \r
+ Lex();\r
+ Expression();\r
+ funcstate->AddDefaultParam(_fs->TopTarget());\r
+ defparams++;\r
+ }\r
+ else {\r
+ if(defparams > 0) Error(_SC("expected '='"));\r
+ }\r
+ if(_token == _SC(',')) Lex();\r
+ else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));\r
+ }\r
+ }\r
+ Expect(_SC(')'));\r
+ for(SQInteger n = 0; n < defparams; n++) {\r
+ _fs->PopTarget();\r
+ }\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
+ //_fs->->_stacksize = _fs->_stacksize;\r
+ SQFunctionProto *func = funcstate->BuildProto();\r
+#ifdef _DEBUG_DUMP\r
+ funcstate->Dump(func);\r
+#endif\r
+ _fs = currchunk;\r
+ _fs->_functions.push_back(func);\r
+ _fs->PopChildState();\r
+ }\r
+ void CleanStack(SQInteger stacksize)\r
+ {\r
+ if(_fs->GetStackSize() != stacksize)\r
+ _fs->SetStackSize(stacksize);\r
+ }\r
+ void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)\r
+ {\r
+ while(ntoresolve > 0) {\r
+ SQInteger 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, SQInteger ntoresolve, SQInteger targetpos)\r
+ {\r
+ while(ntoresolve > 0) {\r
+ SQInteger 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
+ SQInteger _token;\r
+ SQFuncState *_fs;\r
+ SQObjectPtr _sourcename;\r
+ SQLexer _lex;\r
+ bool _lineinfo;\r
+ bool _raiseerror;\r
+ SQInteger _debugline;\r
+ SQInteger _debugop;\r
+ ExpStateVec _expstates;\r
+ SQChar *compilererror;\r
+ jmp_buf _errorjmp;\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 */
-#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
-#define TK_STATIC 322
-#define TK_ENUM 323
-#define TK_CONST 324
-
-
-typedef void(*CompilerErrorFunc)(void *ud, const SQChar *s);
-bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo);
-#endif //_SQCOMPILER_H_
+/* 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
+#define TK_STATIC 322\r
+#define TK_ENUM 323\r
+#define TK_CONST 324\r
+\r
+\r
+typedef void(*CompilerErrorFunc)(void *ud, const SQChar *s);\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
-*/
-#include "sqpcheader.h"
-#include <stdarg.h>
-#include "sqvm.h"
-#include "sqfuncproto.h"
-#include "sqclosure.h"
-#include "sqstring.h"
-
-SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi)
-{
- SQInteger cssize = v->_callsstacksize;
- if (cssize > level) {
- SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];
- if(sq_isclosure(ci._closure)) {
- SQClosure *c = _closure(ci._closure);
- SQFunctionProto *proto = _funcproto(c->_function);
- fi->funcid = proto;
- fi->name = type(proto->_name) == OT_STRING?_stringval(proto->_name):_SC("unknown");
- fi->source = type(proto->_name) == OT_STRING?_stringval(proto->_sourcename):_SC("unknown");
- return SQ_OK;
- }
- }
- return sq_throwerror(v,_SC("the object is not a closure"));
-}
-
-SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si)
-{
- SQInteger cssize = v->_callsstacksize;
- 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; //shutup compiler
- }
- return SQ_OK;
- }
- return SQ_ERROR;
-}
-
-void SQVM::Raise_Error(const SQChar *s, ...)
-{
- va_list vl;
- va_start(vl, s);
- scvsprintf(_sp(rsl((SQInteger)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(SQInteger nparam,SQInteger typemask,SQInteger type)
-{
- SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1);
- SQInteger found = 0;
- for(SQInteger i=0; i<16; i++)
- {
- SQInteger 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));
-}
+/*\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_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi)\r
+{\r
+ SQInteger cssize = v->_callsstacksize;\r
+ if (cssize > level) {\r
+ SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];\r
+ if(sq_isclosure(ci._closure)) {\r
+ SQClosure *c = _closure(ci._closure);\r
+ SQFunctionProto *proto = _funcproto(c->_function);\r
+ fi->funcid = proto;\r
+ fi->name = type(proto->_name) == OT_STRING?_stringval(proto->_name):_SC("unknown");\r
+ fi->source = type(proto->_name) == OT_STRING?_stringval(proto->_sourcename):_SC("unknown");\r
+ return SQ_OK;\r
+ }\r
+ }\r
+ return sq_throwerror(v,_SC("the object is not a closure"));\r
+}\r
+\r
+SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si)\r
+{\r
+ SQInteger cssize = v->_callsstacksize;\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
+ default: break; //shutup compiler\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((SQInteger)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(SQInteger nparam,SQInteger typemask,SQInteger type)\r
+{\r
+ SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1);\r
+ SQInteger found = 0; \r
+ for(SQInteger i=0; i<16; i++)\r
+ {\r
+ SQInteger 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 */
-#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;
- SQUnsignedInteger _start_op;
- SQUnsignedInteger _end_op;
- SQUnsignedInteger _pos;
-};
-
-struct SQLineInfo { SQInteger _line;SQInteger _op; };
-
-typedef sqvector<SQOuterVar> SQOuterVarVec;
-typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;
-typedef sqvector<SQLineInfo> SQLineInfoVec;
-
-#define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf,defparams) (sizeof(SQFunctionProto) \
- +((ni-1)*sizeof(SQInstruction))+(nl*sizeof(SQObjectPtr)) \
- +(nparams*sizeof(SQObjectPtr))+(nfuncs*sizeof(SQObjectPtr)) \
- +(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \
- +(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger)))
-
-#define _CONSTRUCT_VECTOR(type,size,ptr) { \
- for(SQInteger n = 0; n < size; n++) { \
- new (&ptr[n]) type(); \
- } \
-}
-
-#define _DESTRUCT_VECTOR(type,size,ptr) { \
- for(SQInteger nl = 0; nl < size; nl++) { \
- ptr[nl].~type(); \
- } \
-}
-struct SQFunctionProto : public SQRefCounted
-{
-private:
- SQFunctionProto(){
- _stacksize=0;
- _bgenerator=false;}
-public:
- static SQFunctionProto *Create(SQInteger ninstructions,
- SQInteger nliterals,SQInteger nparameters,
- SQInteger nfunctions,SQInteger noutervalues,
- SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams)
- {
- SQFunctionProto *f;
- //I compact the whole class and members in a single memory allocation
- f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams));
- new (f) SQFunctionProto;
- f->_ninstructions = ninstructions;
- f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions];
- f->_nliterals = nliterals;
- f->_parameters = (SQObjectPtr*)&f->_literals[nliterals];
- f->_nparameters = nparameters;
- f->_functions = (SQObjectPtr*)&f->_parameters[nparameters];
- f->_nfunctions = nfunctions;
- f->_outervalues = (SQOuterVar*)&f->_functions[nfunctions];
- f->_noutervalues = noutervalues;
- f->_lineinfos = (SQLineInfo *)&f->_outervalues[noutervalues];
- f->_nlineinfos = nlineinfos;
- f->_localvarinfos = (SQLocalVarInfo *)&f->_lineinfos[nlineinfos];
- f->_nlocalvarinfos = nlocalvarinfos;
- f->_defaultparams = (SQInteger *)&f->_localvarinfos[nlocalvarinfos];
- f->_ndefaultparams = ndefaultparams;
-
- _CONSTRUCT_VECTOR(SQObjectPtr,f->_nliterals,f->_literals);
- _CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters);
- _CONSTRUCT_VECTOR(SQObjectPtr,f->_nfunctions,f->_functions);
- _CONSTRUCT_VECTOR(SQOuterVar,f->_noutervalues,f->_outervalues);
- //_CONSTRUCT_VECTOR(SQLineInfo,f->_nlineinfos,f->_lineinfos); //not required are 2 integers
- _CONSTRUCT_VECTOR(SQLocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos);
- return f;
- }
- void Release(){
- _DESTRUCT_VECTOR(SQObjectPtr,_nliterals,_literals);
- _DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters);
- _DESTRUCT_VECTOR(SQObjectPtr,_nfunctions,_functions);
- _DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues);
- //_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers
- _DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos);
- SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams);
- this->~SQFunctionProto();
- sq_vm_free(this,size);
- }
- const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);
- SQInteger GetLine(SQInstruction *curr);
- bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
- static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
-
- SQObjectPtr _sourcename;
- SQObjectPtr _name;
- SQInteger _stacksize;
- bool _bgenerator;
- bool _varparams;
-
- SQInteger _nlocalvarinfos;
- SQLocalVarInfo *_localvarinfos;
-
- SQInteger _nlineinfos;
- SQLineInfo *_lineinfos;
-
- SQInteger _nliterals;
- SQObjectPtr *_literals;
-
- SQInteger _nparameters;
- SQObjectPtr *_parameters;
-
- SQInteger _nfunctions;
- SQObjectPtr *_functions;
-
- SQInteger _noutervalues;
- SQOuterVar *_outervalues;
-
- SQInteger _ndefaultparams;
- SQInteger *_defaultparams;
-
- SQInteger _ninstructions;
- SQInstruction _instructions[1];
-};
-
-#endif //_SQFUNCTION_H_
+/* 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
+ SQUnsignedInteger _start_op;\r
+ SQUnsignedInteger _end_op;\r
+ SQUnsignedInteger _pos;\r
+};\r
+\r
+struct SQLineInfo { SQInteger _line;SQInteger _op; };\r
+\r
+typedef sqvector<SQOuterVar> SQOuterVarVec;\r
+typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;\r
+typedef sqvector<SQLineInfo> SQLineInfoVec;\r
+\r
+#define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf,defparams) (sizeof(SQFunctionProto) \\r
+ +((ni-1)*sizeof(SQInstruction))+(nl*sizeof(SQObjectPtr)) \\r
+ +(nparams*sizeof(SQObjectPtr))+(nfuncs*sizeof(SQObjectPtr)) \\r
+ +(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \\r
+ +(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger)))\r
+\r
+#define _CONSTRUCT_VECTOR(type,size,ptr) { \\r
+ for(SQInteger n = 0; n < size; n++) { \\r
+ new (&ptr[n]) type(); \\r
+ } \\r
+}\r
+\r
+#define _DESTRUCT_VECTOR(type,size,ptr) { \\r
+ for(SQInteger nl = 0; nl < size; nl++) { \\r
+ ptr[nl].~type(); \\r
+ } \\r
+}\r
+struct SQFunctionProto : public SQRefCounted\r
+{\r
+private:\r
+ SQFunctionProto(){\r
+ _stacksize=0;\r
+ _bgenerator=false;}\r
+public:\r
+ static SQFunctionProto *Create(SQInteger ninstructions,\r
+ SQInteger nliterals,SQInteger nparameters,\r
+ SQInteger nfunctions,SQInteger noutervalues,\r
+ SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams)\r
+ {\r
+ SQFunctionProto *f;\r
+ //I compact the whole class and members in a single memory allocation\r
+ f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams));\r
+ new (f) SQFunctionProto;\r
+ f->_ninstructions = ninstructions;\r
+ f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions];\r
+ f->_nliterals = nliterals;\r
+ f->_parameters = (SQObjectPtr*)&f->_literals[nliterals];\r
+ f->_nparameters = nparameters;\r
+ f->_functions = (SQObjectPtr*)&f->_parameters[nparameters];\r
+ f->_nfunctions = nfunctions;\r
+ f->_outervalues = (SQOuterVar*)&f->_functions[nfunctions];\r
+ f->_noutervalues = noutervalues;\r
+ f->_lineinfos = (SQLineInfo *)&f->_outervalues[noutervalues];\r
+ f->_nlineinfos = nlineinfos;\r
+ f->_localvarinfos = (SQLocalVarInfo *)&f->_lineinfos[nlineinfos];\r
+ f->_nlocalvarinfos = nlocalvarinfos;\r
+ f->_defaultparams = (SQInteger *)&f->_localvarinfos[nlocalvarinfos];\r
+ f->_ndefaultparams = ndefaultparams;\r
+\r
+ _CONSTRUCT_VECTOR(SQObjectPtr,f->_nliterals,f->_literals);\r
+ _CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters);\r
+ _CONSTRUCT_VECTOR(SQObjectPtr,f->_nfunctions,f->_functions);\r
+ _CONSTRUCT_VECTOR(SQOuterVar,f->_noutervalues,f->_outervalues);\r
+ //_CONSTRUCT_VECTOR(SQLineInfo,f->_nlineinfos,f->_lineinfos); //not required are 2 integers\r
+ _CONSTRUCT_VECTOR(SQLocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos);\r
+ return f;\r
+ }\r
+ void Release(){ \r
+ _DESTRUCT_VECTOR(SQObjectPtr,_nliterals,_literals);\r
+ _DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters);\r
+ _DESTRUCT_VECTOR(SQObjectPtr,_nfunctions,_functions);\r
+ _DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues);\r
+ //_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers\r
+ _DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos);\r
+ SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams);\r
+ this->~SQFunctionProto();\r
+ sq_vm_free(this,size);\r
+ }\r
+ const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);\r
+ SQInteger GetLine(SQInstruction *curr);\r
+ bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);\r
+ static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);\r
+\r
+ SQObjectPtr _sourcename;\r
+ SQObjectPtr _name;\r
+ SQInteger _stacksize;\r
+ bool _bgenerator;\r
+ bool _varparams;\r
+\r
+ SQInteger _nlocalvarinfos;\r
+ SQLocalVarInfo *_localvarinfos;\r
+\r
+ SQInteger _nlineinfos;\r
+ SQLineInfo *_lineinfos;\r
+\r
+ SQInteger _nliterals;\r
+ SQObjectPtr *_literals;\r
+\r
+ SQInteger _nparameters;\r
+ SQObjectPtr *_parameters;\r
+ \r
+ SQInteger _nfunctions;\r
+ SQObjectPtr *_functions;\r
+\r
+ SQInteger _noutervalues;\r
+ SQOuterVar *_outervalues;\r
+\r
+ SQInteger _ndefaultparams;\r
+ SQInteger *_defaultparams;\r
+ \r
+ SQInteger _ninstructions;\r
+ SQInstruction _instructions[1];\r
+};\r
+\r
+#endif //_SQFUNCTION_H_\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_LOADINT")},
- {_SC("_OP_LOADFLOAT")},
- {_SC("_OP_DLOAD")},
- {_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_LOADBOOL")},
- {_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_POSTFOREACH")},
- {_SC("_OP_DELEGATE")},
- {_SC("_OP_CLONE")},
- {_SC("_OP_TYPEOF")},
- {_SC("_OP_PUSHTRAP")},
- {_SC("_OP_POPTRAP")},
- {_SC("_OP_THROW")},
- {_SC("_OP_CLASS")},
- {_SC("_OP_NEWSLOTA")}
-};
-#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;
- case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
- default: scprintf(_SC("(%s %p)"),GetTypeName(o),_rawval(o));break; break; //shut up compiler
- }
-}
-
-SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
-{
- _nliterals = 0;
- _literals = SQTable::Create(ss,0);
- _strings = SQTable::Create(ss,0);
- _sharedstate = ss;
- _lastline = 0;
- _optimization = true;
- _parent = parent;
- _stacksize = 0;
- _traps = 0;
- _returnexp = 0;
- _varparams = false;
- _errfunc = efunc;
- _errtarget = ed;
- _bgenerator = false;
-
-}
-
-void SQFuncState::Error(const SQChar *err)
-{
- _errfunc(_errtarget,err);
-}
-
-#ifdef _DEBUG_DUMP
-void SQFuncState::Dump(SQFunctionProto *func)
-{
- SQUnsignedInteger n=0,i;
- SQInteger si;
- 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(false,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(si=0;si<func->_nlocalvarinfos;si++){
- SQLocalVarInfo lvi=func->_localvarinfos[si];
- 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_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
-
- SQInteger lidx = inst._arg1;
- scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
- if(lidx >= 0xFFFFFFFF)
- scprintf(_SC("null"));
- else {
- SQInteger refidx;
- SQObjectPtr val,key,refo;
- while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
- refo = refidx;
- }
- DumpLiteral(key);
- }
- if(inst.op != _OP_DLOAD) {
- scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
- }
- else {
- scprintf(_SC(" %d "),inst._arg2);
- lidx = inst._arg3;
- if(lidx >= 0xFFFFFFFF)
- scprintf(_SC("null"));
- else {
- SQInteger refidx;
- SQObjectPtr val,key,refo;
- while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
- refo = refidx;
- }
- DumpLiteral(key);
- scprintf(_SC("\n"));
- }
- }
- }
- else if(inst.op==_OP_LOADFLOAT) {
- scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),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
-
-SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
-{
- return GetConstant(SQObjectPtr(cons));
-}
-
-SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
-{
- return GetConstant(SQObjectPtr(cons));
-}
-
-SQInteger SQFuncState::GetConstant(const SQObject &cons)
-{
- SQObjectPtr val;
- if(!_table(_literals)->Get(cons,val))
- {
- val = _nliterals;
- _table(_literals)->NewSlot(cons,val);
- _nliterals++;
- if(_nliterals > MAX_LITERALS) {
- val.Null();
- Error(_SC("internal compiler error: too many literals"));
- }
- }
- return _integer(val);
-}
-
-void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
-{
- _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
- _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
- _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
- _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
-}
-
-void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
-{
- switch(arg){
- case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
- case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
- case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
- case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
- };
-}
-
-SQInteger SQFuncState::AllocStackPos()
-{
- SQInteger npos=_vlocals.size();
- _vlocals.push_back(SQLocalVarInfo());
- if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
- if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
- _stacksize=_vlocals.size();
- }
- return npos;
-}
-
-SQInteger SQFuncState::PushTarget(SQInteger n)
-{
- if(n!=-1){
- _targetstack.push_back(n);
- return n;
- }
- n=AllocStackPos();
- _targetstack.push_back(n);
- return n;
-}
-
-SQInteger SQFuncState::GetUpTarget(SQInteger n){
- return _targetstack[((_targetstack.size()-1)-n)];
-}
-
-SQInteger SQFuncState::TopTarget(){
- return _targetstack.back();
-}
-SQInteger SQFuncState::PopTarget()
-{
- SQInteger npos=_targetstack.back();
- SQLocalVarInfo t=_vlocals[_targetstack.back()];
- if(type(t._name)==OT_NULL){
- _vlocals.pop_back();
- }
- _targetstack.pop_back();
- return npos;
-}
-
-SQInteger SQFuncState::GetStackSize()
-{
- return _vlocals.size();
-}
-
-void SQFuncState::SetStackSize(SQInteger n)
-{
- SQInteger 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::IsConstant(const SQObject &name,SQObject &e)
-{
- SQObjectPtr val;
- if(_table(_sharedstate->_consts)->Get(name,val)) {
- e = val;
- return true;
- }
- return false;
-}
-
-bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
-{
- if(stkpos>=_vlocals.size())return false;
- else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
- return false;
-}
-
-SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
-{
- SQInteger pos=_vlocals.size();
- SQLocalVarInfo lvi;
- lvi._name=name;
- lvi._start_op=GetCurrentPos()+1;
- lvi._pos=_vlocals.size();
- _vlocals.push_back(lvi);
- if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
-
- return pos;
-}
-
-SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
-{
- SQInteger 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;
-}
-
-SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
-{
- SQInteger outers = _outervalues.size();
- for(SQInteger i = 0; i<outers; i++) {
- if(_string(_outervalues[i]._name) == _string(name))
- return i;
- }
- return -1;
-}
-
-void SQFuncState::AddOuterValue(const SQObject &name)
-{
- SQInteger 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 SQObject &name)
-{
- PushLocalVariable(name);
- _parameters.push_back(name);
-}
-
-void SQFuncState::AddLineInfos(SQInteger 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)
-{
- SQInteger 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_LOAD:
- if(pi.op == _OP_LOAD && i._arg1 < 256) {
- pi.op = _OP_DLOAD;
- 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:
- 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,SQInteger len)
-{
- SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
- _table(_strings)->NewSlot(ns,(SQInteger)1);
- return ns;
-}
-
-SQObject SQFuncState::CreateTable()
-{
- SQObjectPtr nt(SQTable::Create(_sharedstate,0));
- _table(_strings)->NewSlot(nt,(SQInteger)1);
- return nt;
-}
-
-SQFunctionProto *SQFuncState::BuildProto()
-{
- SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(),
- _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
- _lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
-
- SQObjectPtr refidx,key,val;
- SQInteger idx;
-
- f->_stacksize = _stacksize;
- f->_sourcename = _sourcename;
- f->_bgenerator = _bgenerator;
- f->_name = _name;
-
- while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
- f->_literals[_integer(val)]=key;
- refidx=idx;
- }
-
- for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];
- for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];
- for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];
- for(SQUnsignedInteger no = 0; no < _localvarinfos.size(); no++) f->_localvarinfos[no] = _localvarinfos[no];
- for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no];
- for(SQUnsignedInteger no = 0; no < _defaultparams.size(); no++) f->_defaultparams[no] = _defaultparams[no];
-
- memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
-
- f->_varparams = _varparams;
-
- return f;
-}
-
-SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
-{
- SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
- new (child) SQFuncState(ss,this,_errfunc,_errtarget);
- _childstates.push_back(child);
- return child;
-}
-
-void SQFuncState::PopChildState()
-{
- SQFuncState *child = _childstates.back();
- sq_delete(child,SQFuncState);
- _childstates.pop_back();
-}
-
-SQFuncState::~SQFuncState()
-{
- while(_childstates.size() > 0)
- {
- PopChildState();
- }
-}
+/*\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_LOADINT")},\r
+ {_SC("_OP_LOADFLOAT")},\r
+ {_SC("_OP_DLOAD")},\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_LOADBOOL")},\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_POSTFOREACH")},\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
+};\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
+ case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;\r
+ default: scprintf(_SC("(%s %p)"),GetTypeName(o),_rawval(o));break; break; //shut up compiler\r
+ }\r
+}\r
+\r
+SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)\r
+{\r
+ _nliterals = 0;\r
+ _literals = SQTable::Create(ss,0);\r
+ _strings = SQTable::Create(ss,0);\r
+ _sharedstate = ss;\r
+ _lastline = 0;\r
+ _optimization = true;\r
+ _parent = parent;\r
+ _stacksize = 0;\r
+ _traps = 0;\r
+ _returnexp = 0;\r
+ _varparams = false;\r
+ _errfunc = efunc;\r
+ _errtarget = ed;\r
+ _bgenerator = false;\r
+\r
+}\r
+\r
+void SQFuncState::Error(const SQChar *err)\r
+{\r
+ _errfunc(_errtarget,err);\r
+}\r
+\r
+#ifdef _DEBUG_DUMP\r
+void SQFuncState::Dump(SQFunctionProto *func)\r
+{\r
+ SQUnsignedInteger n=0,i;\r
+ SQInteger si;\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(false,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(si=0;si<func->_nlocalvarinfos;si++){\r
+ SQLocalVarInfo lvi=func->_localvarinfos[si];\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_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){\r
+ \r
+ SQInteger 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
+ SQInteger refidx;\r
+ SQObjectPtr val,key,refo;\r
+ while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {\r
+ refo = refidx; \r
+ }\r
+ DumpLiteral(key);\r
+ }\r
+ if(inst.op != _OP_DLOAD) {\r
+ scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);\r
+ }\r
+ else {\r
+ scprintf(_SC(" %d "),inst._arg2);\r
+ lidx = inst._arg3;\r
+ if(lidx >= 0xFFFFFFFF)\r
+ scprintf(_SC("null"));\r
+ else {\r
+ SQInteger refidx;\r
+ SQObjectPtr val,key,refo;\r
+ while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {\r
+ refo = refidx; \r
+ }\r
+ DumpLiteral(key);\r
+ scprintf(_SC("\n"));\r
+ }\r
+ }\r
+ }\r
+ else if(inst.op==_OP_LOADFLOAT) {\r
+ scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),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
+\r
+SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)\r
+{\r
+ return GetConstant(SQObjectPtr(cons));\r
+}\r
+\r
+SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)\r
+{\r
+ return GetConstant(SQObjectPtr(cons));\r
+}\r
+\r
+SQInteger SQFuncState::GetConstant(const SQObject &cons)\r
+{\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) {\r
+ val.Null();\r
+ Error(_SC("internal compiler error: too many literals"));\r
+ }\r
+ }\r
+ return _integer(val);\r
+}\r
+\r
+void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)\r
+{\r
+ _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);\r
+ _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);\r
+ _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);\r
+ _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);\r
+}\r
+\r
+void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)\r
+{\r
+ switch(arg){\r
+ case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;\r
+ case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;\r
+ case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;\r
+ case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;\r
+ };\r
+}\r
+\r
+SQInteger SQFuncState::AllocStackPos()\r
+{\r
+ SQInteger npos=_vlocals.size();\r
+ _vlocals.push_back(SQLocalVarInfo());\r
+ if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {\r
+ if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));\r
+ _stacksize=_vlocals.size();\r
+ }\r
+ return npos;\r
+}\r
+\r
+SQInteger SQFuncState::PushTarget(SQInteger 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
+SQInteger SQFuncState::GetUpTarget(SQInteger n){\r
+ return _targetstack[((_targetstack.size()-1)-n)];\r
+}\r
+\r
+SQInteger SQFuncState::TopTarget(){\r
+ return _targetstack.back();\r
+}\r
+SQInteger SQFuncState::PopTarget()\r
+{\r
+ SQInteger 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
+SQInteger SQFuncState::GetStackSize()\r
+{\r
+ return _vlocals.size();\r
+}\r
+\r
+void SQFuncState::SetStackSize(SQInteger n)\r
+{\r
+ SQInteger 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::IsConstant(const SQObject &name,SQObject &e)\r
+{\r
+ SQObjectPtr val;\r
+ if(_table(_sharedstate->_consts)->Get(name,val)) {\r
+ e = val;\r
+ return true;\r
+ }\r
+ return false;\r
+}\r
+\r
+bool SQFuncState::IsLocal(SQUnsignedInteger 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
+SQInteger SQFuncState::PushLocalVariable(const SQObject &name)\r
+{\r
+ SQInteger 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()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();\r
+ \r
+ return pos;\r
+}\r
+\r
+SQInteger SQFuncState::GetLocalVariable(const SQObject &name)\r
+{\r
+ SQInteger 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
+SQInteger SQFuncState::GetOuterVariable(const SQObject &name)\r
+{\r
+ SQInteger outers = _outervalues.size();\r
+ for(SQInteger 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 SQObject &name)\r
+{\r
+ SQInteger 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 SQObject &name)\r
+{\r
+ PushLocalVariable(name);\r
+ _parameters.push_back(name);\r
+}\r
+\r
+void SQFuncState::AddLineInfos(SQInteger 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
+ SQInteger 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
+ case _OP_LOAD:\r
+ if(pi.op == _OP_LOAD && i._arg1 < 256) {\r
+ pi.op = _OP_DLOAD;\r
+ pi._arg2 = i._arg0;\r
+ pi._arg3 = (unsigned char)i._arg1;\r
+ return;\r
+ }\r
+ break;\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
+ 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,SQInteger len)\r
+{\r
+ SQObjectPtr ns(SQString::Create(_sharedstate,s,len));\r
+ _table(_strings)->NewSlot(ns,(SQInteger)1);\r
+ return ns;\r
+}\r
+\r
+SQObject SQFuncState::CreateTable()\r
+{\r
+ SQObjectPtr nt(SQTable::Create(_sharedstate,0));\r
+ _table(_strings)->NewSlot(nt,(SQInteger)1);\r
+ return nt;\r
+}\r
+\r
+SQFunctionProto *SQFuncState::BuildProto()\r
+{\r
+ SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(),\r
+ _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),\r
+ _lineinfos.size(),_localvarinfos.size(),_defaultparams.size());\r
+\r
+ SQObjectPtr refidx,key,val;\r
+ SQInteger idx;\r
+\r
+ f->_stacksize = _stacksize;\r
+ f->_sourcename = _sourcename;\r
+ f->_bgenerator = _bgenerator;\r
+ f->_name = _name;\r
+\r
+ while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {\r
+ f->_literals[_integer(val)]=key;\r
+ refidx=idx;\r
+ }\r
+\r
+ for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];\r
+ for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];\r
+ for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];\r
+ for(SQUnsignedInteger no = 0; no < _localvarinfos.size(); no++) f->_localvarinfos[no] = _localvarinfos[no];\r
+ for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no];\r
+ for(SQUnsignedInteger no = 0; no < _defaultparams.size(); no++) f->_defaultparams[no] = _defaultparams[no];\r
+\r
+ memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));\r
+\r
+ f->_varparams = _varparams;\r
+\r
+ return f;\r
+}\r
+\r
+SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)\r
+{\r
+ SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));\r
+ new (child) SQFuncState(ss,this,_errfunc,_errtarget);\r
+ _childstates.push_back(child);\r
+ return child;\r
+}\r
+\r
+void SQFuncState::PopChildState()\r
+{\r
+ SQFuncState *child = _childstates.back();\r
+ sq_delete(child,SQFuncState);\r
+ _childstates.pop_back();\r
+}\r
+\r
+SQFuncState::~SQFuncState()\r
+{\r
+ while(_childstates.size() > 0)\r
+ {\r
+ PopChildState();\r
+ }\r
+}\r
-/* see copyright notice in squirrel.h */
-#ifndef _SQFUNCSTATE_H_
-#define _SQFUNCSTATE_H_
-///////////////////////////////////
-#include "squtils.h"
-
-struct SQFuncState
-{
- SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed);
- ~SQFuncState();
-#ifdef _DEBUG_DUMP
- void Dump(SQFunctionProto *func);
-#endif
- void Error(const SQChar *err);
- SQFuncState *PushChildState(SQSharedState *ss);
- void PopChildState();
- void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}
- void AddInstruction(SQInstruction &i);
- void SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2=0,SQInteger arg3=0);
- void SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val);
- SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];}
- void PopInstructions(SQInteger size){for(SQInteger i=0;i<size;i++)_instructions.pop_back();}
- void SetStackSize(SQInteger n);
- void SnoozeOpt(){_optimization=false;}
- void AddDefaultParam(SQInteger trg) { _defaultparams.push_back(trg); }
- SQInteger GetDefaultParamCount() { return _defaultparams.size(); }
- SQInteger GetCurrentPos(){return _instructions.size()-1;}
- SQInteger GetNumericConstant(const SQInteger cons);
- SQInteger GetNumericConstant(const SQFloat cons);
- SQInteger PushLocalVariable(const SQObject &name);
- void AddParameter(const SQObject &name);
- void AddOuterValue(const SQObject &name);
- SQInteger GetLocalVariable(const SQObject &name);
- SQInteger GetOuterVariable(const SQObject &name);
- SQInteger GenerateCode();
- SQInteger GetStackSize();
- SQInteger CalcStackFrameSize();
- void AddLineInfos(SQInteger line,bool lineop,bool force=false);
- SQFunctionProto *BuildProto();
- SQInteger AllocStackPos();
- SQInteger PushTarget(SQInteger n=-1);
- SQInteger PopTarget();
- SQInteger TopTarget();
- SQInteger GetUpTarget(SQInteger n);
- bool IsLocal(SQUnsignedInteger stkpos);
- SQObject CreateString(const SQChar *s,SQInteger len = -1);
- SQObject CreateTable();
- bool IsConstant(const SQObject &name,SQObject &e);
- SQInteger _returnexp;
- SQLocalVarInfoVec _vlocals;
- SQIntVec _targetstack;
- SQInteger _stacksize;
- bool _varparams;
- bool _bgenerator;
- SQIntVec _unresolvedbreaks;
- SQIntVec _unresolvedcontinues;
- SQObjectPtrVec _functions;
- SQObjectPtrVec _parameters;
- SQOuterVarVec _outervalues;
- SQInstructionVec _instructions;
- SQLocalVarInfoVec _localvarinfos;
- SQObjectPtr _literals;
- SQObjectPtr _strings;
- SQObjectPtr _name;
- SQObjectPtr _sourcename;
- SQInteger _nliterals;
- SQLineInfoVec _lineinfos;
- SQFuncState *_parent;
- SQIntVec _breaktargets;
- SQIntVec _continuetargets;
- SQIntVec _defaultparams;
- SQInteger _lastline;
- SQInteger _traps; //contains number of nested exception traps
- bool _optimization;
- SQSharedState *_sharedstate;
- sqvector<SQFuncState*> _childstates;
- SQInteger GetConstant(const SQObject &cons);
-private:
- CompilerErrorFunc _errfunc;
- void *_errtarget;
-};
-
-
-#endif //_SQFUNCSTATE_H_
-
+/* see copyright notice in squirrel.h */\r
+#ifndef _SQFUNCSTATE_H_\r
+#define _SQFUNCSTATE_H_\r
+///////////////////////////////////\r
+#include "squtils.h"\r
+\r
+struct SQFuncState\r
+{\r
+ SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed);\r
+ ~SQFuncState();\r
+#ifdef _DEBUG_DUMP\r
+ void Dump(SQFunctionProto *func);\r
+#endif\r
+ void Error(const SQChar *err);\r
+ SQFuncState *PushChildState(SQSharedState *ss);\r
+ void PopChildState();\r
+ void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}\r
+ void AddInstruction(SQInstruction &i);\r
+ void SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2=0,SQInteger arg3=0);\r
+ void SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val);\r
+ SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];}\r
+ void PopInstructions(SQInteger size){for(SQInteger i=0;i<size;i++)_instructions.pop_back();}\r
+ void SetStackSize(SQInteger n);\r
+ void SnoozeOpt(){_optimization=false;}\r
+ void AddDefaultParam(SQInteger trg) { _defaultparams.push_back(trg); }\r
+ SQInteger GetDefaultParamCount() { return _defaultparams.size(); }\r
+ SQInteger GetCurrentPos(){return _instructions.size()-1;}\r
+ SQInteger GetNumericConstant(const SQInteger cons);\r
+ SQInteger GetNumericConstant(const SQFloat cons);\r
+ SQInteger PushLocalVariable(const SQObject &name);\r
+ void AddParameter(const SQObject &name);\r
+ void AddOuterValue(const SQObject &name);\r
+ SQInteger GetLocalVariable(const SQObject &name);\r
+ SQInteger GetOuterVariable(const SQObject &name);\r
+ SQInteger GenerateCode();\r
+ SQInteger GetStackSize();\r
+ SQInteger CalcStackFrameSize();\r
+ void AddLineInfos(SQInteger line,bool lineop,bool force=false);\r
+ SQFunctionProto *BuildProto();\r
+ SQInteger AllocStackPos();\r
+ SQInteger PushTarget(SQInteger n=-1);\r
+ SQInteger PopTarget();\r
+ SQInteger TopTarget();\r
+ SQInteger GetUpTarget(SQInteger n);\r
+ bool IsLocal(SQUnsignedInteger stkpos);\r
+ SQObject CreateString(const SQChar *s,SQInteger len = -1);\r
+ SQObject CreateTable();\r
+ bool IsConstant(const SQObject &name,SQObject &e);\r
+ SQInteger _returnexp;\r
+ SQLocalVarInfoVec _vlocals;\r
+ SQIntVec _targetstack;\r
+ SQInteger _stacksize;\r
+ bool _varparams;\r
+ bool _bgenerator;\r
+ SQIntVec _unresolvedbreaks;\r
+ SQIntVec _unresolvedcontinues;\r
+ SQObjectPtrVec _functions;\r
+ SQObjectPtrVec _parameters;\r
+ SQOuterVarVec _outervalues;\r
+ SQInstructionVec _instructions;\r
+ SQLocalVarInfoVec _localvarinfos;\r
+ SQObjectPtr _literals;\r
+ SQObjectPtr _strings;\r
+ SQObjectPtr _name;\r
+ SQObjectPtr _sourcename;\r
+ SQInteger _nliterals;\r
+ SQLineInfoVec _lineinfos;\r
+ SQFuncState *_parent;\r
+ SQIntVec _breaktargets;\r
+ SQIntVec _continuetargets;\r
+ SQIntVec _defaultparams;\r
+ SQInteger _lastline;\r
+ SQInteger _traps; //contains number of nested exception traps\r
+ bool _optimization;\r
+ SQSharedState *_sharedstate;\r
+ sqvector<SQFuncState*> _childstates;\r
+ SQInteger GetConstant(const SQObject &cons);\r
+private:\r
+ CompilerErrorFunc _errfunc;\r
+ void *_errtarget;\r
+};\r
+\r
+\r
+#endif //_SQFUNCSTATE_H_\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,CompilerErrorFunc efunc,void *ed)
-{
- _errfunc = efunc;
- _errtarget = ed;
- _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);
- ADD_KEYWORD(static,TK_STATIC);
- ADD_KEYWORD(enum,TK_ENUM);
- ADD_KEYWORD(const,TK_CONST);
-
- _readf = rg;
- _up = up;
- _lasttokenline = _currentline = 1;
- _currentcolumn = 0;
- _prevtoken = -1;
- Next();
-}
-
-void SQLexer::Error(const SQChar *err)
-{
- _errfunc(_errtarget,err);
-}
-
-void SQLexer::Next()
-{
- SQInteger t = _readf(_up);
- if(t > MAX_CHAR) Error(_SC("Invalid character"));
- if(t != 0) {
- _currdata = (LexChar)t;
- return;
- }
- _currdata = SQUIRREL_EOB;
-}
-
-const SQChar *SQLexer::Tok2Str(SQInteger tok)
-{
- SQObjectPtr itr, key, val;
- SQInteger nitr;
- while((nitr = _keywords->Next(false,itr, key, val)) != -1) {
- itr = (SQInteger)nitr;
- if(((SQInteger)_integer(val)) == tok)
- return _stringval(key);
- }
- return NULL;
-}
-
-void SQLexer::LexBlockComment()
-{
- bool done = false;
- while(!done) {
- switch(CUR_CHAR) {
- case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;
- case _SC('\n'): _currentline++; NEXT(); continue;
- case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment"));
- default: NEXT();
- }
- }
-}
-
-SQInteger 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('@'): {
- SQInteger stype;
- NEXT();
- if(CUR_CHAR != _SC('"'))
- Error(_SC("string expected"));
- if((stype=ReadString('"',true))!=-1) {
- RETURN_TOKEN(stype);
- }
- Error(_SC("error parsing the string"));
- }
- case _SC('"'):
- case _SC('\''): {
- SQInteger stype;
- if((stype=ReadString(CUR_CHAR,false))!=-1){
- RETURN_TOKEN(stype);
- }
- Error(_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('~'):
- {SQInteger ret = CUR_CHAR;
- NEXT(); RETURN_TOKEN(ret); }
- case _SC('.'):
- NEXT();
- if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') }
- NEXT();
- if (CUR_CHAR != _SC('.')){ Error(_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)) {
- SQInteger ret = ReadNumber();
- RETURN_TOKEN(ret);
- }
- else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {
- SQInteger t = ReadID();
- RETURN_TOKEN(t);
- }
- else {
- SQInteger c = CUR_CHAR;
- if (sciscntrl((int)c)) Error(_SC("unexpected character(control)"));
- NEXT();
- RETURN_TOKEN(c);
- }
- RETURN_TOKEN(0);
- }
- }
- }
- return 0;
-}
-
-SQInteger SQLexer::GetIDType(SQChar *s)
-{
- SQObjectPtr t;
- if(_keywords->Get(SQString::Create(_sharedstate, s), t)) {
- return SQInteger(_integer(t));
- }
- return TK_IDENTIFIER;
-}
-
-
-SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim)
-{
- INIT_TEMP_STRING();
- NEXT();
- if(IS_EOB()) return -1;
- for(;;) {
- while(CUR_CHAR != ndelim) {
- switch(CUR_CHAR) {
- case SQUIRREL_EOB:
- Error(_SC("unfinished string"));
- return -1;
- case _SC('\n'):
- if(!verbatim) Error(_SC("newline in a constant"));
- APPEND_CHAR(CUR_CHAR); NEXT();
- _currentline++;
- break;
- case _SC('\\'):
- if(verbatim) {
- APPEND_CHAR('\\'); NEXT();
- }
- else {
- NEXT();
- switch(CUR_CHAR) {
- case _SC('x'): NEXT(); {
- if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected"));
- const SQInteger maxdigits = 4;
- SQChar temp[maxdigits+1];
- SQInteger n = 0;
- while(isxdigit(CUR_CHAR) && n < maxdigits) {
- temp[n] = CUR_CHAR;
- n++;
- NEXT();
- }
- temp[n] = 0;
- SQChar *sTemp;
- APPEND_CHAR((SQChar)scstrtoul(temp,&sTemp,16));
- }
- break;
- 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:
- Error(_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();
- SQInteger len = _longstr.size()-1;
- if(ndelim == _SC('\'')) {
- if(len == 0) Error(_SC("empty constant"));
- if(len > 1) Error(_SC("constant too long"));
- _nvalue = _longstr[0];
- return TK_INTEGER;
- }
- _svalue = &_longstr[0];
- return TK_STRING_LITERAL;
-}
-
-void LexHexadecimal(const SQChar *s,SQUnsignedInteger *res)
-{
- *res = 0;
- while(*s != 0)
- {
- if(scisdigit(*s)) *res = (*res)*16+((*s++)-'0');
- else if(scisxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10);
- else { assert(0); }
- }
-}
-
-void LexInteger(const SQChar *s,SQUnsignedInteger *res)
-{
- *res = 0;
- while(*s != 0)
- {
- *res = (*res)*10+((*s++)-'0');
- }
-}
-
-SQInteger scisodigit(SQInteger c) { return c >= _SC('0') && c <= _SC('7'); }
-
-void LexOctal(const SQChar *s,SQUnsignedInteger *res)
-{
- *res = 0;
- while(*s != 0)
- {
- if(scisodigit(*s)) *res = (*res)*8+((*s++)-'0');
- else { assert(0); }
- }
-}
-
-SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; }
-
-
-#define MAX_HEX_DIGITS (sizeof(SQInteger)*2)
-SQInteger SQLexer::ReadNumber()
-{
-#define TINT 1
-#define TFLOAT 2
-#define THEX 3
-#define TSCIENTIFIC 4
-#define TOCTAL 5
- SQInteger type = TINT, firstchar = CUR_CHAR;
- SQChar *sTemp;
- INIT_TEMP_STRING();
- NEXT();
- if(firstchar == _SC('0') && (toupper(CUR_CHAR) == _SC('X') || scisodigit(CUR_CHAR)) ) {
- if(scisodigit(CUR_CHAR)) {
- type = TOCTAL;
- while(scisodigit(CUR_CHAR)) {
- APPEND_CHAR(CUR_CHAR);
- NEXT();
- }
- if(scisdigit(CUR_CHAR)) Error(_SC("invalid octal number"));
- }
- else {
- NEXT();
- type = THEX;
- while(isxdigit(CUR_CHAR)) {
- APPEND_CHAR(CUR_CHAR);
- NEXT();
- }
- if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number"));
- }
- }
- else {
- APPEND_CHAR((int)firstchar);
- while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) {
- if(CUR_CHAR == _SC('.')) type = TFLOAT;
- if(isexponent(CUR_CHAR)) {
- if(type != TFLOAT) Error(_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)) Error(_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:
- LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
- return TK_INTEGER;
- case THEX:
- LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
- return TK_INTEGER;
- case TOCTAL:
- LexOctal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);
- return TK_INTEGER;
- }
- return 0;
-}
-
-SQInteger SQLexer::ReadID()
-{
- SQInteger res;
- 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 || res == TK_CONSTRUCTOR) {
- _svalue = &_longstr[0];
- }
- return res;
-}
+/*\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,CompilerErrorFunc efunc,void *ed)\r
+{\r
+ _errfunc = efunc;\r
+ _errtarget = ed;\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
+ ADD_KEYWORD(static,TK_STATIC);\r
+ ADD_KEYWORD(enum,TK_ENUM);\r
+ ADD_KEYWORD(const,TK_CONST);\r
+\r
+ _readf = rg;\r
+ _up = up;\r
+ _lasttokenline = _currentline = 1;\r
+ _currentcolumn = 0;\r
+ _prevtoken = -1;\r
+ Next();\r
+}\r
+\r
+void SQLexer::Error(const SQChar *err)\r
+{\r
+ _errfunc(_errtarget,err);\r
+}\r
+\r
+void SQLexer::Next()\r
+{\r
+ SQInteger t = _readf(_up);\r
+ if(t > MAX_CHAR) Error(_SC("Invalid character"));\r
+ if(t != 0) {\r
+ _currdata = (LexChar)t;\r
+ return;\r
+ }\r
+ _currdata = SQUIRREL_EOB;\r
+}\r
+\r
+const SQChar *SQLexer::Tok2Str(SQInteger tok)\r
+{\r
+ SQObjectPtr itr, key, val;\r
+ SQInteger nitr;\r
+ while((nitr = _keywords->Next(false,itr, key, val)) != -1) {\r
+ itr = (SQInteger)nitr;\r
+ if(((SQInteger)_integer(val)) == tok)\r
+ return _stringval(key);\r
+ }\r
+ return NULL;\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('\n'): _currentline++; NEXT(); continue;\r
+ case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment"));\r
+ default: NEXT();\r
+ }\r
+ }\r
+}\r
+\r
+SQInteger 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
+ SQInteger stype;\r
+ NEXT(); \r
+ if(CUR_CHAR != _SC('"'))\r
+ Error(_SC("string expected"));\r
+ if((stype=ReadString('"',true))!=-1) {\r
+ RETURN_TOKEN(stype);\r
+ }\r
+ Error(_SC("error parsing the string"));\r
+ }\r
+ case _SC('"'):\r
+ case _SC('\''): {\r
+ SQInteger stype;\r
+ if((stype=ReadString(CUR_CHAR,false))!=-1){\r
+ RETURN_TOKEN(stype);\r
+ }\r
+ Error(_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
+ {SQInteger 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('.')){ Error(_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
+ SQInteger ret = ReadNumber();\r
+ RETURN_TOKEN(ret);\r
+ }\r
+ else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {\r
+ SQInteger t = ReadID();\r
+ RETURN_TOKEN(t);\r
+ }\r
+ else {\r
+ SQInteger c = CUR_CHAR;\r
+ if (sciscntrl((int)c)) Error(_SC("unexpected character(control)"));\r
+ NEXT();\r
+ RETURN_TOKEN(c); \r
+ }\r
+ RETURN_TOKEN(0);\r
+ }\r
+ }\r
+ }\r
+ return 0; \r
+}\r
+ \r
+SQInteger SQLexer::GetIDType(SQChar *s)\r
+{\r
+ SQObjectPtr t;\r
+ if(_keywords->Get(SQString::Create(_sharedstate, s), t)) {\r
+ return SQInteger(_integer(t));\r
+ }\r
+ return TK_IDENTIFIER;\r
+}\r
+\r
+\r
+SQInteger SQLexer::ReadString(SQInteger 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
+ Error(_SC("unfinished string"));\r
+ return -1;\r
+ case _SC('\n'): \r
+ if(!verbatim) Error(_SC("newline in a constant")); \r
+ APPEND_CHAR(CUR_CHAR); NEXT(); \r
+ _currentline++;\r
+ break;\r
+ case _SC('\\'):\r
+ if(verbatim) {\r
+ APPEND_CHAR('\\'); NEXT(); \r
+ }\r
+ else {\r
+ NEXT();\r
+ switch(CUR_CHAR) {\r
+ case _SC('x'): NEXT(); {\r
+ if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected")); \r
+ const SQInteger maxdigits = 4;\r
+ SQChar temp[maxdigits+1];\r
+ SQInteger n = 0;\r
+ while(isxdigit(CUR_CHAR) && n < maxdigits) {\r
+ temp[n] = CUR_CHAR;\r
+ n++;\r
+ NEXT();\r
+ }\r
+ temp[n] = 0;\r
+ SQChar *sTemp;\r
+ APPEND_CHAR((SQChar)scstrtoul(temp,&sTemp,16));\r
+ }\r
+ break;\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
+ Error(_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
+ SQInteger len = _longstr.size()-1;\r
+ if(ndelim == _SC('\'')) {\r
+ if(len == 0) Error(_SC("empty constant"));\r
+ if(len > 1) Error(_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
+void LexHexadecimal(const SQChar *s,SQUnsignedInteger *res)\r
+{\r
+ *res = 0;\r
+ while(*s != 0)\r
+ {\r
+ if(scisdigit(*s)) *res = (*res)*16+((*s++)-'0');\r
+ else if(scisxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10);\r
+ else { assert(0); }\r
+ }\r
+}\r
+\r
+void LexInteger(const SQChar *s,SQUnsignedInteger *res)\r
+{\r
+ *res = 0;\r
+ while(*s != 0)\r
+ {\r
+ *res = (*res)*10+((*s++)-'0');\r
+ }\r
+}\r
+\r
+SQInteger scisodigit(SQInteger c) { return c >= _SC('0') && c <= _SC('7'); }\r
+\r
+void LexOctal(const SQChar *s,SQUnsignedInteger *res)\r
+{\r
+ *res = 0;\r
+ while(*s != 0)\r
+ {\r
+ if(scisodigit(*s)) *res = (*res)*8+((*s++)-'0');\r
+ else { assert(0); }\r
+ }\r
+}\r
+\r
+SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; }\r
+\r
+\r
+#define MAX_HEX_DIGITS (sizeof(SQInteger)*2)\r
+SQInteger SQLexer::ReadNumber()\r
+{\r
+#define TINT 1\r
+#define TFLOAT 2\r
+#define THEX 3\r
+#define TSCIENTIFIC 4\r
+#define TOCTAL 5\r
+ SQInteger type = TINT, firstchar = CUR_CHAR;\r
+ SQChar *sTemp;\r
+ INIT_TEMP_STRING();\r
+ NEXT();\r
+ if(firstchar == _SC('0') && (toupper(CUR_CHAR) == _SC('X') || scisodigit(CUR_CHAR)) ) {\r
+ if(scisodigit(CUR_CHAR)) {\r
+ type = TOCTAL;\r
+ while(scisodigit(CUR_CHAR)) {\r
+ APPEND_CHAR(CUR_CHAR);\r
+ NEXT();\r
+ }\r
+ if(scisdigit(CUR_CHAR)) Error(_SC("invalid octal number"));\r
+ }\r
+ else {\r
+ NEXT();\r
+ type = THEX;\r
+ while(isxdigit(CUR_CHAR)) {\r
+ APPEND_CHAR(CUR_CHAR);\r
+ NEXT();\r
+ }\r
+ if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number"));\r
+ }\r
+ }\r
+ else {\r
+ APPEND_CHAR((int)firstchar);\r
+ while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) {\r
+ if(CUR_CHAR == _SC('.') || isexponent(CUR_CHAR)) type = TFLOAT;\r
+ if(isexponent(CUR_CHAR)) {\r
+ if(type != TFLOAT) Error(_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)) Error(_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
+ LexInteger(&_longstr[0],(SQUnsignedInteger *)&_nvalue);\r
+ return TK_INTEGER;\r
+ case THEX:\r
+ LexHexadecimal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);\r
+ return TK_INTEGER;\r
+ case TOCTAL:\r
+ LexOctal(&_longstr[0],(SQUnsignedInteger *)&_nvalue);\r
+ return TK_INTEGER;\r
+ }\r
+ return 0;\r
+}\r
+\r
+SQInteger SQLexer::ReadID()\r
+{\r
+ SQInteger res;\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 || res == TK_CONSTRUCTOR) {\r
+ _svalue = &_longstr[0];\r
+ }\r
+ return res;\r
+}\r
-/* see copyright notice in squirrel.h */
-#ifndef _SQLEXER_H_
-#define _SQLEXER_H_
-
-#ifdef SQUNICODE
-typedef SQChar LexChar;
-#else
-typedef unsigned char LexChar;
-#endif
-
-struct SQLexer
-{
- SQLexer();
- ~SQLexer();
- void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up,CompilerErrorFunc efunc,void *ed);
- void Error(const SQChar *err);
- SQInteger Lex();
- const SQChar *Tok2Str(SQInteger tok);
-private:
- SQInteger GetIDType(SQChar *s);
- SQInteger ReadString(SQInteger ndelim,bool verbatim);
- SQInteger ReadNumber();
- void LexBlockComment();
- SQInteger ReadID();
- void Next();
- SQInteger _curtoken;
- SQTable *_keywords;
-public:
- SQInteger _prevtoken;
- SQInteger _currentline;
- SQInteger _lasttokenline;
- SQInteger _currentcolumn;
- const SQChar *_svalue;
- SQInteger _nvalue;
- SQFloat _fvalue;
- SQLEXREADFUNC _readf;
- SQUserPointer _up;
- LexChar _currdata;
- SQSharedState *_sharedstate;
- sqvector<SQChar> _longstr;
- CompilerErrorFunc _errfunc;
- void *_errtarget;
-};
-
-#endif
+/* see copyright notice in squirrel.h */\r
+#ifndef _SQLEXER_H_\r
+#define _SQLEXER_H_\r
+\r
+#ifdef SQUNICODE\r
+typedef SQChar LexChar;\r
+#else\r
+typedef unsigned char LexChar;\r
+#endif\r
+\r
+struct SQLexer\r
+{\r
+ SQLexer();\r
+ ~SQLexer();\r
+ void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up,CompilerErrorFunc efunc,void *ed);\r
+ void Error(const SQChar *err);\r
+ SQInteger Lex();\r
+ const SQChar *Tok2Str(SQInteger tok);\r
+private:\r
+ SQInteger GetIDType(SQChar *s);\r
+ SQInteger ReadString(SQInteger ndelim,bool verbatim);\r
+ SQInteger ReadNumber();\r
+ void LexBlockComment();\r
+ SQInteger ReadID();\r
+ void Next();\r
+ SQInteger _curtoken;\r
+ SQTable *_keywords;\r
+public:\r
+ SQInteger _prevtoken;\r
+ SQInteger _currentline;\r
+ SQInteger _lasttokenline;\r
+ SQInteger _currentcolumn;\r
+ const SQChar *_svalue;\r
+ SQInteger _nvalue;\r
+ SQFloat _fvalue;\r
+ SQLEXREADFUNC _readf;\r
+ SQUserPointer _up;\r
+ LexChar _currdata;\r
+ SQSharedState *_sharedstate;\r
+ sqvector<SQChar> _longstr;\r
+ CompilerErrorFunc _errfunc;\r
+ void *_errtarget;\r
+};\r
+\r
+#endif\r
-/*
- see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-void *sq_vm_malloc(SQUnsignedInteger size){ return malloc(size); }
-
-void *sq_vm_realloc(void *p, SQUnsignedInteger oldsize, SQUnsignedInteger size){ return realloc(p, size); }
-
-void sq_vm_free(void *p, SQUnsignedInteger size){ free(p); }
+/*\r
+ see copyright notice in squirrel.h\r
+*/\r
+#include "sqpcheader.h"\r
+void *sq_vm_malloc(SQUnsignedInteger size){ return malloc(size); }\r
+\r
+void *sq_vm_realloc(void *p, SQUnsignedInteger oldsize, SQUnsignedInteger size){ return realloc(p, size); }\r
+\r
+void sq_vm_free(void *p, SQUnsignedInteger size){ free(p); }\r
+++ /dev/null
-/* see copyright notice in squirrel.h */
-#ifndef _SQMEM_H_
-#define _SQMEM_H_
-
-void *sq_vm_malloc(SQUnsignedInteger size);
-void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size);
-void sq_vm_free(void *p,SQUnsignedInteger size);
-#endif //_SQMEM_H_
-/*
- 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"
-
-
-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");
- case _RT_WEAKREF: return _SC("weakref");
- default:
- return NULL;
- }
-}
-
-const SQChar *GetTypeName(const SQObjectPtr &obj1)
-{
- return IdType2Name(type(obj1));
-}
-
-SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)
-{
- SQString *str=ADD_STRING(ss,s,len);
- str->_sharedstate=ss;
- return str;
-}
-
-void SQString::Release()
-{
- REMOVE_STRING(_sharedstate,this);
-}
-
-SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
-{
- SQInteger idx = (SQInteger)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;
-}
-
-SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx)
-{
- switch(type(idx)){
- case OT_NULL:
- return 0;
- case OT_INTEGER:
- return (SQUnsignedInteger)_integer(idx);
- default: assert(0); break;
- }
- return 0;
-}
-
-SQWeakRef *SQRefCounted::GetWeakRef(SQObjectType type)
-{
- if(!_weakref) {
- sq_new(_weakref,SQWeakRef);
- _weakref->_obj._type = type;
- _weakref->_obj._unVal.pRefCounted = this;
- }
- return _weakref;
-}
-
-SQRefCounted::~SQRefCounted()
-{
- if(_weakref) {
- _weakref->_obj._type = OT_NULL;
- _weakref->_obj._unVal.pRefCounted = NULL;
- }
-}
-
-void SQWeakRef::Release() {
- if(ISREFCOUNTED(_obj._type)) {
- _obj._unVal.pRefCounted->_weakref = NULL;
- }
- sq_delete(this,SQWeakRef);
-}
-
-bool SQDelegable::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) {
- if(_delegate) {
- return _delegate->Get((*_ss(v)->_metamethods)[mm],res);
- }
- return false;
-}
-
-bool SQDelegable::SetDelegate(SQTable *mt)
-{
- SQTable *temp = mt;
- if(temp == this) return false;
- while (temp) {
- if (temp->_delegate == this) return false; //cycle detected
- temp = temp->_delegate;
- }
- if (mt) __ObjAddRef(mt);
- __ObjRelease(_delegate);
- _delegate = mt;
- return true;
-}
-
-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; }
- SQInteger size = v->_top-v->_stackbase;
- _ci=*v->ci;
- _stack.resize(size);
- for(SQInteger n =0; n<size; n++) {
- _stack._vals[n] = v->_stack[v->_stackbase+n];
- v->_stack[v->_stackbase+n] = _null_;
- }
- SQInteger nvargs = v->ci->_vargs.size;
- SQInteger vargsbase = v->ci->_vargs.base;
- for(SQInteger j = nvargs - 1; j >= 0; j--) {
- _vargsstack.push_back(v->_vargsstack[vargsbase+j]);
- }
- _ci._generator=NULL;
- for(SQInteger 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,SQInteger target)
-{
- SQInteger 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; }
- SQInteger prevtop=v->_top-v->_stackbase;
- PUSH_CALLINFO(v,_ci);
- SQInteger oldstackbase=v->_stackbase;
- v->_stackbase = v->_top;
- v->ci->_target = (SQInt32)target;
- v->ci->_generator = this;
- v->ci->_vargs.size = (unsigned short)_vargsstack.size();
-
- for(SQInteger i=0;i<_ci._etraps;i++) {
- v->_etraps.push_back(_etraps.top());
- _etraps.pop_back();
- }
- for(SQInteger 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 = (unsigned short)(v->_vargsstack.size() - v->ci->_vargs.size);
- v->_top=v->_stackbase+size;
- v->ci->_prevtop = (SQInt32)prevtop;
- v->ci->_prevstkbase = (SQInt32)(v->_stackbase - oldstackbase);
- _state=eRunning;
- if (type(v->_debughook) != OT_NULL && _rawval(v->_debughook) != _rawval(v->ci->_closure))
- v->CallDebugHook(_SC('c'));
-
- return true;
-}
-
-void SQArray::Extend(const SQArray *a){
- SQInteger xlen;
- if((xlen=a->Size()))
- for(SQInteger i=0;i<xlen;i++)
- Append(a->_values[i]);
-}
-
-const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop)
-{
- SQUnsignedInteger nvars=_nlocalvarinfos;
- const SQChar *res=NULL;
- if(nvars>=nseq){
- for(SQUnsignedInteger 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;
-}
-
-SQInteger SQFunctionProto::GetLine(SQInstruction *curr)
-{
- SQInteger op = (SQInteger)(curr-_instructions);
- SQInteger line=_lineinfos[0]._line;
- for(SQInteger i=1;i<_nlineinfos;i++){
- if(_lineinfos[i]._op>=op)
- return line;
- line=_lineinfos[i]._line;
- }
- return line;
-}
-
-#define _CHECK_IO(exp) { if(!exp)return false; }
-bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger 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,SQInteger 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,SQInteger tag)
-{
- return SafeWrite(v,write,up,&tag,sizeof(tag));
-}
-
-bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag)
-{
- SQInteger 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:{
- SQInteger 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,SQObjectPtr &ret)
-{
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));
- _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));
- SQObjectPtr func;
- _CHECK_IO(SQFunctionProto::Load(v,up,read,func));
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));
- ret = SQClosure::Create(_ss(v),_funcproto(func));
- return true;
-}
-
-bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
-{
- SQInteger i,nliterals = _nliterals,nparameters = _nparameters;
- SQInteger noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos;
- SQInteger nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions;
- SQInteger ndefaultparams = _ndefaultparams;
- _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,&nliterals,sizeof(nliterals)));
- _CHECK_IO(SafeWrite(v,write,up,&nparameters,sizeof(nparameters)));
- _CHECK_IO(SafeWrite(v,write,up,&noutervalues,sizeof(noutervalues)));
- _CHECK_IO(SafeWrite(v,write,up,&nlocalvarinfos,sizeof(nlocalvarinfos)));
- _CHECK_IO(SafeWrite(v,write,up,&nlineinfos,sizeof(nlineinfos)));
- _CHECK_IO(SafeWrite(v,write,up,&ndefaultparams,sizeof(ndefaultparams)));
- _CHECK_IO(SafeWrite(v,write,up,&ninstructions,sizeof(ninstructions)));
- _CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions)));
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- for(i=0;i<nliterals;i++){
- _CHECK_IO(WriteObject(v,up,write,_literals[i]));
- }
-
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- for(i=0;i<nparameters;i++){
- _CHECK_IO(WriteObject(v,up,write,_parameters[i]));
- }
-
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- for(i=0;i<noutervalues;i++){
- _CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(SQUnsignedInteger)));
- _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));
- for(i=0;i<nlocalvarinfos;i++){
- SQLocalVarInfo &lvi=_localvarinfos[i];
- _CHECK_IO(WriteObject(v,up,write,lvi._name));
- _CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(SQUnsignedInteger)));
- _CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(SQUnsignedInteger)));
- _CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(SQUnsignedInteger)));
- }
-
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- _CHECK_IO(SafeWrite(v,write,up,_lineinfos,sizeof(SQLineInfo)*nlineinfos));
-
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- _CHECK_IO(SafeWrite(v,write,up,_defaultparams,sizeof(SQInteger)*ndefaultparams));
-
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- _CHECK_IO(SafeWrite(v,write,up,_instructions,sizeof(SQInstruction)*ninstructions));
-
- _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
- for(i=0;i<nfunctions;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,SQObjectPtr &ret)
-{
- SQInteger i, nliterals,nparameters;
- SQInteger noutervalues ,nlocalvarinfos ;
- SQInteger nlineinfos,ninstructions ,nfunctions,ndefaultparams ;
- SQObjectPtr sourcename, name;
- 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, &nliterals, sizeof(nliterals)));
- _CHECK_IO(SafeRead(v,read,up, &nparameters, sizeof(nparameters)));
- _CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues)));
- _CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos)));
- _CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos)));
- _CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams)));
- _CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions)));
- _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));
-
-
- SQFunctionProto *f = SQFunctionProto::Create(ninstructions,nliterals,nparameters,
- nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);
- SQObjectPtr proto = f; //gets a ref in case of failure
- f->_sourcename = sourcename;
- f->_name = name;
-
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-
- for(i = 0;i < nliterals; i++){
- _CHECK_IO(ReadObject(v, up, read, o));
- f->_literals[i] = o;
- }
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-
- for(i = 0; i < nparameters; i++){
- _CHECK_IO(ReadObject(v, up, read, o));
- f->_parameters[i] = o;
- }
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-
- for(i = 0; i < noutervalues; i++){
- SQUnsignedInteger type;
- SQObjectPtr name;
- _CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger)));
- _CHECK_IO(ReadObject(v, up, read, o));
- _CHECK_IO(ReadObject(v, up, read, name));
- f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type);
- }
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-
- for(i = 0; i < nlocalvarinfos; i++){
- SQLocalVarInfo lvi;
- _CHECK_IO(ReadObject(v, up, read, lvi._name));
- _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(SQUnsignedInteger)));
- _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(SQUnsignedInteger)));
- _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(SQUnsignedInteger)));
- f->_localvarinfos[i] = lvi;
- }
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
- _CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(SQLineInfo)*nlineinfos));
-
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
- _CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(SQInteger)*ndefaultparams));
-
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
- _CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(SQInstruction)*ninstructions));
-
- _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
- for(i = 0; i < nfunctions; i++){
- _CHECK_IO(_funcproto(o)->Load(v, up, read, o));
- f->_functions[i] = o;
- }
- _CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize)));
- _CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator)));
- _CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams)));
-
- ret = f;
- 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(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
- for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);
- for(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain);
- END_MARK()
-}
-
-void SQArray::Mark(SQCollectable **chain)
-{
- START_MARK()
- SQInteger len = _values.size();
- for(SQInteger i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain);
- END_MARK()
-}
-void SQTable::Mark(SQCollectable **chain)
-{
- START_MARK()
- if(_delegate) _delegate->Mark(chain);
- SQInteger len = _numofnodes;
- for(SQInteger 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(SQUnsignedInteger i =0; i< _defaultvalues.size(); i++) {
- SQSharedState::MarkObject(_defaultvalues[i].val, chain);
- SQSharedState::MarkObject(_defaultvalues[i].attrs, chain);
- }
- for(SQUnsignedInteger j =0; j< _methods.size(); j++) {
- SQSharedState::MarkObject(_methods[j].val, chain);
- SQSharedState::MarkObject(_methods[j].attrs, chain);
- }
- for(SQUnsignedInteger k =0; k< _metamethods.size(); k++) {
- SQSharedState::MarkObject(_metamethods[k], chain);
- }
- END_MARK()
-}
-
-void SQInstance::Mark(SQCollectable **chain)
-{
- START_MARK()
- _class->Mark(chain);
- SQUnsignedInteger nvalues = _class->_defaultvalues.size();
- for(SQUnsignedInteger i =0; i< nvalues; i++) {
- SQSharedState::MarkObject(_values[i], chain);
- }
- END_MARK()
-}
-
-void SQGenerator::Mark(SQCollectable **chain)
-{
- START_MARK()
- for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
- for(SQUnsignedInteger 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(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);
- for(SQUnsignedInteger i = 0; i < _defaultparams.size(); i++) SQSharedState::MarkObject(_defaultparams[i], chain);
- END_MARK()
-}
-
-void SQNativeClosure::Mark(SQCollectable **chain)
-{
- START_MARK()
- for(SQUnsignedInteger 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
-
+/*\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
+\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
+ case _RT_WEAKREF: return _SC("weakref");\r
+ default:\r
+ return NULL;\r
+ }\r
+}\r
+\r
+const SQChar *GetTypeName(const SQObjectPtr &obj1)\r
+{\r
+ return IdType2Name(type(obj1)); \r
+}\r
+\r
+SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger 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
+SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)\r
+{\r
+ SQInteger idx = (SQInteger)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
+SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx)\r
+{\r
+ switch(type(idx)){\r
+ case OT_NULL:\r
+ return 0;\r
+ case OT_INTEGER:\r
+ return (SQUnsignedInteger)_integer(idx);\r
+ default: assert(0); break;\r
+ }\r
+ return 0;\r
+}\r
+\r
+SQWeakRef *SQRefCounted::GetWeakRef(SQObjectType type)\r
+{\r
+ if(!_weakref) {\r
+ sq_new(_weakref,SQWeakRef);\r
+ _weakref->_obj._type = type;\r
+ _weakref->_obj._unVal.pRefCounted = this;\r
+ }\r
+ return _weakref;\r
+}\r
+\r
+SQRefCounted::~SQRefCounted()\r
+{\r
+ if(_weakref) {\r
+ _weakref->_obj._type = OT_NULL;\r
+ _weakref->_obj._unVal.pRefCounted = NULL;\r
+ }\r
+}\r
+\r
+void SQWeakRef::Release() { \r
+ if(ISREFCOUNTED(_obj._type)) { \r
+ _obj._unVal.pRefCounted->_weakref = NULL;\r
+ } \r
+ sq_delete(this,SQWeakRef);\r
+}\r
+\r
+bool SQDelegable::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) {\r
+ if(_delegate) {\r
+ return _delegate->Get((*_ss(v)->_metamethods)[mm],res);\r
+ }\r
+ return false;\r
+}\r
+\r
+bool SQDelegable::SetDelegate(SQTable *mt)\r
+{\r
+ SQTable *temp = mt;\r
+ if(temp == this) return false;\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 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
+ SQInteger size = v->_top-v->_stackbase;\r
+ _ci=*v->ci;\r
+ _stack.resize(size);\r
+ for(SQInteger n =0; n<size; n++) {\r
+ _stack._vals[n] = v->_stack[v->_stackbase+n];\r
+ v->_stack[v->_stackbase+n] = _null_;\r
+ }\r
+ SQInteger nvargs = v->ci->_vargs.size;\r
+ SQInteger vargsbase = v->ci->_vargs.base;\r
+ for(SQInteger j = nvargs - 1; j >= 0; j--) {\r
+ _vargsstack.push_back(v->_vargsstack[vargsbase+j]);\r
+ }\r
+ _ci._generator=NULL;\r
+ for(SQInteger 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,SQInteger target)\r
+{\r
+ SQInteger 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
+ SQInteger prevtop=v->_top-v->_stackbase;\r
+ PUSH_CALLINFO(v,_ci);\r
+ SQInteger oldstackbase=v->_stackbase;\r
+ v->_stackbase = v->_top;\r
+ v->ci->_target = (SQInt32)target;\r
+ v->ci->_generator = this;\r
+ v->ci->_vargs.size = (unsigned short)_vargsstack.size();\r
+ \r
+ for(SQInteger i=0;i<_ci._etraps;i++) {\r
+ v->_etraps.push_back(_etraps.top());\r
+ _etraps.pop_back();\r
+ }\r
+ for(SQInteger 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 = (unsigned short)(v->_vargsstack.size() - v->ci->_vargs.size);\r
+ v->_top=v->_stackbase+size;\r
+ v->ci->_prevtop = (SQInt32)prevtop;\r
+ v->ci->_prevstkbase = (SQInt32)(v->_stackbase - oldstackbase);\r
+ _state=eRunning;\r
+ if (type(v->_debughook) != OT_NULL && _rawval(v->_debughook) != _rawval(v->ci->_closure))\r
+ v->CallDebugHook(_SC('c'));\r
+\r
+ return true;\r
+}\r
+\r
+void SQArray::Extend(const SQArray *a){\r
+ SQInteger xlen;\r
+ if((xlen=a->Size()))\r
+ for(SQInteger i=0;i<xlen;i++)\r
+ Append(a->_values[i]);\r
+}\r
+\r
+const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop)\r
+{\r
+ SQUnsignedInteger nvars=_nlocalvarinfos;\r
+ const SQChar *res=NULL; \r
+ if(nvars>=nseq){\r
+ for(SQUnsignedInteger 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
+SQInteger SQFunctionProto::GetLine(SQInstruction *curr)\r
+{\r
+ SQInteger op = (SQInteger)(curr-_instructions);\r
+ SQInteger line=_lineinfos[0]._line;\r
+ for(SQInteger i=1;i<_nlineinfos;i++){\r
+ if(_lineinfos[i]._op>=op)\r
+ return line;\r
+ line=_lineinfos[i]._line;\r
+ }\r
+ return line;\r
+}\r
+\r
+#define _CHECK_IO(exp) { if(!exp)return false; }\r
+bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger 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,SQInteger 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,SQInteger tag)\r
+{\r
+ return SafeWrite(v,write,up,&tag,sizeof(tag));\r
+}\r
+\r
+bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag)\r
+{\r
+ SQInteger 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
+ SQInteger 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,SQObjectPtr &ret)\r
+{\r
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));\r
+ _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));\r
+ SQObjectPtr func;\r
+ _CHECK_IO(SQFunctionProto::Load(v,up,read,func));\r
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));\r
+ ret = SQClosure::Create(_ss(v),_funcproto(func));\r
+ return true;\r
+}\r
+\r
+bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)\r
+{\r
+ SQInteger i,nliterals = _nliterals,nparameters = _nparameters;\r
+ SQInteger noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos;\r
+ SQInteger nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions;\r
+ SQInteger ndefaultparams = _ndefaultparams;\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,&nliterals,sizeof(nliterals)));\r
+ _CHECK_IO(SafeWrite(v,write,up,&nparameters,sizeof(nparameters)));\r
+ _CHECK_IO(SafeWrite(v,write,up,&noutervalues,sizeof(noutervalues)));\r
+ _CHECK_IO(SafeWrite(v,write,up,&nlocalvarinfos,sizeof(nlocalvarinfos)));\r
+ _CHECK_IO(SafeWrite(v,write,up,&nlineinfos,sizeof(nlineinfos)));\r
+ _CHECK_IO(SafeWrite(v,write,up,&ndefaultparams,sizeof(ndefaultparams)));\r
+ _CHECK_IO(SafeWrite(v,write,up,&ninstructions,sizeof(ninstructions)));\r
+ _CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions)));\r
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+ for(i=0;i<nliterals;i++){\r
+ _CHECK_IO(WriteObject(v,up,write,_literals[i]));\r
+ }\r
+\r
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+ for(i=0;i<nparameters;i++){\r
+ _CHECK_IO(WriteObject(v,up,write,_parameters[i]));\r
+ }\r
+\r
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+ for(i=0;i<noutervalues;i++){\r
+ _CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(SQUnsignedInteger)));\r
+ _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));\r
+ _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));\r
+ }\r
+\r
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+ for(i=0;i<nlocalvarinfos;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(SQUnsignedInteger)));\r
+ _CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(SQUnsignedInteger)));\r
+ _CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(SQUnsignedInteger)));\r
+ }\r
+\r
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+ _CHECK_IO(SafeWrite(v,write,up,_lineinfos,sizeof(SQLineInfo)*nlineinfos));\r
+\r
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+ _CHECK_IO(SafeWrite(v,write,up,_defaultparams,sizeof(SQInteger)*ndefaultparams));\r
+\r
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+ _CHECK_IO(SafeWrite(v,write,up,_instructions,sizeof(SQInstruction)*ninstructions));\r
+\r
+ _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));\r
+ for(i=0;i<nfunctions;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,SQObjectPtr &ret)\r
+{\r
+ SQInteger i, nliterals,nparameters;\r
+ SQInteger noutervalues ,nlocalvarinfos ;\r
+ SQInteger nlineinfos,ninstructions ,nfunctions,ndefaultparams ;\r
+ SQObjectPtr sourcename, name;\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
+ \r
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+ _CHECK_IO(SafeRead(v,read,up, &nliterals, sizeof(nliterals)));\r
+ _CHECK_IO(SafeRead(v,read,up, &nparameters, sizeof(nparameters)));\r
+ _CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues)));\r
+ _CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos)));\r
+ _CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos)));\r
+ _CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams)));\r
+ _CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions)));\r
+ _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));\r
+ \r
+\r
+ SQFunctionProto *f = SQFunctionProto::Create(ninstructions,nliterals,nparameters,\r
+ nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);\r
+ SQObjectPtr proto = f; //gets a ref in case of failure\r
+ f->_sourcename = sourcename;\r
+ f->_name = name;\r
+\r
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+\r
+ for(i = 0;i < nliterals; i++){\r
+ _CHECK_IO(ReadObject(v, up, read, o));\r
+ f->_literals[i] = o;\r
+ }\r
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+\r
+ for(i = 0; i < nparameters; i++){\r
+ _CHECK_IO(ReadObject(v, up, read, o));\r
+ f->_parameters[i] = o;\r
+ }\r
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+\r
+ for(i = 0; i < noutervalues; i++){\r
+ SQUnsignedInteger type;\r
+ SQObjectPtr name;\r
+ _CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger)));\r
+ _CHECK_IO(ReadObject(v, up, read, o));\r
+ _CHECK_IO(ReadObject(v, up, read, name));\r
+ f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type);\r
+ }\r
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+\r
+ for(i = 0; i < nlocalvarinfos; i++){\r
+ SQLocalVarInfo lvi;\r
+ _CHECK_IO(ReadObject(v, up, read, lvi._name));\r
+ _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(SQUnsignedInteger)));\r
+ _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(SQUnsignedInteger)));\r
+ _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(SQUnsignedInteger)));\r
+ f->_localvarinfos[i] = lvi;\r
+ }\r
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+ _CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(SQLineInfo)*nlineinfos));\r
+\r
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+ _CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(SQInteger)*ndefaultparams));\r
+\r
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+ _CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(SQInstruction)*ninstructions));\r
+\r
+ _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));\r
+ for(i = 0; i < nfunctions; i++){\r
+ _CHECK_IO(_funcproto(o)->Load(v, up, read, o));\r
+ f->_functions[i] = o;\r
+ }\r
+ _CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize)));\r
+ _CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator)));\r
+ _CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams)));\r
+ \r
+ ret = f;\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(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
+ for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain);\r
+ for(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain);\r
+ END_MARK()\r
+}\r
+\r
+void SQArray::Mark(SQCollectable **chain)\r
+{\r
+ START_MARK()\r
+ SQInteger len = _values.size();\r
+ for(SQInteger 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
+ SQInteger len = _numofnodes;\r
+ for(SQInteger 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(SQUnsignedInteger i =0; i< _defaultvalues.size(); i++) {\r
+ SQSharedState::MarkObject(_defaultvalues[i].val, chain);\r
+ SQSharedState::MarkObject(_defaultvalues[i].attrs, chain);\r
+ }\r
+ for(SQUnsignedInteger j =0; j< _methods.size(); j++) {\r
+ SQSharedState::MarkObject(_methods[j].val, chain);\r
+ SQSharedState::MarkObject(_methods[j].attrs, chain);\r
+ }\r
+ for(SQUnsignedInteger 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
+ SQUnsignedInteger nvalues = _class->_defaultvalues.size();\r
+ for(SQUnsignedInteger i =0; i< nvalues; 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(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);\r
+ for(SQUnsignedInteger 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(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain);\r
+ for(SQUnsignedInteger i = 0; i < _defaultparams.size(); i++) SQSharedState::MarkObject(_defaultparams[i], chain);\r
+ END_MARK()\r
+}\r
+\r
+void SQNativeClosure::Mark(SQCollectable **chain)\r
+{\r
+ START_MARK()\r
+ for(SQUnsignedInteger 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 */
-#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'))
-
-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_TOSTRING=15,
- MT_NEWMEMBER=16,
- MT_INHERITED=17,
- MT_LAST = 18
-};
-
-#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 MM_TOSTRING _SC("_tostring")
-#define MM_NEWMEMBER _SC("_newmember")
-#define MM_INHERITED _SC("_inherited")
-
-#define MINPOWER2 4
-
-struct SQRefCounted
-{
- SQRefCounted() { _uiRef = 0; _weakref = NULL; }
- virtual ~SQRefCounted();
- SQWeakRef *GetWeakRef(SQObjectType type);
- SQUnsignedInteger _uiRef;
- struct SQWeakRef *_weakref;
- virtual void Release()=0;
-};
-
-struct SQWeakRef : SQRefCounted
-{
- void Release();
- SQObject _obj;
-};
-
-#define _realval(o) (type((o)) != OT_WEAKREF?(SQObject)o:_weakref(o)->_obj)
-
-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 _weakref(obj) ((obj)._unVal.pWeakRef)
-#define _refcounted(obj) ((obj)._unVal.pRefCounted)
-#define _rawval(obj) ((obj)._unVal.raw)
-
-#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()
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_NULL;
- _unVal.pUserPointer=NULL;
- }
- SQObjectPtr(const SQObjectPtr &o)
- {
- SQ_OBJECT_RAWINIT()
- _type=o._type;
- _unVal=o._unVal;
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(const SQObject &o)
- {
- SQ_OBJECT_RAWINIT()
- _type=o._type;
- _unVal=o._unVal;
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQTable *pTable)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_TABLE;
- _unVal.pTable=pTable;
- assert(_unVal.pTable);
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQClass *pClass)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_CLASS;
- _unVal.pClass=pClass;
- assert(_unVal.pClass);
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQInstance *pInstance)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_INSTANCE;
- _unVal.pInstance=pInstance;
- assert(_unVal.pInstance);
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQArray *pArray)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_ARRAY;
- _unVal.pArray=pArray;
- assert(_unVal.pArray);
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQClosure *pClosure)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_CLOSURE;
- _unVal.pClosure=pClosure;
- assert(_unVal.pClosure);
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQGenerator *pGenerator)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_GENERATOR;
- _unVal.pGenerator=pGenerator;
- assert(_unVal.pGenerator);
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQNativeClosure *pNativeClosure)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_NATIVECLOSURE;
- _unVal.pNativeClosure=pNativeClosure;
- assert(_unVal.pNativeClosure);
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQString *pString)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_STRING;
- _unVal.pString=pString;
- assert(_unVal.pString);
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQUserData *pUserData)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_USERDATA;
- _unVal.pUserData=pUserData;
- assert(_unVal.pUserData);
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQVM *pThread)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_THREAD;
- _unVal.pThread=pThread;
- assert(_unVal.pThread);
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQWeakRef *pWeakRef)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_WEAKREF;
- _unVal.pWeakRef=pWeakRef;
- assert(_unVal.pWeakRef);
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQFunctionProto *pFunctionProto)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_FUNCPROTO;
- _unVal.pFunctionProto=pFunctionProto;
- assert(_unVal.pFunctionProto);
- __AddRef(_type,_unVal);
- }
- SQObjectPtr(SQInteger nInteger)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_INTEGER;
- _unVal.nInteger=nInteger;
- }
- SQObjectPtr(SQFloat fFloat)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_FLOAT;
- _unVal.fFloat=fFloat;
- }
- SQObjectPtr(bool bBool)
- {
- SQ_OBJECT_RAWINIT()
- _type = OT_BOOL;
- _unVal.nInteger = bBool?1:0;
- }
- SQObjectPtr(SQUserPointer pUserPointer)
- {
- SQ_OBJECT_RAWINIT()
- _type=OT_USERPOINTER;
- _unVal.pUserPointer=pUserPointer;
- }
- ~SQObjectPtr()
- {
- __Release(_type,_unVal);
- }
- inline void Null()
- {
- SQObjectType tOldType;
- SQObjectValue unOldVal;
- tOldType = _type;
- unOldVal = _unVal;
- _type = OT_NULL;
- _unVal.pUserPointer = NULL;
- __Release(tOldType,unOldVal);
- }
- inline SQObjectPtr& operator=(SQInteger i)
- {
- __Release(_type,_unVal);
- _unVal.nInteger = i;
- _type = OT_INTEGER;
- return *this;
- }
- inline SQObjectPtr& operator=(SQFloat f)
- {
- __Release(_type,_unVal);
- _unVal.fFloat = f;
- _type = OT_FLOAT;
- return *this;
- }
- inline 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;
- }
- inline 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 {
- bool SetDelegate(SQTable *m);
- virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);
- SQTable *_delegate;
-};
-
-SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx);
-typedef sqvector<SQObjectPtr> SQObjectPtrVec;
-typedef sqvector<SQInteger> SQIntVec;
-const SQChar *GetTypeName(const SQObjectPtr &obj1);
-const SQChar *IdType2Name(SQObjectType type);
-
-
-
-#endif //_SQOBJECT_H_
+/* 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
+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_TOSTRING=15,\r
+ MT_NEWMEMBER=16,\r
+ MT_INHERITED=17,\r
+ MT_LAST = 18\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
+#define MM_TOSTRING _SC("_tostring")\r
+#define MM_NEWMEMBER _SC("_newmember")\r
+#define MM_INHERITED _SC("_inherited")\r
+\r
+#define MINPOWER2 4\r
+\r
+struct SQRefCounted\r
+{\r
+ SQRefCounted() { _uiRef = 0; _weakref = NULL; }\r
+ virtual ~SQRefCounted();\r
+ SQWeakRef *GetWeakRef(SQObjectType type);\r
+ SQUnsignedInteger _uiRef;\r
+ struct SQWeakRef *_weakref;\r
+ virtual void Release()=0;\r
+};\r
+\r
+struct SQWeakRef : SQRefCounted\r
+{\r
+ void Release();\r
+ SQObject _obj;\r
+};\r
+\r
+#define _realval(o) (type((o)) != OT_WEAKREF?(SQObject)o:_weakref(o)->_obj)\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 _weakref(obj) ((obj)._unVal.pWeakRef)\r
+#define _refcounted(obj) ((obj)._unVal.pRefCounted)\r
+#define _rawval(obj) ((obj)._unVal.raw)\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
+/////////////////////////////////////////////////////////////////////////////////////\r
+struct SQObjectPtr : public SQObject\r
+{\r
+ SQObjectPtr()\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_NULL;\r
+ _unVal.pUserPointer=NULL;\r
+ }\r
+ SQObjectPtr(const SQObjectPtr &o)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=o._type;\r
+ _unVal=o._unVal;\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(const SQObject &o)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=o._type;\r
+ _unVal=o._unVal;\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQTable *pTable)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_TABLE;\r
+ _unVal.pTable=pTable;\r
+ assert(_unVal.pTable);\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQClass *pClass)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_CLASS;\r
+ _unVal.pClass=pClass;\r
+ assert(_unVal.pClass);\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQInstance *pInstance)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_INSTANCE;\r
+ _unVal.pInstance=pInstance;\r
+ assert(_unVal.pInstance);\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQArray *pArray)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_ARRAY;\r
+ _unVal.pArray=pArray;\r
+ assert(_unVal.pArray);\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQClosure *pClosure)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_CLOSURE;\r
+ _unVal.pClosure=pClosure;\r
+ assert(_unVal.pClosure);\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQGenerator *pGenerator)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_GENERATOR;\r
+ _unVal.pGenerator=pGenerator;\r
+ assert(_unVal.pGenerator);\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQNativeClosure *pNativeClosure)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_NATIVECLOSURE;\r
+ _unVal.pNativeClosure=pNativeClosure;\r
+ assert(_unVal.pNativeClosure);\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQString *pString)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_STRING;\r
+ _unVal.pString=pString;\r
+ assert(_unVal.pString);\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQUserData *pUserData)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_USERDATA;\r
+ _unVal.pUserData=pUserData;\r
+ assert(_unVal.pUserData);\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQVM *pThread)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_THREAD;\r
+ _unVal.pThread=pThread;\r
+ assert(_unVal.pThread);\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQWeakRef *pWeakRef)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_WEAKREF;\r
+ _unVal.pWeakRef=pWeakRef;\r
+ assert(_unVal.pWeakRef);\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQFunctionProto *pFunctionProto)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_FUNCPROTO;\r
+ _unVal.pFunctionProto=pFunctionProto;\r
+ assert(_unVal.pFunctionProto);\r
+ __AddRef(_type,_unVal);\r
+ }\r
+ SQObjectPtr(SQInteger nInteger)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_INTEGER;\r
+ _unVal.nInteger=nInteger;\r
+ }\r
+ SQObjectPtr(SQFloat fFloat)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_FLOAT;\r
+ _unVal.fFloat=fFloat;\r
+ }\r
+ SQObjectPtr(bool bBool)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type = OT_BOOL;\r
+ _unVal.nInteger = bBool?1:0;\r
+ }\r
+ SQObjectPtr(SQUserPointer pUserPointer)\r
+ {\r
+ SQ_OBJECT_RAWINIT()\r
+ _type=OT_USERPOINTER;\r
+ _unVal.pUserPointer=pUserPointer;\r
+ }\r
+ ~SQObjectPtr()\r
+ {\r
+ __Release(_type,_unVal);\r
+ }\r
+ inline void Null()\r
+ {\r
+ SQObjectType tOldType;\r
+ SQObjectValue unOldVal;\r
+ tOldType = _type;\r
+ unOldVal = _unVal;\r
+ _type = OT_NULL;\r
+ _unVal.pUserPointer = NULL;\r
+ __Release(tOldType,unOldVal);\r
+ }\r
+ inline SQObjectPtr& operator=(SQInteger i)\r
+ { \r
+ __Release(_type,_unVal);\r
+ SQ_OBJECT_RAWINIT()\r
+ _unVal.nInteger = i;\r
+ _type = OT_INTEGER;\r
+ return *this;\r
+ }\r
+ inline SQObjectPtr& operator=(SQFloat f)\r
+ { \r
+ __Release(_type,_unVal);\r
+ SQ_OBJECT_RAWINIT()\r
+ _unVal.fFloat = f;\r
+ _type = OT_FLOAT;\r
+ return *this;\r
+ }\r
+ inline 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
+ inline 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
+inline void _Swap(SQObject &a,SQObject &b)\r
+{\r
+ SQObjectType tOldType = a._type;\r
+ SQObjectValue unOldVal = a._unVal;\r
+ a._type = b._type;\r
+ a._unVal = b._unVal;\r
+ b._type = tOldType;\r
+ b._unVal = unOldVal;\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
+ bool SetDelegate(SQTable *m);\r
+ virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);\r
+ SQTable *_delegate;\r
+};\r
+\r
+SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx);\r
+typedef sqvector<SQObjectPtr> SQObjectPtrVec;\r
+typedef sqvector<SQInteger> SQIntVec;\r
+const SQChar *GetTypeName(const SQObjectPtr &obj1);\r
+const SQChar *IdType2Name(SQObjectType type);\r
+\r
+\r
+\r
+#endif //_SQOBJECT_H_\r
-/* see copyright notice in squirrel.h */
-#ifndef _SQOPCODES_H_
-#define _SQOPCODES_H_
-
-#define MAX_FUNC_STACKSIZE 0xFF
-#define MAX_LITERALS ((SQInteger)0x7FFFFFFF)
-
-enum BitWiseOP {
- BW_AND = 0,
- BW_OR = 2,
- BW_XOR = 3,
- BW_SHIFTL = 4,
- BW_SHIFTR = 5,
- BW_USHIFTR = 6
-};
-
-enum CmpOP {
- CMP_G = 0,
- CMP_GE = 2,
- CMP_L = 3,
- CMP_LE = 4
-};
-enum SQOpcode
-{
- _OP_LINE= 0x00,
- _OP_LOAD= 0x01,
- _OP_LOADINT= 0x02,
- _OP_LOADFLOAT= 0x03,
- _OP_DLOAD= 0x04,
- _OP_TAILCALL= 0x05,
- _OP_CALL= 0x06,
- _OP_PREPCALL= 0x07,
- _OP_PREPCALLK= 0x08,
- _OP_GETK= 0x09,
- _OP_MOVE= 0x0A,
- _OP_NEWSLOT= 0x0B,
- _OP_DELETE= 0x0C,
- _OP_SET= 0x0D,
- _OP_GET= 0x0E,
- _OP_EQ= 0x0F,
- _OP_NE= 0x10,
- _OP_ARITH= 0x11,
- _OP_BITW= 0x12,
- _OP_RETURN= 0x13,
- _OP_LOADNULLS= 0x14,
- _OP_LOADROOTTABLE= 0x15,
- _OP_LOADBOOL= 0x16,
- _OP_DMOVE= 0x17,
- _OP_JMP= 0x18,
- _OP_JNZ= 0x19,
- _OP_JZ= 0x1A,
- _OP_LOADFREEVAR= 0x1B,
- _OP_VARGC= 0x1C,
- _OP_GETVARGV= 0x1D,
- _OP_NEWTABLE= 0x1E,
- _OP_NEWARRAY= 0x1F,
- _OP_APPENDARRAY= 0x20,
- _OP_GETPARENT= 0x21,
- _OP_COMPARITH= 0x22,
- _OP_COMPARITHL= 0x23,
- _OP_INC= 0x24,
- _OP_INCL= 0x25,
- _OP_PINC= 0x26,
- _OP_PINCL= 0x27,
- _OP_CMP= 0x28,
- _OP_EXISTS= 0x29,
- _OP_INSTANCEOF= 0x2A,
- _OP_AND= 0x2B,
- _OP_OR= 0x2C,
- _OP_NEG= 0x2D,
- _OP_NOT= 0x2E,
- _OP_BWNOT= 0x2F,
- _OP_CLOSURE= 0x30,
- _OP_YIELD= 0x31,
- _OP_RESUME= 0x32,
- _OP_FOREACH= 0x33,
- _OP_POSTFOREACH= 0x34,
- _OP_DELEGATE= 0x35,
- _OP_CLONE= 0x36,
- _OP_TYPEOF= 0x37,
- _OP_PUSHTRAP= 0x38,
- _OP_POPTRAP= 0x39,
- _OP_THROW= 0x3A,
- _OP_CLASS= 0x3B,
- _OP_NEWSLOTA= 0x3C,
-};
-
-struct SQInstructionDesc {
- const SQChar *name;
-};
-
-struct SQInstruction
-{
- SQInstruction(){};
- SQInstruction(SQOpcode _op,SQInteger a0=0,SQInteger a1=0,SQInteger a2=0,SQInteger a3=0)
- { op = _op;
- _arg0 = (unsigned char)a0;_arg1 = (SQInt32)a1;
- _arg2 = (unsigned char)a2;_arg3 = (unsigned char)a3;
- }
-
-
- SQInt32 _arg1;
- unsigned char op;
- unsigned char _arg0;
- unsigned char _arg2;
- unsigned char _arg3;
-};
-
-#include "squtils.h"
-typedef sqvector<SQInstruction> SQInstructionVec;
-
-#define NEW_SLOT_ATTRIBUTES_FLAG 0x01
-#define NEW_SLOT_STATIC_FLAG 0x02
-
-#endif // _SQOPCODES_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 ((SQInteger)0x7FFFFFFF)\r
+\r
+enum BitWiseOP {\r
+ BW_AND = 0,\r
+ BW_OR = 2, \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, \r
+ CMP_L = 3,\r
+ CMP_LE = 4\r
+};\r
+enum SQOpcode\r
+{\r
+ _OP_LINE= 0x00, \r
+ _OP_LOAD= 0x01,\r
+ _OP_LOADINT= 0x02,\r
+ _OP_LOADFLOAT= 0x03,\r
+ _OP_DLOAD= 0x04,\r
+ _OP_TAILCALL= 0x05, \r
+ _OP_CALL= 0x06, \r
+ _OP_PREPCALL= 0x07, \r
+ _OP_PREPCALLK= 0x08, \r
+ _OP_GETK= 0x09, \r
+ _OP_MOVE= 0x0A, \r
+ _OP_NEWSLOT= 0x0B, \r
+ _OP_DELETE= 0x0C, \r
+ _OP_SET= 0x0D, \r
+ _OP_GET= 0x0E,\r
+ _OP_EQ= 0x0F,\r
+ _OP_NE= 0x10,\r
+ _OP_ARITH= 0x11,\r
+ _OP_BITW= 0x12,\r
+ _OP_RETURN= 0x13, \r
+ _OP_LOADNULLS= 0x14, \r
+ _OP_LOADROOTTABLE= 0x15,\r
+ _OP_LOADBOOL= 0x16,\r
+ _OP_DMOVE= 0x17, \r
+ _OP_JMP= 0x18, \r
+ _OP_JNZ= 0x19, \r
+ _OP_JZ= 0x1A, \r
+ _OP_LOADFREEVAR= 0x1B, \r
+ _OP_VARGC= 0x1C, \r
+ _OP_GETVARGV= 0x1D, \r
+ _OP_NEWTABLE= 0x1E, \r
+ _OP_NEWARRAY= 0x1F, \r
+ _OP_APPENDARRAY= 0x20, \r
+ _OP_GETPARENT= 0x21, \r
+ _OP_COMPARITH= 0x22, \r
+ _OP_COMPARITHL= 0x23, \r
+ _OP_INC= 0x24, \r
+ _OP_INCL= 0x25, \r
+ _OP_PINC= 0x26, \r
+ _OP_PINCL= 0x27, \r
+ _OP_CMP= 0x28,\r
+ _OP_EXISTS= 0x29, \r
+ _OP_INSTANCEOF= 0x2A,\r
+ _OP_AND= 0x2B,\r
+ _OP_OR= 0x2C,\r
+ _OP_NEG= 0x2D,\r
+ _OP_NOT= 0x2E,\r
+ _OP_BWNOT= 0x2F, \r
+ _OP_CLOSURE= 0x30, \r
+ _OP_YIELD= 0x31, \r
+ _OP_RESUME= 0x32,\r
+ _OP_FOREACH= 0x33,\r
+ _OP_POSTFOREACH= 0x34,\r
+ _OP_DELEGATE= 0x35,\r
+ _OP_CLONE= 0x36,\r
+ _OP_TYPEOF= 0x37,\r
+ _OP_PUSHTRAP= 0x38,\r
+ _OP_POPTRAP= 0x39,\r
+ _OP_THROW= 0x3A,\r
+ _OP_CLASS= 0x3B,\r
+ _OP_NEWSLOTA= 0x3C,\r
+}; \r
+\r
+struct SQInstructionDesc { \r
+ const SQChar *name; \r
+}; \r
+\r
+struct SQInstruction \r
+{\r
+ SQInstruction(){};\r
+ SQInstruction(SQOpcode _op,SQInteger a0=0,SQInteger a1=0,SQInteger a2=0,SQInteger a3=0)\r
+ { op = _op;\r
+ _arg0 = (unsigned char)a0;_arg1 = (SQInt32)a1;\r
+ _arg2 = (unsigned char)a2;_arg3 = (unsigned char)a3;\r
+ }\r
+ \r
+ \r
+ SQInt32 _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
+#define NEW_SLOT_ATTRIBUTES_FLAG 0x01\r
+#define NEW_SLOT_STATIC_FLAG 0x02\r
+\r
+#endif // _SQOPCODES_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_
+/* 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
-*/
-#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_((SQInteger)1);
-SQObjectPtr _minusone_((SQInteger)-1);
-
-SQSharedState::SQSharedState()
-{
- _compilererrorhandler = NULL;
- _printfunc = NULL;
- _debuginfo = false;
- _notifyallexceptions = 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)
-{
- SQInteger i = 0;
-
- SQInteger mask = 0;
- while(typemask[i] != 0) {
-
- switch(typemask[i]){
- case 'o': mask |= _RT_NULL; break;
- 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 'r': mask |= _RT_WEAKREF; 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)
-{
- SQInteger 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);
- newmetamethod(MM_TOSTRING);
- newmetamethod(MM_NEWMEMBER);
- newmetamethod(MM_INHERITED);
-
- _constructoridx = SQString::Create(this,_SC("constructor"));
- _registry = SQTable::Create(this,0);
- _consts = 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);
- _weakref_default_delegate = CreateDefaultDelegate(this,_weakref_default_delegate_funcz);
-
-}
-
-SQSharedState::~SQSharedState()
-{
- _constructoridx = _null_;
- _table(_registry)->Finalize();
- _table(_consts)->Finalize();
- _table(_metamethodsmap)->Finalize();
- _registry = _null_;
- _consts = _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_;
- _weakref_default_delegate = _null_;
- _refs_table.Finalize();
-#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; //shutup compiler
- }
-}
-
-
-SQInteger SQSharedState::CollectGarbage(SQVM *vm)
-{
- SQInteger n=0;
- SQCollectable *tchain=NULL;
- SQVM *vms = _thread(_root_vm);
-
- vms->Mark(&tchain);
- SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed();
- _refs_table.Mark(&tchain);
- MarkObject(_registry,&tchain);
- MarkObject(_consts,&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);
- MarkObject(_weakref_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;
- SQInteger 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(SQInteger size)
-{
- SQInteger 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;
-}
-
-RefTable::RefTable()
-{
- AllocNodes(4);
-}
-
-void RefTable::Finalize()
-{
- RefNode *nodes = _nodes;
- for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
- nodes->obj = _null_;
- nodes++;
- }
-}
-
-RefTable::~RefTable()
-{
- SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode)));
-}
-
-#ifndef NO_GARBAGE_COLLECTOR
-void RefTable::Mark(SQCollectable **chain)
-{
- RefNode *nodes = (RefNode *)_nodes;
- for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
- if(type(nodes->obj) != OT_NULL) {
- SQSharedState::MarkObject(nodes->obj,chain);
- }
- nodes++;
- }
-}
-#endif
-
-void RefTable::AddRef(SQObject &obj)
-{
- SQHash mainpos;
- RefNode *prev;
- RefNode *ref = Get(obj,mainpos,&prev,true);
- ref->refs++;
-}
-
-SQBool RefTable::Release(SQObject &obj)
-{
- SQHash mainpos;
- RefNode *prev;
- RefNode *ref = Get(obj,mainpos,&prev,false);
- if(ref) {
- if(--ref->refs == 0) {
- SQObjectPtr o = ref->obj;
- if(prev) {
- prev->next = ref->next;
- }
- else {
- _buckets[mainpos] = ref->next;
- }
- ref->next = _freelist;
- _freelist = ref;
- _slotused--;
- ref->obj = _null_;
- //<<FIXME>>test for shrink?
- return SQTrue;
- }
- }
- else {
- assert(0);
- }
- return SQFalse;
-}
-
-void RefTable::Resize(SQUnsignedInteger size)
-{
- RefNode **oldbucks = _buckets;
- RefNode *t = _nodes;
- SQUnsignedInteger oldnumofslots = _numofslots;
- AllocNodes(size);
- //rehash
- SQUnsignedInteger nfound = 0;
- for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {
- if(type(t->obj) != OT_NULL) {
- //add back;
- assert(t->refs != 0);
- RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj);
- nn->refs = t->refs;
- t->obj = _null_;
- nfound++;
- }
- t++;
- }
- assert(nfound == oldnumofslots);
- SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode)));
-}
-
-RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj)
-{
- RefNode *t = _buckets[mainpos];
- RefNode *newnode = _freelist;
- newnode->obj = obj;
- _buckets[mainpos] = newnode;
- _freelist = _freelist->next;
- newnode->next = t;
- assert(newnode->refs == 0);
- _slotused++;
- return newnode;
-}
-
-RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add)
-{
- RefNode *ref;
- mainpos = ::HashObj(obj)&(_numofslots-1);
- *prev = NULL;
- for (ref = _buckets[mainpos]; ref; ) {
- if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj))
- break;
- *prev = ref;
- ref = ref->next;
- }
- if(ref == NULL && add) {
- if(_numofslots == _slotused) {
- assert(_freelist == 0);
- Resize(_numofslots*2);
- mainpos = ::HashObj(obj)&(_numofslots-1);
- }
- ref = Add(mainpos,obj);
- }
- return ref;
-}
-
-void RefTable::AllocNodes(SQUnsignedInteger size)
-{
- RefNode **bucks;
- RefNode *nodes;
- bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode)));
- nodes = (RefNode *)&bucks[size];
- RefNode *temp = nodes;
- SQUnsignedInteger n;
- for(n = 0; n < size - 1; n++) {
- bucks[n] = NULL;
- temp->refs = 0;
- new (&temp->obj) SQObjectPtr;
- temp->next = temp+1;
- temp++;
- }
- bucks[n] = NULL;
- temp->refs = 0;
- new (&temp->obj) SQObjectPtr;
- temp->next = NULL;
- _freelist = nodes;
- _nodes = nodes;
- _buckets = bucks;
- _slotused = 0;
- _numofslots = size;
-}
-//////////////////////////////////////////////////////////////////////////
-//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
-*/
-
-StringTable::StringTable()
-{
- AllocNodes(4);
- _slotused = 0;
-}
-
-StringTable::~StringTable()
-{
- SQ_FREE(_strings,sizeof(SQString*)*_numofslots);
- _strings = NULL;
-}
-
-void StringTable::AllocNodes(SQInteger size)
-{
- _numofslots = size;
- _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
- memset(_strings,0,sizeof(SQString*)*_numofslots);
-}
-
-SQString *StringTable::Add(const SQChar *news,SQInteger len)
-{
- if(len<0)
- len = (SQInteger)scstrlen(news);
- SQHash 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];
- _strings[h] = t;
- _slotused++;
- if (_slotused > _numofslots) /* too crowded? */
- Resize(_numofslots*2);
- return t;
-}
-
-void StringTable::Resize(SQInteger size)
-{
- SQInteger oldsize=_numofslots;
- SQString **oldtable=_strings;
- AllocNodes(size);
- for (SQInteger i=0; i<oldsize; i++){
- SQString *p = oldtable[i];
- while(p){
- SQString *next = p->_next;
- SQHash 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;
- SQHash 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--;
- SQInteger 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
-}
+/*\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_((SQInteger)1);\r
+SQObjectPtr _minusone_((SQInteger)-1);\r
+\r
+SQSharedState::SQSharedState()\r
+{\r
+ _compilererrorhandler = NULL;\r
+ _printfunc = NULL;\r
+ _debuginfo = false;\r
+ _notifyallexceptions = 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
+ SQInteger i = 0;\r
+ \r
+ SQInteger mask = 0;\r
+ while(typemask[i] != 0) {\r
+ \r
+ switch(typemask[i]){\r
+ case 'o': mask |= _RT_NULL; break;\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 'r': mask |= _RT_WEAKREF; 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
+ SQInteger 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,SQStringTable);\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
+ newmetamethod(MM_TOSTRING);\r
+ newmetamethod(MM_NEWMEMBER);\r
+ newmetamethod(MM_INHERITED);\r
+\r
+ _constructoridx = SQString::Create(this,_SC("constructor"));\r
+ _registry = SQTable::Create(this,0);\r
+ _consts = 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
+ _weakref_default_delegate = CreateDefaultDelegate(this,_weakref_default_delegate_funcz);\r
+\r
+}\r
+\r
+SQSharedState::~SQSharedState()\r
+{\r
+ _constructoridx = _null_;\r
+ _table(_registry)->Finalize();\r
+ _table(_consts)->Finalize();\r
+ _table(_metamethodsmap)->Finalize();\r
+ _registry = _null_;\r
+ _consts = _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
+ _weakref_default_delegate = _null_;\r
+ _refs_table.Finalize();\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+ SQCollectable *t = _gc_chain;\r
+ SQCollectable *nx = NULL;\r
+ if(t) {\r
+ t->_uiRef++;\r
+ while(t) {\r
+ t->Finalize();\r
+ nx = t->_next;\r
+ if(nx) nx->_uiRef++;\r
+ if(--t->_uiRef == 0)\r
+ t->Release();\r
+ t = nx;\r
+ }\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
+\r
+ sq_delete(_types,SQObjectPtrVec);\r
+ sq_delete(_systemstrings,SQObjectPtrVec);\r
+ sq_delete(_metamethods,SQObjectPtrVec);\r
+ sq_delete(_stringtable,SQStringTable);\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
+ default: break; //shutup compiler\r
+ }\r
+}\r
+\r
+\r
+SQInteger SQSharedState::CollectGarbage(SQVM *vm)\r
+{\r
+ SQInteger n=0;\r
+ SQCollectable *tchain=NULL;\r
+ SQVM *vms = _thread(_root_vm);\r
+ \r
+ vms->Mark(&tchain);\r
+ SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed();\r
+ _refs_table.Mark(&tchain);\r
+ MarkObject(_registry,&tchain);\r
+ MarkObject(_consts,&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
+ MarkObject(_weakref_default_delegate,&tchain);\r
+ \r
+ SQCollectable *t = _gc_chain;\r
+ SQCollectable *nx = NULL;\r
+ if(t) {\r
+ t->_uiRef++;\r
+ while(t) {\r
+ t->Finalize();\r
+ nx = t->_next;\r
+ if(nx) nx->_uiRef++;\r
+ if(--t->_uiRef == 0)\r
+ t->Release();\r
+ t = nx;\r
+ n++;\r
+ }\r
+ }\r
+\r
+ t = tchain;\r
+ while(t) {\r
+ t->UnMark();\r
+ t = t->_next;\r
+ }\r
+ _gc_chain = tchain;\r
+ SQInteger 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(SQInteger size)\r
+{\r
+ SQInteger 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
+RefTable::RefTable()\r
+{\r
+ AllocNodes(4);\r
+}\r
+\r
+void RefTable::Finalize()\r
+{\r
+ RefNode *nodes = _nodes;\r
+ for(SQUnsignedInteger n = 0; n < _numofslots; n++) {\r
+ nodes->obj = _null_;\r
+ nodes++;\r
+ }\r
+}\r
+\r
+RefTable::~RefTable()\r
+{\r
+ SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode)));\r
+}\r
+\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+void RefTable::Mark(SQCollectable **chain)\r
+{\r
+ RefNode *nodes = (RefNode *)_nodes;\r
+ for(SQUnsignedInteger n = 0; n < _numofslots; n++) {\r
+ if(type(nodes->obj) != OT_NULL) {\r
+ SQSharedState::MarkObject(nodes->obj,chain);\r
+ }\r
+ nodes++;\r
+ }\r
+}\r
+#endif\r
+\r
+void RefTable::AddRef(SQObject &obj)\r
+{\r
+ SQHash mainpos;\r
+ RefNode *prev;\r
+ RefNode *ref = Get(obj,mainpos,&prev,true);\r
+ ref->refs++;\r
+}\r
+\r
+SQBool RefTable::Release(SQObject &obj)\r
+{\r
+ SQHash mainpos;\r
+ RefNode *prev;\r
+ RefNode *ref = Get(obj,mainpos,&prev,false);\r
+ if(ref) {\r
+ if(--ref->refs == 0) {\r
+ SQObjectPtr o = ref->obj;\r
+ if(prev) {\r
+ prev->next = ref->next;\r
+ }\r
+ else {\r
+ _buckets[mainpos] = ref->next;\r
+ }\r
+ ref->next = _freelist;\r
+ _freelist = ref;\r
+ _slotused--;\r
+ ref->obj = _null_;\r
+ //<<FIXME>>test for shrink?\r
+ return SQTrue;\r
+ }\r
+ }\r
+ else {\r
+ assert(0);\r
+ }\r
+ return SQFalse;\r
+}\r
+\r
+void RefTable::Resize(SQUnsignedInteger size)\r
+{\r
+ RefNode **oldbucks = _buckets;\r
+ RefNode *t = _nodes;\r
+ SQUnsignedInteger oldnumofslots = _numofslots;\r
+ AllocNodes(size);\r
+ //rehash\r
+ SQUnsignedInteger nfound = 0;\r
+ for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {\r
+ if(type(t->obj) != OT_NULL) {\r
+ //add back;\r
+ assert(t->refs != 0);\r
+ RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj);\r
+ nn->refs = t->refs; \r
+ t->obj = _null_;\r
+ nfound++;\r
+ }\r
+ t++;\r
+ }\r
+ assert(nfound == oldnumofslots);\r
+ SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode)));\r
+}\r
+\r
+RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj)\r
+{\r
+ RefNode *t = _buckets[mainpos];\r
+ RefNode *newnode = _freelist;\r
+ newnode->obj = obj;\r
+ _buckets[mainpos] = newnode;\r
+ _freelist = _freelist->next;\r
+ newnode->next = t;\r
+ assert(newnode->refs == 0);\r
+ _slotused++;\r
+ return newnode;\r
+}\r
+\r
+RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add)\r
+{\r
+ RefNode *ref;\r
+ mainpos = ::HashObj(obj)&(_numofslots-1);\r
+ *prev = NULL;\r
+ for (ref = _buckets[mainpos]; ref; ) {\r
+ if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj))\r
+ break;\r
+ *prev = ref;\r
+ ref = ref->next;\r
+ }\r
+ if(ref == NULL && add) {\r
+ if(_numofslots == _slotused) {\r
+ assert(_freelist == 0);\r
+ Resize(_numofslots*2);\r
+ mainpos = ::HashObj(obj)&(_numofslots-1);\r
+ }\r
+ ref = Add(mainpos,obj);\r
+ }\r
+ return ref;\r
+}\r
+\r
+void RefTable::AllocNodes(SQUnsignedInteger size)\r
+{\r
+ RefNode **bucks;\r
+ RefNode *nodes;\r
+ bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode)));\r
+ nodes = (RefNode *)&bucks[size];\r
+ RefNode *temp = nodes;\r
+ SQUnsignedInteger n;\r
+ for(n = 0; n < size - 1; n++) {\r
+ bucks[n] = NULL;\r
+ temp->refs = 0;\r
+ new (&temp->obj) SQObjectPtr;\r
+ temp->next = temp+1;\r
+ temp++;\r
+ }\r
+ bucks[n] = NULL;\r
+ temp->refs = 0;\r
+ new (&temp->obj) SQObjectPtr;\r
+ temp->next = NULL;\r
+ _freelist = nodes;\r
+ _nodes = nodes;\r
+ _buckets = bucks;\r
+ _slotused = 0;\r
+ _numofslots = size;\r
+}\r
+//////////////////////////////////////////////////////////////////////////\r
+//SQStringTable\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
+SQStringTable::SQStringTable()\r
+{\r
+ AllocNodes(4);\r
+ _slotused = 0;\r
+}\r
+\r
+SQStringTable::~SQStringTable()\r
+{\r
+ SQ_FREE(_strings,sizeof(SQString*)*_numofslots);\r
+ _strings = NULL;\r
+}\r
+\r
+void SQStringTable::AllocNodes(SQInteger size)\r
+{\r
+ _numofslots = size;\r
+ _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);\r
+ memset(_strings,0,sizeof(SQString*)*_numofslots);\r
+}\r
+\r
+SQString *SQStringTable::Add(const SQChar *news,SQInteger len)\r
+{\r
+ if(len<0)\r
+ len = (SQInteger)scstrlen(news);\r
+ SQHash 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
+ _strings[h] = t;\r
+ _slotused++;\r
+ if (_slotused > _numofslots) /* too crowded? */\r
+ Resize(_numofslots*2);\r
+ return t;\r
+}\r
+\r
+void SQStringTable::Resize(SQInteger size)\r
+{\r
+ SQInteger oldsize=_numofslots;\r
+ SQString **oldtable=_strings;\r
+ AllocNodes(size);\r
+ for (SQInteger i=0; i<oldsize; i++){\r
+ SQString *p = oldtable[i];\r
+ while(p){\r
+ SQString *next = p->_next;\r
+ SQHash 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 SQStringTable::Remove(SQString *bs)\r
+{\r
+ SQString *s;\r
+ SQString *prev=NULL;\r
+ SQHash 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
+ SQInteger 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 */
-#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();
- SQString *Add(const SQChar *,SQInteger len);
- void Remove(SQString *);
-private:
- void Resize(SQInteger size);
- void AllocNodes(SQInteger size);
- SQString **_strings;
- SQUnsignedInteger _numofslots;
- SQUnsignedInteger _slotused;
-};
-
-struct RefTable {
- struct RefNode {
- SQObjectPtr obj;
- SQUnsignedInteger refs;
- struct RefNode *next;
- };
- RefTable();
- ~RefTable();
- void AddRef(SQObject &obj);
- SQBool Release(SQObject &obj);
-#ifndef NO_GARBAGE_COLLECTOR
- void Mark(SQCollectable **chain);
-#endif
- void Finalize();
-private:
- RefNode *Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add);
- RefNode *Add(SQHash mainpos,SQObject &obj);
- void Resize(SQUnsignedInteger size);
- void AllocNodes(SQUnsignedInteger size);
- SQUnsignedInteger _numofslots;
- SQUnsignedInteger _slotused;
- RefNode *_nodes;
- RefNode *_freelist;
- RefNode **_buckets;
-};
-
-#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(SQInteger size);
- SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name);
-#ifndef NO_GARBAGE_COLLECTOR
- SQInteger CollectGarbage(SQVM *vm);
- static void MarkObject(SQObjectPtr &o,SQCollectable **chain);
-#endif
- SQObjectPtrVec *_metamethods;
- SQObjectPtr _metamethodsmap;
- SQObjectPtrVec *_systemstrings;
- SQObjectPtrVec *_types;
- StringTable *_stringtable;
- RefTable _refs_table;
- SQObjectPtr _registry;
- SQObjectPtr _consts;
- 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[];
- SQObjectPtr _weakref_default_delegate;
- static SQRegFunction _weakref_default_delegate_funcz[];
-
- SQCOMPILERERROR _compilererrorhandler;
- SQPRINTFUNCTION _printfunc;
- bool _debuginfo;
- bool _notifyallexceptions;
-private:
- SQChar *_scratchpad;
- SQInteger _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)
-#define _weakref_ddel _table(_sharedstate->_weakref_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);
-#endif //_SQSTATE_H_
+/* 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 SQStringTable\r
+{\r
+ SQStringTable();\r
+ ~SQStringTable();\r
+ SQString *Add(const SQChar *,SQInteger len);\r
+ void Remove(SQString *);\r
+private:\r
+ void Resize(SQInteger size);\r
+ void AllocNodes(SQInteger size);\r
+ SQString **_strings;\r
+ SQUnsignedInteger _numofslots;\r
+ SQUnsignedInteger _slotused;\r
+};\r
+\r
+struct RefTable {\r
+ struct RefNode {\r
+ SQObjectPtr obj;\r
+ SQUnsignedInteger refs;\r
+ struct RefNode *next;\r
+ };\r
+ RefTable();\r
+ ~RefTable();\r
+ void AddRef(SQObject &obj);\r
+ SQBool Release(SQObject &obj);\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+ void Mark(SQCollectable **chain);\r
+#endif\r
+ void Finalize();\r
+private:\r
+ RefNode *Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add);\r
+ RefNode *Add(SQHash mainpos,SQObject &obj);\r
+ void Resize(SQUnsignedInteger size);\r
+ void AllocNodes(SQUnsignedInteger size);\r
+ SQUnsignedInteger _numofslots;\r
+ SQUnsignedInteger _slotused;\r
+ RefNode *_nodes;\r
+ RefNode *_freelist;\r
+ RefNode **_buckets;\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(SQInteger size);\r
+ SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name);\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+ SQInteger 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
+ SQStringTable *_stringtable;\r
+ RefTable _refs_table;\r
+ SQObjectPtr _registry;\r
+ SQObjectPtr _consts;\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
+ SQObjectPtr _weakref_default_delegate;\r
+ static SQRegFunction _weakref_default_delegate_funcz[];\r
+ \r
+ SQCOMPILERERROR _compilererrorhandler;\r
+ SQPRINTFUNCTION _printfunc;\r
+ bool _debuginfo;\r
+ bool _notifyallexceptions;\r
+private:\r
+ SQChar *_scratchpad;\r
+ SQInteger _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
+#define _weakref_ddel _table(_sharedstate->_weakref_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(SQUnsignedInteger size);\r
+void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size);\r
+void sq_vm_free(void *p,SQUnsignedInteger size);\r
+#endif //_SQSTATE_H_\r
-/* see copyright notice in squirrel.h */
-#ifndef _SQSTRING_H_
-#define _SQSTRING_H_
-
-inline SQHash _hashstr (const SQChar *s, size_t l)
-{
- SQHash h = (SQHash)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 *, SQInteger len = -1 );
- SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
- void Release();
- SQSharedState *_sharedstate;
- SQString *_next; //chain for the string table
- SQInteger _len;
- SQHash _hash;
- SQChar _val[1];
-};
-
-
-
-#endif //_SQSTRING_H_
+/* see copyright notice in squirrel.h */\r
+#ifndef _SQSTRING_H_\r
+#define _SQSTRING_H_\r
+\r
+inline SQHash _hashstr (const SQChar *s, size_t l)\r
+{\r
+ SQHash h = (SQHash)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 *, SQInteger len = -1 );\r
+ SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);\r
+ void Release();\r
+ SQSharedState *_sharedstate;\r
+ SQString *_next; //chain for the string table\r
+ SQInteger _len;\r
+ SQHash _hash;\r
+ SQChar _val[1];\r
+};\r
+\r
+\r
+\r
+#endif //_SQSTRING_H_\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,SQInteger nInitialSize)
-{
- SQInteger pow2size=MINPOWER2;
- while(nInitialSize>pow2size)pow2size=pow2size<<1;
- AllocNodes(pow2size);
- _usednodes = 0;
- _delegate = NULL;
- INIT_CHAIN();
- ADD_TO_CHAIN(&_sharedstate->_gc_chain,this);
-}
-
-void SQTable::Remove(const SQObjectPtr &key)
-{
-
- _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
- if (n) {
- n->val = n->key = _null_;
- _usednodes--;
- Rehash(false);
- }
-}
-
-void SQTable::AllocNodes(SQInteger nSize)
-{
- _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize);
- for(SQInteger i=0;i<nSize;i++){
- new (&nodes[i]) _HashNode;
- nodes[i].next=NULL;
- }
- _numofnodes=nSize;
- _nodes=nodes;
- _firstfree=&_nodes[_numofnodes-1];
-}
-
-void SQTable::Rehash(bool force)
-{
- SQInteger oldsize=_numofnodes;
- //prevent problems with the integer division
- if(oldsize<4)oldsize=4;
- _HashNode *nold=_nodes;
- SQInteger 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 (SQInteger i=0; i<oldsize; i++) {
- _HashNode *old = nold+i;
- if (type(old->key) != OT_NULL)
- NewSlot(old->key,old->val);
- }
- for(SQInteger 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(true,ridx,key,val))!=-1){
- nt->NewSlot(key,val);
- }
- nt->SetDelegate(_delegate);
- return nt;
-}
-
-bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val)
-{
- if(type(key) == OT_NULL)
- return false;
- _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
- if (n) {
- val = _realval(n->val);
- return true;
- }
- return false;
-}
-bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)
-{
- assert(type(key) != OT_NULL);
- SQHash h = HashObj(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) {
- n = _firstfree; /* get a free place */
- SQHash mph = HashObj(mp->key) & (_numofnodes - 1);
- _HashNode *othern; /* main position of colliding node */
-
- if (mp > n && (othern = &_nodes[mph]) != mp){
- /* yes; move colliding node into free position */
- while (othern->next != mp){
- assert(othern->next != NULL);
- othern = othern->next; /* find previous */
- }
- othern->next = n; /* redo the chain with `n' in place of `mp' */
- n->key = mp->key;
- n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */
- n->next = mp->next;
- mp->key = _null_;
- mp->val = _null_;
- 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 && _firstfree->next == 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);
-}
-
-SQInteger SQTable::Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
-{
- SQInteger idx = (SQInteger)TranslateIndex(refpos);
- while (idx < _numofnodes) {
- if(type(_nodes[idx].key) != OT_NULL) {
- //first found
- _HashNode &n = _nodes[idx];
- outkey = n.key;
- outval = getweakrefs?(SQObject)n.val:_realval(n.val);
- //return idx for the next iteration
- return ++idx;
- }
- ++idx;
- }
- //nothing to iterate anymore
- return -1;
-}
-
-
-bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val)
-{
- _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
- if (n) {
- n->val = val;
- return true;
- }
- return false;
-}
-
-void SQTable::_ClearNodes()
-{
- for(SQInteger i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; }
-}
-
-void SQTable::Finalize()
-{
- _ClearNodes();
- SetDelegate(NULL);
-}
-
-void SQTable::Clear()
-{
- _ClearNodes();
- _usednodes = 0;
- Rehash(true);
-}
+/*\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,SQInteger nInitialSize)\r
+{\r
+ SQInteger pow2size=MINPOWER2;\r
+ while(nInitialSize>pow2size)pow2size=pow2size<<1;\r
+ AllocNodes(pow2size);\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
+ \r
+ _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));\r
+ if (n) {\r
+ n->val = n->key = _null_;\r
+ _usednodes--;\r
+ Rehash(false);\r
+ }\r
+}\r
+\r
+void SQTable::AllocNodes(SQInteger nSize)\r
+{\r
+ _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize);\r
+ for(SQInteger 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
+void SQTable::Rehash(bool force)\r
+{\r
+ SQInteger oldsize=_numofnodes;\r
+ //prevent problems with the integer division\r
+ if(oldsize<4)oldsize=4;\r
+ _HashNode *nold=_nodes;\r
+ SQInteger 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 (SQInteger 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(SQInteger 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(true,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
+ if(type(key) == OT_NULL)\r
+ return false;\r
+ _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));\r
+ if (n) {\r
+ val = _realval(n->val);\r
+ return true;\r
+ }\r
+ return false;\r
+}\r
+bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)\r
+{\r
+ assert(type(key) != OT_NULL);\r
+ SQHash h = HashObj(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
+\r
+ //key not found I'll insert it\r
+ //main pos is not free\r
+\r
+ if(type(mp->key) != OT_NULL) {\r
+ n = _firstfree; /* get a free place */\r
+ SQHash mph = HashObj(mp->key) & (_numofnodes - 1);\r
+ _HashNode *othern; /* main position of colliding node */\r
+ \r
+ if (mp > n && (othern = &_nodes[mph]) != mp){\r
+ /* yes; move colliding node into free position */\r
+ while (othern->next != mp){\r
+ assert(othern->next != NULL);\r
+ othern = othern->next; /* find previous */\r
+ }\r
+ othern->next = n; /* redo the chain with `n' in place of `mp' */\r
+ n->key = mp->key;\r
+ n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */\r
+ n->next = mp->next;\r
+ mp->key = _null_;\r
+ mp->val = _null_;\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 && _firstfree->next == 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
+SQInteger SQTable::Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)\r
+{\r
+ SQInteger idx = (SQInteger)TranslateIndex(refpos);\r
+ while (idx < _numofnodes) {\r
+ if(type(_nodes[idx].key) != OT_NULL) {\r
+ //first found\r
+ _HashNode &n = _nodes[idx];\r
+ outkey = n.key;\r
+ outval = getweakrefs?(SQObject)n.val:_realval(n.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
+\r
+bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val)\r
+{\r
+ _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));\r
+ if (n) {\r
+ n->val = val;\r
+ return true;\r
+ }\r
+ return false;\r
+}\r
+\r
+void SQTable::_ClearNodes()\r
+{\r
+ for(SQInteger i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; }\r
+}\r
+\r
+void SQTable::Finalize()\r
+{\r
+ _ClearNodes();\r
+ SetDelegate(NULL);\r
+}\r
+\r
+void SQTable::Clear()\r
+{\r
+ _ClearNodes();\r
+ _usednodes = 0;\r
+ Rehash(true);\r
+}\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) ((SQHash)(((SQInteger)p) >> 3))
-
-inline SQHash HashObj(const SQObjectPtr &key)
-{
- switch(type(key)) {
- case OT_STRING: return _string(key)->_hash;
- case OT_FLOAT: return (SQHash)((SQInteger)_float(key));
- case OT_BOOL: case OT_INTEGER: return (SQHash)((SQInteger)_integer(key));
- default: return hashptr(key._unVal.pRefCounted);
- }
-}
-
-struct SQTable : public SQDelegable
-{
-private:
- struct _HashNode
- {
- _HashNode() { next = NULL; }
- SQObjectPtr val;
- SQObjectPtr key;
- _HashNode *next;
- };
- _HashNode *_firstfree;
- _HashNode *_nodes;
- SQInteger _numofnodes;
- SQInteger _usednodes;
-
-///////////////////////////
- void AllocNodes(SQInteger nSize);
- void Rehash(bool force);
- SQTable(SQSharedState *ss, SQInteger nInitialSize);
- void _ClearNodes();
-public:
- static SQTable* Create(SQSharedState *ss,SQInteger 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 (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();
- SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode));
- }
-#ifndef NO_GARBAGE_COLLECTOR
- void Mark(SQCollectable **chain);
-#endif
- inline _HashNode *_Get(const SQObjectPtr &key,SQHash 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);
- SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
-
- SQInteger CountUsed(){ return _usednodes;}
- void Clear();
- void Release()
- {
- sq_delete(this, SQTable);
- }
-
-};
-
-#endif //_SQTABLE_H_
+/* 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
+\r
+#define hashptr(p) ((SQHash)(((SQInteger)p) >> 3))\r
+\r
+inline SQHash HashObj(const SQObjectPtr &key)\r
+{\r
+ switch(type(key)) {\r
+ case OT_STRING: return _string(key)->_hash;\r
+ case OT_FLOAT: return (SQHash)((SQInteger)_float(key));\r
+ case OT_BOOL: case OT_INTEGER: return (SQHash)((SQInteger)_integer(key));\r
+ default: return hashptr(key._unVal.pRefCounted);\r
+ }\r
+}\r
+\r
+struct SQTable : public SQDelegable \r
+{\r
+private:\r
+ struct _HashNode\r
+ {\r
+ _HashNode() { next = NULL; }\r
+ SQObjectPtr val;\r
+ SQObjectPtr key;\r
+ _HashNode *next;\r
+ };\r
+ _HashNode *_firstfree;\r
+ _HashNode *_nodes;\r
+ SQInteger _numofnodes;\r
+ SQInteger _usednodes;\r
+ \r
+///////////////////////////\r
+ void AllocNodes(SQInteger nSize);\r
+ void Rehash(bool force);\r
+ SQTable(SQSharedState *ss, SQInteger nInitialSize);\r
+ void _ClearNodes();\r
+public:\r
+ static SQTable* Create(SQSharedState *ss,SQInteger 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 (SQInteger 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 _HashNode *_Get(const SQObjectPtr &key,SQHash 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
+ SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);\r
+ \r
+ SQInteger CountUsed(){ return _usednodes;}\r
+ void Clear();\r
+ void Release()\r
+ {\r
+ sq_delete(this, SQTable);\r
+ }\r
+ \r
+};\r
+\r
+#endif //_SQTABLE_H_\r
-/* see copyright notice in squirrel.h */
-#ifndef _SQUSERDATA_H_
-#define _SQUSERDATA_H_
-
-struct SQUserData : SQDelegable
-{
- SQUserData(SQSharedState *ss){ _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, SQInteger 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);
- SQInteger tsize = _size - 1;
- this->~SQUserData();
- SQ_FREE(this, sizeof(SQUserData) + tsize);
- }
-
- SQInteger _size;
- SQRELEASEHOOK _hook;
- SQUserPointer _typetag;
- SQChar _val[1];
-};
-
-#endif //_SQUSERDATA_H_
+/* see copyright notice in squirrel.h */\r
+#ifndef _SQUSERDATA_H_\r
+#define _SQUSERDATA_H_\r
+\r
+struct SQUserData : SQDelegable\r
+{\r
+ SQUserData(SQSharedState *ss){ _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, SQInteger 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
+ SQInteger tsize = _size - 1;\r
+ this->~SQUserData();\r
+ SQ_FREE(this, sizeof(SQUserData) + tsize);\r
+ }\r
+ \r
+ SQInteger _size;\r
+ SQRELEASEHOOK _hook;\r
+ SQUserPointer _typetag;\r
+ SQChar _val[1];\r
+};\r
+\r
+#endif //_SQUSERDATA_H_\r
-/* see copyright notice in squirrel.h */
-#ifndef _SQUTILS_H_
-#define _SQUTILS_H_
-
-#include "sqmem.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(SQUnsignedInteger i = 0; i < v._size; i++) {
- new ((void *)&_vals[i]) T(v._vals[i]);
- }
- _size = v._size;
- }
- ~sqvector()
- {
- if(_allocated) {
- for(SQUnsignedInteger i = 0; i < _size; i++)
- _vals[i].~T();
- SQ_FREE(_vals, (_allocated * sizeof(T)));
- }
- }
- void reserve(SQUnsignedInteger newsize) { _realloc(newsize); }
- void resize(SQUnsignedInteger 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(SQUnsignedInteger 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 SQUnsignedInteger size() const { return _size; }
- bool empty() const { return (_size <= 0); }
- inline T &push_back(const T& val = T())
- {
- if(_allocated <= _size)
- _realloc(_size * 2);
- return *(new ((void *)&_vals[_size++]) T(val));
- }
- inline void pop_back()
- {
- _size--; _vals[_size].~T();
- }
- void insert(SQUnsignedInteger idx, const T& val)
- {
- resize(_size + 1);
- for(SQUnsignedInteger i = _size - 1; i > idx; i--) {
- _vals[i] = _vals[i - 1];
- }
- _vals[idx] = val;
- }
- void remove(SQUnsignedInteger idx)
- {
- _vals[idx].~T();
- if(idx < (_size - 1)) {
- memmove(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1));
- }
- _size--;
- }
- SQUnsignedInteger capacity() { return _allocated; }
- inline T &back() const { return _vals[_size - 1]; }
- inline T& operator[](SQUnsignedInteger pos) const{ return _vals[pos]; }
- T* _vals;
-private:
- void _realloc(SQUnsignedInteger newsize)
- {
- newsize = (newsize > 0)?newsize:4;
- _vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T));
- _allocated = newsize;
- }
- SQUnsignedInteger _size;
- SQUnsignedInteger _allocated;
-};
-
-#endif //_SQUTILS_H_
+/* see copyright notice in squirrel.h */\r
+#ifndef _SQUTILS_H_\r
+#define _SQUTILS_H_\r
+\r
+/* clang fix: "error: call to function 'sq_vm_free' that is neither visible in the template definition nor found by argument-dependent lookup" */\r
+void *sq_vm_malloc(SQUnsignedInteger size);\r
+void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size);\r
+void sq_vm_free(void *p,SQUnsignedInteger size);\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(SQUnsignedInteger 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(SQUnsignedInteger i = 0; i < _size; i++)\r
+ _vals[i].~T();\r
+ SQ_FREE(_vals, (_allocated * sizeof(T)));\r
+ }\r
+ }\r
+ void reserve(SQUnsignedInteger newsize) { _realloc(newsize); }\r
+ void resize(SQUnsignedInteger 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(SQUnsignedInteger 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 SQUnsignedInteger size() const { return _size; }\r
+ bool empty() const { return (_size <= 0); }\r
+ inline T &push_back(const T& val = T())\r
+ {\r
+ if(_allocated <= _size)\r
+ _realloc(_size * 2);\r
+ return *(new ((void *)&_vals[_size++]) T(val));\r
+ }\r
+ inline void pop_back()\r
+ {\r
+ _size--; _vals[_size].~T();\r
+ }\r
+ void insert(SQUnsignedInteger idx, const T& val)\r
+ {\r
+ resize(_size + 1);\r
+ for(SQUnsignedInteger i = _size - 1; i > idx; i--) {\r
+ _vals[i] = _vals[i - 1];\r
+ }\r
+ _vals[idx] = val;\r
+ }\r
+ void remove(SQUnsignedInteger idx)\r
+ {\r
+ _vals[idx].~T();\r
+ if(idx < (_size - 1)) {\r
+ memmove(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1));\r
+ }\r
+ _size--;\r
+ }\r
+ SQUnsignedInteger capacity() { return _allocated; }\r
+ inline T &back() const { return _vals[_size - 1]; }\r
+ inline T& operator[](SQUnsignedInteger pos) const{ return _vals[pos]; }\r
+ T* _vals;\r
+private:\r
+ void _realloc(SQUnsignedInteger 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
+ SQUnsignedInteger _size;\r
+ SQUnsignedInteger _allocated;\r
+};\r
+\r
+#endif //_SQUTILS_H_\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._vals[_top-1])
-
-#define CLEARSTACK(_last_top) { if((_last_top) >= _top) ClearStack(_last_top); }
-void SQVM::ClearStack(SQInteger last_top)
-{
- SQObjectType tOldType;
- SQObjectValue unOldVal;
- while (last_top >= _top) {
- SQObjectPtr &o = _stack._vals[last_top--];
- tOldType = o._type;
- unOldVal = o._unVal;
- o._type = OT_NULL;
- o._unVal.pUserPointer = NULL;
- __Release(tOldType,unOldVal);
- }
-}
-
-bool SQVM::BW_OP(SQUnsignedInteger 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)(*((SQUnsignedInteger*)&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(SQUnsignedInteger 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)) {
- SQInteger res, i1 = _integer(o1), i2 = _integer(o2);
- switch(op) {
- case '+': res = i1 + i2; break;
- case '-': res = i1 - i2; break;
- case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; }
- res = i1 / i2;
- break;
- case '*': res = i1 * i2; break;
- case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; }
- res = i1 % i2;
- break;
- default: res = 0xDEADBEEF;
- }
- trg = res;
- }else{
- SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2);
- switch(op) {
- case '+': res = f1 + f2; break;
- case '-': res = f1 - f2; break;
- case '/': res = f1 / f2; break;
- case '*': res = f1 * f2; break;
- case '%': res = SQFloat(fmod((double)f1,(double)f2)); break;
- default: res = 0x0f;
- }
- trg = res;
- }
- } 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;
-}
-
-SQVM::SQVM(SQSharedState *ss)
-{
- _sharedstate=ss;
- _suspended = SQFalse;
- _suspended_target=-1;
- _suspended_root = SQFalse;
- _suspended_traps=-1;
- _foreignptr=NULL;
- _nnativecalls=0;
- _lasterror = _null_;
- _errorhandler = _null_;
- _debughook = _null_;
- ci = 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_;
- _callstackdata.resize(0);
- SQInteger size=_stack.size();
- for(SQInteger i=0;i<size;i++)
- _stack[i]=_null_;
-}
-
-SQVM::~SQVM()
-{
- Finalize();
- //sq_free(_callsstack,_alloccallsstacksize*sizeof(CallInfo));
- REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
-}
-
-bool SQVM::ArithMetaMethod(SQInteger 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;
- default: mm = MT_ADD; assert(0); break; //shutup compiler
- }
- 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;
- }
- }
- default:break; //shutup compiler
- }
- 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,SQInteger &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:
- if(_delegable(o1)->_delegate) {
- Push(o1);Push(o2);
- if(CallMetaMethod(_delegable(o1),MT_CMP,2,res)) break;
- }
- //continues through (no break needed)
- default:
- _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 );
- }
- 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)
-{
- SQInteger 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;
-}
-
-void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
-{
- switch(type(o)) {
- case OT_STRING:
- res = o;
- return;
- case OT_FLOAT:
- scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%g"),_float(o));
- break;
- case OT_INTEGER:
- scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%d"),_integer(o));
- break;
- case OT_BOOL:
- scsprintf(_sp(rsl(6)),_integer(o)?_SC("true"):_SC("false"));
- break;
- case OT_TABLE:
- case OT_USERDATA:
- case OT_INSTANCE:
- if(_delegable(o)->_delegate) {
- Push(o);
- if(CallMetaMethod(_delegable(o),MT_TOSTRING,1,res)) {
- if(type(res) == OT_STRING)
- return;
- //else keeps going to the default
- }
- }
- default:
- scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o));
- }
- res = SQString::Create(_ss(this),_spval);
-}
-
-
-bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)
-{
- SQObjectPtr a, b;
- ToString(str, a);
- ToString(obj, b);
- SQInteger l = _string(a)->_len , ol = _string(b)->_len;
- SQChar *s = _sp(rsl(l + ol + 1));
- memcpy(s, _stringval(a), rsl(l));
- memcpy(s + l, _stringval(b), rsl(ol));
- dest = SQString::Create(_ss(this), _spval, l + ol);
- return true;
-}
-
-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, SQInteger stacksize)
-{
- _stack.resize(stacksize);
- _alloccallsstacksize = 4;
- _callstackdata.resize(_alloccallsstacksize);
- _callsstacksize = 0;
- _callsstack = &_callstackdata[0];
- _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,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall)
-{
- SQFunctionProto *func = _funcproto(closure->_function);
-
- const SQInteger paramssize = func->_nparameters;
- const SQInteger newtop = stackbase + func->_stacksize;
- SQInteger nargs = args;
- if (paramssize != nargs) {
- SQInteger ndef = func->_ndefaultparams;
- SQInteger diff;
- if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) {
- for(SQInteger n = ndef - diff; n < ndef; n++) {
- _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n];
- }
- }
- else if(func->_varparams)
- {
- if (nargs < paramssize) {
- Raise_Error(_SC("wrong number of parameters"));
- return false;
- }
- for(SQInteger n = 0; n < nargs - paramssize; n++) {
- _vargsstack.push_back(_stack._vals[stackbase+paramssize+n]);
- _stack._vals[stackbase+paramssize+n] = _null_;
- }
- }
- else {
- Raise_Error(_SC("wrong number of parameters"));
- return false;
- }
- }
-
- if(type(closure->_env) == OT_WEAKREF) {
- _stack._vals[stackbase] = _weakref(closure->_env)->_obj;
- }
-
- if (!tailcall) {
- CallInfo lc;
- lc._generator = NULL;
- lc._etraps = 0;
- lc._prevstkbase = (SQInt32) ( stackbase - _stackbase );
- lc._target = (SQInt32) target;
- lc._prevtop = (SQInt32) (_top - _stackbase);
- lc._ncalls = 1;
- lc._root = SQFalse;
- PUSH_CALLINFO(this, lc);
- }
- else {
- ci->_ncalls++;
- }
- ci->_vargs.size = (SQInt32)(nargs - paramssize);
- ci->_vargs.base = (SQInt32)(_vargsstack.size()-(ci->_vargs.size));
- ci->_closure = closure;
- ci->_literals = func->_literals;
- ci->_ip = func->_instructions;
- //grows the stack if needed
- if (((SQUnsignedInteger)newtop + (func->_stacksize<<1)) > _stack.size()) {
- _stack.resize(_stack.size() + (func->_stacksize<<1));
- }
-
- _top = newtop;
- _stackbase = stackbase;
- if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
- CallDebugHook(_SC('c'));
- return true;
-}
-
-bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval)
-{
- if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))
- for(SQInteger i=0;i<ci->_ncalls;i++)
- CallDebugHook(_SC('r'));
-
- SQBool broot = ci->_root;
- SQInteger last_top = _top;
- SQInteger target = ci->_target;
- SQInteger oldstackbase = _stackbase;
- _stackbase -= ci->_prevstkbase;
- _top = _stackbase + ci->_prevtop;
- if(ci->_vargs.size) PopVarArgs(ci->_vargs);
- POP_CALLINFO(this);
- if (broot) {
- if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack._vals[oldstackbase+_arg1];
- else retval = _null_;
- }
- else {
- if(target != -1) { //-1 is when a class contructor ret value has to be ignored
- if (_arg0 != MAX_FUNC_STACKSIZE)
- STK(target) = _stack._vals[oldstackbase+_arg1];
- else
- STK(target) = _null_;
- }
- }
-
- CLEARSTACK(last_top);
- assert(oldstackbase >= _stackbase);
- return broot?true:false;
-}
-
-#define _RET_ON_FAIL(exp) { if(!exp) return false; }
-
-bool SQVM::LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)
-{
- _RET_ON_FAIL(ARITH_OP( op , target, a, incr));
- a = target;
- return true;
-}
-
-bool SQVM::PLOCAL_INC(SQInteger 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(SQInteger 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 (*((SQInt32 *)&_i_._arg1))
-#define arg2 (_i_._arg2)
-#define arg3 (_i_._arg3)
-#define sarg3 ((SQInteger)*((signed 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(SQInteger n = 0; n< vargs.size; n++)
- _vargsstack.pop_back();
-}
-
-#define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; }
-bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
-&o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump)
-{
- SQInteger nrefidx;
- switch(type(o1)) {
- case OT_TABLE:
- if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(exitpos);
- o4 = (SQInteger)nrefidx; _FINISH(1);
- case OT_ARRAY:
- if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(exitpos);
- o4 = (SQInteger) nrefidx; _FINISH(1);
- case OT_STRING:
- if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos);
- o4 = (SQInteger)nrefidx; _FINISH(1);
- case OT_CLASS:
- if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos);
- o4 = (SQInteger)nrefidx; _FINISH(1);
- 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(exitpos);
- if(!Get(o1, itr, o3, false,false)) {
- Raise_Error(_SC("_nexti returned an invalid idx"));
- return false;
- }
- _FINISH(1);
- }
- Raise_Error(_SC("_nexti failed"));
- return false;
- }
- break;
- case OT_GENERATOR:
- if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(exitpos);
- 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(0);
- }
- default:
- 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)
-{
- SQInteger nouters;
- SQClosure *closure = SQClosure::Create(_ss(this), func);
- if((nouters = func->_noutervalues)) {
- closure->_outervalues.reserve(nouters);
- for(SQInteger 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;
- }
- }
- }
- SQInteger ndefparams;
- if((ndefparams = func->_ndefaultparams)) {
- closure->_defaultparams.reserve(ndefparams);
- for(SQInteger i = 0; i < ndefparams; i++) {
- SQInteger spos = func->_defaultparams[i];
- closure->_defaultparams.push_back(_stack._vals[_stackbase + spos]);
- }
- }
- 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;
- }
- SQInteger 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,SQInteger baseclass,SQInteger attributes)
-{
- SQClass *base = NULL;
- SQObjectPtr attrs;
- if(baseclass != -1) {
- 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);
- if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) {
- int nparams = 2;
- SQObjectPtr ret;
- Push(target); Push(attrs);
- Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false);
- Pop(nparams);
- }
- _class(target)->_attributes = attrs;
- return true;
-}
-
-
-
-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)) {
- SQInteger cmpres;
- if(!ObjCmp(o1, o2,cmpres)) return false;
- res = (cmpres == 0);
- }
- else {
- res = false;
- }
- }
- return true;
-}
-
-bool SQVM::IsFalse(SQObjectPtr &o)
-{
- if((type(o) & SQOBJECT_CANBEFALSE) && ( (type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0)) )
- || (_integer(o) == 0) ) { //OT_NULL|OT_INTEGER|OT_BOOL
- return true;
- }
- return false;
-}
-
-bool SQVM::GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target)
-{
- switch(type(o)) {
- case OT_TABLE: target = _table(o)->_delegate?SQObjectPtr(_table(o)->_delegate):_null_;
- break;
- case OT_CLASS: target = _class(o)->_base?_class(o)->_base:_null_;
- break;
- default:
- Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(o));
- return false;
- }
- return true;
-}
-
-bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et)
-{
- if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }
- _nnativecalls++;
- AutoDec ad(&_nnativecalls);
- SQInteger traps = 0;
- //temp_reg vars for OP_CALL
- SQInteger ct_target;
- SQInteger ct_stackbase;
- bool ct_tailcall;
-
- switch(et) {
- case ET_CALL: {
- SQInteger last_top = _top;
- temp_reg = closure;
- if(!StartCall(_closure(temp_reg), _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;
- }
- if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) {
- SQFunctionProto *f = _funcproto(_closure(temp_reg)->_function);
- SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg));
- _GUARD(gen->Yield(this));
- Return(1, ci->_target, temp_reg);
- outres = gen;
- CLEARSTACK(last_top);
- return true;
- }
- ci->_root = SQTrue;
- }
- break;
- case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = SQTrue; traps += ci->_etraps; break;
- case ET_RESUME_VM:
- case ET_RESUME_THROW_VM:
- traps = _suspended_traps;
- ci->_root = _suspended_root;
- ci->_vargs = _suspend_varargs;
- _suspended = SQFalse;
- if(et == ET_RESUME_THROW_VM) { SQ_THROW(); }
- break;
- }
-
-exception_restore:
- //
- {
- 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_LOADINT: TARGET = (SQInteger)arg1; continue;
- case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue;
- case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;
- case _OP_TAILCALL:
- temp_reg = STK(arg1);
- if (type(temp_reg) == OT_CLOSURE && !_funcproto(_closure(temp_reg)->_function)->_bgenerator){
- ct_tailcall = true;
- if(ci->_vargs.size) PopVarArgs(ci->_vargs);
- for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);
- ct_target = ci->_target;
- ct_stackbase = _stackbase;
- goto common_call;
- }
- case _OP_CALL: {
- ct_tailcall = false;
- ct_target = arg0;
- temp_reg = STK(arg1);
- ct_stackbase = _stackbase+arg2;
-
-common_call:
- SQObjectPtr clo = temp_reg;
- SQInteger last_top = _top;
- switch (type(clo)) {
- case OT_CLOSURE:{
- _GUARD(StartCall(_closure(clo), ct_target, arg3, ct_stackbase, ct_tailcall));
- if (_funcproto(_closure(clo)->_function)->_bgenerator) {
- SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(clo));
- _GUARD(gen->Yield(this));
- Return(1, ct_target, clo);
- STK(ct_target) = gen;
- CLEARSTACK(last_top);
- continue;
- }
- }
- continue;
- case OT_NATIVECLOSURE: {
- bool suspend;
- _GUARD(CallNative(_nativeclosure(clo), arg3, ct_stackbase, clo,suspend));
- if(suspend){
- _suspended = SQTrue;
- _suspended_target = ct_target;
- _suspended_root = ci->_root;
- _suspended_traps = traps;
- _suspend_varargs = ci->_vargs;
- outres = clo;
- return true;
- }
- if(ct_target != -1) { //skip return value for constructors
- STK(ct_target) = clo;
- }
- }
- continue;
- case OT_CLASS:{
- SQObjectPtr inst;
- _GUARD(CreateClassInstance(_class(clo),inst,temp_reg));
- STK(ct_target) = inst;
- ct_target = -1; //fakes return value target so that is not overwritten by the constructor
- if(type(temp_reg) != OT_NULL) {
- _stack._vals[ct_stackbase] = inst;
- goto common_call; //hard core spaghetti code(reissues the OP_CALL to invoke the constructor)
- }
- }
- break;
- case OT_TABLE:
- case OT_USERDATA:
- case OT_INSTANCE:
- {
- Push(clo);
- for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i));
- if (_delegable(clo) && CallMetaMethod(_delegable(clo), MT_CALL, arg3+1, clo)){
- STK(ct_target) = clo;
- break;
- }
- Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
- SQ_THROW();
- }
- default:
- Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
- SQ_THROW();
- }
- }
- continue;
- case _OP_PREPCALL:
- case _OP_PREPCALLK:
- {
- SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1);
- SQObjectPtr &o = STK(arg2);
- if (!Get(o, key, temp_reg,false,true)) {
- if(type(o) == OT_CLASS) { //hack?
- if(_class_ddel->Get(key,temp_reg)) {
- STK(arg3) = o;
- TARGET = temp_reg;
- continue;
- }
- }
- { Raise_IdxError(key); SQ_THROW();}
- }
-
- STK(arg3) = type(o) == OT_CLASS?STK(0):o;
- 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),false));
- 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(ci->_generator) {
- ci->_generator->Kill();
- }
- if(Return(arg0, arg1, temp_reg)){
- assert(traps==0);
- outres = temp_reg;
- return true;
- }
- continue;
- case _OP_LOADNULLS:{ for(SQInt32 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: _GUARD(GETPARENT_OP(STK(arg1),TARGET)); continue;
- case _OP_COMPARITH: _GUARD(DerefInc(arg3, TARGET, STK((((SQUnsignedInteger)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) {
- SQInteger t = _integer(STK(arg1));
- TARGET = SQInteger(~t);
- 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(ci->_generator) {
- if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);
- _GUARD(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:{ int tojump;
- _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump));
- ci->_ip += tojump; }
- continue;
- case _OP_POSTFOREACH:
- assert(type(STK(arg0)) == OT_GENERATOR);
- if(_generator(STK(arg0))->_state == SQGenerator::eDead)
- ci->_ip += (sarg1 - 1);
- 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:{
- SQInstruction *_iv = _funcproto(_closure(ci->_closure)->_function)->_instructions;
- _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++;
- ci->_etraps++;
- }
- continue;
- case _OP_POPTRAP: {
- for(SQInteger 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:
- bool bstatic = (arg0&NEW_SLOT_STATIC_FLAG)?true:false;
- if(type(STK(arg1)) == OT_CLASS) {
- if(type(_class(STK(arg1))->_metamethods[MT_NEWMEMBER]) != OT_NULL ) {
- Push(STK(arg1)); Push(STK(arg2)); Push(STK(arg3));
- Push((arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : _null_);
- int nparams = 4;
- if(Call(_class(STK(arg1))->_metamethods[MT_NEWMEMBER], nparams, _top - nparams, temp_reg,SQFalse)) {
- Pop(nparams);
- continue;
- }
- }
- }
- _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),bstatic));
- if((arg0&NEW_SLOT_ATTRIBUTES_FLAG)) {
- _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1));
- }
- continue;
- }
-
- }
- }
-exception_trap:
- {
- SQObjectPtr currerror = _lasterror;
-// dumpstack(_stackbase);
- SQInteger n = 0;
- SQInteger last_top = _top;
- if(ci) {
- if(_ss(this)->_notifyallexceptions) CallErrorHandler(currerror);
-
- if(traps) {
- do {
- if(ci->_etraps > 0) {
- SQExceptionTrap &et = _etraps.top();
- ci->_ip = et._ip;
- _top = et._stacksize;
- _stackbase = et._stackbase;
- _stack._vals[_stackbase+et._extarget] = currerror;
- _etraps.pop_back(); traps--; ci->_etraps--;
- CLEARSTACK(last_top);
- goto exception_restore;
- }
- //if is a native closure
- if(type(ci->_closure) != OT_CLOSURE && n)
- break;
- if(ci->_generator) ci->_generator->Kill();
- PopVarArgs(ci->_vargs);
- POP_CALLINFO(this);
- n++;
- } while(_callsstacksize);
- }
- else {
- //call the hook
- if(raiseerror && !_ss(this)->_notifyallexceptions)
- CallErrorHandler(currerror);
- }
- //remove call stack until a C function is found or the cstack is empty
- if(ci) do {
- SQBool exitafterthisone = ci->_root;
- if(ci->_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(_callsstacksize);
-
- CLEARSTACK(last_top);
- }
- _lasterror = currerror;
- return false;
- }
- assert(0);
-}
-
-bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor)
-{
- inst = theclass->CreateInstance();
- if(!theclass->Get(_ss(this)->_constructoridx,constructor)) {
- constructor = _null_;
- }
- return true;
-}
-
-void SQVM::CallErrorHandler(SQObjectPtr &error)
-{
- if(type(_errorhandler) != OT_NULL) {
- SQObjectPtr out;
- Push(_roottable); Push(error);
- Call(_errorhandler, 2, _top-2, out,SQFalse);
- Pop(2);
- }
-}
-
-void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline)
-{
- SQObjectPtr temp_reg;
- SQInteger 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,SQFalse);
- Pop(nparams);
-}
-
-bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackbase,SQObjectPtr &retval,bool &suspend)
-{
- if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }
- SQInteger nparamscheck = nclosure->_nparamscheck;
- if(((nparamscheck > 0) && (nparamscheck != nargs))
- || ((nparamscheck < 0) && (nargs < (-nparamscheck)))) {
- Raise_Error(_SC("wrong number of parameters"));
- return false;
- }
-
- SQInteger tcs;
- if((tcs = nclosure->_typecheck.size())) {
- for(SQInteger i = 0; i < nargs && i < tcs; i++)
- if((nclosure->_typecheck._vals[i] != -1) && !(type(_stack._vals[stackbase+i]) & nclosure->_typecheck[i])) {
- Raise_ParamTypeError(i,nclosure->_typecheck._vals[i],type(_stack._vals[stackbase+i]));
- return false;
- }
- }
- _nnativecalls++;
- if ((_top + MIN_STACK_OVERHEAD) > (SQInteger)_stack.size()) {
- _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD<<1));
- }
- SQInteger oldtop = _top;
- SQInteger oldstackbase = _stackbase;
- _top = stackbase + nargs;
- CallInfo lci;
- lci._closure = nclosure;
- lci._generator = NULL;
- lci._etraps = 0;
- lci._prevstkbase = (SQInt32) (stackbase - _stackbase);
- lci._ncalls = 1;
- lci._prevtop = (SQInt32) (oldtop - oldstackbase);
- PUSH_CALLINFO(this, lci);
- _stackbase = stackbase;
- //push free variables
- SQInteger outers = nclosure->_outervalues.size();
- for (SQInteger i = 0; i < outers; i++) {
- Push(nclosure->_outervalues[i]);
- }
-
- if(type(nclosure->_env) == OT_WEAKREF) {
- _stack[stackbase] = _weakref(nclosure->_env)->_obj;
- }
-
-
- SQInteger 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(); TOP().Null(); }
- 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; //shut up compiler
- }
- 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((int)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);
- case OT_WEAKREF:
- if(raw)return false;
- return _weakref_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;
- SQObjectPtr newobj;
- switch(type(self)){
- case OT_TABLE:
- newobj = _table(self)->Clone();
- goto cloned_mt;
- case OT_INSTANCE:
- newobj = _instance(self)->Clone(_ss(this));
-cloned_mt:
- if(_delegable(newobj)->_delegate){
- Push(newobj);
- Push(self);
- CallMetaMethod(_delegable(newobj),MT_CLONED,2,temp_reg);
- }
- target = newobj;
- 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,bool bstatic)
-{
- 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_INSTANCE: {
- SQObjectPtr res;
- Push(self);Push(key);Push(val);
- if(!CallMetaMethod(_instance(self),MT_NEWSLOT,3,res)) {
- Raise_Error(_SC("class instances do not support the new slot operator"));
- return false;
- }
- break;}
- case OT_CLASS:
- if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) {
- 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,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror)
-{
-#ifdef _DEBUG
-SQInteger prevstackbase = _stackbase;
-#endif
- switch(type(closure)) {
- case OT_CLOSURE:
- return Execute(closure, _top - nparams, nparams, stackbase,outres,raiseerror);
- break;
- case OT_NATIVECLOSURE:{
- bool suspend;
- return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend);
-
- }
- break;
- case OT_CLASS: {
- SQObjectPtr constr;
- SQObjectPtr temp;
- CreateClassInstance(_class(closure),outres,constr);
- if(type(constr) != OT_NULL) {
- _stack[stackbase] = outres;
- return Call(constr,nparams,stackbase,temp,raiseerror);
- }
- return true;
- }
- break;
- default:
- return false;
- }
-#ifdef _DEBUG
- if(!_suspended) {
- assert(_stackbase == prevstackbase);
- }
-#endif
- return true;
-}
-
-bool SQVM::CallMetaMethod(SQDelegable *del,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres)
-{
- SQObjectPtr closure;
- if(del->GetMetaMethod(this, mm, closure)) {
- if(Call(closure, nparams, _top - nparams, outres, SQFalse)) {
- Pop(nparams);
- return true;
- }
- }
- Pop(nparams);
- return false;
-}
-
-void SQVM::Remove(SQInteger n) {
- n = (n >= 0)?n + _stackbase - 1:_top + n;
- for(SQInteger i = n; i < _top; i++){
- _stack[i] = _stack[i+1];
- }
- _stack[_top] = _null_;
- _top--;
-}
-
-void SQVM::Pop() {
- _stack[--_top] = _null_;
-}
-
-void SQVM::Pop(SQInteger n) {
- for(SQInteger i = 0; i < n; i++){
- _stack[--_top] = _null_;
- }
-}
-
-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(SQInteger n) { return _stack[_top+n]; }
-SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; }
-
-#ifdef _DEBUG_DUMP
-void SQVM::dumpstack(SQInteger stackbase,bool dumpall)
-{
- SQInteger size=dumpall?_stack.size():_top;
- SQInteger n=0;
- scprintf(_SC("\n>>>>stack dump<<<<\n"));
- CallInfo &ci=_callsstack[_callsstacksize-1];
- scprintf(_SC("IP: %p\n"),ci._ip);
- scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase);
- scprintf(_SC("prev top: %d\n"),ci._prevtop);
- for(SQInteger 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 %p"),_generator(obj));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;
- case OT_WEAKREF: scprintf(_SC("WEAKERF %p"),_weakref(obj));break;
- default:
- assert(0);
- break;
- };
- scprintf(_SC("\n"));
- ++n;
- }
-}
-
-
-
-#endif
+/*\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._vals[_top-1])\r
+\r
+#define CLEARSTACK(_last_top) { if((_last_top) >= _top) ClearStack(_last_top); }\r
+void SQVM::ClearStack(SQInteger last_top)\r
+{\r
+ SQObjectType tOldType;\r
+ SQObjectValue unOldVal;\r
+ while (last_top >= _top) {\r
+ SQObjectPtr &o = _stack._vals[last_top--];\r
+ tOldType = o._type;\r
+ unOldVal = o._unVal;\r
+ o._type = OT_NULL;\r
+ o._unVal.pUserPointer = NULL;\r
+ __Release(tOldType,unOldVal);\r
+ }\r
+}\r
+\r
+bool SQVM::BW_OP(SQUnsignedInteger 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)(*((SQUnsignedInteger*)&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(SQUnsignedInteger 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
+ SQInteger res, i1 = _integer(o1), i2 = _integer(o2);\r
+ switch(op) {\r
+ case '+': res = i1 + i2; break;\r
+ case '-': res = i1 - i2; break;\r
+ case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; }\r
+ res = i1 / i2; \r
+ break;\r
+ case '*': res = i1 * i2; break;\r
+ case '%': if(i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; }\r
+ res = i1 % i2; \r
+ break;\r
+ default: res = 0xDEADBEEF;\r
+ }\r
+ trg = res;\r
+ }else{\r
+ SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2);\r
+ switch(op) {\r
+ case '+': res = f1 + f2; break;\r
+ case '-': res = f1 - f2; break;\r
+ case '/': res = f1 / f2; break;\r
+ case '*': res = f1 * f2; break;\r
+ case '%': res = SQFloat(fmod((double)f1,(double)f2)); break;\r
+ default: res = 0x0f;\r
+ }\r
+ trg = res;\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
+SQVM::SQVM(SQSharedState *ss)\r
+{\r
+ _sharedstate=ss;\r
+ _suspended = SQFalse;\r
+ _suspended_target=-1;\r
+ _suspended_root = SQFalse;\r
+ _suspended_traps=-1;\r
+ _foreignptr=NULL;\r
+ _nnativecalls=0;\r
+ _lasterror = _null_;\r
+ _errorhandler = _null_;\r
+ _debughook = _null_;\r
+ ci = 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
+ _callstackdata.resize(0);\r
+ SQInteger size=_stack.size();\r
+ for(SQInteger i=0;i<size;i++)\r
+ _stack[i]=_null_;\r
+}\r
+\r
+SQVM::~SQVM()\r
+{\r
+ Finalize();\r
+ //sq_free(_callsstack,_alloccallsstacksize*sizeof(CallInfo));\r
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);\r
+}\r
+\r
+bool SQVM::ArithMetaMethod(SQInteger 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
+ default: mm = MT_ADD; assert(0); break; //shutup compiler\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
+ default:break; //shutup compiler\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,SQInteger &result)\r
+{\r
+ if(type(o1)==type(o2)){\r
+ if(_rawval(o1)==_rawval(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
+ if(_delegable(o1)->_delegate) {\r
+ Push(o1);Push(o2);\r
+ if(CallMetaMethod(_delegable(o1),MT_CMP,2,res)) break;\r
+ }\r
+ //continues through (no break needed)\r
+ default: \r
+ _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 );\r
+ }\r
+ if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; }\r
+ _RET_SUCCEED(_integer(res));\r
+ \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
+ SQInteger 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
+void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)\r
+{\r
+ switch(type(o)) {\r
+ case OT_STRING:\r
+ res = o;\r
+ return;\r
+ case OT_FLOAT:\r
+ scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%g"),_float(o));\r
+ break;\r
+ case OT_INTEGER:\r
+ scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%d"),_integer(o));\r
+ break;\r
+ case OT_BOOL:\r
+ scsprintf(_sp(rsl(6)),_integer(o)?_SC("true"):_SC("false"));\r
+ break;\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_TOSTRING,1,res)) {\r
+ if(type(res) == OT_STRING)\r
+ return;\r
+ //else keeps going to the default\r
+ }\r
+ }\r
+ default:\r
+ scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o));\r
+ }\r
+ res = SQString::Create(_ss(this),_spval);\r
+}\r
+\r
+\r
+bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)\r
+{\r
+ SQObjectPtr a, b;\r
+ ToString(str, a);\r
+ ToString(obj, b);\r
+ SQInteger l = _string(a)->_len , ol = _string(b)->_len;\r
+ SQChar *s = _sp(rsl(l + ol + 1));\r
+ memcpy(s, _stringval(a), rsl(l)); \r
+ memcpy(s + l, _stringval(b), rsl(ol));\r
+ dest = SQString::Create(_ss(this), _spval, l + ol);\r
+ return true;\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, SQInteger stacksize)\r
+{\r
+ _stack.resize(stacksize);\r
+ _alloccallsstacksize = 4;\r
+ _callstackdata.resize(_alloccallsstacksize);\r
+ _callsstacksize = 0;\r
+ _callsstack = &_callstackdata[0];\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,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall)\r
+{\r
+ SQFunctionProto *func = _funcproto(closure->_function);\r
+ \r
+ const SQInteger paramssize = func->_nparameters;\r
+ const SQInteger newtop = stackbase + func->_stacksize;\r
+ SQInteger nargs = args;\r
+ if (paramssize != nargs) {\r
+ SQInteger ndef = func->_ndefaultparams;\r
+ SQInteger diff;\r
+ if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) {\r
+ for(SQInteger n = ndef - diff; n < ndef; n++) {\r
+ _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n];\r
+ }\r
+ }\r
+ else if(func->_varparams)\r
+ {\r
+ if (nargs < paramssize) {\r
+ Raise_Error(_SC("wrong number of parameters"));\r
+ return false;\r
+ }\r
+ for(SQInteger n = 0; n < nargs - paramssize; n++) {\r
+ _vargsstack.push_back(_stack._vals[stackbase+paramssize+n]);\r
+ _stack._vals[stackbase+paramssize+n] = _null_;\r
+ }\r
+ }\r
+ else {\r
+ Raise_Error(_SC("wrong number of parameters"));\r
+ return false;\r
+ }\r
+ }\r
+\r
+ if(type(closure->_env) == OT_WEAKREF) {\r
+ _stack._vals[stackbase] = _weakref(closure->_env)->_obj;\r
+ }\r
+\r
+ if (!tailcall) {\r
+ CallInfo lc;\r
+ lc._generator = NULL;\r
+ lc._etraps = 0;\r
+ lc._prevstkbase = (SQInt32) ( stackbase - _stackbase );\r
+ lc._target = (SQInt32) target;\r
+ lc._prevtop = (SQInt32) (_top - _stackbase);\r
+ lc._ncalls = 1;\r
+ lc._root = SQFalse;\r
+ PUSH_CALLINFO(this, lc);\r
+ }\r
+ else {\r
+ ci->_ncalls++;\r
+ }\r
+ ci->_vargs.size = (SQInt32)(nargs - paramssize);\r
+ ci->_vargs.base = (SQInt32)(_vargsstack.size()-(ci->_vargs.size));\r
+ ci->_closure = closure;\r
+ ci->_literals = func->_literals;\r
+ ci->_ip = func->_instructions;\r
+ //grows the stack if needed\r
+ if (((SQUnsignedInteger)newtop + (func->_stacksize<<1)) > _stack.size()) {\r
+ _stack.resize(_stack.size() + (func->_stacksize<<1));\r
+ }\r
+ \r
+ _top = newtop;\r
+ _stackbase = stackbase;\r
+ if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))\r
+ CallDebugHook(_SC('c'));\r
+ return true;\r
+}\r
+\r
+bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval)\r
+{\r
+ if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure))\r
+ for(SQInteger i=0;i<ci->_ncalls;i++)\r
+ CallDebugHook(_SC('r'));\r
+ \r
+ SQBool broot = ci->_root;\r
+ SQInteger last_top = _top;\r
+ SQInteger target = ci->_target;\r
+ SQInteger oldstackbase = _stackbase;\r
+ _stackbase -= ci->_prevstkbase;\r
+ _top = _stackbase + ci->_prevtop;\r
+ if(ci->_vargs.size) PopVarArgs(ci->_vargs);\r
+ POP_CALLINFO(this);\r
+ if (broot) {\r
+ if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack._vals[oldstackbase+_arg1];\r
+ else retval = _null_;\r
+ }\r
+ else {\r
+ if(target != -1) { //-1 is when a class contructor ret value has to be ignored\r
+ if (_arg0 != MAX_FUNC_STACKSIZE)\r
+ STK(target) = _stack._vals[oldstackbase+_arg1];\r
+ else\r
+ STK(target) = _null_;\r
+ }\r
+ }\r
+\r
+ CLEARSTACK(last_top);\r
+ assert(oldstackbase >= _stackbase); \r
+ return broot?true:false;\r
+}\r
+\r
+#define _RET_ON_FAIL(exp) { if(!exp) return false; }\r
+\r
+bool SQVM::LOCAL_INC(SQInteger 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(SQInteger 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(SQInteger 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 (*((SQInt32 *)&_i_._arg1))\r
+#define arg2 (_i_._arg2)\r
+#define arg3 (_i_._arg3)\r
+#define sarg3 ((SQInteger)*((signed 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(SQInteger n = 0; n< vargs.size; n++)\r
+ _vargsstack.pop_back();\r
+}\r
+\r
+#define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; }\r
+bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr \r
+&o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump)\r
+{\r
+ SQInteger nrefidx;\r
+ switch(type(o1)) {\r
+ case OT_TABLE:\r
+ if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(exitpos);\r
+ o4 = (SQInteger)nrefidx; _FINISH(1);\r
+ case OT_ARRAY:\r
+ if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(exitpos);\r
+ o4 = (SQInteger) nrefidx; _FINISH(1);\r
+ case OT_STRING:\r
+ if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos);\r
+ o4 = (SQInteger)nrefidx; _FINISH(1);\r
+ case OT_CLASS:\r
+ if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos);\r
+ o4 = (SQInteger)nrefidx; _FINISH(1);\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(exitpos);\r
+ if(!Get(o1, itr, o3, false,false)) {\r
+ Raise_Error(_SC("_nexti returned an invalid idx"));\r
+ return false;\r
+ }\r
+ _FINISH(1);\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(exitpos);\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(0);\r
+ }\r
+ default: \r
+ Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));\r
+ }\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
+ SQInteger nouters;\r
+ SQClosure *closure = SQClosure::Create(_ss(this), func);\r
+ if((nouters = func->_noutervalues)) {\r
+ closure->_outervalues.reserve(nouters);\r
+ for(SQInteger 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
+ SQInteger ndefparams;\r
+ if((ndefparams = func->_ndefaultparams)) {\r
+ closure->_defaultparams.reserve(ndefparams);\r
+ for(SQInteger i = 0; i < ndefparams; i++) {\r
+ SQInteger spos = func->_defaultparams[i];\r
+ closure->_defaultparams.push_back(_stack._vals[_stackbase + spos]);\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
+ SQInteger 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,SQInteger baseclass,SQInteger attributes)\r
+{\r
+ SQClass *base = NULL;\r
+ SQObjectPtr attrs;\r
+ if(baseclass != -1) {\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
+ if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) {\r
+ int nparams = 2;\r
+ SQObjectPtr ret;\r
+ Push(target); Push(attrs);\r
+ Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false);\r
+ Pop(nparams);\r
+ }\r
+ _class(target)->_attributes = attrs;\r
+ return true;\r
+}\r
+\r
+\r
+\r
+bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res)\r
+{\r
+ if(type(o1) == type(o2)) {\r
+ res = ((_rawval(o1) == _rawval(o2)?true:false));\r
+ }\r
+ else {\r
+ if(sq_isnumeric(o1) && sq_isnumeric(o2)) {\r
+ SQInteger 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::IsFalse(SQObjectPtr &o)\r
+{\r
+ if((type(o) & SQOBJECT_CANBEFALSE) && ( (type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0)) )\r
+ || (_integer(o) == 0) ) { //OT_NULL|OT_INTEGER|OT_BOOL\r
+ return true;\r
+ }\r
+ return false;\r
+}\r
+\r
+bool SQVM::GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target)\r
+{\r
+ switch(type(o)) {\r
+ case OT_TABLE: target = _table(o)->_delegate?SQObjectPtr(_table(o)->_delegate):_null_;\r
+ break;\r
+ case OT_CLASS: target = _class(o)->_base?_class(o)->_base:_null_;\r
+ break;\r
+ default:\r
+ Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(o));\r
+ return false;\r
+ }\r
+ return true;\r
+}\r
+\r
+bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,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
+ SQInteger traps = 0;\r
+ //temp_reg vars for OP_CALL\r
+ SQInteger ct_target;\r
+ SQInteger ct_stackbase;\r
+ bool ct_tailcall; \r
+\r
+ switch(et) {\r
+ case ET_CALL: {\r
+ SQInteger last_top = _top;\r
+ temp_reg = closure;\r
+ if(!StartCall(_closure(temp_reg), _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
+ if (_funcproto(_closure(temp_reg)->_function)->_bgenerator) {\r
+ SQFunctionProto *f = _funcproto(_closure(temp_reg)->_function);\r
+ SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(temp_reg));\r
+ _GUARD(gen->Yield(this));\r
+ Return(1, ci->_target, temp_reg);\r
+ outres = gen;\r
+ CLEARSTACK(last_top);\r
+ return true;\r
+ }\r
+ ci->_root = SQTrue;\r
+ }\r
+ break;\r
+ case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = SQTrue; traps += ci->_etraps; break;\r
+ case ET_RESUME_VM:\r
+ case ET_RESUME_THROW_VM:\r
+ traps = _suspended_traps;\r
+ ci->_root = _suspended_root;\r
+ ci->_vargs = _suspend_varargs;\r
+ _suspended = SQFalse;\r
+ if(et == ET_RESUME_THROW_VM) { SQ_THROW(); }\r
+ break;\r
+ }\r
+ \r
+exception_restore:\r
+ //\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_LOADINT: TARGET = (SQInteger)arg1; continue;\r
+ case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue;\r
+ case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;\r
+ case _OP_TAILCALL:\r
+ temp_reg = STK(arg1);\r
+ if (type(temp_reg) == OT_CLOSURE && !_funcproto(_closure(temp_reg)->_function)->_bgenerator){ \r
+ ct_tailcall = true;\r
+ if(ci->_vargs.size) PopVarArgs(ci->_vargs);\r
+ for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);\r
+ ct_target = ci->_target;\r
+ ct_stackbase = _stackbase;\r
+ goto common_call;\r
+ }\r
+ case _OP_CALL: {\r
+ ct_tailcall = false;\r
+ ct_target = arg0;\r
+ temp_reg = STK(arg1);\r
+ ct_stackbase = _stackbase+arg2;\r
+\r
+common_call:\r
+ SQObjectPtr clo = temp_reg;\r
+ SQInteger last_top = _top;\r
+ switch (type(clo)) {\r
+ case OT_CLOSURE:{\r
+ _GUARD(StartCall(_closure(clo), ct_target, arg3, ct_stackbase, ct_tailcall));\r
+ if (_funcproto(_closure(clo)->_function)->_bgenerator) {\r
+ SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(clo));\r
+ _GUARD(gen->Yield(this));\r
+ Return(1, ct_target, clo);\r
+ STK(ct_target) = gen;\r
+ CLEARSTACK(last_top);\r
+ continue;\r
+ }\r
+ }\r
+ continue;\r
+ case OT_NATIVECLOSURE: {\r
+ bool suspend;\r
+ _GUARD(CallNative(_nativeclosure(clo), arg3, ct_stackbase, clo,suspend));\r
+ if(suspend){\r
+ _suspended = SQTrue;\r
+ _suspended_target = ct_target;\r
+ _suspended_root = ci->_root;\r
+ _suspended_traps = traps;\r
+ _suspend_varargs = ci->_vargs;\r
+ outres = clo;\r
+ return true;\r
+ }\r
+ if(ct_target != -1) { //skip return value for constructors\r
+ STK(ct_target) = clo;\r
+ }\r
+ }\r
+ continue;\r
+ case OT_CLASS:{\r
+ SQObjectPtr inst;\r
+ _GUARD(CreateClassInstance(_class(clo),inst,temp_reg));\r
+ STK(ct_target) = inst;\r
+ ct_target = -1; //fakes return value target so that is not overwritten by the constructor\r
+ if(type(temp_reg) != OT_NULL) {\r
+ _stack._vals[ct_stackbase] = inst;\r
+ goto common_call; //hard core spaghetti code(reissues the OP_CALL to invoke the constructor)\r
+ }\r
+ }\r
+ break;\r
+ case OT_TABLE:\r
+ case OT_USERDATA:\r
+ case OT_INSTANCE:\r
+ {\r
+ Push(clo);\r
+ for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i));\r
+ if (_delegable(clo) && CallMetaMethod(_delegable(clo), MT_CALL, arg3+1, clo)){\r
+ STK(ct_target) = clo;\r
+ break;\r
+ }\r
+ Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));\r
+ SQ_THROW();\r
+ }\r
+ default:\r
+ Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));\r
+ SQ_THROW();\r
+ }\r
+ }\r
+ continue;\r
+ case _OP_PREPCALL:\r
+ case _OP_PREPCALLK:\r
+ {\r
+ SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1);\r
+ SQObjectPtr &o = STK(arg2);\r
+ if (!Get(o, key, temp_reg,false,true)) {\r
+ if(type(o) == OT_CLASS) { //hack?\r
+ if(_class_ddel->Get(key,temp_reg)) {\r
+ STK(arg3) = o;\r
+ TARGET = temp_reg;\r
+ continue;\r
+ }\r
+ }\r
+ { Raise_IdxError(key); SQ_THROW();}\r
+ }\r
+\r
+ STK(arg3) = type(o) == OT_CLASS?STK(0):o;\r
+ TARGET = temp_reg;\r
+ }\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),false));\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(ci->_generator) {\r
+ 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(SQInt32 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: _GUARD(GETPARENT_OP(STK(arg1),TARGET)); continue;\r
+ case _OP_COMPARITH: _GUARD(DerefInc(arg3, TARGET, STK((((SQUnsignedInteger)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
+ SQInteger t = _integer(STK(arg1));\r
+ TARGET = SQInteger(~t);\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(ci->_generator) {\r
+ if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);\r
+ _GUARD(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:{ int tojump;\r
+ _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump));\r
+ ci->_ip += tojump; }\r
+ continue;\r
+ case _OP_POSTFOREACH:\r
+ assert(type(STK(arg0)) == OT_GENERATOR);\r
+ if(_generator(STK(arg0))->_state == SQGenerator::eDead) \r
+ ci->_ip += (sarg1 - 1);\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
+ SQInstruction *_iv = _funcproto(_closure(ci->_closure)->_function)->_instructions;\r
+ _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++;\r
+ ci->_etraps++;\r
+ }\r
+ continue;\r
+ case _OP_POPTRAP: {\r
+ for(SQInteger i = 0; i < arg0; i++) {\r
+ _etraps.pop_back(); traps--;\r
+ ci->_etraps--;\r
+ }\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
+ bool bstatic = (arg0&NEW_SLOT_STATIC_FLAG)?true:false;\r
+ if(type(STK(arg1)) == OT_CLASS) {\r
+ if(type(_class(STK(arg1))->_metamethods[MT_NEWMEMBER]) != OT_NULL ) {\r
+ Push(STK(arg1)); Push(STK(arg2)); Push(STK(arg3));\r
+ Push((arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : _null_);\r
+ Push(bstatic);\r
+ int nparams = 5;\r
+ if(Call(_class(STK(arg1))->_metamethods[MT_NEWMEMBER], nparams, _top - nparams, temp_reg,SQFalse)) {\r
+ Pop(nparams);\r
+ continue;\r
+ }\r
+ }\r
+ }\r
+ _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),bstatic));\r
+ if((arg0&NEW_SLOT_ATTRIBUTES_FLAG)) {\r
+ _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1));\r
+ }\r
+ continue;\r
+ }\r
+ \r
+ }\r
+ }\r
+exception_trap:\r
+ {\r
+ SQObjectPtr currerror = _lasterror;\r
+// dumpstack(_stackbase);\r
+ SQInteger n = 0;\r
+ SQInteger last_top = _top;\r
+ if(ci) {\r
+ if(_ss(this)->_notifyallexceptions) CallErrorHandler(currerror);\r
+\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._vals[_stackbase+et._extarget] = currerror;\r
+ _etraps.pop_back(); traps--; ci->_etraps--;\r
+ CLEARSTACK(last_top);\r
+ goto exception_restore;\r
+ }\r
+ //if is a native closure\r
+ if(type(ci->_closure) != OT_CLOSURE && n)\r
+ break;\r
+ if(ci->_generator) ci->_generator->Kill();\r
+ PopVarArgs(ci->_vargs);\r
+ POP_CALLINFO(this);\r
+ n++;\r
+ } while(_callsstacksize);\r
+ }\r
+ else {\r
+ //call the hook\r
+ if(raiseerror && !_ss(this)->_notifyallexceptions)\r
+ CallErrorHandler(currerror);\r
+ }\r
+ //remove call stack until a C function is found or the cstack is empty\r
+ if(ci) do {\r
+ SQBool exitafterthisone = ci->_root;\r
+ if(ci->_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(_callsstacksize);\r
+\r
+ CLEARSTACK(last_top);\r
+ }\r
+ _lasterror = currerror;\r
+ return false;\r
+ }\r
+ assert(0);\r
+}\r
+\r
+bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor)\r
+{\r
+ inst = theclass->CreateInstance();\r
+ if(!theclass->Get(_ss(this)->_constructoridx,constructor)) {\r
+ constructor = _null_;\r
+ }\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,SQFalse);\r
+ Pop(2);\r
+ }\r
+}\r
+\r
+void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline)\r
+{\r
+ SQObjectPtr temp_reg;\r
+ SQInteger 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,SQFalse);\r
+ Pop(nparams);\r
+}\r
+\r
+bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackbase,SQObjectPtr &retval,bool &suspend)\r
+{\r
+ if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }\r
+ SQInteger 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
+ SQInteger tcs;\r
+ if((tcs = nclosure->_typecheck.size())) {\r
+ for(SQInteger i = 0; i < nargs && i < tcs; i++)\r
+ if((nclosure->_typecheck._vals[i] != -1) && !(type(_stack._vals[stackbase+i]) & nclosure->_typecheck[i])) {\r
+ Raise_ParamTypeError(i,nclosure->_typecheck._vals[i],type(_stack._vals[stackbase+i]));\r
+ return false;\r
+ }\r
+ }\r
+ _nnativecalls++;\r
+ if ((_top + MIN_STACK_OVERHEAD) > (SQInteger)_stack.size()) {\r
+ _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD<<1));\r
+ }\r
+ SQInteger oldtop = _top;\r
+ SQInteger oldstackbase = _stackbase;\r
+ _top = stackbase + nargs;\r
+ CallInfo lci;\r
+ lci._closure = nclosure;\r
+ lci._generator = NULL;\r
+ lci._etraps = 0;\r
+ lci._prevstkbase = (SQInt32) (stackbase - _stackbase);\r
+ lci._ncalls = 1;\r
+ lci._prevtop = (SQInt32) (oldtop - oldstackbase);\r
+ PUSH_CALLINFO(this, lci);\r
+ _stackbase = stackbase;\r
+ //push free variables\r
+ SQInteger outers = nclosure->_outervalues.size();\r
+ for (SQInteger i = 0; i < outers; i++) {\r
+ Push(nclosure->_outervalues[i]);\r
+ }\r
+\r
+ if(type(nclosure->_env) == OT_WEAKREF) {\r
+ _stack[stackbase] = _weakref(nclosure->_env)->_obj;\r
+ }\r
+\r
+ \r
+ SQInteger 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(); TOP().Null(); }\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
+ default:break; //shut up compiler\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((int)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
+ case OT_WEAKREF:\r
+ if(raw)return false;\r
+ return _weakref_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
+ SQObjectPtr newobj;\r
+ switch(type(self)){\r
+ case OT_TABLE:\r
+ newobj = _table(self)->Clone();\r
+ goto cloned_mt;\r
+ case OT_INSTANCE:\r
+ newobj = _instance(self)->Clone(_ss(this));\r
+cloned_mt:\r
+ if(_delegable(newobj)->_delegate){\r
+ Push(newobj);\r
+ Push(self);\r
+ CallMetaMethod(_delegable(newobj),MT_CLONED,2,temp_reg);\r
+ }\r
+ target = newobj;\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,bool bstatic)\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_INSTANCE: {\r
+ SQObjectPtr res;\r
+ Push(self);Push(key);Push(val);\r
+ if(!CallMetaMethod(_instance(self),MT_NEWSLOT,3,res)) {\r
+ Raise_Error(_SC("class instances do not support the new slot operator"));\r
+ return false;\r
+ }\r
+ break;}\r
+ case OT_CLASS: \r
+ if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) {\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,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror)\r
+{\r
+#ifdef _DEBUG\r
+SQInteger prevstackbase = _stackbase;\r
+#endif\r
+ switch(type(closure)) {\r
+ case OT_CLOSURE:\r
+ return Execute(closure, _top - nparams, nparams, stackbase,outres,raiseerror);\r
+ break;\r
+ case OT_NATIVECLOSURE:{\r
+ bool suspend;\r
+ return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend);\r
+ \r
+ }\r
+ break;\r
+ case OT_CLASS: {\r
+ SQObjectPtr constr;\r
+ SQObjectPtr temp;\r
+ CreateClassInstance(_class(closure),outres,constr);\r
+ if(type(constr) != OT_NULL) {\r
+ _stack[stackbase] = outres;\r
+ return Call(constr,nparams,stackbase,temp,raiseerror);\r
+ }\r
+ return true;\r
+ }\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,SQInteger nparams,SQObjectPtr &outres)\r
+{\r
+ SQObjectPtr closure;\r
+ if(del->GetMetaMethod(this, mm, closure)) {\r
+ if(Call(closure, nparams, _top - nparams, outres, SQFalse)) {\r
+ Pop(nparams);\r
+ return true;\r
+ }\r
+ }\r
+ Pop(nparams);\r
+ return false;\r
+}\r
+\r
+void SQVM::Remove(SQInteger n) {\r
+ n = (n >= 0)?n + _stackbase - 1:_top + n;\r
+ for(SQInteger i = n; i < _top; i++){\r
+ _stack[i] = _stack[i+1];\r
+ }\r
+ _stack[_top] = _null_;\r
+ _top--;\r
+}\r
+\r
+void SQVM::Pop() {\r
+ _stack[--_top] = _null_;\r
+}\r
+\r
+void SQVM::Pop(SQInteger n) {\r
+ for(SQInteger i = 0; i < n; i++){\r
+ _stack[--_top] = _null_;\r
+ }\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(SQInteger n) { return _stack[_top+n]; }\r
+SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; }\r
+\r
+#ifdef _DEBUG_DUMP\r
+void SQVM::dumpstack(SQInteger stackbase,bool dumpall)\r
+{\r
+ SQInteger size=dumpall?_stack.size():_top;\r
+ SQInteger n=0;\r
+ scprintf(_SC("\n>>>>stack dump<<<<\n"));\r
+ CallInfo &ci=_callsstack[_callsstacksize-1];\r
+ scprintf(_SC("IP: %p\n"),ci._ip);\r
+ scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase);\r
+ scprintf(_SC("prev top: %d\n"),ci._prevtop);\r
+ for(SQInteger 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 %p"),_generator(obj));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
+ case OT_WEAKREF: scprintf(_SC("WEAKERF %p"),_weakref(obj));break;\r
+ default:\r
+ assert(0);\r
+ break;\r
+ };\r
+ scprintf(_SC("\n"));\r
+ ++n;\r
+ }\r
+}\r
+\r
+\r
+\r
+#endif\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(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}
- SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; }
- SQInteger _stackbase;
- SQInteger _stacksize;
- SQInstruction *_ip;
- SQInteger _extarget;
-};
-
-#define _INLINE
-
-#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; }
- unsigned short size;
- unsigned short base;
- };
-
- struct CallInfo{
- //CallInfo() { _generator._type = OT_NULL;}
- SQInstruction *_ip;
- SQObjectPtr *_literals;
- SQObjectPtr _closure;
- SQGenerator *_generator;
- SQInt32 _etraps;
- SQInt32 _prevstkbase;
- SQInt32 _prevtop;
- SQInt32 _target;
- SQInt32 _ncalls;
- SQBool _root;
- VarArgs _vargs;
- };
-
-typedef sqvector<CallInfo> CallInfoVec;
-public:
- enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM, ET_RESUME_THROW_VM };
- SQVM(SQSharedState *ss);
- ~SQVM();
- bool Init(SQVM *friendvm, SQInteger stacksize);
- bool Execute(SQObjectPtr &func, SQInteger target, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL);
- //starts a native call return when the NATIVE closure returns
- bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger stackbase, SQObjectPtr &retval,bool &suspend);
- //starts a SQUIRREL call in the same "Execution loop"
- bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);
- bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor);
- //call a generic closure pure SQUIRREL or NATIVE
- bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror);
- SQRESULT Suspend();
-
- void CallDebugHook(SQInteger type,SQInteger 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 bstatic);
- 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,SQInteger &res);
- bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);
- bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res);
- void ToString(const SQObjectPtr &o,SQObjectPtr &res);
- 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(SQInteger nparam,SQInteger typemask,SQInteger type);
-
- void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);
- bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres);
- bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
- bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval);
- //new stuff
- _INLINE bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
- _INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
- _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);
- _INLINE 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,SQInteger base,SQInteger attrs);
- bool GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target);
- //return true if the loop is finished
- bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump);
- bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2);
- _INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
- _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
- _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix);
- void PopVarArgs(VarArgs &vargs);
- void ClearStack(SQInteger last_top);
-#ifdef _DEBUG_DUMP
- void dumpstack(SQInteger stackbase=-1, bool dumpall = false);
-#endif
-
-#ifndef NO_GARBAGE_COLLECTOR
- void Mark(SQCollectable **chain);
-#endif
- void Finalize();
- void GrowCallStack() {
- SQInteger newsize = _alloccallsstacksize*2;
- _callstackdata.resize(newsize);
- _callsstack = &_callstackdata[0];
- _alloccallsstacksize = newsize;
- }
- void Release(){ sq_delete(this,SQVM); } //does nothing
-////////////////////////////////////////////////////////////////////////////
- //stack functions for the api
- void Remove(SQInteger n);
-
- bool IsFalse(SQObjectPtr &o);
-
- void Pop();
- void Pop(SQInteger n);
- void Push(const SQObjectPtr &o);
- SQObjectPtr &Top();
- SQObjectPtr &PopGet();
- SQObjectPtr &GetUp(SQInteger n);
- SQObjectPtr &GetAt(SQInteger n);
-
- SQObjectPtrVec _stack;
- SQObjectPtrVec _vargsstack;
- SQInteger _top;
- SQInteger _stackbase;
- SQObjectPtr _roottable;
- SQObjectPtr _lasterror;
- SQObjectPtr _errorhandler;
- SQObjectPtr _debughook;
-
- SQObjectPtr temp_reg;
-
-
- CallInfo* _callsstack;
- SQInteger _callsstacksize;
- SQInteger _alloccallsstacksize;
- sqvector<CallInfo> _callstackdata;
-
- ExceptionsTraps _etraps;
- CallInfo *ci;
- void *_foreignptr;
- //VMs sharing the same state
- SQSharedState *_sharedstate;
- SQInteger _nnativecalls;
- //suspend infos
- SQBool _suspended;
- SQBool _suspended_root;
- SQInteger _suspended_target;
- SQInteger _suspended_traps;
- VarArgs _suspend_varargs;
-};
-
-struct AutoDec{
- AutoDec(SQInteger *n) { _n = n; }
- ~AutoDec() { (*_n)--; }
- SQInteger *_n;
-};
-
-inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}
-
-#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){ \
- if(v->_callsstacksize == v->_alloccallsstacksize) { \
- v->GrowCallStack(); \
- } \
- v->ci = &v->_callsstack[v->_callsstacksize]; \
- *(v->ci) = nci; \
- v->_callsstacksize++; \
-}
-
-#define POP_CALLINFO(v){ \
- v->_callsstacksize--; \
- v->ci->_closure.Null(); \
- if(v->_callsstacksize) \
- v->ci = &v->_callsstack[v->_callsstacksize-1] ; \
- else \
- v->ci = NULL; \
-}
-#endif //_SQVM_H_
+/* 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(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}\r
+ SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; }\r
+ SQInteger _stackbase;\r
+ SQInteger _stacksize;\r
+ SQInstruction *_ip;\r
+ SQInteger _extarget;\r
+};\r
+\r
+#define _INLINE \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
+ unsigned short size;\r
+ unsigned short base;\r
+ };\r
+\r
+ struct CallInfo{\r
+ //CallInfo() { _generator._type = OT_NULL;}\r
+ SQInstruction *_ip;\r
+ SQObjectPtr *_literals;\r
+ SQObjectPtr _closure;\r
+ SQGenerator *_generator;\r
+ SQInt32 _etraps;\r
+ SQInt32 _prevstkbase;\r
+ SQInt32 _prevtop;\r
+ SQInt32 _target;\r
+ SQInt32 _ncalls;\r
+ SQBool _root;\r
+ VarArgs _vargs;\r
+ };\r
+ \r
+typedef sqvector<CallInfo> CallInfoVec;\r
+public:\r
+ enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM, ET_RESUME_THROW_VM };\r
+ SQVM(SQSharedState *ss);\r
+ ~SQVM();\r
+ bool Init(SQVM *friendvm, SQInteger stacksize);\r
+ bool Execute(SQObjectPtr &func, SQInteger target, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL);\r
+ //starts a native call return when the NATIVE closure returns\r
+ bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger stackbase, SQObjectPtr &retval,bool &suspend);\r
+ //starts a SQUIRREL call in the same "Execution loop"\r
+ bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);\r
+ bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor);\r
+ //call a generic closure pure SQUIRREL or NATIVE\r
+ bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror);\r
+ SQRESULT Suspend();\r
+\r
+ void CallDebugHook(SQInteger type,SQInteger 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,bool bstatic);\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,SQInteger &res);\r
+ bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);\r
+ bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res);\r
+ void ToString(const SQObjectPtr &o,SQObjectPtr &res);\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(SQInteger nparam,SQInteger typemask,SQInteger type);\r
+\r
+ void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);\r
+ bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres);\r
+ bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);\r
+ bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval);\r
+ //new stuff\r
+ _INLINE bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);\r
+ _INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);\r
+ _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);\r
+ _INLINE 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,SQInteger base,SQInteger attrs);\r
+ bool GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target);\r
+ //return true if the loop is finished\r
+ bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump);\r
+ bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2);\r
+ _INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);\r
+ _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);\r
+ _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix);\r
+ void PopVarArgs(VarArgs &vargs);\r
+ void ClearStack(SQInteger last_top);\r
+#ifdef _DEBUG_DUMP\r
+ void dumpstack(SQInteger stackbase=-1, bool dumpall = false);\r
+#endif\r
+\r
+#ifndef NO_GARBAGE_COLLECTOR\r
+ void Mark(SQCollectable **chain);\r
+#endif\r
+ void Finalize();\r
+ void GrowCallStack() {\r
+ SQInteger newsize = _alloccallsstacksize*2;\r
+ _callstackdata.resize(newsize);\r
+ _callsstack = &_callstackdata[0];\r
+ _alloccallsstacksize = newsize;\r
+ }\r
+ void Release(){ sq_delete(this,SQVM); } //does nothing\r
+////////////////////////////////////////////////////////////////////////////\r
+ //stack functions for the api\r
+ void Remove(SQInteger n);\r
+\r
+ bool IsFalse(SQObjectPtr &o);\r
+ \r
+ void Pop();\r
+ void Pop(SQInteger n);\r
+ void Push(const SQObjectPtr &o);\r
+ SQObjectPtr &Top();\r
+ SQObjectPtr &PopGet();\r
+ SQObjectPtr &GetUp(SQInteger n);\r
+ SQObjectPtr &GetAt(SQInteger n);\r
+\r
+ SQObjectPtrVec _stack;\r
+ SQObjectPtrVec _vargsstack;\r
+ SQInteger _top;\r
+ SQInteger _stackbase;\r
+ SQObjectPtr _roottable;\r
+ SQObjectPtr _lasterror;\r
+ SQObjectPtr _errorhandler;\r
+ SQObjectPtr _debughook;\r
+\r
+ SQObjectPtr temp_reg;\r
+ \r
+\r
+ CallInfo* _callsstack;\r
+ SQInteger _callsstacksize;\r
+ SQInteger _alloccallsstacksize;\r
+ sqvector<CallInfo> _callstackdata;\r
+\r
+ ExceptionsTraps _etraps;\r
+ CallInfo *ci;\r
+ void *_foreignptr;\r
+ //VMs sharing the same state\r
+ SQSharedState *_sharedstate;\r
+ SQInteger _nnativecalls;\r
+ //suspend infos\r
+ SQBool _suspended;\r
+ SQBool _suspended_root;\r
+ SQInteger _suspended_target;\r
+ SQInteger _suspended_traps;\r
+ VarArgs _suspend_varargs;\r
+};\r
+\r
+struct AutoDec{\r
+ AutoDec(SQInteger *n) { _n = n; }\r
+ ~AutoDec() { (*_n)--; }\r
+ SQInteger *_n;\r
+};\r
+\r
+inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}\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
+ if(v->_callsstacksize == v->_alloccallsstacksize) { \\r
+ v->GrowCallStack(); \\r
+ } \\r
+ v->ci = &v->_callsstack[v->_callsstacksize]; \\r
+ *(v->ci) = nci; \\r
+ v->_callsstacksize++; \\r
+}\r
+\r
+#define POP_CALLINFO(v){ \\r
+ v->_callsstacksize--; \\r
+ v->ci->_closure.Null(); \\r
+ if(v->_callsstacksize) \\r
+ v->ci = &v->_callsstack[v->_callsstacksize-1] ; \\r
+ else \\r
+ v->ci = NULL; \\r
+}\r
+#endif //_SQVM_H_\r