summaryrefslogtreecommitdiffstats
path: root/squirrel_3_0_1_stable
diff options
context:
space:
mode:
authorfaketruth <faketruth@0a769ca7-a7f5-676a-18bf-c427514a06d6>2011-11-08 02:25:01 +0100
committerfaketruth <faketruth@0a769ca7-a7f5-676a-18bf-c427514a06d6>2011-11-08 02:25:01 +0100
commit8285a11a26d78784f26b76e6bcdfa479f6c1a345 (patch)
tree6d567d22754b2d65258b1557e18ea8b590c2c709 /squirrel_3_0_1_stable
parentFixed bug in cChunk.cpp not calculating RedstoneCircuits at the correct positions. Also, forgot to mention you can now place colored wool. (diff)
downloadcuberite-8285a11a26d78784f26b76e6bcdfa479f6c1a345.tar
cuberite-8285a11a26d78784f26b76e6bcdfa479f6c1a345.tar.gz
cuberite-8285a11a26d78784f26b76e6bcdfa479f6c1a345.tar.bz2
cuberite-8285a11a26d78784f26b76e6bcdfa479f6c1a345.tar.lz
cuberite-8285a11a26d78784f26b76e6bcdfa479f6c1a345.tar.xz
cuberite-8285a11a26d78784f26b76e6bcdfa479f6c1a345.tar.zst
cuberite-8285a11a26d78784f26b76e6bcdfa479f6c1a345.zip
Diffstat (limited to 'squirrel_3_0_1_stable')
-rw-r--r--squirrel_3_0_1_stable/COMPILE41
-rw-r--r--squirrel_3_0_1_stable/COPYRIGHT21
-rw-r--r--squirrel_3_0_1_stable/HISTORY422
-rw-r--r--squirrel_3_0_1_stable/Makefile18
-rw-r--r--squirrel_3_0_1_stable/README23
-rw-r--r--squirrel_3_0_1_stable/include/sqstdaux.h16
-rw-r--r--squirrel_3_0_1_stable/include/sqstdblob.h20
-rw-r--r--squirrel_3_0_1_stable/include/sqstdio.h53
-rw-r--r--squirrel_3_0_1_stable/include/sqstdmath.h15
-rw-r--r--squirrel_3_0_1_stable/include/sqstdstring.h33
-rw-r--r--squirrel_3_0_1_stable/include/sqstdsystem.h15
-rw-r--r--squirrel_3_0_1_stable/include/squirrel.h500
-rw-r--r--squirrel_3_0_1_stable/sqplus/Makefile18
-rw-r--r--squirrel_3_0_1_stable/sqplus/SqPlus.cpp382
-rw-r--r--squirrel_3_0_1_stable/sqplus/SqPlusCallTemplates.h337
-rw-r--r--squirrel_3_0_1_stable/sqplus/SqPlusConst.h74
-rw-r--r--squirrel_3_0_1_stable/sqplus/SqPlusFunctionCallImpl.h114
-rw-r--r--squirrel_3_0_1_stable/sqplus/SqPlusOCharBuf.cpp61
-rw-r--r--squirrel_3_0_1_stable/sqplus/SqPlusOCharBuf.h193
-rw-r--r--squirrel_3_0_1_stable/sqplus/SqPlusOverload.h819
-rw-r--r--squirrel_3_0_1_stable/sqplus/SqPlusSetup.h129
-rw-r--r--squirrel_3_0_1_stable/sqplus/SqPlusSmartPointer.h141
-rw-r--r--squirrel_3_0_1_stable/sqplus/SqPlusTypeMask.h169
-rw-r--r--squirrel_3_0_1_stable/sqplus/SqPlusUtf8.cpp133
-rw-r--r--squirrel_3_0_1_stable/sqplus/SqPlusUtf8.h15
-rw-r--r--squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtils.cpp161
-rw-r--r--squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtils.h152
-rw-r--r--squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtilsWin32.cpp31
-rw-r--r--squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtilsWin32.h41
-rw-r--r--squirrel_3_0_1_stable/sqplus/SquirrelObject.cpp702
-rw-r--r--squirrel_3_0_1_stable/sqplus/SquirrelObject.h256
-rw-r--r--squirrel_3_0_1_stable/sqplus/SquirrelVM.cpp505
-rw-r--r--squirrel_3_0_1_stable/sqplus/SquirrelVM.h179
-rw-r--r--squirrel_3_0_1_stable/sqplus/changes.txt359
-rw-r--r--squirrel_3_0_1_stable/sqplus/sqplus.cbp190
-rw-r--r--squirrel_3_0_1_stable/sqplus/sqplus.h2327
-rw-r--r--squirrel_3_0_1_stable/sqplus/sqplus.vcproj355
-rw-r--r--squirrel_3_0_1_stable/sqplus/sqplus.vcxproj159
-rw-r--r--squirrel_3_0_1_stable/sqplus/sqplus.vcxproj.filters65
-rw-r--r--squirrel_3_0_1_stable/sqplus/sqplus.vcxproj.user3
-rw-r--r--squirrel_3_0_1_stable/sqplus/sqplus71.vcproj235
-rw-r--r--squirrel_3_0_1_stable/sqplus/sqplusWin32.h7
-rw-r--r--squirrel_3_0_1_stable/sqstdlib/Makefile41
-rw-r--r--squirrel_3_0_1_stable/sqstdlib/sqstdaux.cpp129
-rw-r--r--squirrel_3_0_1_stable/sqstdlib/sqstdblob.cpp275
-rw-r--r--squirrel_3_0_1_stable/sqstdlib/sqstdblobimpl.h108
-rw-r--r--squirrel_3_0_1_stable/sqstdlib/sqstdio.cpp419
-rw-r--r--squirrel_3_0_1_stable/sqstdlib/sqstdlib.dsp131
-rw-r--r--squirrel_3_0_1_stable/sqstdlib/sqstdmath.cpp107
-rw-r--r--squirrel_3_0_1_stable/sqstdlib/sqstdrex.cpp638
-rw-r--r--squirrel_3_0_1_stable/sqstdlib/sqstdstream.cpp336
-rw-r--r--squirrel_3_0_1_stable/sqstdlib/sqstdstream.h18
-rw-r--r--squirrel_3_0_1_stable/sqstdlib/sqstdstring.cpp378
-rw-r--r--squirrel_3_0_1_stable/sqstdlib/sqstdsystem.cpp147
-rw-r--r--squirrel_3_0_1_stable/squirrel.dsw77
-rw-r--r--squirrel_3_0_1_stable/squirrel/Makefile52
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqapi.cpp1456
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqarray.h94
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqbaselib.cpp1110
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqclass.cpp213
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqclass.h158
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqclosure.h193
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqcompiler.cpp1504
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqcompiler.h77
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqdebug.cpp116
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqfuncproto.h154
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqfuncstate.cpp652
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqfuncstate.h91
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqlexer.cpp489
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqlexer.h47
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqmem.cpp9
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqobject.cpp655
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqobject.h354
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqopcodes.h132
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqpcheader.h19
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqstate.cpp648
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqstate.h144
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqstring.h31
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqtable.cpp220
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqtable.h92
-rw-r--r--squirrel_3_0_1_stable/squirrel/squirrel.dsp302
-rw-r--r--squirrel_3_0_1_stable/squirrel/squserdata.h40
-rw-r--r--squirrel_3_0_1_stable/squirrel/squtils.h112
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqvm.cpp1714
-rw-r--r--squirrel_3_0_1_stable/squirrel/sqvm.h208
85 files changed, 23379 insertions, 0 deletions
diff --git a/squirrel_3_0_1_stable/COMPILE b/squirrel_3_0_1_stable/COMPILE
new file mode 100644
index 000000000..d032a2f4e
--- /dev/null
+++ b/squirrel_3_0_1_stable/COMPILE
@@ -0,0 +1,41 @@
+Squirrel 3.0 stable
+--------------------------------------------------------
+What is in this distribution?
+
+squirrel
+ static library implementing the compiler and interpreter of the language
+
+sqstdlib
+ the standard utility libraries
+
+sq
+ stand alone interpreter
+
+doc
+ The manual
+
+etc
+ a minimalistic embedding sample
+
+samples
+ samples programs
+
+
+HOW TO COMPILE
+---------------------------------------------------------
+GCC USERS
+.........................................................
+There is a very simple makefile that compiles all libraries and exes
+from the root of the project run 'make'
+
+for 32 bits systems
+
+ $ make
+
+for 64 bits systems
+
+ $ make sq64
+
+VISUAL C++ USERS
+.........................................................
+Open squirrel.dsw from the root project directory and build(dho!) \ No newline at end of file
diff --git a/squirrel_3_0_1_stable/COPYRIGHT b/squirrel_3_0_1_stable/COPYRIGHT
new file mode 100644
index 000000000..40bea1615
--- /dev/null
+++ b/squirrel_3_0_1_stable/COPYRIGHT
@@ -0,0 +1,21 @@
+Copyright (c) 2003-2011 Alberto Demichelis
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------
+END OF COPYRIGHT
diff --git a/squirrel_3_0_1_stable/HISTORY b/squirrel_3_0_1_stable/HISTORY
new file mode 100644
index 000000000..d16ae44cc
--- /dev/null
+++ b/squirrel_3_0_1_stable/HISTORY
@@ -0,0 +1,422 @@
+***version 3.0.1 stable***
+-added # as alternative symbol for "line comment"(mostly useful for shell scripts)
+-added sq_throwobject() to throw an arbitrary object from the C API
+-added alignement flag for userdata types, SQ_ALIGNMENT (thx Shigemasa)
+-added rawset() and rawget() to class and instance default delegate
+-changed bytecode format now ensures matching integer size and float size
+-now inherited classes also inherit userdatasize
+-added SQUIRREL_VERSION_NUMBER in squirrel.h and _versionnumber_ global symbol
+-fixed sq_getmemberhandle
+-fixed sq_getrefcount
+-refactored some sqstdio code
+-refactored some clone code
+-refactored some stuff in the string lib
+-added -s and -fno-exceptions in GCC makefile(better performance when using GCC)
+
+***2011-03-13 ***
+***version 3.0 stable***
+-added sq_getcallee()
+-sq_getfreevariable() also works for native closures
+-minior optimizations
+-removed several warning when compiling with GCC 4.x
+-fixed some errors in the documentation
+-fixed bug when using SQUSEDOUBLE and 32bits intengers
+-fixed bug when invoking generators with closure.call() (thx huntercool)
+
+***2010-12-19 ***
+***version 3.0 release candidate 1(RC 1)***
+-improved metamethods error handling
+-added parameter 'isstatic' to _newmember metamethod(thx G.Meyer)
+-added sq_getrefcount() to return number of refences from C++(thx G.Meyer)
+
+***2010-11-07 ***
+***version 3.0 beta 3***
+-license changed to "MIT license"
+-added sq_resurrectunreachable() and resurrectunreachable()
+-added callee() built in function, returns the current running closure
+-added thread.getstackinfos()
+-added sq_objtouserpointer()
+-added sq_newtableex()
+-various refactoring and optimizations
+-fixed several 64bits issues regarding integer to string conversions
+-fixed some bugs when SQUSEDOUBLE is used in 32bits systems
+
+***2010-08-18 ***
+***version 3.0 beta 2.1***
+-fixed bug in class constructor
+-fixed bug in compound arith
+
+***2010-08-12 ***
+***version 3.0 beta 2***
+-class methods can be added or replaced after the class as been instantiated
+-JSON compliant table syntax, this is currently an experimental feature (thx atai)
+-sq_getsize() now returns userdatasize for classes and instances
+-now setroottable() and setconsttable() return the previous value of the respective table
+-fixed bug in compound arith operators when used on a free variable (thx ellon)
+-fixed some x64 minor bugs
+-fixed minor bug in the compiler
+-refactored some VM internals
+-documented sq_getmemberhandle, sq_getbyhandle, sq_setbyhandle to set and get value from classes
+
+***2009-11-15 ***
+***version 3.0 beta 1***
+-various refactoring and optimizations
+-fixed bug in free variables (thx mokehehe)
+-fixed bug in functions with default parameters (thx ara & Yexo)
+-fixed bug in exception handling
+-improved error propagation in _set and _get metamethods ( and 'throw null' for clean failure)
+-added sq_getmemberhandle, sq_getbyhandle, sq_setbyhandle to set and get value from classes
+
+***2009-06-30 ***
+***version 3.0 alpha 2***
+-added real free variables(thx Paul Ruizendaal)
+-added refactored function call implementation and compiler(thx Paul Ruizendaal)
+-added sq_getfunctioninfo
+-added compile time flag SQUSEDOUBLE to use double precision floats
+-added global slot _floatsize_ int the base lib to recognize single precision and double precision builds
+-sq_wakeupvm can now resume the vm with an exception
+-added sqstd_format
+-now blobs can be cloned
+-generators can now be instantiated by calling sq_call() or closure.call()
+-fixed debughook bug
+-fixed cooroutine error propagation
+
+***2008-07-23 ***
+***version 3.0 alpha 1***
+-first branch from 2.x source tree
+-added 'base' keyword
+-removed 'delegate' keyword
+-now compiled scripts are vararg functions
+-added setdelegate() and getdelegate() table builtin methods
+-added <=> 3 ways compare operator
+-added lambda expression @(a,b) a + b
+-added local function statement
+-added array built-in map(),reduce(),apply(),filter() and find()
+-generators hold only a weak reference of the enviroment object
+-removed 'vargv' and 'vargc' keywords
+-now var args are passed as an array called vargv(as a paramter)
+-removed 'parent' keyword
+-added class getbase() built in method
+-instanceof doesn't throw an exception if the left expression is not a class
+-lexical scoping for free variables(free variables are no longer in the second parameter list)
+-sq_setprintfunc accept error func
+-sq_geterrorfunc()
+-added sq_arrayremove() and sq_arrayinsert()
+-error() built in function(works like print but prints using the errorfunc)
+-added native debug hook
+
+***2008-02-17 ***
+***version 2.2 stable***
+-added _newslot metamethod in classes
+-added enums added constants
+-added sq_pushconsttable, sq_setconsttable
+-added default param
+-added octal literals(thx Dinosaur)
+-fixed debug hook, 'calls' and 'returns' are properly notified in the same number.
+-fixed a coroutine bug
+
+***2007-07-29 ***
+***version 2.1.2 stable***
+-new behaviour for generators iteration using foreach
+now when a generator is iterated by foreach the value returned by a 'return val' statement
+will terminate the iteration but will not be returned as foreach iteration
+-added sq_setclassudsize()
+-added sq_clear()
+-added table.clear(), array.clear()
+-fixed sq_cmp() (thx jyuill)
+-fixed minor bugs
+
+***2006-08-21 ***
+***version 2.1.1 stable***
+-vm refactoring
+-optimized internal function memory layout
+-new global symbol _version_ (is the version string)
+-code size optimization for float literals(on 32bits float builts)
+-now the raw ref API(sq_addref etc...) is fully reentrant.
+-fixed a bug in sq_getdelegate() now pushes null if the object doesn't have a delegate(thx MatzeB)
+-improved C reference performances in NO_GARBAGE_COLLECTOR builds
+-sq_getlocal() now enumerates also outer values.
+-fixed regexp library for GCC users.
+
+***2006-03-19 ***
+***version 2.1 stable***
+-added static class fields, new keyword static
+-added 64bits architecture support
+-added global slot _intsize_ int the base lib to recognize 32bits and 64bits builds
+-added functions with fixed environment, closure.bindenv() built-in function
+-all types except userdata and null implement the tostring() method
+-string concatenation now invokes metamethod _tostring
+-new metamethods for class objects _newmember and _inherited
+-sq_call() sq_resume() sq_wakeupvm() have a new signature
+-new C referencing implementation(scales more with the amount of references)
+-refactored hash table
+-new api functions sq_newslot(),sq_tobool(),sq_getbase(), sq_instanceof(), sq_bindenv()
+-the api func sq_createslot was deprecated but still supported in form of C macro on top of sq_newslot
+-sq_setreleasehook() now also works for classes
+-stream.readstr() and stream.writestr() have been deprecated(this affects file and blob)
+-fixed squirrel.h undeclared api calls
+-fixed few minor bugs
+-SQChar is now defined as wchar_t
+-removed warning when building with -Wall -pedantic for GCC users
+-added new std io function writeclosuretofile()
+-added new std string functions strip(),rstrip(),lstrip() and split()
+-regular expressions operators (+,*) now have more POSIX greedyness behaviour
+-class constructors are now invoked as normal functions
+
+***2005-10-02 ***
+***version 2.0.5 stable***
+-fixed some 64bits incompatibilities (thx sarge)
+-fixed minor bug in the stdlib format() function (thx Rick)
+-fixed a bug in dofile() that was preventing to compile empty files
+-added new API sq_poptop() & sq_getfreevariable()
+-some performance improvements
+
+***2005-08-14 ***
+***version 2.0.4 stable***
+-weak references and related API calls
+-added sq_objtobool()
+-class instances memory policies improved(1 mem allocation for the whole instance)
+-typetags are now declared as SQUserPointer instead of unsigned int
+-first pass for 64bits compatibility
+-fixed minor bug in the stdio stream
+-fixed a bug in format()
+-fixed bug in string.tointeger() and string.tofloat()
+
+***2005-06-24 ***
+***version 2.0.3 stable***
+-dofile() and loadfile() in the iolib now can decode ASCII, UTF8 files UCS2 big-endian and little-endian
+-sq_setparamscheck() : now typemesk can check for null
+-added string escape sequence \xhhhh
+-fixed some C++ standard incompatibilities
+
+***2005-05-15 ***
+***version 2.0.2 stable***
+-performances improvements (expecially for GCC users)
+-removed all dependencies from C++ exception handling
+-various bugfixes
+
+***2005-04-12 ***
+***version 2.0.1 stable***
+-various bugfixes
+-sq_setparamscheck() now allows spaces in the typemask
+
+***2005-04-03 ***
+***version 2.0 stable***
+-added API sq_gettypetag()
+-added built-in function to the bool type(tointeger, tostring etc...)
+
+***2005-02-27 ***
+***version 2.0 release candidate 1(RC 1)***
+-added API sq_reseterror()
+-modified sq_release()
+-now class instances can be cloned
+-various bufixes
+
+***2005-01-26 ***
+***version 2.0 beta 1***
+-added bool type
+-class properties can be redefined in a derived class
+-added ops *= /= and %=
+-new syntax for class attributes declaration </ and /> instead of ( and )
+-increased the max number of literals per function from 65535 to 16777215
+-now free variables have proper lexical scoping
+-added API sq_createinstance(), sq_pushbool(), sq_getbool()
+-added built-in function type()
+-added built-in function obj.rawin(key) in table,class and instance
+-sq_rawget() and sq_rawset() now work also on classes and instances
+-the VM no longer uses C++ exception handling (more suitable for embedded devices)
+-various bufixes
+
+***2004-12-21 ***
+***version 2.0 alpha 2***
+-globals scoping changed, now if :: is omitted the VM automatically falls back on the root table
+-various bufixes
+-added class level attributes
+
+***2004-12-12 ***
+***version 2.0 alpha 1***
+-codebase branch from version 1.x
+-added classes
+-added functions with variable number of parameters(vargc & vargv and the ...)
+-0 and 0.0 are now considered 'false' by all conditional statements(if,while,for,?,do-while)
+-added new api functions sq_newclass() sq_setinstanceup() sq_getinstanceup() sq_getattributes() sq_setattributes()
+-modified api sq_settypetag()
+
+***2004-11-01 ***
+***version 1.0 stable***
+-fixed some minor bug
+-improved operator 'delete' performances
+-added scientific notation for float numbers( eg. 2.e16 or 2.e-2)
+
+***2004-08-30 ***
+***version 1.0 release candidate 2(RC 2)***
+-fixed bug in the vm(thx Pierre Renaux)
+-fixed bug in the optimizer(thx Pierre Renaux)
+-fixed some bug in the documentation(thx JD)
+-added new api functions for raw object handling
+-removed nested multiline comments
+-reduced memory footprint in C references
+
+***2004-08-23 ***
+***version 1.0 release candidate 1(RC 1)***
+-fixed division by zero
+-the 'in' operator and obj.rawget() do not query the default delegate anymore
+-added function sq_getprintfunc()
+-added new standard library 'auxlib'(implements default error handlers)
+
+***2004-07-12 ***
+***version 1.0 beta 4***
+-fixed a bug in the integer.tochar() built-in method
+-fixed unary minus operator
+-fixed bug in dofile()
+-fixed inconsistency between != and == operators(on float/integer comparison)
+-added javascript style unsigned right shift operator '>>>'
+-added array(size) constructor built-in function
+-array.resize(size,[fill]) built-in function accepts an optional 'fill' value
+-improved debug API, added sq_getclosureinfo() and sq_setnativeclosurename()
+
+***2004-05-23 ***
+***version 1.0 beta 3***
+-minor vm bug fixes
+-string allocation is now faster
+-tables and array memory usage is now less conservative(they shrink)
+-added regular expression routines in the standard library
+-The 'c' expression now accepts only 1 character(thx irbrian)
+-multiline strings <[ ]> have been substituted with C# style verbatim strings (eg. @"string")
+-added new keyword 'parent' for accessing the delegate of tables and unserdata
+-The metamethod '_clone' has been renamed '_cloned'
+-the _delslot metamethod's behaviour and prototype have been changed
+-new default function in the integer and float object 'tochar()'
+-the built-in function chcode2string has been removed
+-the default method [table].getdelegate() has been removed
+-new api sq_rawdeleteslot()
+-new table built-in method rawdelete(key)
+-the dynamic mudule loading has been removed from the standard distribution
+-some optimizations in the VM
+
+***2004-04-21 ***
+***version 1.0 beta 2***
+-minor compiler/parser bug fixes
+-sq_newclosure has a different prototype, the "paramscheck" of paramter has been moved to the new function sq_setparamscheck()
+-sq_setparamscheck allows to add automatic parameters type checking in native closures
+-sq_compile() lost the lineinfo parameter
+-new api sq_enabledebuginfo() globally sets compiler's debug info generation
+-added consistency check on bytecode serialization
+-fixed += operator, now works on strings like +
+-added global slot in the base lib _charsize_ to recognize unicode builds from ascii builds runtime
+-added registry table
+-new api call sq_pushregistrytable()
+-added type tag to the userdata type sq_settypetag()
+-sq_getuserdata now queries the userdata typetag
+-the built in function collect_garbage() as been renamed collectgarbage() for consistency reasons
+-new standard libraries(sqlibs are now obsolete)
+
+***2004-02-20 ***
+***version 1.0 beta 1***
+-fixed a bug in the compiler (thanks Martin Kofler)
+-fixed bug in the switch case statement
+-fixed the _unm metamethod
+-fixed minor bugs in the API
+-fixed automatic stack resizing
+-first beta version
+ first pass code clean up in the VM and base lib
+ first pass code coverege test has been done on VM and built-in lib
+-new VM creation API sq_open() sq_close() (sq_newvm and sq_releasevm are now obsolete)
+-new api allows to specifiy a "print" function to output text(sq_printfunc)
+-added some small optimizations
+-new cooperative multi-threading capabilities in the base library(coroutines), VMs are now a built in type("thread")
+-new built in functions have been added for manipulating the new "thread" type
+-friend virtual machines share the same root table, error handler and debug hook by default
+-new compile time options
+
+***2004-01-19 ***
+***version 0.9 alpha***
+-fixed a garbage collection bug
+-fixed some API bugs(thanks to Joshua Jensen)
+-fixed tail calls (in the version 0.8 the tail call optimization was erroneously disabled)
+-new function parameters semantic, now passing a wrong number of parameters generates an exception
+-native closures have now a built in parameter number checking
+-sq_rawget and sq_rawset now work also on arrays
+-sq_getsize now woks also on userdata
+-the userdata release hook prototype is changed(now passes the size of the userdata)
+-the lexer reader function now returns an integer instead of a char that allows better error checking on the input(thx Joshua Jensen)
+-faster compiler
+-try/catch blocks do not cause any runtime memory allocation anymore
+
+***2003-12-06 ***
+***version 0.8 alpha***
+-fixed a bug that was preventing to have callable userdata throught the metamethod _call
+-fixed a garbage collection bug
+-fixed == operator now can compare correctly different types
+-new built in method getstackinfos(level)
+-improved line informations precision for the debug hook
+-new api call sq_compilebuffer()
+-new built-in api function compilestring()
+-new syntactic sugar for function declarations inside tables
+-the debug API has been finalized
+
+***2003-11-17 ***
+***version 0.7 alpha***
+-fixed critical bug SQInteger the tail call system
+-fixed bug in the continue statement code generation
+-fixed func call param issue(thanks to Rewoonenco Andrew)
+-added _delslot metamethod(thanks to Rewoonenco Andrew)
+-new multiline string expression ( delimited by <[ and ]> )
+-normal strings ("") do not allow embedded new line anymore
+-reduced vm memory footprint(C refs are shared between friend VMs)
+-new api method sq_deleteslot()
+-new debug hook event 'r' is triggered when a function returns
+
+***2003-11-04 ***
+***version 0.6 alpha***
+-fixed switch statement(was executing the default case after a break)
+-sq_call() doesn't pop the closure (just the params)
+-the vm execution can be suspended from the C API anytime (micro-threads)
+-new api calls sq_suspendvm() sq_wakeupvm() sq_getvmstate() and sq_reservestack()
+
+***2003-10-13 ***
+***version 0.5 alpha***
+-fixed some minor bug
+-tested with non ASCII identifiers in unicode mode(I've tried chinese chars)
+-added built-in function string.find()
+-the built-in function array.sort() optionally accepts a cmp(a,b) function
+-the debug hook function now has a new prototype debug_hook(event_type,sourcefile,line,functionname)
+-fixed some debug info imprecision
+
+***2003-10-01 ***
+***version 0.4 alpha***
+-faster VM
+-sq_call will pop arguments and closure also in case of failure
+-fixed a bug in sq_remove
+-now the VM detects delegation cycles(and throws an exception)
+-new operators ++ and --
+-new operator ',' comma operator
+-fixed some expression precedence issue
+-fixed bug in sq_arraypop
+
+***2003-09-15 ***
+***version 0.3 alpha***
+-fixed a bug in array::insert()
+-optional Unicode core(define SQUNICODE or _UNICODE on Win32)
+-sq_compiler uses a new reader function SQLEXREADFUNC
+-the debug hook passes 'l' instead of 'line' for line callbacks
+ and 'c' instead of 'call' for call callbacks
+-new array.extend() bulit-in function
+-new API sq_clone()
+
+***2003-09-10 ***
+***version 0.2 pre-alpha***
+-new completely reentrant VM (sq_open and sq_close are now obsolete)
+-sq_newvm() has a new prototype
+-allocators are now global and linked in the VM
+-_newslot meta method added
+-rawset creates a slot if doesn't exists
+-the compiler error callback pass the vm handle(thanks Pierre Renaux)
+-sq_setforeignptr() sq_getforeingptr() are now public
+-sq_resume() now is possible to resume generators from C
+-sq_getlasterror() retrieve the last thrown error
+-improved docs
+
+***2003-09-06 ***
+***version 0.1 pre-alpha***
+first release
diff --git a/squirrel_3_0_1_stable/Makefile b/squirrel_3_0_1_stable/Makefile
new file mode 100644
index 000000000..8218f5bfa
--- /dev/null
+++ b/squirrel_3_0_1_stable/Makefile
@@ -0,0 +1,18 @@
+
+SQUIRREL=.
+MAKE=make
+
+sq32:
+ cd squirrel; $(MAKE)
+ cd sqstdlib; $(MAKE)
+ cd sq; $(MAKE)
+
+sqprof:
+ cd squirrel; $(MAKE) sqprof
+ cd sqstdlib; $(MAKE) sqprof
+ cd sq; $(MAKE) sqprof
+
+sq64:
+ cd squirrel; $(MAKE) sq64
+ cd sqstdlib; $(MAKE) sq64
+ cd sq; $(MAKE) sq64
diff --git a/squirrel_3_0_1_stable/README b/squirrel_3_0_1_stable/README
new file mode 100644
index 000000000..803b26aa1
--- /dev/null
+++ b/squirrel_3_0_1_stable/README
@@ -0,0 +1,23 @@
+The programming language SQUIRREL 3.0 stable
+
+--------------------------------------------------
+The project has been compiled and run on Windows(x86 and x64) and
+Linux(x86 and x64) and Solaris(x86 and x64).
+
+Has been tested with the following compilers:
+ MS Visual C++ 6.0,7.0,7.1,8.0,9.0,10.0 (32 and 64bits)
+ MinGW gcc 3.2 (mingw special 20020817-1)
+ Cygnus gcc 3.2
+ Linux gcc 3.2.3
+ Linux gcc 4.0.0 (x86 & 64bits)
+ Solaris gcc 4.0.0 (x86 & 64bits)
+
+
+Feedback and suggestions are appreciated
+project page - http://www.squirrel-lang.org
+community forums - http://forum.squirrel-lang.org
+wiki - http://wiki.squirrel-lang.org
+author - alberto@demichelis.net
+
+END OF README
+
diff --git a/squirrel_3_0_1_stable/include/sqstdaux.h b/squirrel_3_0_1_stable/include/sqstdaux.h
new file mode 100644
index 000000000..b90034823
--- /dev/null
+++ b/squirrel_3_0_1_stable/include/sqstdaux.h
@@ -0,0 +1,16 @@
+/* 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_ */
diff --git a/squirrel_3_0_1_stable/include/sqstdblob.h b/squirrel_3_0_1_stable/include/sqstdblob.h
new file mode 100644
index 000000000..eda4cc9c5
--- /dev/null
+++ b/squirrel_3_0_1_stable/include/sqstdblob.h
@@ -0,0 +1,20 @@
+/* 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_*/
+
diff --git a/squirrel_3_0_1_stable/include/sqstdio.h b/squirrel_3_0_1_stable/include/sqstdio.h
new file mode 100644
index 000000000..1174201a9
--- /dev/null
+++ b/squirrel_3_0_1_stable/include/sqstdio.h
@@ -0,0 +1,53 @@
+/* see copyright notice in squirrel.h */
+#ifndef _SQSTDIO_H_
+#define _SQSTDIO_H_
+
+#ifdef __cplusplus
+
+#define SQSTD_STREAM_TYPE_TAG 0x80000000
+
+struct 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_*/
+
diff --git a/squirrel_3_0_1_stable/include/sqstdmath.h b/squirrel_3_0_1_stable/include/sqstdmath.h
new file mode 100644
index 000000000..420f2ce67
--- /dev/null
+++ b/squirrel_3_0_1_stable/include/sqstdmath.h
@@ -0,0 +1,15 @@
+/* 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_*/
diff --git a/squirrel_3_0_1_stable/include/sqstdstring.h b/squirrel_3_0_1_stable/include/sqstdstring.h
new file mode 100644
index 000000000..771c2f658
--- /dev/null
+++ b/squirrel_3_0_1_stable/include/sqstdstring.h
@@ -0,0 +1,33 @@
+/* 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_*/
diff --git a/squirrel_3_0_1_stable/include/sqstdsystem.h b/squirrel_3_0_1_stable/include/sqstdsystem.h
new file mode 100644
index 000000000..daefa0fd5
--- /dev/null
+++ b/squirrel_3_0_1_stable/include/sqstdsystem.h
@@ -0,0 +1,15 @@
+/* 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_ */
diff --git a/squirrel_3_0_1_stable/include/squirrel.h b/squirrel_3_0_1_stable/include/squirrel.h
new file mode 100644
index 000000000..baaaf39c5
--- /dev/null
+++ b/squirrel_3_0_1_stable/include/squirrel.h
@@ -0,0 +1,500 @@
+/*
+Copyright (c) 2003-2011 Alberto Demichelis
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#ifndef _SQUIRREL_H_
+#define _SQUIRREL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SQUIRREL_API
+#define SQUIRREL_API extern
+#endif
+
+#if (defined(_WIN64) || defined(_LP64))
+#ifndef _SQ64
+#define _SQ64
+#endif
+#endif
+
+#ifdef _SQ64
+
+#ifdef _MSC_VER
+typedef __int64 SQInteger;
+typedef unsigned __int64 SQUnsignedInteger;
+typedef unsigned __int64 SQHash; /*should be the same size of a pointer*/
+#else
+typedef long long SQInteger;
+typedef unsigned long long SQUnsignedInteger;
+typedef unsigned long long SQHash; /*should be the same size of a pointer*/
+#endif
+typedef int SQInt32;
+typedef unsigned int SQUnsignedInteger32;
+#else
+typedef int SQInteger;
+typedef int SQInt32; /*must be 32 bits(also on 64bits processors)*/
+typedef unsigned int SQUnsignedInteger32; /*must be 32 bits(also on 64bits processors)*/
+typedef unsigned int SQUnsignedInteger;
+typedef unsigned int SQHash; /*should be the same size of a pointer*/
+#endif
+
+
+#ifdef SQUSEDOUBLE
+typedef double SQFloat;
+#else
+typedef float SQFloat;
+#endif
+
+#if defined(SQUSEDOUBLE) && !defined(_SQ64) || !defined(SQUSEDOUBLE) && defined(_SQ64)
+#ifdef _MSC_VER
+typedef __int64 SQRawObjectVal; //must be 64bits
+#else
+typedef long long SQRawObjectVal; //must be 64bits
+#endif
+#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
+
+#ifndef SQ_ALIGNMENT // SQ_ALIGNMENT shall be less than or equal to SQ_MALLOC alignments, and its value shall be power of 2.
+#if defined(SQUSEDOUBLE) || defined(_SQ64)
+#define SQ_ALIGNMENT 8
+#else
+#define SQ_ALIGNMENT 4
+#endif
+#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;
+struct SQOuter;
+
+#ifdef _UNICODE
+#define SQUNICODE
+#endif
+
+#ifdef SQUNICODE
+#if (defined(_MSC_VER) && _MSC_VER >= 1400) // 1400 = VS8
+
+#if !defined(_NATIVE_WCHAR_T_DEFINED) //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
+#ifdef _SQ64
+#define scstrtol _wcstoi64
+#else
+#define scstrtol wcstol
+#endif
+#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
+#ifdef _SQ64
+#ifdef _MSC_VER
+#define scstrtol _strtoi64
+#else
+#define scstrtol strtoll
+#endif
+#else
+#define scstrtol strtol
+#endif
+#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
+
+#ifdef _SQ64
+#define _PRINT_INT_PREC _SC("ll")
+#define _PRINT_INT_FMT _SC("%lld")
+#else
+#define _PRINT_INT_FMT _SC("%d")
+#endif
+
+#define SQUIRREL_VERSION _SC("Squirrel 3.0.1 stable")
+#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2011 Alberto Demichelis")
+#define SQUIRREL_AUTHOR _SC("Alberto Demichelis")
+#define SQUIRREL_VERSION_NUMBER 301
+
+#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
+#define _RT_OUTER 0x00020000
+
+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),
+ OT_OUTER = (_RT_OUTER|SQOBJECT_REF_COUNTED) //internal usage only
+}SQObjectType;
+
+#define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED)
+
+
+typedef union tagSQObjectValue
+{
+ struct SQTable *pTable;
+ struct SQArray *pArray;
+ struct SQClosure *pClosure;
+ struct SQOuter *pOuter;
+ 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 tagSQMemberHandle{
+ SQBool _static;
+ SQInteger _index;
+}SQMemberHandle;
+
+typedef struct tagSQStackInfos{
+ const SQChar* funcname;
+ const SQChar* source;
+ SQInteger line;
+}SQStackInfos;
+
+typedef struct SQVM* HSQUIRRELVM;
+typedef SQObject HSQOBJECT;
+typedef SQMemberHandle HSQMEMBERHANDLE;
+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 void (*SQDEBUGHOOK)(HSQUIRRELVM /*v*/, SQInteger /*type*/, const SQChar * /*sourcename*/, SQInteger /*line*/, const SQChar * /*funcname*/);
+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,SQPRINTFUNCTION errfunc);
+SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v);
+SQUIRREL_API SQPRINTFUNCTION sq_geterrorfunc(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 SQRESULT 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_newtableex(HSQUIRRELVM v,SQInteger initialcapacity);
+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 SQRESULT 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);
+SQUIRREL_API SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle);
+SQUIRREL_API SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle);
+SQUIRREL_API SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle);
+
+/*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 SQRESULT sq_getcallee(HSQUIRRELVM v);
+SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
+SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err);
+SQUIRREL_API SQRESULT sq_throwobject(HSQUIRRELVM v);
+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 SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po);
+SQUIRREL_API void sq_resetobject(HSQOBJECT *po);
+SQUIRREL_API const SQChar *sq_objtostring(const HSQOBJECT *o);
+SQUIRREL_API SQBool sq_objtobool(const HSQOBJECT *o);
+SQUIRREL_API SQInteger sq_objtointeger(const HSQOBJECT *o);
+SQUIRREL_API SQFloat sq_objtofloat(const HSQOBJECT *o);
+SQUIRREL_API SQUserPointer sq_objtouserpointer(const HSQOBJECT *o);
+SQUIRREL_API SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag);
+
+/*GC*/
+SQUIRREL_API SQInteger sq_collectgarbage(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_resurrectunreachable(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);
+SQUIRREL_API void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook);
+
+/*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
+
+#endif /*_SQUIRREL_H_*/
diff --git a/squirrel_3_0_1_stable/sqplus/Makefile b/squirrel_3_0_1_stable/sqplus/Makefile
new file mode 100644
index 000000000..1bef39832
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/Makefile
@@ -0,0 +1,18 @@
+SQUIRREL= ..
+
+OUT= $(SQUIRREL)/lib/libsqplus.a
+INCDIRS= -I$(SQUIRREL)/include -I. -Iinclude
+
+ALLSRCS = $(wildcard *.cpp)
+WIN32SRCS = $(wildcard *Win32*)
+SRCS = $(filter-out $(WIN32SRCS),$(ALLSRCS))
+
+sqplus:
+# g++ -fno-rtti -c $(SRCS) $(INCDIRS)
+ g++ -O3 -fno-rtti -Os -c $(SRCS) $(INCDIRS)
+ ar rc $(OUT) *.o
+ rm *.o
+
+
+#g++ -O3 -fno-rtti -Os -c $(SRCS) $(INCDIRS)
+#g++ -ggdb -fno-rtti -c $(SRCS) $(INCDIRS)
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlus.cpp b/squirrel_3_0_1_stable/sqplus/SqPlus.cpp
new file mode 100644
index 000000000..a2eaacb72
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SqPlus.cpp
@@ -0,0 +1,382 @@
+#include "sqplus.h"
+#include <stdio.h>
+
+#ifdef SQPLUS_SMARTPOINTER_OPT
+#define SQPLUS_SMARTPOINTER_CPP_DECLARATION
+#include "SqPlusSmartPointer.h"
+#endif
+
+namespace SqPlus {
+
+static int getVarInfo(StackHandler & sa,VarRefPtr & vr) {
+ HSQOBJECT htable = sa.GetObjectHandle(1);
+ SquirrelObject table(htable);
+ const SQChar * el = sa.GetString(2);
+ ScriptStringVar256 varNameTag;
+ getVarNameTag(varNameTag,sizeof(varNameTag),el);
+ SQUserPointer data=0;
+ if (!table.RawGetUserData(varNameTag,&data)) {
+ return sa.ThrowError(_SC("getVarInfo: Could not retrieve UserData")); // Results in variable not being found error.
+ }
+ vr = (VarRefPtr)data;
+ return SQ_OK;
+} // getVarInfo
+
+static int getInstanceVarInfo(StackHandler & sa,VarRefPtr & vr,SQUserPointer & data) {
+ HSQOBJECT ho = sa.GetObjectHandle(1);
+ SquirrelObject instance(ho);
+ const SQChar * el = sa.GetString(2);
+ ScriptStringVar256 varNameTag;
+ getVarNameTag(varNameTag,sizeof(varNameTag),el);
+ SQUserPointer ivrData=0;
+ if (!instance.RawGetUserData(varNameTag,&ivrData)) {
+ return sa.ThrowError(_SC("getInstanceVarInfo: Could not retrieve UserData")); // Results in variable not being found error.
+ }
+ vr = (VarRefPtr)ivrData;
+
+ char * up;
+ if (!(vr->m_access & (VAR_ACCESS_STATIC|VAR_ACCESS_CONSTANT))) {
+ SQUserPointer typetag;
+ instance.GetTypeTag(&typetag);
+
+#if defined(SQ_USE_CLASS_INHERITANCE)
+ if (typetag != vr->instanceType) {
+ SquirrelObject typeTable = instance.GetValue(SQ_CLASS_OBJECT_TABLE_NAME);
+ up = (char *)typeTable.GetUserPointer(INT((size_t)vr->instanceType)); // <TODO> 64-bit compatible version.
+ if (!up) {
+ throw SquirrelError(_SC("Invalid Instance Type"));
+ }
+ } else {
+ up = (char *)instance.GetInstanceUP(0);
+ } // if
+
+#elif defined(SQ_USE_CLASS_INHERITANCE_SIMPLE)
+ ClassTypeBase *ctb = (ClassTypeBase*)vr->instanceType;
+ up = (char *)instance.GetInstanceUP(0);
+ // Walk base classes until type tag match, adjust for inheritence offset
+ while(ctb && typetag!=ctb) {
+ up = (char*)up - ctb->m_offset;
+ ctb = ctb->m_pbase;
+ }
+ if (!ctb) {
+ throw SquirrelError(_SC("Invalid Instance Type"));
+ }
+#else
+ up = (char *)instance.GetInstanceUP(0);
+#endif
+
+#ifdef SQPLUS_SMARTPOINTER_OPT
+#define SQPLUS_SMARTPOINTER_INSTANCE_VARINFO
+#include "SqPlusSmartPointer.h"
+#endif
+
+ up += (size_t)vr->offsetOrAddrOrConst; // Offset
+ } else {
+ up = (char *)vr->offsetOrAddrOrConst; // Address
+ } // if
+ data = up;
+ return SQ_OK;
+} // getInstanceVarInfo
+
+
+// If not static/global, message can (and will) disappear before arriving at catch (G++)
+static ScriptStringVar256 g_msg_throw;
+
+static int setVar(StackHandler & sa,VarRef * vr,void * data) {
+ if (vr->m_access & (VAR_ACCESS_READ_ONLY|VAR_ACCESS_CONSTANT)) {
+ const SQChar * el = sa.GetString(2);
+ SCSNPRINTF(g_msg_throw.s,sizeof(g_msg_throw),_SC("setVar(): Cannot write to constant: %s"),el);
+ throw SquirrelError(g_msg_throw.s);
+ } // if
+ switch (vr->m_type) {
+ case TypeInfo<INT>::TypeID: {
+ INT * val = (INT *)data; // Address
+ if (val) {
+ INT v = sa.GetInt(3);
+ // Support for different int sizes
+ switch( vr->m_size ) {
+ case 1: v = (*(char*)val = (char)v); break;
+ case 2: v = (*(short*)val = (short)v); break;
+#ifdef _SQ64
+ case 4: v = (*(int*)val = (int)v); break;
+#endif
+ default: *val = v;
+ }
+ return sa.Return(v);
+ } // if
+ break;
+ } // case
+ case TypeInfo<unsigned>::TypeID: {
+ unsigned * val = (unsigned *)data; // Address
+ if (val) {
+ *val = sa.GetInt(3);
+ return sa.Return(static_cast<INT>(*val));
+ } // if
+ break;
+ } // case
+ case TypeInfo<FLOAT>::TypeID: {
+ FLOAT * val = (FLOAT *)data; // Address
+ if (val) {
+ *val = sa.GetFloat(3);
+ return sa.Return(*val);
+ } // if
+ break;
+ } // case
+ case TypeInfo<bool>::TypeID: {
+ bool * val = (bool *)data; // Address
+ if (val) {
+ *val = sa.GetBool(3) ? true : false;
+ return sa.Return(*val);
+ } // if
+ break;
+ } // case
+ case VAR_TYPE_INSTANCE: {
+ HSQUIRRELVM v = sa.GetVMPtr();
+ SQUserPointer src = sa.GetInstanceUp(3,(SQUserPointer)vr->varType); // Effectively performs: ClassType<>::type() == ClassType<>().
+ if (!src) {
+ throw SquirrelError(_SC("INSTANCE type assignment mismatch"));
+ }
+ vr->varType->vgetCopyFunc()(data,src);
+ return 0;
+ }
+ case TypeInfo<SQUserPointer>::TypeID: {
+ const SQChar * el = sa.GetString(2);
+ SCSNPRINTF(g_msg_throw.s,sizeof(g_msg_throw),_SC("setVar(): Cannot write to an SQUserPointer: %s"),el);
+ throw SquirrelError(g_msg_throw.s);
+ } // case
+ case TypeInfo<ScriptStringVarBase>::TypeID: {
+ ScriptStringVarBase * val = (ScriptStringVarBase *)data; // Address
+ if (val) {
+ const SQChar * strVal = sa.GetString(3);
+ if (strVal) {
+ *val = strVal;
+ return sa.Return(val->s);
+ } // if
+ } // if
+ break;
+ } // case
+#if defined(SQPLUS_SUPPORT_STD_STRING) && !defined(SQUNICODE)
+ case TypeInfo<std::string>::TypeID: {
+ std::string *val = (std::string*)data; // Address
+ if (val) {
+ const SQChar *strVal = sa.GetString(3);
+ if (strVal) {
+ *val = strVal;
+ return sa.Return(val->c_str());
+ } // if
+ } // if
+ break;
+ } // case
+#endif
+ } // switch
+ return SQ_ERROR;
+} // setVar
+
+static int getVar(StackHandler & sa,VarRef * vr,void * data) {
+ switch (vr->m_type) {
+ case TypeInfo<INT>::TypeID: {
+ if (!(vr->m_access & VAR_ACCESS_CONSTANT)) {
+ if (data) {
+ INT v;
+ // Support for different int sizes
+ switch( vr->m_size ){
+ case 1: v = *(char*)data; break;
+ case 2: v = *(short*)data; break;
+#ifdef _SQ64
+ case 4: v = *(int*)data; break;
+#endif
+ default: v = *(INT*)data;
+ }
+ return sa.Return(v);
+ } // if
+ } else {
+ INT * val = (INT *)&data; // Constant value
+ return sa.Return(*val);
+ } // if
+ break;
+ } // case
+ case TypeInfo<unsigned>::TypeID: {
+ if (!(vr->m_access & VAR_ACCESS_CONSTANT)) {
+ unsigned * val = (unsigned *)data; // Address
+ if (val){
+ return sa.Return(static_cast<INT>(*val));
+ }
+ } else {
+ unsigned * val = (unsigned *)&data; // Constant value
+ return sa.Return(static_cast<INT>(*val));
+ } // if
+ break;
+ } // case
+ case TypeInfo<FLOAT>::TypeID: {
+ if (!(vr->m_access & VAR_ACCESS_CONSTANT)) {
+ FLOAT * val = (FLOAT *)data; // Address
+ if (val) {
+ return sa.Return(*val);
+ } // if
+ } else {
+ FLOAT * val = (FLOAT *)&data; // Constant value
+ return sa.Return(*val);
+ } // if
+ break;
+ } // case
+ case TypeInfo<bool>::TypeID: {
+ if (!(vr->m_access & VAR_ACCESS_CONSTANT)) {
+ bool * val = (bool *)data; // Address
+ if (val) {
+ return sa.Return(*val);
+ } // if
+ } else {
+ bool * val = (bool *)&data; // Constant value
+ return sa.Return(*val);
+ } // if
+ break;
+ } // case
+ case VAR_TYPE_INSTANCE:
+ if (!CreateNativeClassInstance(sa.GetVMPtr(),vr->varType->GetTypeName(),data,0)) { // data = address. Allocates memory.
+ SCSNPRINTF(g_msg_throw.s,sizeof(g_msg_throw),_SC("getVar(): Could not create instance: %s"),vr->varType->GetTypeName());
+ throw SquirrelError(g_msg_throw.s);
+ } // if
+ return 1;
+ case TypeInfo<SQUserPointer>::TypeID:
+ return sa.Return(data); // The address of member variable, not the variable itself.
+ case TypeInfo<ScriptStringVarBase>::TypeID: {
+ if (!(vr->m_access & VAR_ACCESS_CONSTANT)) {
+ ScriptStringVarBase * val = (ScriptStringVarBase *)data; // Address
+ if (val) {
+ return sa.Return(val->s);
+ } // if
+ } else {
+ throw SquirrelError(_SC("getVar(): Invalid type+access: 'ScriptStringVarBase' with VAR_ACCESS_CONSTANT (use VAR_ACCESS_READ_ONLY instead)"));
+ }
+ break;
+ } // case
+ case TypeInfo<const SQChar *>::TypeID: {
+ if (!(vr->m_access & VAR_ACCESS_CONSTANT)) {
+ if( vr->m_access==VAR_ACCESS_READ_WRITE )
+ throw SquirrelError(_SC("getVar(): Invalid type+access: 'const SQChar *' without VAR_ACCESS_CONSTANT"));
+ // It is OK to read from a SQChar* if requested
+ return sa.Return(*(const SQChar **)data); // Address
+ } else {
+ return sa.Return((const SQChar *)data); // Address
+ }
+ break;
+ } // case
+#ifdef SQPLUS_SUPPORT_STD_STRING
+ case TypeInfo<std::string>::TypeID: {
+ if (!(vr->m_access & VAR_ACCESS_CONSTANT)) {
+ std::string *val = (std::string *)data; // Address
+ if (val) {
+ return sa.Return(val->c_str());
+ }
+ } else {
+ throw SquirrelError(_SC("getVar(): Invalid type+access: 'std::string' with VAR_ACCESS_CONSTANT (use VAR_ACCESS_READ_ONLY instead)"));
+ }
+ break;
+ } // case
+#endif
+ } // switch
+ return SQ_ERROR;
+} // getVar
+
+// === Global Vars ===
+
+int setVarFunc(HSQUIRRELVM v) {
+ SquirrelVM::Init(v); // For handling multi-VM setting right
+ StackHandler sa(v);
+ if (sa.GetType(1) == OT_TABLE) {
+ VarRefPtr vr;
+ int res = getVarInfo(sa,vr);
+ if (res != SQ_OK) return res;
+ return setVar(sa,vr,vr->offsetOrAddrOrConst);
+ } // if
+ return SQ_ERROR;
+} // setVarFunc
+
+int getVarFunc(HSQUIRRELVM v) {
+ SquirrelVM::Init(v); // For handling multi-VM setting right
+ StackHandler sa(v);
+ if (sa.GetType(1) == OT_TABLE) {
+ VarRefPtr vr;
+ int res = getVarInfo(sa,vr);
+ if (res != SQ_OK) return res;
+ return getVar(sa,vr,vr->offsetOrAddrOrConst);
+ } // if
+ return SQ_ERROR;
+} // getVarFunc
+
+// === Instance Vars ===
+
+int setInstanceVarFunc(HSQUIRRELVM v) {
+ SquirrelVM::Init(v); // For handling multi-VM setting right
+ StackHandler sa(v);
+ if (sa.GetType(1) == OT_INSTANCE) {
+ VarRefPtr vr;
+ void * data;
+ int res = getInstanceVarInfo(sa,vr,data);
+ if (res != SQ_OK) return res;
+ return setVar(sa,vr,data);
+ } // if
+ return SQ_ERROR;
+} // setInstanceVarFunc
+
+int getInstanceVarFunc(HSQUIRRELVM v) {
+ SquirrelVM::Init(v); // For handling multi-VM setting right
+ StackHandler sa(v);
+ if (sa.GetType(1) == OT_INSTANCE) {
+ VarRefPtr vr;
+ void * data;
+ int res = getInstanceVarInfo(sa,vr,data);
+ if (res != SQ_OK) return res;
+ return getVar(sa,vr,data);
+ } // if
+ return SQ_ERROR;
+} // getInstanceVarFunc
+
+// === Classes ===
+
+BOOL CreateClass(HSQUIRRELVM v,SquirrelObject & newClass,SQUserPointer classType,const SQChar * name,const SQChar * baseName) {
+ int n = 0;
+ int oldtop = sq_gettop(v);
+ sq_pushroottable(v);
+ sq_pushstring(v,name,-1);
+ if (baseName) {
+ sq_pushstring(v,baseName,-1);
+ if (SQ_FAILED(sq_get(v,-3))) { // Make sure the base exists if specified by baseName.
+ sq_settop(v,oldtop);
+ return FALSE;
+ } // if
+ } // if
+ if (SQ_FAILED(sq_newclass(v,baseName ? 1 : 0))) { // Will inherit from base class on stack from sq_get() above.
+ sq_settop(v,oldtop);
+ return FALSE;
+ } // if
+ newClass.AttachToStackObject(-1);
+ sq_settypetag(v,-1,classType);
+ sq_createslot(v,-3);
+ sq_pop(v,1);
+ return TRUE;
+} // CreateClass
+
+SquirrelObject RegisterClassType(HSQUIRRELVM v,const SQChar * scriptClassName,SQUserPointer classType,SQFUNCTION constructor) {
+ SquirrelVM::Init(v); // For handling multi-VM setting right
+ int top = sq_gettop(v);
+ SquirrelObject newClass;
+ if (CreateClass(v,newClass,classType,scriptClassName)) {
+ SquirrelVM::CreateFunction(newClass,constructor,_SC("constructor"));
+ } // if
+ sq_settop(v,top);
+ return newClass;
+} // RegisterClassType
+
+
+///////////////////////////////////////////////////////////////////////////
+// GCC sometimes has problems with finding inline functions at link time
+// (that also have a template definition). To solve the problem,
+// non-inlines goes here.
+#ifdef GCC_INLINE_WORKAROUND
+# include "SqPlusFunctionCallImpl.h"
+#endif // GCC_INLINE_WORKAROUND
+///////////////////////////////////////////////////////////////////////////
+
+} // namespace SqPlus
+
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlusCallTemplates.h b/squirrel_3_0_1_stable/sqplus/SqPlusCallTemplates.h
new file mode 100644
index 000000000..75e4887c5
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SqPlusCallTemplates.h
@@ -0,0 +1,337 @@
+
+// This file is included multiple times, with varying options - No header guard.
+
+// Include this file to generate Call templates with or without these options:
+// - SQPLUS_APPLY_CONST - const qualifier after functions signature (const func / member func)
+// - SQPLUS_APPLY_CDECL - qualifier before class name (MSVC specific calling convention)
+
+#undef CONST_QUAL
+#undef CALL_QUAL
+
+#ifdef SQPLUS_APPLY_CONST
+ #define CONST_QUAL const
+#else
+ #define CONST_QUAL
+#endif
+
+#ifdef SQPLUS_APPLY_CDECL
+ #define CALL_QUAL __cdecl
+#else
+ #define CALL_QUAL
+#endif
+
+
+#ifdef SQPLUS_CALL_MFUNC_RET0
+
+ // Include this file again, with __cdecl also (Visual C++ specific)
+ #if defined(SQPLUS_ENABLE_CDECL_MEMBER_FUNCTIONS) && !defined(SQPLUS_APPLY_CDECL)
+ #define SQPLUS_APPLY_CDECL
+ #include "SqPlusCallTemplates.h"
+ #undef CALL_QUAL
+ #define CALL_QUAL
+ #endif
+
+ template <typename Callee>
+ static int Call(Callee & callee,RT (CALL_QUAL Callee::*func)() CONST_QUAL,HSQUIRRELVM v,int /*index*/) {
+ RT ret = (callee.*func)();
+ Push(v,ret);
+ return 1;
+ }
+
+ template <typename Callee,typename P1>
+ static int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1) CONST_QUAL,HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ RT ret = (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename Callee,typename P1,typename P2>
+ static int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2) CONST_QUAL,HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ RT ret = (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename Callee,typename P1,typename P2,typename P3>
+ static int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3) CONST_QUAL,HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ RT ret = (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename Callee,typename P1,typename P2,typename P3,typename P4>
+ static int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4) CONST_QUAL,HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ RT ret = (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5>
+ static int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5) CONST_QUAL,HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ sq_argassert(5,index + 4);
+ RT ret = (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3),
+ Get(TypeWrapper<P5>(),v,index + 4)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
+ static int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5,P6) CONST_QUAL,HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ sq_argassert(5,index + 4);
+ sq_argassert(6,index + 5);
+ RT ret = (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3),
+ Get(TypeWrapper<P5>(),v,index + 4),
+ Get(TypeWrapper<P6>(),v,index + 5)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
+ static int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5,P6,P7) CONST_QUAL,HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ sq_argassert(5,index + 4);
+ sq_argassert(6,index + 5);
+ sq_argassert(7,index + 6);
+ RT ret = (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3),
+ Get(TypeWrapper<P5>(),v,index + 4),
+ Get(TypeWrapper<P6>(),v,index + 5),
+ Get(TypeWrapper<P7>(),v,index + 6)
+ );
+ Push(v,ret);
+ return 1;
+ }
+#undef SQPLUS_CALL_MFUNC_RET0
+#endif // SQPLUS_CALL_MFUNC_RET0
+
+
+#ifdef SQPLUS_CALL_MFUNC_NORET
+
+ // Include this very same thing with __cdecl also
+ #if defined(SQPLUS_ENABLE_CDECL_MEMBER_FUNCTIONS) && !defined(SQPLUS_APPLY_CDECL)
+ #define SQPLUS_APPLY_CDECL
+ #include "SqPlusCallTemplates.h"
+ #undef CALL_QUAL
+ #define CALL_QUAL
+ #endif
+
+ // === Member function calls ===
+
+ template<typename Callee>
+ static int Call(Callee & callee,void (CALL_QUAL Callee::*func)() CONST_QUAL, HSQUIRRELVM,int /*index*/) {
+ (callee.*func)();
+ return 0;
+ }
+
+ template<typename Callee,typename P1>
+ static int Call(Callee & callee,void (CALL_QUAL Callee::*func)(P1) CONST_QUAL, HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0)
+ );
+ return 0;
+ }
+
+ template<typename Callee,typename P1,typename P2>
+ static int Call(Callee & callee,void (CALL_QUAL Callee::*func)(P1,P2) CONST_QUAL, HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1)
+ );
+ return 0;
+ }
+
+ template<typename Callee,typename P1,typename P2,typename P3>
+ static int Call(Callee & callee,void (CALL_QUAL Callee::*func)(P1,P2,P3) CONST_QUAL, HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2)
+ );
+ return 0;
+ }
+
+ template<typename Callee,typename P1,typename P2,typename P3,typename P4>
+ static int Call(Callee & callee,void (CALL_QUAL Callee::*func)(P1,P2,P3,P4) CONST_QUAL, HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3)
+ );
+ return 0;
+ }
+
+ template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5>
+ static int Call(Callee & callee,void (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5) CONST_QUAL, HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ sq_argassert(5,index + 4);
+ (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3),
+ Get(TypeWrapper<P5>(),v,index + 4)
+ );
+ return 0;
+ }
+
+ template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
+ static int Call(Callee & callee,void (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5,P6) CONST_QUAL, HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ sq_argassert(5,index + 4);
+ sq_argassert(6,index + 5);
+ (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3),
+ Get(TypeWrapper<P5>(),v,index + 4),
+ Get(TypeWrapper<P6>(),v,index + 5)
+ );
+ return 0;
+ }
+
+ template<typename Callee,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
+ static int Call(Callee & callee,void (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5,P6,P7) CONST_QUAL, HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ sq_argassert(5,index + 4);
+ sq_argassert(6,index + 5);
+ sq_argassert(7,index + 6);
+ (callee.*func)(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3),
+ Get(TypeWrapper<P5>(),v,index + 4),
+ Get(TypeWrapper<P6>(),v,index + 5),
+ Get(TypeWrapper<P7>(),v,index + 6)
+ );
+ return 0;
+ }
+#undef SQPLUS_CALL_MFUNC_NORET
+#endif // SQPLUS_CALL_MFUNC_NORET
+
+
+#ifdef SQPLUS_CALL_MFUNC_RET1
+
+ // Include this very same thing with __cdecl also
+ #if defined(SQPLUS_ENABLE_CDECL_MEMBER_FUNCTIONS) && !defined(SQPLUS_APPLY_CDECL)
+ #define SQPLUS_APPLY_CDECL
+ #include "SqPlusCallTemplates.h"
+ #undef CALL_QUAL
+ #define CALL_QUAL
+ #endif
+
+ template<typename Callee,typename RT>
+ int Call(Callee & callee, RT (CALL_QUAL Callee::*func)() CONST_QUAL, HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(callee,func,v,index);
+ }
+
+ template<typename Callee,typename RT,typename P1>
+ int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1) CONST_QUAL, HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(callee,func,v,index);
+ }
+
+ template<typename Callee,typename RT,typename P1,typename P2>
+ int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2) CONST_QUAL, HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(callee,func,v,index);
+ }
+
+ template<typename Callee,typename RT,typename P1,typename P2,typename P3>
+ int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3) CONST_QUAL, HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(callee,func,v,index);
+ }
+
+ template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4>
+ int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4) CONST_QUAL, HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(callee,func,v,index);
+ }
+
+ template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5>
+ int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5) CONST_QUAL, HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(callee,func,v,index);
+ }
+
+ template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
+ int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5,P6) CONST_QUAL, HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(callee,func,v,index);
+ }
+
+ template<typename Callee,typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
+ int Call(Callee & callee,RT (CALL_QUAL Callee::*func)(P1,P2,P3,P4,P5,P6,P7) CONST_QUAL, HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(callee,func,v,index);
+ }
+
+#undef SQPLUS_CALL_MFUNC_RET1
+#endif // SQPLUS_CALL_MFUNC_RET1
+
+// We will be reusing these symbols later
+#undef SQPLUS_APPLY_CDECL
+#undef SQPLUS_APPLY_CONST
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlusConst.h b/squirrel_3_0_1_stable/sqplus/SqPlusConst.h
new file mode 100644
index 000000000..0fd6b72ae
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SqPlusConst.h
@@ -0,0 +1,74 @@
+// SqPlusConst.h
+// SqPlus constant type and constant member function support created by Simon Michelmore.
+// Modular integration 11/14/05 jcs.
+
+#ifdef SQPLUS_DECLARE_INSTANCE_TYPE_CONST
+#undef SQPLUS_DECLARE_INSTANCE_TYPE_CONST
+
+// Kamaitati's NULL_INSTANCE support. 5/28/06 jcs
+
+#ifdef SQPLUS_SUPPORT_NULL_INSTANCES
+
+#define DECLARE_INSTANCE_TYPE_NAME_CONST_BASE(TYPE,NAME) \
+inline bool Match(TypeWrapper<const TYPE &>,HSQUIRRELVM v,int idx) { return GetInstance<TYPE,false>(v,idx) != NULL; } \
+inline const TYPE & Get(TypeWrapper<const TYPE &>,HSQUIRRELVM v,int idx) { return *GetInstance<TYPE,true>(v,idx); }
+
+// Ordinary case
+#define DECLARE_INSTANCE_TYPE_NAME_CONST(TYPE,NAME) \
+ DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) \
+ namespace SqPlus { \
+ DECLARE_INSTANCE_TYPE_NAME_CONST_BASE(TYPE,NAME) \
+ template<> inline void Push(HSQUIRRELVM v,const TYPE * value) { \
+ if (!value) sq_pushnull(v); \
+ else if (!CreateNativeClassInstance(v,GetTypeName(*value),(TYPE*)value,0)) \
+ throw SquirrelError(_SC("Push(): could not create INSTANCE (check registration name)")); } \
+ template<> inline void Push(HSQUIRRELVM v,const TYPE & value) { if (!CreateCopyInstance(v,GetTypeName(value),value)) throw SquirrelError(_SC("Push(): could not create INSTANCE copy (check registration name)")); } \
+ } // nameSpace SqPlus
+
+// Case for custom Push implementation (covariant return type)
+#define DECLARE_INSTANCE_TYPE_NAME_CONST_CUSTOM(TYPE,NAME) \
+ DECLARE_INSTANCE_TYPE_NAME_CUSTOM_(TYPE,NAME) \
+ namespace SqPlus { \
+ DECLARE_INSTANCE_TYPE_NAME_CONST_BASE(TYPE,NAME) \
+ template<> void Push(HSQUIRRELVM v,const TYPE * value); \
+ template<> void Push(HSQUIRRELVM v,const TYPE & value); \
+ } // nameSpace SqPlus
+
+
+#else
+
+#define DECLARE_INSTANCE_TYPE_NAME_CONST(TYPE,NAME) \
+ DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) \
+ namespace SqPlus { \
+ template<> inline void Push(HSQUIRRELVM v,const TYPE * value) { if (!CreateNativeClassInstance(v,GetTypeName(*value),(TYPE*)value,0)) throw SquirrelError(_SC("Push(): could not create INSTANCE (check registration name)")); } \
+ template<> inline void Push(HSQUIRRELVM v,const TYPE & value) { if (!CreateCopyInstance(v,GetTypeName(value),value)) throw SquirrelError(_SC("Push(): could not create INSTANCE copy (check registration name)")); } \
+ template<> inline bool Match(TypeWrapper<const TYPE &>,HSQUIRRELVM v,int idx) { return GetInstance<TYPE,false>(v,idx) != NULL; } \
+ template<> inline const TYPE & Get(TypeWrapper<const TYPE &>,HSQUIRRELVM v,int idx) { return *GetInstance<TYPE,true>(v,idx); } \
+ } // nameSpace SqPlus
+
+#endif
+
+#define DECLARE_INSTANCE_TYPE(TYPE) DECLARE_INSTANCE_TYPE_NAME_CONST(TYPE,TYPE)
+#define DECLARE_INSTANCE_TYPE_NAME(TYPE,NAME) DECLARE_INSTANCE_TYPE_NAME_CONST(TYPE,NAME)
+#define DECLARE_INSTANCE_TYPE_CUSTOM(TYPE) DECLARE_INSTANCE_TYPE_NAME_CONST_CUSTOM(TYPE,TYPE)
+#define DECLARE_INSTANCE_TYPE_NAME_CUSTOM(TYPE,NAME) DECLARE_INSTANCE_TYPE_NAME_CONST_CUSTOM(TYPE,NAME)
+#endif
+
+#define SQPLUS_APPLY_CONST
+#include "SqPlusCallTemplates.h"
+
+
+#ifdef SQ_REG_CONST_STATIC_VAR
+#undef SQ_REG_CONST_STATIC_VAR
+template<typename VarType>
+SQClassDefBase & staticVar(const VarType * pvar,const SQChar * name,VarAccessType access=VAR_ACCESS_READ_ONLY) {
+ struct CV {
+ const VarType * var;
+ } cv; // Cast Variable helper.
+ cv.var = pvar;
+ RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(VarType **)&cv,name,VarAccessType(access|VAR_ACCESS_STATIC));
+ return *this;
+} // staticVar
+#endif
+
+// SqPlusConst.h
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlusFunctionCallImpl.h b/squirrel_3_0_1_stable/sqplus/SqPlusFunctionCallImpl.h
new file mode 100644
index 000000000..c0752a7f3
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SqPlusFunctionCallImpl.h
@@ -0,0 +1,114 @@
+#ifndef _SQPLUS_FUNCTION_CALL_IMPL_H_
+#define _SQPLUS_FUNCTION_CALL_IMPL_H_
+
+#ifdef GCC_INLINE_WORKAROUND
+# define SQINLINE
+#else
+# define SQINLINE inline
+#endif
+
+SQINLINE void Push(HSQUIRRELVM v,char value) { sq_pushinteger(v,value); }
+SQINLINE void Push(HSQUIRRELVM v,unsigned char value) { sq_pushinteger(v,value); }
+SQINLINE void Push(HSQUIRRELVM v,short value) { sq_pushinteger(v,value); }
+SQINLINE void Push(HSQUIRRELVM v,unsigned short value) { sq_pushinteger(v,value); }
+SQINLINE void Push(HSQUIRRELVM v,int value) { sq_pushinteger(v,value); }
+SQINLINE void Push(HSQUIRRELVM v,unsigned int value) { sq_pushinteger(v,value); }
+SQINLINE void Push(HSQUIRRELVM v,long value) { sq_pushinteger(v,value); }
+SQINLINE void Push(HSQUIRRELVM v,unsigned long value) { sq_pushinteger(v,value); }
+SQINLINE void Push(HSQUIRRELVM v,double value) { sq_pushfloat(v,(FLOAT)value); }
+SQINLINE void Push(HSQUIRRELVM v,float value) { sq_pushfloat(v,(FLOAT)value); }
+SQINLINE void Push(HSQUIRRELVM v,const SQChar * value) { sq_pushstring(v,value,-1); }
+SQINLINE void Push(HSQUIRRELVM v,SQChar * value) { sq_pushstring(v,value,-1); }
+SQINLINE void Push(HSQUIRRELVM v,const SquirrelNull &) { sq_pushnull(v); }
+SQINLINE void Push(HSQUIRRELVM v,SQFUNCTION value) { sq_pushuserpointer(v,(void*)value); }
+SQINLINE void Push(HSQUIRRELVM v,SQAnythingPtr value) { sq_pushuserpointer(v,(void*)value); } // Cast to SQAnythingPtr instead of void * if USE_ARGUMENT_DEPENDANT_OVERLOADS can't be used by your compiler.
+SQINLINE void Push(HSQUIRRELVM v,SquirrelObject & so) { sq_pushobject(v,so.GetObjectHandle()); }
+
+#ifdef USE_ARGUMENT_DEPENDANT_OVERLOADS
+#ifdef _MSC_VER
+#pragma warning (disable:4675) // Disable warning: "resolved overload was found by argument-dependent lookup" when class/struct pointers are used as function arguments.
+#endif
+// === BEGIN Argument Dependent Overloads ===
+SQINLINE void Push(HSQUIRRELVM v,bool value) { sq_pushbool(v,value); } // Pass bool as int if USE_ARGUMENT_DEPENDANT_OVERLOADS can't be used by your compiler.
+SQINLINE void Push(HSQUIRRELVM v,const void * value) { sq_pushuserpointer(v,(void*)value); } // Pass SQAnythingPtr instead of void * " "
+SQINLINE void Push(HSQUIRRELVM v,const SQUserPointer & value) { sq_pushuserpointer(v,(void*)value); }
+// === END Argument Dependent Overloads ===
+#endif
+
+#define SQPLUS_CHECK_GET(res) if (!SQ_SUCCEEDED(res)) throw SquirrelError(_SC("sq_get*() failed (type error)"))
+
+//SQINLINE bool Match(TypeWrapper<bool>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_BOOL; }
+SQINLINE bool Match(TypeWrapper<bool>,HSQUIRRELVM v,int idx) { return true; } // All types can be cast to bool
+SQINLINE bool Match(TypeWrapper<char>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_INTEGER; }
+SQINLINE bool Match(TypeWrapper<unsigned char>,HSQUIRRELVM v, int idx) { return sq_gettype(v,idx) == OT_INTEGER; }
+SQINLINE bool Match(TypeWrapper<short>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_INTEGER; }
+SQINLINE bool Match(TypeWrapper<unsigned short>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_INTEGER; }
+SQINLINE bool Match(TypeWrapper<int>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_INTEGER; }
+SQINLINE bool Match(TypeWrapper<unsigned int>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_INTEGER; }
+SQINLINE bool Match(TypeWrapper<long>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_INTEGER; }
+SQINLINE bool Match(TypeWrapper<unsigned long>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_INTEGER; }
+SQINLINE bool Match(TypeWrapper<float>,HSQUIRRELVM v,int idx) { int type = sq_gettype(v,idx); return type == OT_FLOAT; }
+SQINLINE bool Match(TypeWrapper<double>,HSQUIRRELVM v,int idx) { int type = sq_gettype(v,idx); return type == OT_FLOAT; }
+SQINLINE bool Match(TypeWrapper<const SQChar *>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_STRING; }
+SQINLINE bool Match(TypeWrapper<SQChar *>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_STRING; }
+SQINLINE bool Match(TypeWrapper<HSQUIRRELVM>,HSQUIRRELVM v,int idx) { return true; } // See Get() for HSQUIRRELVM below (v is always present).
+SQINLINE bool Match(TypeWrapper<void*>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_USERPOINTER; }
+SQINLINE bool Match(TypeWrapper<SquirrelObject>,HSQUIRRELVM v,int idx) { return true; } // See sq_getstackobj(): always returns true.
+
+SQINLINE void Get(TypeWrapper<void>,HSQUIRRELVM v,int) {}
+//SQINLINE bool Get(TypeWrapper<bool>,HSQUIRRELVM v,int idx) { SQBool b; SQPLUS_CHECK_GET(sq_getbool(v,idx,&b)); return b != 0; }
+SQINLINE char Get(TypeWrapper<char>,HSQUIRRELVM v,int idx) { INT i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<char>(i); }
+SQINLINE unsigned char Get(TypeWrapper<unsigned char>,HSQUIRRELVM v,int idx) { INT i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned char>(i); }
+SQINLINE short Get(TypeWrapper<short>,HSQUIRRELVM v,int idx) { INT i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<short>(i); }
+SQINLINE unsigned short Get(TypeWrapper<unsigned short>,HSQUIRRELVM v,int idx) { INT i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned short>(i); }
+SQINLINE int Get(TypeWrapper<int>,HSQUIRRELVM v,int idx) { INT i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return i; }
+SQINLINE unsigned int Get(TypeWrapper<unsigned int>,HSQUIRRELVM v,int idx) { INT i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned int>(i); }
+SQINLINE long Get(TypeWrapper<long>,HSQUIRRELVM v,int idx) { INT i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<long>(i); }
+SQINLINE unsigned long Get(TypeWrapper<unsigned long>,HSQUIRRELVM v,int idx) { INT i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return static_cast<unsigned long>(i); }
+SQINLINE float Get(TypeWrapper<float>,HSQUIRRELVM v,int idx) { FLOAT f; SQPLUS_CHECK_GET(sq_getfloat(v,idx,&f)); return f; }
+SQINLINE double Get(TypeWrapper<double>,HSQUIRRELVM v,int idx) { FLOAT f; SQPLUS_CHECK_GET(sq_getfloat(v,idx,&f)); return static_cast<double>(f); }
+SQINLINE const SQChar * Get(TypeWrapper<const SQChar *>,HSQUIRRELVM v,int idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return s; }
+SQINLINE SquirrelNull Get(TypeWrapper<SquirrelNull>,HSQUIRRELVM v,int idx) { (void)v, (void)idx; return SquirrelNull(); }
+SQINLINE void * Get(TypeWrapper<void *>,HSQUIRRELVM v,int idx) { SQUserPointer p; SQPLUS_CHECK_GET(sq_getuserpointer(v,idx,&p)); return p; }
+SQINLINE HSQUIRRELVM Get(TypeWrapper<HSQUIRRELVM>,HSQUIRRELVM v,int /*idx*/) { sq_poptop(v); return v; } // sq_poptop(v): remove UserData from stack so GetParamCount() matches normal behavior.
+SQINLINE SquirrelObject Get(TypeWrapper<SquirrelObject>,HSQUIRRELVM v,int idx) { HSQOBJECT o; SQPLUS_CHECK_GET(sq_getstackobj(v,idx,&o)); return SquirrelObject(o); }
+
+SQINLINE bool Get(TypeWrapper<bool>,HSQUIRRELVM v,int idx){
+ switch( sq_gettype(v,idx) ){
+ case OT_NULL:{ return false; }
+ case OT_BOOL:{ SQBool b; SQPLUS_CHECK_GET(sq_getbool(v,idx,&b)); return b != 0; }
+ case OT_INTEGER:{ INT i; SQPLUS_CHECK_GET(sq_getinteger(v,idx,&i)); return i != 0; }
+ case OT_FLOAT:{ FLOAT f; SQPLUS_CHECK_GET(sq_getfloat(v,idx,&f)); return f != (FLOAT)0.0; }
+ default: return true; } }
+
+#ifdef SQPLUS_AUTOCONVERT_OTHER_CHAR
+SQINLINE void Push(HSQUIRRELVM v, const SQOtherChar *value){ SQDefCharBuf cb(value); sq_pushstring(v,(const SQChar*)cb,-1); }
+SQINLINE void Push(HSQUIRRELVM v, SQOtherChar *value){ SQDefCharBuf cb(value); sq_pushstring(v,(const SQChar*)cb,-1); }
+SQINLINE bool Match(TypeWrapper<const SQOtherChar *>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_STRING; }
+SQINLINE bool Match(TypeWrapper<SQOtherChar *>,HSQUIRRELVM v,int idx) { return sq_gettype(v,idx) == OT_STRING; }
+/*SQINLINE SQOtherChar* Get(TypeWrapper<const SQOtherChar *>,HSQUIRRELVM v,int idx) {
+ const SQChar *s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s));
+ static SQOthCharBuf ocb[SQPLUS_AUTOCONVERT_MAX_INSTANCES]; static int st_buf_cnt;
+ return ocb[st_buf_cnt++%SQPLUS_AUTOCONVERT_MAX_INSTANCES].Set(s); }*/
+SQINLINE SQOthCharBuf Get(TypeWrapper<const SQOtherChar *>,HSQUIRRELVM v,int idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return SQOthCharBuf(s); }
+#endif // SQPLUS_AUTOCONVERT_OTHER_CHAR
+
+#if defined(SQPLUS_SUPPORT_STD_STRING) && !defined(SQUNICODE)
+SQINLINE void Push(HSQUIRRELVM v,const std::string& value) { sq_pushstring(v,value.c_str(),-1); }
+SQINLINE bool Match(TypeWrapper<const std::string&>, HSQUIRRELVM v, int idx) { return sq_gettype(v,idx) == OT_STRING; }
+SQINLINE std::string Get(TypeWrapper<const std::string&>,HSQUIRRELVM v,int idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return std::string(s); }
+#endif // defined(SQPLUS_SUPPORT_STD_STRING) && !defined(SQUNICODE)
+
+// Added jflanglois suggestion, 8/20/06. jcs
+#ifdef SQPLUS_SUPPORT_SQ_STD_STRING
+typedef std::basic_string<SQChar> sq_std_string;
+SQINLINE void Push(HSQUIRRELVM v,const sq_std_string & value) { sq_pushstring(v,value.c_str(),-1); }
+SQINLINE bool Match(TypeWrapper<const sq_std_string &>, HSQUIRRELVM v, int idx) { return sq_gettype(v,idx) == OT_STRING; }
+SQINLINE sq_std_string Get(TypeWrapper<const sq_std_string &>,HSQUIRRELVM v,int idx) { const SQChar * s; SQPLUS_CHECK_GET(sq_getstring(v,idx,&s)); return sq_std_string(s); }
+#endif
+
+// Specialization to support void return type.
+SQINLINE void GetRet(TypeWrapper<void>,HSQUIRRELVM v,int idx) { sq_pop(v,2); }
+
+#endif // _SQPLUS_FUNCTION_CALL_IMPL_H_
+
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlusOCharBuf.cpp b/squirrel_3_0_1_stable/sqplus/SqPlusOCharBuf.cpp
new file mode 100644
index 000000000..4a0bd2a9b
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SqPlusOCharBuf.cpp
@@ -0,0 +1,61 @@
+
+#include "sqplus.h"
+#include "SqPlusOCharBuf.h"
+
+#include <wchar.h>
+
+// Conversion functions, between char* string and wchar_t* strings.
+
+int ol_strlen(const wchar_t* pwc){ return (int)wcslen(pwc); }
+int ol_buflen(const wchar_t* pwc){ return (int)wcslen(pwc); }
+int ol_charlen(const wchar_t* pwc){ return 1; }
+//int ol_charlen(const wchar_t pwc){ return 1; }
+int ol_char(const wchar_t* pwc){ return (int)*pwc; }
+bool ol_writechar(wchar_t*& pwc, int ch){ *pwc=(wchar_t)ch; pwc++; return true; }
+
+int ol_buflen(const char* pc){ return (int)strlen(pc); }
+
+#if SQPLUS_USE_LATIN1==1
+ // Convert to 8-bit LATIN1 char set. The only thing to do is convert chars out of range to '?'
+ int ol_strlen(const char* pc){ return (int)strlen(pc); }
+ int ol_charlen(const char* pc){ return 1; }
+ //int ol_charlen(int pc){ return 1; }
+ int ol_char(const char* pc){ return (int)*(unsigned char*)pc; }
+ bool ol_writechar(char*& pc, int ch){ *pc=(char)(ch>255?'?':ch); pc++; return true; }
+#else
+ #include "SqPlusUtf8.h"
+ // Convert to 8-Bit UTF8 encoding. Some more work here.
+ int ol_strlen(const char* pc){ return sqplus_utf8_strlen(pc); }
+ int ol_charlen(const char* pc){ return sqplus_utf8_len_first(pc); }
+ //int ol_charlen(int ch){ char buf[8]; return sqplus_wchar_to_utf8(buf,ch,8); }
+ int ol_char(const char* pc){ int chr=-1; sqplus_utf8_to_wchar(&chr,pc); return chr; }
+ bool ol_writechar(char*& pc, int ch) {
+ int l=sqplus_wchar_to_utf8(pc,ch,8);
+ if(l>0){
+ pc += l;
+ return true;
+ }
+ else return false;
+ }
+#endif
+
+
+#ifdef SQUNICODE
+ // SQChar is wchar_t, convert to/from to either Latin1 or UTF8
+ SQDefCharBuf CH2SQ( const char* ps ){
+ return SQDefCharBuf(ps);
+ }
+ SQOthCharBuf SQ2CH( const wchar_t* pws ){
+ return SQOthCharBuf(pws);
+ }
+#else
+ // SQChar is char, convert to/from wchar_t
+ SQDefCharBuf WC2SQ( const wchar_t* pws ){
+ return SQDefCharBuf(pws);
+ }
+ SQOthCharBuf SQ2WC( const char* ps ){
+ return SQOthCharBuf(ps);
+ }
+#endif
+
+
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlusOCharBuf.h b/squirrel_3_0_1_stable/sqplus/SqPlusOCharBuf.h
new file mode 100644
index 000000000..c27e7c803
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SqPlusOCharBuf.h
@@ -0,0 +1,193 @@
+
+#ifndef SQPLUS_OCHARBUF_H
+#define SQPLUS_OCHARBUF_H
+
+// Conversion routines between different character encodings, to be used in
+// Push/Get/Match handlers of SqPlus. It enables using both of char* and
+// wchar_t* as function arguments.
+//
+// When converting from wchar_t to char, the choice is between using a Latin1
+// or a UTF8 representation in 8-bit mode. This is probably most useful if
+// Squirrel is compiled in ANSI mode and the app uses some wchar_t strings
+// (UNICODE mode on Win32).
+//
+
+// A char is either
+// - A Latin1 character (first code page, coincides with Unicode points 0..255)
+// - Part of an UTF8 character
+//
+// Note: SQUTF8 requires Squirrel sources that have been patched for UTF8 strings
+// internally (when converting function arguments).
+
+#ifndef SQUTF8
+ // Default to Latin1 conversion
+ //#undef SQPLUS_USE_LATIN1
+ #ifndef SQPLUS_USE_LATIN1
+ #define SQPLUS_USE_LATIN1 1
+ #endif
+#else
+ // Using Squirrel with internal UTF8 string encoding
+ //#undef SQPLUS_USE_LATIN1
+ #ifndef SQPLUS_USE_LATIN1
+ #define SQPLUS_USE_LATIN1 0
+ #endif
+#endif
+
+
+// The various ol_... functions sets up for a conversion scheme
+// that can be used in both wchar_t => char and char => wchar_t.
+int ol_strlen(const wchar_t* pwc);
+int ol_buflen(const wchar_t* pwc);
+int ol_charlen(const wchar_t* pwc);
+int ol_char(const wchar_t* pwc);
+bool ol_writechar(wchar_t*& pwc, int ch);
+
+int ol_strlen(const char* pc);
+int ol_buflen(const char* pc);
+int ol_charlen(const char* pc);
+int ol_char(const char* pc);
+bool ol_writechar(char*& pc, int ch);
+
+#ifdef SQUNICODE
+ // SQChar is wchar_t, convert to/from either Latin1 or UTF8
+ typedef char SQOtherChar;
+#else
+ // SQChar is char, convert to/from wchar_t
+ typedef wchar_t SQOtherChar;
+#endif
+
+
+// Buffer to hold a string and release it in destructor.
+// SQT is input character type
+// SQOT is the opposite type of SQChar
+// If 'try_borrow' is set, it will not allocate a new buffer when no
+// conversion is done, it will just keep the input pointer (beware).
+template<class SQT, class SQOT, bool use_latin1>
+struct SQCharBufImpl {
+
+ // Allocate a buffer from string of same type
+ SQCharBufImpl(const SQT *poc=NULL, bool try_borrow=true ) : m_poc(0), m_own(false) {
+ Init( poc, try_borrow );
+ }
+
+ // This does conversion from other char type
+ SQCharBufImpl(const SQOT *ps, bool try_borrow=false ) : m_poc(0), m_own(false) {
+ Init( ps ); // Cannot borrow pointer when doing conversion
+ }
+
+ void Init( const SQT *poc, bool try_borrow ){
+ m_own = !try_borrow;
+ if( try_borrow ){
+ m_poc = (SQT*)poc;
+ }
+ else {
+ int sl = poc ? ol_buflen(poc) : 0;
+ if( poc ){
+ m_poc = poc ? new SQT[sl+1] : NULL;
+ if( m_poc ) memcpy( m_poc, poc, (sl+1)*sizeof(SQT) );
+ }
+ else
+ m_poc = NULL;
+ }
+ }
+
+ void Init( const SQOT *ps ){
+ m_own = true;
+ if( ps ){
+ int sl = ps ? ol_strlen(ps) : 0; // Length of string in characters (not bytes)
+ int scl = 0; // Length of converted string in char/wchar_t count
+ // How much storage needed?
+ if( !use_latin1 && sizeof(SQT)<sizeof(SQOT) ){
+ // Converting wchar_t => UTF8
+ const SQOT *ps1 = ps; // It is wchar_t* here
+ SQT tmp_buf[8];
+ SQT *ptmp;
+ while( *ps1 ){
+ ptmp = tmp_buf;
+ if( ol_writechar(ptmp,*ps1++) )
+ scl += ol_charlen(tmp_buf);
+ else
+ scl++;
+ }
+ }
+ else scl = sl; // Converting to wchar_t or Latin1, keep length
+
+ m_poc = new SQT[scl+1];
+ if( !m_poc ) return;
+
+ // Convert
+ SQT *poc = m_poc;
+ while( *ps ){
+ ol_writechar( poc, ol_char(ps) );
+ ps += ol_charlen(ps);
+ }
+ *poc = 0; // Terminating zero
+ }
+ else
+ m_poc = NULL;
+ }
+
+ ~SQCharBufImpl(){ Release(); }
+
+ void Release( ){
+ if(m_poc && m_own )
+ delete [] m_poc;
+ m_poc = NULL;
+ }
+
+ SQT* Set( const SQOT *ps ){
+ Release( );
+ Init( ps );
+ return m_poc;
+ }
+
+ operator SQT*() const { return m_poc; }
+
+ SQCharBufImpl<SQT,SQOT,use_latin1>& operator = (const SQT *ps){
+ Release();
+ Init( ps, false );
+ return *this;
+ }
+
+ SQCharBufImpl<SQT,SQOT,use_latin1>& operator = (const SQOT *ps){
+ Release();
+ Init( ps );
+ return *this;
+ }
+
+ // Move string from other here - Note: Empties the input argument (other)
+ SQCharBufImpl<SQT,SQOT,use_latin1>& operator = (const SQCharBufImpl<SQT,SQOT,use_latin1>& other){
+ Release();
+ m_poc = other.m_poc;
+ m_own = other.m_own;
+ SQT **psqt = (SQT**)&other.m_poc;
+ *psqt = NULL;
+ return *this;
+ }
+
+protected:
+ SQT *m_poc;
+ bool m_own;
+};
+
+typedef SQCharBufImpl<SQOtherChar, SQChar, bool(SQPLUS_USE_LATIN1)> SQOthCharBuf;
+typedef SQCharBufImpl<SQChar, SQOtherChar, bool(SQPLUS_USE_LATIN1)> SQDefCharBuf;
+typedef SQCharBufImpl<wchar_t, char, bool(SQPLUS_USE_LATIN1)> SQWCharBuf;
+typedef SQCharBufImpl<char, wchar_t, bool(SQPLUS_USE_LATIN1)> SQACharBuf;
+
+#ifdef SQUNICODE
+ // SQChar is wchar_t, convert to/from to either Latin1 or UTF8
+ #define WC2SQ(s) s
+ #define SQ2WC(s) s
+ SQDefCharBuf CH2SQ( const char* ps );
+ SQOthCharBuf SQ2CH( const wchar_t* pws );
+#else
+ // SQChar is char, convert to/from wchar_t
+ SQDefCharBuf WC2SQ( const wchar_t* pws );
+ SQOthCharBuf SQ2WC( const char* pws );
+ #define CH2SQ(s) s
+ #define SQ2CH(s) s
+#endif
+
+#endif // SQPLUS_CHARBUF_H
+
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlusOverload.h b/squirrel_3_0_1_stable/sqplus/SqPlusOverload.h
new file mode 100644
index 000000000..e205de366
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SqPlusOverload.h
@@ -0,0 +1,819 @@
+// SqPlusOverload.h
+// SqPlus function overloading support created by Katsuaki Kawachi.
+//
+// Const member function fixed Tegan
+// from http://squirrel-lang.org/forums/thread/2160.aspx
+
+#ifdef SQPLUS_OVERLOAD_RELEASE_HOOK
+#undef SQPLUS_OVERLOAD_RELEASE_HOOK
+
+ // These end up int ClassType<T> now
+ static inline int destruct(SQUserPointer up, SQInteger size) {
+ if (up) {
+ static_cast<T*>(up)->~T();
+ sq_free(up, size);
+ }
+ return 0;
+ }
+
+ static inline SQRELEASEHOOK &release(void) {
+ static SQRELEASEHOOK hook = ClassType<T>::destruct;
+ return hook;
+ }
+
+ void releaseHook(SQRELEASEHOOK releaseHook) {
+ release() = releaseHook;
+ //return *this;
+ }
+
+ static inline SQRELEASEHOOK &getReleaseHook(void) {
+ return release();
+ }
+
+#endif // SQPLUS_OVERLOAD_RELEASE_HOOK
+
+
+#ifdef SQPLUS_OVERLOAD_DECLARATION
+#undef SQPLUS_OVERLOAD_DECLARATION
+
+template<typename Func> struct Arg;
+
+#endif // SQPLUS_OVERLOAD_DECLARATION
+
+
+#ifdef SQPLUS_OVERLOAD_IMPLEMENTATION
+#undef SQPLUS_OVERLOAD_IMPLEMENTATION
+private:
+ class SQFuncHolder {
+ private:
+ template<typename T>
+ class FlexArray {
+ protected:
+ SquirrelObject array;
+ public:
+ FlexArray(int size = 0) {
+ this->resize(size);
+ }
+ int size(void) const {
+ return array.Len();
+ }
+ void resize(int newSize) {
+ if (this->size() == 0) {
+ array = SquirrelVM::CreateArray(newSize);
+ } else {
+ array.ArrayResize(newSize);
+ }
+ }
+ void push_back(const T &t) {
+ this->set(this->size(), t);
+ }
+ void set(int index, const T &t) {
+ get(index) = t;
+ }
+ T &get(int index) {
+ if (index >= array.Len()) {
+ resize(index + 1);
+ }
+ SQUserPointer up = array.GetUserPointer(index);
+ if (!up) {
+ up = sq_newuserdata(SquirrelVM::GetVMPtr(), sizeof(T));
+ new(static_cast<T*>(up)) T;
+ array.SetUserPointer(index, up);
+ }
+ return *static_cast<T*>(up);
+ }
+ };
+ /*
+ storage of wrapped C++ functions
+ */
+ typedef SQInteger(*WrappedFunction)(HSQUIRRELVM, bool, int);
+ typedef FlexArray<WrappedFunction> SQWrappedFuncArray;
+ typedef FlexArray<SQWrappedFuncArray> SQWrappedFuncArray2 ;
+ typedef FlexArray<SQWrappedFuncArray2> SQWrappedFuncArray3 ;
+
+ struct MemberHolder {
+ static SQWrappedFuncArray &funcs(int functionIndex,
+ int paramCount) {
+ static SQWrappedFuncArray3 funcs;
+ return funcs.get(paramCount).get(functionIndex);
+ }
+ };
+ struct StaticHolder {
+ static SQWrappedFuncArray &funcs(int functionIndex,
+ int paramCount) {
+ static SQWrappedFuncArray3 funcs;
+ return funcs.get(paramCount).get(functionIndex);
+ }
+ };
+ struct ConstructorHolder {
+ static SQWrappedFuncArray &funcs(int paramCount) {
+ static SQWrappedFuncArray2 funcs;
+ return funcs.get(paramCount);
+ }
+ };
+
+ /*
+ wrapper for C++ functions
+ */
+ template<typename Mfunc> struct MemberDispatcher {
+ static inline FlexArray<Mfunc> &mfunc(void) {
+ static FlexArray<Mfunc> mfunc;
+ return mfunc;
+ }
+ static inline SQInteger
+ dispatch(HSQUIRRELVM v, bool execute, int functionIndex) {
+ return execute ?
+ Call(*GetInstance<TClassType, true>(v, 1),
+ mfunc().get(functionIndex), v, 2) :
+ Arg<Mfunc>::argTypeDistance(v);
+ }
+ };
+ template<typename Sfunc> struct StaticDispatcher {
+ static inline FlexArray<Sfunc> &sfunc(void) {
+ static FlexArray<Sfunc> sfunc;
+ return sfunc;
+ }
+ static inline SQInteger
+ dispatch(HSQUIRRELVM v, bool execute, int functionIndex) {
+ return execute ?
+ Call(sfunc().get(functionIndex), v, 2) :
+ Arg<Sfunc>::argTypeDistance(v);
+ }
+ };
+ template<typename Cfunc> struct Constructor {
+ static inline Cfunc &cfunc(void) {
+ static Cfunc cfunc = 0;
+ return cfunc;
+ }
+ static inline SQInteger
+ construct(HSQUIRRELVM v, bool execute, int) {
+ return execute ?
+ Call(cfunc(), v, 2) :
+ Arg<Cfunc>::argTypeDistance(v);
+ }
+ };
+
+ // search and call an overloaded function on runtime
+ static inline SQInteger
+ call(SQWrappedFuncArray &funcs, HSQUIRRELVM v, int functionIndex = 0) {
+ bool ambiguous = false;
+ int imin = -1;
+ int dmin = INT_MAX;
+ for (int i = 0, size = funcs.size(); i < size; ++i) {
+ // FIXME: to be refactored
+ const int d = (**funcs.get(i))(v, false, functionIndex);
+ if (d == 0) { // complete match
+ imin = i;
+ ambiguous = false;
+ goto SQPLUS_OVERLOAD_CALL_IMMEDIATE_EXECUTION;
+ } else if (0 < d && d < dmin) {
+ dmin = d;
+ imin = i;
+ ambiguous = false;
+ } else if (d == dmin) {
+ ambiguous = true;
+ }
+ }
+
+ if (ambiguous) {
+ return sq_throwerror(
+ v, _SC("Call of overloaded function is ambiguous")
+ );
+ } else if (imin == -1) {
+ return sq_throwerror(
+ v, _SC("No match for given arguments")
+ );
+ }
+
+ SQPLUS_OVERLOAD_CALL_IMMEDIATE_EXECUTION:
+ // FIXME: to be refactored
+ return (**funcs.get(imin))(v, true, functionIndex);
+ }
+
+ public:
+ template<typename Mfunc> static inline void
+ addMemberFunc(int functionIndex, Mfunc mfunc) {
+ MemberHolder::funcs(functionIndex, Arg<Mfunc>::num()).push_back(
+ &MemberDispatcher<Mfunc>::dispatch
+ );
+ MemberDispatcher<Mfunc>::mfunc().set(functionIndex, mfunc);
+ }
+ template<typename Sfunc> static inline void
+ addStaticFunc(int functionIndex, Sfunc sfunc) {
+ StaticHolder::funcs(functionIndex, Arg<Sfunc>::num()).push_back(
+ &StaticDispatcher<Sfunc>::dispatch
+ );
+ StaticDispatcher<Sfunc>::sfunc().set(functionIndex, sfunc);
+ }
+ template<typename Cfunc> static inline void
+ addConstructor(Cfunc cfunc) {
+ ConstructorHolder::funcs(Arg<Cfunc>::num()).push_back(
+ &Constructor<Cfunc>::construct
+ );
+ Constructor<Cfunc>::cfunc() = cfunc;
+ }
+
+ static inline SQInteger
+ memberCall(int paramCount, HSQUIRRELVM v, int functionIndex) {
+ return call(MemberHolder::funcs(functionIndex, paramCount),
+ v, functionIndex);
+ }
+ static inline SQInteger
+ staticCall(int paramCount, HSQUIRRELVM v, int functionIndex) {
+ return call(StaticHolder::funcs(functionIndex, paramCount),
+ v, functionIndex);
+ }
+ static inline SQInteger
+ constructorCall(int paramCount, HSQUIRRELVM v, int) {
+ return call(ConstructorHolder::funcs(paramCount), v);
+ }
+ }; // class SQFuncHolder
+
+
+ struct FunctionNameEnumerator {
+ SquirrelObject names;
+ FunctionNameEnumerator(void) : names(SquirrelVM::CreateTable()) {}
+ int index(const SQChar *n) {
+ int i;
+ SquirrelObject v = names.GetValue(n);
+ if (v.IsNull()) {
+ i = names.Len();
+ names.SetValue(n, i);
+ } else {
+ i = v.ToInteger();
+ }
+ return i;
+ }
+ };
+
+ FunctionNameEnumerator overloadedMemberNames;
+ FunctionNameEnumerator overloadedStaticMemberNames;
+
+ static SquirrelObject &
+ functionIndexHolders(HSQUIRRELVM v) {
+ static SquirrelObject indexHolders;
+ if (indexHolders.IsNull()) {
+ sq_newtable(v);
+ indexHolders.AttachToStackObject(-1);
+ sq_pop(v, 1);
+ }
+ return indexHolders;
+ }
+
+ template<int N>
+ static SquirrelObject &
+ indexHolder(HSQUIRRELVM v) {
+ static SquirrelObject holder;
+ if (holder.IsNull()) {
+ sq_pushobject(v, functionIndexHolders(v).GetObjectHandle());
+ sq_pushinteger(v, N);
+ if (SQ_OK == sq_rawget(v, -2)) {
+ holder.AttachToStackObject(-1);
+ sq_pop(v, 3);
+ } else {
+ sq_pushinteger(v, N);
+ sq_newtable(v);
+ holder.AttachToStackObject(-1);
+ sq_rawset(v, -3);
+ sq_pop(v, 1);
+ }
+ }
+ return holder;
+ }
+
+ template<typename Func>
+ class SQOverloader {
+ private:
+ static inline SQInteger switcher(HSQUIRRELVM v,
+ int(*caller)(int, HSQUIRRELVM, int),
+ int fidx) {
+ return (*caller)(StackHandler(v).GetParamCount() - 1,
+ v,
+ fidx);
+ }
+
+ static inline SQInteger memberSwitcher(HSQUIRRELVM v) {
+ SQInteger fidx;
+ sq_pushobject(v, indexHolder<0>(v).GetObjectHandle());
+ sq_push(v, 0); // native closure
+ sq_rawget(v, -2);
+ sq_getinteger(v, -1, &fidx);
+ sq_pop(v, 2);
+ return switcher(v, SQFuncHolder::memberCall, fidx);
+ }
+ static inline SQInteger staticSwitcher(HSQUIRRELVM v) {
+ SQInteger fidx;
+ sq_pushobject(v, indexHolder<1>(v).GetObjectHandle());
+ sq_push(v, 0); // native closure
+ sq_rawget(v, -2);
+ sq_getinteger(v, -1, &fidx);
+ sq_pop(v, 2);
+ return switcher(v, SQFuncHolder::staticCall, fidx);
+ }
+ static inline SQInteger constructorSwitcher(HSQUIRRELVM v) {
+ return switcher(v, SQFuncHolder::constructorCall, 0);
+ }
+
+ public:
+ static inline void addMemberFunc(SQClassDefBase<TClassType,TClassBase> *def,
+ Func mfunc,
+ const SQChar *name) {
+ const int fidx = def->overloadedMemberNames.index(name);
+ SQFuncHolder::addMemberFunc(fidx, mfunc);
+ def->staticFuncVarArgs(memberSwitcher, name);
+
+ HSQUIRRELVM v = def->v;
+ // get closure
+ sq_pushobject(v, def->newClass.GetObjectHandle());
+ sq_pushstring(v, name, -1);
+ sq_rawget(v, -2);
+ // holder[closure] = fidx
+ sq_pushobject(v, indexHolder<0>(v).GetObjectHandle());
+ sq_push(v, -2);
+ sq_pushinteger(v, fidx);
+ sq_rawset(v, -3);
+ //
+ sq_pop(v, 3);
+ }
+
+ static inline void addOperatorFunc(SQClassDefBase<TClassType,TClassBase> *def,
+ Func ofunc,
+ const SQChar *name) {
+ if (Arg<Func>::num() != 1) {
+ //assert(false &&
+ // "Cannot add this function as operator (argc != 1)");
+ abort();
+ }
+ SQChar proxy[256];
+ scsprintf(proxy, _SC("overloaded%s"), name);
+
+ addMemberFunc(def, ofunc, proxy);
+
+ SQChar script[512];
+ scsprintf(script, _SC("%s.%s<-function(o){return %s.%s(o);}"),
+ def->name, name, def->name, proxy);
+ SquirrelVM::RunScript(SquirrelVM::CompileBuffer(script));
+ }
+
+ static inline void addStaticFunc(SQClassDefBase<TClassType,TClassBase> *def,
+ Func sfunc,
+ const SQChar *name) {
+ const int fidx = def->overloadedStaticMemberNames.index(name);
+ SQFuncHolder::addStaticFunc(fidx, sfunc);
+ def->staticFuncVarArgs(staticSwitcher, name);
+
+ HSQUIRRELVM v = def->v;
+ // get closure
+ sq_pushobject(v, def->newClass.GetObjectHandle());
+ sq_pushstring(v, name, -1);
+ sq_rawget(v, -2);
+
+ // holder[closure] = fidx
+ sq_pushobject(v, indexHolder<1>(v).GetObjectHandle());
+ sq_push(v, -2);
+ sq_pushinteger(v, fidx);
+ sq_rawset(v, -3);
+ //
+ sq_pop(v, 3);
+ }
+ template<typename Cfunc>
+ static inline void addConstructor(SQClassDefBase<TClassType,TClassBase> *def,
+ Cfunc cfunc) {
+ SQFuncHolder::addConstructor(cfunc);
+ def->staticFuncVarArgs(constructorSwitcher, _SC("constructor"));
+ }
+ static inline void addGlobalFunc(SQClassDefBase<TClassType,TClassBase> *def,
+ Func gfunc,
+ const SQChar *name) {
+ const int fidx = def->overloadedStaticMemberNames.index(name);
+ SQFuncHolder::addStaticFunc(fidx, gfunc);
+ SquirrelVM::CreateFunctionGlobal(staticSwitcher, name, _SC("*"));
+
+ HSQUIRRELVM v = def->v;
+ // get closure
+ sq_pushroottable(v);
+ sq_pushstring(v, name, -1);
+ sq_rawget(v, -2);
+
+ // holder[closure] = fidx
+ sq_pushobject(v, indexHolder<1>(v).GetObjectHandle());
+ sq_push(v, -2);
+ sq_pushinteger(v, fidx);
+ sq_rawset(v, -3);
+ //
+ sq_pop(v, 3);
+ }
+ };
+
+public:
+ template<typename Mfunc>
+ SQClassDefBase<TClassType,TClassBase> &overloadFunc(Mfunc mfunc, const SQChar *n) {
+ SQOverloader<Mfunc>::addMemberFunc(this, mfunc, n);
+ return *this;
+ }
+ template<typename Ofunc>
+ SQClassDefBase<TClassType,TClassBase> &overloadOperator(Ofunc ofunc, const SQChar *n){
+ SQOverloader<Ofunc>::addOperatorFunc(this, ofunc, n);
+ return *this;
+ }
+ template<typename Sfunc>
+ SQClassDefBase<TClassType,TClassBase> &overloadStaticFunc(Sfunc sfunc,
+ const SQChar *n) {
+ SQOverloader<Sfunc>::addStaticFunc(this, sfunc, n);
+ return *this;
+ }
+ template<typename Cmetafunc>
+ SQClassDefBase<TClassType,TClassBase> &overloadConstructor(void) {
+ SQOverloader<Cmetafunc>::addConstructor(this, &Arg<Cmetafunc>::create);
+ return *this;
+ }
+ template<typename Cfunc>
+ SQClassDefBase<TClassType,TClassBase> &overloadConstructor(Cfunc cfunc) {
+ SQOverloader<Cfunc>::addConstructor(this, cfunc);
+ return *this;
+ }
+ template<typename Gfunc>
+ SQClassDefBase<TClassType,TClassBase> &overloadGlobalFunc(Gfunc gfunc,
+ const SQChar *n) {
+ SQOverloader<Gfunc>::addGlobalFunc(this, gfunc, n);
+ return *this;
+ }
+
+
+#endif // SQPLUS_OVERLOAD_IMPLEMENTATION
+
+
+
+#ifdef SQPLUS_OVERLOAD_FUNCTIONS
+#undef SQPLUS_OVERLOAD_FUNCTIONS
+
+struct GlobalFuncOverloader {};
+static inline SQClassDefBase<GlobalFuncOverloader,SQNoBaseClass> &globalFuncOverloader(void)
+{
+ static SQClassDefBase<GlobalFuncOverloader,SQNoBaseClass> fo(_SC("GlobalFuncOverloader"));
+ return fo;
+}
+
+template<typename Gfunc> void
+OverloadGlobal(Gfunc gfunc, const SQChar *n)
+{
+ globalFuncOverloader().overloadGlobalFunc(gfunc, n);
+}
+
+template<typename TYPE> struct CheckInstance {
+ template<typename T> struct unref {typedef T type;};
+ template<typename T> struct unref<T&> {typedef T type;};
+ template<typename T> struct unref<T*> {typedef T type;};
+ template<typename T> struct unref<const T&> {typedef T type;};
+ template<typename T> struct unref<const T*> {typedef T type;};
+
+ /*
+ d = -1 : not in hierarchy
+ d = 0 : same
+ d > 0 : similar (o is d-th subclass of TYPE)
+ */
+ static inline int distance(HSQUIRRELVM v, int index) {
+ HSQOBJECT o;
+ sq_resetobject(&o);
+ sq_getstackobj(v, index, &o);
+
+ const int top = sq_gettop(v);
+ sq_pushroottable(v);
+
+ // Check plain object type
+ int d = -1;
+ if (Match(TypeWrapper<TYPE>(), v, index)) {
+ d = 0;
+
+ // Check instance type hierarchy
+ if (sq_type(o) == OT_INSTANCE) {
+ SQUserPointer dsttype =
+ ClassType<typename unref<TYPE>::type>::type();
+
+ SQUserPointer argtype;
+ for (sq_getclass(v, index);
+ sq_gettypetag(v, -1, &argtype) == SQ_OK;
+ sq_getbase(v, -1)) {
+ if (argtype == dsttype) {
+ goto SQPLUS_OVERLOAD_DISTANCE_IMMEDIATE_RETURN;
+ }
+ ++d;
+ }
+ d = -1; // no matching type found
+ }
+ }
+ SQPLUS_OVERLOAD_DISTANCE_IMMEDIATE_RETURN:
+ sq_settop(v, top);
+ return d;
+ }
+};
+
+
+template<typename T, typename R>
+struct Arg<R(T::*)(void)> {
+ static inline int num(void) {return 0;}
+ static inline int argTypeDistance(HSQUIRRELVM) {
+ return 0;
+ }
+};
+
+template<typename T, typename R, typename A1>
+struct Arg<R(T::*)(A1)> {
+ static inline int num(void) {return 1;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1)>::argTypeDistance(v);
+ }
+};
+
+template<typename T, typename R, typename A1, typename A2>
+struct Arg<R(T::*)(A1, A2)> {
+ static inline int num(void) {return 2;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1, A2)>::argTypeDistance(v);
+ }
+};
+
+template<typename T, typename R, typename A1, typename A2, typename A3>
+struct Arg<R(T::*)(A1, A2, A3)> {
+ static inline int num(void) {return 3;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1, A2, A3)>::argTypeDistance(v);
+ }
+};
+
+template<typename T, typename R, typename A1, typename A2, typename A3, typename A4>
+struct Arg<R(T::*)(A1, A2, A3, A4)> {
+ static inline int num(void) {return 4;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1, A2, A3, A4)>::argTypeDistance(v);
+ }
+};
+
+template<typename T, typename R, typename A1, typename A2, typename A3, typename A4, typename A5>
+struct Arg<R(T::*)(A1, A2, A3, A4, A5)> {
+ static inline int num(void) {return 5;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1, A2, A3, A4, A5)>::argTypeDistance(v);
+ }
+};
+
+template<typename T, typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
+struct Arg<R(T::*)(A1, A2, A3, A4, A5, A6)> {
+ static inline int num(void) {return 6;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1, A2, A3, A4, A5, A6)>::argTypeDistance(v);
+ }
+};
+
+template<typename T, typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
+struct Arg<R(T::*)(A1, A2, A3, A4, A5, A6, A7)> {
+ static inline int num(void) {return 7;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1, A2, A3, A4, A5, A6, A7)>::argTypeDistance(v);
+ }
+};
+
+#ifdef SQPLUS_CONST_OPT
+template<typename T, typename R>
+struct Arg<R(T::*)(void) const> {
+ static inline int num(void) {return 0;}
+ static inline int argTypeDistance(HSQUIRRELVM) {
+ return 0;
+ }
+};
+
+template<typename T, typename R, typename A1>
+struct Arg<R(T::*)(A1) const> {
+ static inline int num(void) {return 1;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1)>::argTypeDistance(v);
+ }
+};
+
+template<typename T, typename R, typename A1, typename A2>
+struct Arg<R(T::*)(A1, A2) const> {
+ static inline int num(void) {return 2;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1, A2)>::argTypeDistance(v);
+ }
+};
+
+template<typename T, typename R, typename A1, typename A2, typename A3>
+struct Arg<R(T::*)(A1, A2, A3) const> {
+ static inline int num(void) {return 3;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1, A2, A3)>::argTypeDistance(v);
+ }
+};
+
+template<typename T, typename R, typename A1, typename A2, typename A3, typename A4>
+struct Arg<R(T::*)(A1, A2, A3, A4) const> {
+ static inline int num(void) {return 4;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1, A2, A3, A4)>::argTypeDistance(v);
+ }
+};
+
+template<typename T, typename R, typename A1, typename A2, typename A3, typename A4, typename A5>
+struct Arg<R(T::*)(A1, A2, A3, A4, A5) const> {
+ static inline int num(void) {return 5;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1, A2, A3, A4, A5)>::argTypeDistance(v);
+ }
+};
+
+template<typename T, typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
+struct Arg<R(T::*)(A1, A2, A3, A4, A5, A6) const> {
+ static inline int num(void) {return 6;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1, A2, A3, A4, A5, A6)>::argTypeDistance(v);
+ }
+};
+
+template<typename T, typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
+struct Arg<R(T::*)(A1, A2, A3, A4, A5, A6, A7) const> {
+ static inline int num(void) {return 7;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ return Arg<R(*)(A1, A2, A3, A4, A5, A6, A7)>::argTypeDistance(v);
+ }
+};
+#endif
+
+static inline int classAllocationError(HSQUIRRELVM v) {
+ return sq_throwerror(v, _SC("Failed to allocate memory"));
+}
+
+template<typename R>
+struct Arg<R(*)(void)> {
+ static inline int num(void) {return 0;}
+ static inline int argTypeDistance(HSQUIRRELVM) {return 0;}
+ static inline int create(void) {
+ HSQUIRRELVM v = SquirrelVM::GetVMPtr();
+ R *r = static_cast<R*>(sq_malloc(sizeof(R)));
+ return r ?
+ PostConstruct<R>(v, new(r) R,
+ ClassType<R>::getReleaseHook()) :
+ classAllocationError(v);
+ }
+};
+
+template<typename R, typename A1>
+struct Arg<R(*)(A1)> {
+ static inline int num(void) {return 1;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ int s, r;
+ r = 0;
+ s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
+ return r;
+ }
+ static inline int create(A1 a1) {
+ HSQUIRRELVM v = SquirrelVM::GetVMPtr();
+ R *r = static_cast<R*>(sq_malloc(sizeof(R)));
+ return r ?
+ PostConstruct<R>(v, new(r) R(a1),
+ ClassType<R>::getReleaseHook()) :
+ classAllocationError(v);
+ }
+};
+
+template<typename R, typename A1, typename A2>
+struct Arg<R(*)(A1, A2)> {
+ static inline int num(void) {return 2;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ int s, r;
+ r = 0;
+ s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A2>::distance(v, 3); if (s < 0) {return -1;} r += s;
+ return r;
+ }
+ static inline int create(A1 a1, A2 a2) {
+ HSQUIRRELVM v = SquirrelVM::GetVMPtr();
+ R *r = static_cast<R*>(sq_malloc(sizeof(R)));
+ return r ?
+ PostConstruct<R>(v, new(r) R(a1, a2),
+ ClassType<R>::getReleaseHook()) :
+ classAllocationError(v);
+ }
+};
+
+template<typename R, typename A1, typename A2, typename A3>
+struct Arg<R(*)(A1, A2, A3)> {
+ static inline int num(void) {return 3;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ int s, r;
+ r = 0;
+ s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A2>::distance(v, 3); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A3>::distance(v, 4); if (s < 0) {return -1;} r += s;
+ return r;
+ }
+ static inline int create(A1 a1, A2 a2, A3 a3) {
+ HSQUIRRELVM v = SquirrelVM::GetVMPtr();
+ R *r = static_cast<R*>(sq_malloc(sizeof(R)));
+ return r ?
+ PostConstruct<R>(v, new(r) R(a1, a2, a3),
+ ClassType<R>::getReleaseHook()) :
+ classAllocationError(v);
+ }
+};
+
+template<typename R, typename A1, typename A2, typename A3, typename A4>
+struct Arg<R(*)(A1, A2, A3, A4)> {
+ static inline int num(void) {return 4;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ int s, r;
+ r = 0;
+ s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A2>::distance(v, 3); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A3>::distance(v, 4); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A4>::distance(v, 5); if (s < 0) {return -1;} r += s;
+ return r;
+ }
+ static inline int create(A1 a1, A2 a2, A3 a3, A4 a4) {
+ HSQUIRRELVM v = SquirrelVM::GetVMPtr();
+ R *r = static_cast<R*>(sq_malloc(sizeof(R)));
+ return r ?
+ PostConstruct<R>(v, new(r) R(a1, a2, a3, a4),
+ ClassType<R>::getReleaseHook()) :
+ classAllocationError(v);
+ }
+};
+
+template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5>
+struct Arg<R(*)(A1, A2, A3, A4, A5)> {
+ static inline int num(void) {return 5;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ int s, r;
+ r = 0;
+ s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A2>::distance(v, 3); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A3>::distance(v, 4); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A4>::distance(v, 5); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A5>::distance(v, 6); if (s < 0) {return -1;} r += s;
+ return r;
+ }
+ static inline int create(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5) {
+ HSQUIRRELVM v = SquirrelVM::GetVMPtr();
+ R *r = static_cast<R*>(sq_malloc(sizeof(R)));
+ return r ?
+ PostConstruct<R>(v, new(r) R(a1, a2, a3, a4, a5),
+ ClassType<R>::getReleaseHook()) :
+ classAllocationError(v);
+ }
+};
+
+template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6>
+struct Arg<R(*)(A1, A2, A3, A4, A5, A6)> {
+ static inline int num(void) {return 6;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ int s, r;
+ r = 0;
+ s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A2>::distance(v, 3); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A3>::distance(v, 4); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A4>::distance(v, 5); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A5>::distance(v, 6); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A6>::distance(v, 7); if (s < 0) {return -1;} r += s;
+ return r;
+ }
+ static inline int create(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6) {
+ HSQUIRRELVM v = SquirrelVM::GetVMPtr();
+ R *r = static_cast<R*>(sq_malloc(sizeof(R)));
+ return r ?
+ PostConstruct<R>(v, new(r) R(a1, a2, a3, a4, a5, a6),
+ ClassType<R>::getReleaseHook()) :
+ classAllocationError(v);
+ }
+};
+
+template<typename R, typename A1, typename A2, typename A3, typename A4, typename A5, typename A6, typename A7>
+struct Arg<R(*)(A1, A2, A3, A4, A5, A6, A7)> {
+ static inline int num(void) {return 7;}
+ static inline int argTypeDistance(HSQUIRRELVM v) {
+ int s, r;
+ r = 0;
+ s = CheckInstance<A1>::distance(v, 2); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A2>::distance(v, 3); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A3>::distance(v, 4); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A4>::distance(v, 5); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A5>::distance(v, 6); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A6>::distance(v, 7); if (s < 0) {return -1;} r += s;
+ s = CheckInstance<A7>::distance(v, 8); if (s < 0) {return -1;} r += s;
+ return r;
+ }
+ static inline int create(A1 a1, A2 a2, A3 a3, A4 a4, A5 a5, A6 a6, A7 a7) {
+ HSQUIRRELVM v = SquirrelVM::GetVMPtr();
+ R *r = static_cast<R*>(sq_malloc(sizeof(R)));
+ return r ?
+ PostConstruct<R>(v, new(r) R(a1, a2, a3, a4, a5, a6, a7),
+ ClassType<R>::getReleaseHook()) :
+ classAllocationError(v);
+ }
+};
+#endif // SQPLUS_OVERLOAD_FUNCTIONS
+
+// SqPlusOverload.h
+
+// Local Variables:
+// mode: c++
+// End:
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlusSetup.h b/squirrel_3_0_1_stable/sqplus/SqPlusSetup.h
new file mode 100644
index 000000000..372e63f69
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SqPlusSetup.h
@@ -0,0 +1,129 @@
+#ifndef SQPLUSSETUP_H
+#define SQPLUSSETUP_H
+
+// Setup file for SqPlus.
+// Comment / uncomment / define options below.
+
+
+// Inheritance in Squirrel allows one class to inherit a base class's
+// functions and variables.
+//
+// Variables are merged: if Derived has a var name 'val' and Base has
+// a var of the same name, the resulting var 'val' will take Derived's
+// initialization value.
+//
+// Functions are not merged, and can be called via Squirrel scoping rules.
+//
+// Define SQ_USE_CLASS_INHERITANCE to enable class inheritance support
+// (requires slightly more memory and adds some CPU overhead).
+//
+// Can also be useful for debugging, as class type information is
+// checked before dispatching instance function calls and before
+// accessing instance member variables.
+#define SQ_USE_CLASS_INHERITANCE
+
+
+// This is a new C++ template based inheritence scheme that uses no
+// additional memory per instance. To support offset between "this"
+// pointer in base and derived class, use a second class in:
+// SQClassDef< MyClass, MyBaseClass >.
+// NOTE: For new code SQ_USE_CLASS_INHERITANCE_SIMPLE is more
+// efficient than above method.
+//#define SQ_USE_CLASS_INHERITANCE_SIMPLE
+
+// === Instance type info support ===
+#define SQ_SUPPORT_INSTANCE_TYPE_INFO
+
+// === Constant argument and constant member function support ===
+// Define SQPLUS_CONST_OPT before including SqPlus.h for constant
+// argument + constant member function support.
+#define SQPLUS_CONST_OPT
+
+
+// === Uncomment to support smart pointer ===
+// Define SQPLUS_SMARTPOINTER_OPT before including SqPlus.h for
+// smartpointer member function + variable support
+//#define SQPLUS_SMARTPOINTER_OPT
+
+
+// === Function overloading support ===
+#define SQPLUS_OVERLOAD_OPT
+
+// === Uncomment to support std::string ===
+// Requires that Squirrel is compiled with SQChar == char
+//#define SQPLUS_SUPPORT_STD_STRING
+
+// === Uncomment to support typedef std::basic_string<SQChar> sq_std_string ===
+#define SQPLUS_SUPPORT_SQ_STD_STRING
+
+// === Uncomment to support NULL INSTANCE arguments ===
+#define SQPLUS_SUPPORT_NULL_INSTANCES
+
+// === Uncomment to disable copying of class instances ===
+// If classes being exposed have private or protected constructors
+// one cannot do assign (=) in template functions.
+//#define SQPLUS_DISABLE_COPY_INSTANCES
+
+
+// === Auto generating typemasks for registered functions ===
+// This is useful when using Squirrel interactively
+//#define SQPLUS_ENABLE_AUTO_TYPEMASK
+
+// === Uncomment to generate a typeof function for each class ===
+// This is mostly for displaying function help from inside a Squirrel prompt
+//#define SQPLUS_ENABLE_TYPEOF
+
+// === Uncomment to skip sq_argassert() ===
+//#define SQ_SKIP_ARG_ASSERT
+
+// === GCC Inline template fix ===
+// Can solve problems when linking if GCC has problems with inline functions
+//#define GCC_INLINE_WORKAROUND
+
+
+// === MSVC cdecl member functions ===
+// Enable binding member functions with __cdecl calling convention under MSVC.
+// Mostly useful when linking with binaries from other compilers.
+#ifdef _MSC_VER
+//#define SQPLUS_ENABLE_CDECL_MEMBER_FUNCTIONS
+#endif
+
+
+// === Generic Push/Pop/Match handlers ===
+// This enables using a 'fallback' set of Push/Get/Match that operates
+// on class level (not on template level). This opens for handling all
+// members of a certain class hierarchy using the same function
+// GenPush/GenGet/GenMatch overrides (provided the hierarchy has some
+// run-time type mechanism to use). They are used whenever an exact
+// template match is not found.
+//#define SQPLUS_USE_GENERIC_HANDLERS
+
+
+// === Sandbox VM ===
+// This enables giving one VM the role of 'sandbox' VM where scripts
+// of unknown origin may execute and not have access to any SqPlus
+// registered functions. All normal VMs have full access to script
+// functions, but the one given in SetSandboxVm() can only use std
+// Squirrel functions.
+//#define SQPLUS_USE_SANDBOX_VM
+
+
+#if defined(SQPLUS_SUPPORT_STD_STRING) || defined(SQPLUS_SUPPORT_SQ_STD_STRING)
+# include <string>
+#endif
+
+
+// === Conversion of arguments from opposite char type ( char <=> wchar_t ) ===
+// Converts strings to opposite encoding in Push/Get handlers (UTF8 / Latin1)
+#define SQPLUS_AUTOCONVERT_OTHER_CHAR
+
+// === Whether 8 bit chars are treated as Latin1(1) or UTF8(0) ===
+// (leave undefined for undefined for automatic handling)
+#define SQPLUS_USE_LATIN1 1
+
+// === Include system library bindings when creating VM:s in SquirrelVM::Init() ===
+// Define to bind to system lib when VM:s are created automatically in
+// SquirrelVM::Init()
+//#define SQPLUS_SQUIRRELVM_WITH_SYSTEMLIB
+
+#endif // SQPLUSSETUP_H
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlusSmartPointer.h b/squirrel_3_0_1_stable/sqplus/SqPlusSmartPointer.h
new file mode 100644
index 000000000..34996ffd8
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SqPlusSmartPointer.h
@@ -0,0 +1,141 @@
+// SqPlusSmartPointer.h
+// SqPlus smart pointer member function support created by James Whitworth.
+// Modular integration 07/11/07 James Whitworth.
+// you must define the function:
+// unsigned char* getSmartPointerPointee(unsigned char*) {
+// return &(MySmartPointer->pointee);
+// }
+// somewhere in your program so it can correctly lookup member variables on the class pointed to
+// by your smart pointer.
+
+#ifdef SQPLUS_SMARTPOINTER_ACCESSTYPE
+#undef SQPLUS_SMARTPOINTER_ACCESSTYPE
+enum VarAccessType {VAR_ACCESS_READ_WRITE=0,VAR_ACCESS_READ_ONLY=1<<0,VAR_ACCESS_CONSTANT=1<<1,VAR_ACCESS_STATIC=1<<2,VAR_ACCESS_SMARTPOINTER=1<<3};
+#endif // #ifdef SQPLUS_SMARTPOINTER_ACCESSTYPE
+
+#ifdef SQPLUS_SMARTPOINTER_REGISTER_VARIABLE
+#undef SQPLUS_SMARTPOINTER_REGISTER_VARIABLE
+// classType is the type of the member variable's containing class.
+template<typename T>
+void
+RegisterSmartInstanceVariable(SquirrelObject & so,
+ ClassTypeBase *classType,
+ T *var,
+ const SQChar *scriptVarName,
+ VarAccessType access = VAR_ACCESS_READ_WRITE)
+{
+ VarRef *pvr = createVarRef(so,scriptVarName);
+
+ // var must be passed in as &obj->var, where obj = 0
+ // (the address is the offset), or as static/global address.
+ void *offsetOrAddrOrConst = static_cast<void*>(var);
+ *pvr = VarRef(offsetOrAddrOrConst,
+ TypeInfo<T>(),
+ classType,
+ ClassType<T>::type(),
+ sizeof(*var),
+ access);
+ pvr->m_access |= VAR_ACCESS_SMARTPOINTER;
+ createInstanceSetGetHandlers(so);
+}
+#endif // #ifdef SQPLUS_SMARTPOINTER_REGISTER_VARIABLE
+
+#ifdef SQPLUS_SMARTPOINTER_DISPATCH
+#undef SQPLUS_SMARTPOINTER_DISPATCH
+template<typename Callee,typename Pointee,typename Func>
+class DirectCallSmartInstanceMemberFunction {
+public:
+ static inline int Dispatch(HSQUIRRELVM v) {
+ DirectCallInstanceFuncPicker<Callee, Func> p(v);
+ if (!p.instance || !p.func) {
+ sq_throwerror(v, _SC("Invalid Instance Type"));
+ }
+ Pointee *pointeeInstance = static_cast<Pointee*>(p.instance->get());
+ return
+ !pointeeInstance ? sq_throwerror(v, _SC("SmartPointer Pointee NULL")) :
+ Call(*pointeeInstance, *(p.func), v, 2);
+ }
+};
+#endif // #ifdef SQPLUS_SMARTPOINTER_DISPATCH
+
+#ifdef SQPLUS_SMARTPOINTER_DIRECT_CLOSURE
+#undef SQPLUS_SMARTPOINTER_DIRECT_CLOSURE
+
+template<typename Callee,typename Pointee,typename Func>
+inline void sq_pushdirectsmartinstanceclosure(HSQUIRRELVM v,const Callee & callee,const Pointee & pointee,Func func,SQUnsignedInteger nupvalues) {
+ unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
+ memcpy(up,&func,sizeof(func));
+ sq_newclosure(v,DirectCallSmartInstanceMemberFunction<Callee,Pointee,Func>::Dispatch,nupvalues+1);
+} // sq_pushdirectinstanceclosure
+
+#endif // #ifdef SQPLUS_SMARTPOINTER_DIRECT_CLOSURE
+
+#ifdef SQPLUS_SMARTPOINTER_REGISTER_INSTANCE
+#undef SQPLUS_SMARTPOINTER_REGISTER_INSTANCE
+
+template<typename Callee, typename Pointee, typename Func>
+inline void RegisterSmartInstance(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,Pointee & pointee,Func func,const SQChar * name) {
+ sq_pushobject(v,hclass);
+ sq_pushstring(v,name,-1);
+ sq_pushdirectsmartinstanceclosure(v,callee,pointee,func,0);
+ sq_createslot(v,-3);
+ sq_poptop(v); // Remove hclass.
+} // RegisterInstance
+
+#endif // #ifdef SQPLUS_SMARTPOINTER_REGISTER_INSTANCE
+
+#ifdef SQPLUS_SMARTPOINTER_CLASS_DEF_FUNC
+#undef SQPLUS_SMARTPOINTER_CLASS_DEF_FUNC
+
+ // Register a smartpointer member function.
+ template<typename Pointee, typename Func>
+ SQClassDefBase & smartFunc(Func pfunc,const SQChar * name) {
+ RegisterSmartInstance(v,newClass.GetObjectHandle(),*(TClassType *)0,*(Pointee *)0,pfunc,name);
+ return *this;
+ } // func
+
+#endif // #ifdef SQPLUS_SMARTPOINTER_CLASS_DEF_FUNC
+
+#ifdef SQPLUS_SMARTPOINTER_CLASS_DEF_VAR
+#undef SQPLUS_SMARTPOINTER_CLASS_DEF_VAR
+
+ // Register a member variable.
+ template<typename Pointee, typename VarType>
+ SQClassDefBase & smartVar(VarType Pointee::* pvar,const SQChar * name,VarAccessType access=VAR_ACCESS_READ_WRITE) {
+ struct CV {
+ VarType Pointee::* var;
+ } cv; // Cast Variable helper.
+ cv.var = pvar;
+ RegisterSmartInstanceVariable(newClass,ClassType<TClassType>::type(),*(VarType **)&cv,name,access);
+ return *this;
+ } // var
+
+ // Register a member variable as a UserPointer (read only).
+ template<typename Pointee, typename VarType>
+ SQClassDefBase & smartVarAsUserPointer(VarType Pointee::* pvar,const SQChar * name) {
+ struct CV {
+ VarType Pointee::* var;
+ } cv; // Cast Variable helper.
+ cv.var = pvar;
+ RegisterSmartInstanceVariable(newClass,ClassType<TClassType>::type(),*(SQAnything **)&cv,name,VAR_ACCESS_READ_ONLY);
+ return *this;
+ } // varAsUserPointer
+
+#endif // #ifdef SQPLUS_SMARTPOINTER_CLASS_DEF_VAR
+
+
+#ifdef SQPLUS_SMARTPOINTER_CPP_DECLARATION
+#undef SQPLUS_SMARTPOINTER_CPP_DECLARATION
+extern unsigned char* getSmartPointerPointee(unsigned char*);
+#endif
+
+#ifdef SQPLUS_SMARTPOINTER_INSTANCE_VARINFO
+#undef SQPLUS_SMARTPOINTER_INSTANCE_VARINFO
+ if(vr->m_access & VAR_ACCESS_SMARTPOINTER) {
+ up = reinterpret_cast<char*>(
+ getSmartPointerPointee(reinterpret_cast<unsigned char*>(up))
+ );
+ }
+#endif // #ifdef SQPLUS_SMARTPOINTER_CPP_DECLARATION
+
+// SqPlusSmartPointer.h
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlusTypeMask.h b/squirrel_3_0_1_stable/sqplus/SqPlusTypeMask.h
new file mode 100644
index 000000000..975a51a1f
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SqPlusTypeMask.h
@@ -0,0 +1,169 @@
+
+// File to automatically generate a typemask for a function
+
+// Will generate type masks that accepts Instance pointer or null
+#ifndef SQPLUS_ACCEPT_NULL_INSTANCE
+ #define SQPLUS_ACCEPT_NULL_INSTANCE
+#endif
+
+// Macros to reduce typing: (P1), (P1,P2), (P1,P2,P3), ...
+#define P_0
+#define P_1 P1
+#define P_2 P_1,P2
+#define P_3 P_2,P3
+#define P_4 P_3,P4
+#define P_5 P_4,P5
+#define P_6 P_5,P6
+#define P_7 P_6,P7
+
+// Macros to reduce typing: (typename P1), (typename P1,typename P2), ...
+#define PTN_0
+#define PTN_1 typename P1
+#define PTN_2 PTN_1,typename P2
+#define PTN_3 PTN_2,typename P3
+#define PTN_4 PTN_3,typename P4
+#define PTN_5 PTN_4,typename P5
+#define PTN_6 PTN_5,typename P6
+#define PTN_7 PTN_6,typename P7
+
+// Include a comma first in list: ,typename P1,typename P2
+#define PTNC_0
+#define PTNC_1 ,PTN_1
+#define PTNC_2 ,PTN_2
+#define PTNC_3 ,PTN_3
+#define PTNC_4 ,PTN_4
+#define PTNC_5 ,PTN_5
+#define PTNC_6 ,PTN_6
+#define PTNC_7 ,PTN_7
+
+#ifdef SQUNICODE
+#define scstrcpy wcscpy
+#else
+#define scstrcpy strcpy
+#endif
+
+inline const SQChar* strappchar(SQChar *buf, SQChar *in, SQChar ch){
+ int l=scstrlen(in);
+ scstrcpy(buf,in);
+ buf[l] = ch;
+#ifdef SQPLUS_ACCEPT_NULL_INSTANCE
+ if( ch=='x' ){
+ buf[++l] = '|'; // Also accept NULL pointers
+ buf[++l] = 'o';
+ }
+#endif
+ buf[l+1] = 0;
+ return buf;
+}
+
+template<class T>
+struct sqTypeMask { };
+
+
+// Return type not included in type mask, delegate to void case
+
+// Base case, no arguments
+template<typename RT>
+struct sqTypeMask<RT(*)()> {
+ static const SQChar *Get(){
+ static SQChar buf[64];
+ //buf[0] = _SC('t');
+ //buf[1] = 0;
+ //strcpy(buf,"t|x"); // Accept both instance and table, we don't use param anyway
+ buf[0] = _SC('.'); // Accept anything (not used)
+ buf[1] = 0;
+ return buf;
+ }
+};
+
+// Recursive case, peel of one arg at each level
+#define DECLARE_RT_SQTYPEMASK(N,M) \
+template<typename RT PTNC_##N> \
+struct sqTypeMask<RT(*)(P_##N)> { \
+ static const SQChar *Get(){ \
+ static SQChar buf[10]; \
+ return strappchar(buf, (SQChar*)sqTypeMask<RT(*)(P_##M)>::Get(), \
+ (SQChar)TypeInfo<P##N>::TypeMask); \
+ } \
+};
+
+DECLARE_RT_SQTYPEMASK(1,0)
+DECLARE_RT_SQTYPEMASK(2,1)
+DECLARE_RT_SQTYPEMASK(3,2)
+DECLARE_RT_SQTYPEMASK(4,3)
+DECLARE_RT_SQTYPEMASK(5,4)
+DECLARE_RT_SQTYPEMASK(6,5)
+DECLARE_RT_SQTYPEMASK(7,6)
+
+
+// Difference to above is that 1st param is instance instead of table
+
+#define DECLARE_RT_MEMBER_SQTYPEMASK(N,QUAL) \
+template<typename Callee, typename RT PTNC_##N> \
+struct sqTypeMask<RT(Callee::*)(P_##N) QUAL> { \
+ static const SQChar *Get(){ \
+ SQChar *buf = (SQChar*)sqTypeMask<RT(*)(P_##N)>::Get(); \
+ buf[0] = _SC('x'); \
+ return buf; \
+ } \
+};
+
+// buf[1] = 0; \
+
+DECLARE_RT_MEMBER_SQTYPEMASK(0,)
+DECLARE_RT_MEMBER_SQTYPEMASK(1,)
+DECLARE_RT_MEMBER_SQTYPEMASK(2,)
+DECLARE_RT_MEMBER_SQTYPEMASK(3,)
+DECLARE_RT_MEMBER_SQTYPEMASK(4,)
+DECLARE_RT_MEMBER_SQTYPEMASK(5,)
+DECLARE_RT_MEMBER_SQTYPEMASK(6,)
+DECLARE_RT_MEMBER_SQTYPEMASK(7,)
+
+DECLARE_RT_MEMBER_SQTYPEMASK(0,const)
+DECLARE_RT_MEMBER_SQTYPEMASK(1,const)
+DECLARE_RT_MEMBER_SQTYPEMASK(2,const)
+DECLARE_RT_MEMBER_SQTYPEMASK(3,const)
+DECLARE_RT_MEMBER_SQTYPEMASK(4,const)
+DECLARE_RT_MEMBER_SQTYPEMASK(5,const)
+DECLARE_RT_MEMBER_SQTYPEMASK(6,const)
+DECLARE_RT_MEMBER_SQTYPEMASK(7,const)
+
+
+#ifdef _MSC_VER
+
+// Difference to above is we're using __cdecl calling convention here
+// Only makes sense for MSVC where member functions can have different
+// calling conventions (__cdecl or __thiscall)
+
+#define DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(N,QUAL) \
+template<typename Callee, typename RT PTNC_##N> \
+struct sqTypeMask<RT(__cdecl Callee::*)(P_##N) QUAL> { \
+ static const SQChar *Get(){ \
+ SQChar *buf = (SQChar*)sqTypeMask<RT(*)(P_##N)>::Get(); \
+ buf[0] = _SC('x'); \
+ return buf; \
+ } \
+};
+
+// buf[1] = 0; \
+
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(0,)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(1,)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(2,)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(3,)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(4,)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(5,)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(6,)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(7,)
+
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(0,const)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(1,const)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(2,const)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(3,const)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(4,const)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(5,const)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(6,const)
+DECLARE_RT_MEMBER_SQTYPEMASK_CDECL(7,const)
+
+#endif // _MSC_VER
+
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlusUtf8.cpp b/squirrel_3_0_1_stable/sqplus/SqPlusUtf8.cpp
new file mode 100644
index 000000000..7505e9928
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SqPlusUtf8.cpp
@@ -0,0 +1,133 @@
+
+///////////////////////////////////////////////////////////////////////
+// Simple conversion routines, to, from UTF8 and full Unicode character
+// (using int).
+//
+
+// Only when needed
+#if !defined(SQPLUS_USE_LATIN1) || SQPLUS_USE_LATIN1==0
+
+static char g_utf8_length[256];
+static int g_did_init_length;
+
+void sqplus_init_utf8_lengths() {
+ // Fill in lengths in array above
+ for( int lb=0; lb<256; lb++ ){
+ int l = -1;
+ if( !(lb&0x80) ) l=1;
+ else if( (lb&0xE0)==0xC0 ) l=2;
+ else if( (lb&0xF0)==0xE0 ) l=3;
+ else if( (lb&0xF8)==0xF0 ) l=4;
+ else if( (lb&0xFC)==0xF8 ) l=5;
+ else if( (lb&0xFE)==0xFC ) l=6;
+ g_utf8_length[lb] = l;
+ }
+ g_did_init_length = 1;
+}
+
+// Length of a UTF8 encoded Unicode character
+int sqplus_utf8_len(int lead_byte){
+ if( !(lead_byte&0x80) ) return 1; // Special case, make faster
+ if( !g_did_init_length )
+ sqplus_init_utf8_lengths();
+
+ return g_utf8_length[(unsigned char)lead_byte];
+}
+
+int sqplus_utf8_len_first(const char* pc){
+ int lb = *(unsigned char*)pc;
+ if( !(lb&0x80) ) return 1; // Special case, make faster
+ if( !g_did_init_length )
+ sqplus_init_utf8_lengths();
+
+ int l = g_utf8_length[(unsigned char)lb];
+ if( l>0 ) return l;
+
+ // Invalid UTF8 lead byte. Look for next valid character.
+ const char *pc1 = pc+1;
+ while( ((*pc1)&0xC0)==0x80 )
+ pc1++;
+ return int(pc1 - pc);
+}
+
+
+// Length of a UTF8 encoded Unicode string (number of Unicode characters)
+int sqplus_utf8_strlen(const char *str) {
+ if( !str ) return 0;
+ int l, tl=0;
+ while( *str ){
+ l = sqplus_utf8_len_first(str);
+ str += l;
+ tl++;
+ }
+ return tl;
+}
+
+// Convert one UTF8 encoded character to Unicode point
+int sqplus_utf8_to_wchar(int *result, const char *string){
+ int res=-1;
+
+ // Assume argument pointers to be OK
+ unsigned char ch = *string;
+ int l = sqplus_utf8_len(ch);
+
+ if( l<1 ) return -1;
+ int wc = l>1 ? (ch&(0x7F>>l)) : ch;
+ while( l>1 ){
+ wc = (wc<<6) + (*++string & 0x3F);
+ l--;
+ }
+ *result = wc;
+
+ return 0;
+}
+
+// Convert one Unicode point to UTF8 encoded version.
+// Checks if output fits in 1/4/6 bytes buffer.
+int sqplus_wchar_to_utf8(char *s, int wc, int size){
+ if( size<1 ) return -1;
+ if( (unsigned int)wc>=0x80000000 ) return -2;
+
+ // Single byte case
+ if( wc<0x80 ){
+ *s = (char)wc;
+ //*s = (char)wc&0x7F;
+ return 1;
+ }
+ if( size<4 ) return -3;
+
+ // Two or more UTF8 bytes
+ int p = 1; // Index of last UTF8 byte
+ if( wc>0x7FF ){ // 11 bits
+ // Three or more UTF8 bytes
+ p++; // p>=2
+ if( wc>0xFFFF ){ // 16 bits
+ // Four or more UTF8 bytes
+ p++; // p>=3
+ if( wc>0x1FFFFF ){ // 21 bits
+ // Five or more UTF8 bytes
+ if( size<6 ) return -3;
+ p++; // p>=4 UTF8 bytes
+ if( wc>0x3FFFFFF ){ // 26 bits
+ // Six UTF8 bytes
+ p++; // p>=5
+ if( (unsigned int)wc>(unsigned int)0x7FFFFFF ){ // 31 bits
+ // Would need 7 UTF8 bytes. Not supported.
+ return -10;
+ }
+ s[p-4] = 0x80 | ((wc>>24)&0x3F); // Bit 24..29
+ }
+ s[p-3] = 0x80 | ((wc>>18)&0x3F); // Bit 18..23
+ }
+ s[p-2] = 0x80 | ((wc>>12)&0x3F); // Bit 12..17
+ }
+ s[p-1] = 0x80 | ((wc>>6)&0x3F); // Bit 6..11
+ }
+ s[p] = 0x80 | (wc&0x3F); // Bit 0..5
+ s[0] = (0xFC << (5-p)) | (wc>>(p*6));
+
+ return p+1;
+}
+
+#endif // #if !defined(SQPLUS_USE_LATIN1) || SQPLUS_USE_LATIN1==0
+
diff --git a/squirrel_3_0_1_stable/sqplus/SqPlusUtf8.h b/squirrel_3_0_1_stable/sqplus/SqPlusUtf8.h
new file mode 100644
index 000000000..b0c14aa36
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SqPlusUtf8.h
@@ -0,0 +1,15 @@
+#ifndef SQPLUSUTF8_H
+#define SQPLUSUTF8_H
+
+#if defined(SQUTF8) || SQPLUS_USE_LATIN1!=1
+
+// Simple Unicode <-> UTF8 conversion routines
+//int sqplus_utf8_len(char lead_byte);
+int sqplus_utf8_len_first(const char *str);
+int sqplus_utf8_strlen(const char *str);
+int sqplus_utf8_to_wchar(int *result, const char *string);
+int sqplus_wchar_to_utf8(char *s, int wc, int size);
+
+#endif // defined(SQUTF8) || SQPLUS_USE_LATIN1!=1
+
+#endif // SQPLUSUTF8_H
diff --git a/squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtils.cpp b/squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtils.cpp
new file mode 100644
index 000000000..cd337961c
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtils.cpp
@@ -0,0 +1,161 @@
+#include "sqplus.h"
+
+BOOL CreateStaticNamespace(HSQUIRRELVM v,ScriptNamespaceDecl *sn)
+{
+ int n = 0;
+ sq_pushroottable(v);
+ sq_pushstring(v,sn->name,-1);
+ sq_newtable(v);
+ const ScriptClassMemberDecl *members = sn->members;
+ const ScriptClassMemberDecl *m = NULL;
+ while(members[n].name) {
+ m = &members[n];
+ sq_pushstring(v,m->name,-1);
+ sq_newclosure(v,m->func,0);
+ sq_setparamscheck(v,m->params,m->typemask);
+ sq_setnativeclosurename(v,-1,m->name);
+ sq_createslot(v,-3);
+ n++;
+ }
+ const ScriptConstantDecl *consts = sn->constants;
+ const ScriptConstantDecl *c = NULL;
+ n = 0;
+ while(consts[n].name) {
+ c = &consts[n];
+ sq_pushstring(v,c->name,-1);
+ switch(c->type) {
+ case OT_STRING: sq_pushstring(v,c->val.s,-1);break;
+ case OT_INTEGER: sq_pushinteger(v,c->val.i);break;
+ case OT_FLOAT: sq_pushfloat(v,c->val.f);break;
+ }
+ sq_createslot(v,-3);
+ n++;
+ }
+ if(sn->delegate) {
+ const ScriptClassMemberDecl *members = sn->delegate;
+ const ScriptClassMemberDecl *m = NULL;
+ sq_newtable(v);
+ while(members[n].name) {
+ m = &members[n];
+ sq_pushstring(v,m->name,-1);
+ sq_newclosure(v,m->func,0);
+ sq_setparamscheck(v,m->params,m->typemask);
+ sq_setnativeclosurename(v,-1,m->name);
+ sq_createslot(v,-3);
+ n++;
+ }
+ sq_setdelegate(v,-2);
+ }
+ sq_createslot(v,-3);
+ sq_pop(v,1);
+
+ return TRUE;
+}
+
+BOOL CreateClass(HSQUIRRELVM v,SquirrelClassDecl *cd)
+{
+ int n = 0;
+ int oldtop = sq_gettop(v);
+ sq_pushroottable(v);
+ sq_pushstring(v,cd->name,-1);
+ if(cd->base) {
+ sq_pushstring(v,cd->base,-1);
+ if(SQ_FAILED(sq_get(v,-3))) { // Make sure the base exists if specified by cd->base name.
+ sq_settop(v,oldtop);
+ return FALSE;
+ }
+ }
+ if(SQ_FAILED(sq_newclass(v,cd->base?1:0))) { // Will inherit from base class on stack from sq_get() above.
+ sq_settop(v,oldtop);
+ return FALSE;
+ }
+// sq_settypetag(v,-1,(unsigned int)cd);
+#ifdef _WIN32
+#pragma warning(disable : 4311)
+#endif
+ sq_settypetag(v,-1,reinterpret_cast<SQUserPointer>(cd));
+ const ScriptClassMemberDecl *members = cd->members;
+ const ScriptClassMemberDecl *m = NULL;
+ if (members) {
+ while(members[n].name) {
+ m = &members[n];
+ sq_pushstring(v,m->name,-1);
+ sq_newclosure(v,m->func,0);
+ sq_setparamscheck(v,m->params,m->typemask);
+ sq_setnativeclosurename(v,-1,m->name);
+ sq_createslot(v,-3);
+ n++;
+ }
+ } // if
+ sq_createslot(v,-3);
+ sq_pop(v,1);
+ return TRUE;
+}
+
+BOOL CreateNativeClassInstance(HSQUIRRELVM v,
+ const SQChar *classname,
+ SQUserPointer ud,
+ SQRELEASEHOOK hook)
+{
+ // If we don't do this, SquirrelVM keeps an old pointer around and this
+ // will be used by SquirrelObject. That crashes when using several VMs.
+ SquirrelVM::Init( v );
+
+ int oldtop = sq_gettop(v);
+ sq_pushroottable(v);
+ sq_pushstring(v,classname,-1);
+ if(SQ_FAILED(sq_rawget(v,-2))){ //Get the class (created with sq_newclass()).
+ sq_settop(v,oldtop);
+ return FALSE;
+ }
+ //sq_pushroottable(v);
+ if(SQ_FAILED(sq_createinstance(v,-1))) {
+ sq_settop(v,oldtop);
+ return FALSE;
+ }
+
+#ifdef SQ_USE_CLASS_INHERITANCE
+ HSQOBJECT ho;
+ sq_getstackobj(v, -1, &ho); // OT_INSTANCE
+ SquirrelObject instance(ho);
+ SqPlus::PopulateAncestry(v, instance, ud);
+#endif
+
+ sq_remove(v,-3); //removes the root table
+ sq_remove(v,-2); //removes the class
+ if(SQ_FAILED(sq_setinstanceup(v,-1,ud))) {
+ sq_settop(v,oldtop);
+ return FALSE;
+ }
+ sq_setreleasehook(v,-1,hook);
+ return TRUE;
+}
+
+
+
+// Create native class instance and leave on stack.
+BOOL CreateConstructNativeClassInstance(HSQUIRRELVM v,const SQChar * className) {
+ int oldtop = sq_gettop(v);
+ sq_pushroottable(v);
+ sq_pushstring(v,className,-1);
+ if (SQ_FAILED(sq_rawget(v,-2))) { // Get the class (created with sq_newclass()).
+ sq_settop(v,oldtop);
+ return FALSE;
+ } // if
+#if 0
+ sq_remove(v,-3); // Remove the root table.
+ sq_push(v,1); // Push the 'this'.
+#else // Kamaitati's change. 5/28/06 jcs.
+ sq_remove(v,-2); // Remove the root table.
+ sq_pushroottable(v); // Push the 'this'.
+#endif
+ if (SQ_FAILED(sq_call(v,1,SQTrue,SQ_CALL_RAISE_ERROR))) { // Call ClassName(): creates new instance and calls constructor (instead of sq_createinstance() where constructor is not called).
+ sq_settop(v,oldtop);
+ return FALSE;
+ } // if
+ sq_remove(v,-2); // Remove the class.
+ // int newtop = sq_gettop(v);
+ return TRUE;
+} // CreateConstructNativeClassInstance
+
+
diff --git a/squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtils.h b/squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtils.h
new file mode 100644
index 000000000..11ab4be54
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtils.h
@@ -0,0 +1,152 @@
+#ifndef SQUIRREL_BINDINGS_UTILS_H
+#define SQUIRREL_BINDINGS_UTILS_H
+
+struct ScriptClassMemberDecl {
+ const SQChar *name;
+ SQFUNCTION func;
+ int params;
+ const SQChar *typemask;
+};
+
+struct SquirrelClassDecl {
+ const SQChar *name;
+ const SQChar *base;
+ const ScriptClassMemberDecl *members;
+};
+
+struct ScriptConstantDecl {
+ const SQChar *name;
+ SQObjectType type;
+ union value {
+ value(float v){ f = v; }
+ value(int v){ i = v; }
+ value(long int v){ li = v; }
+ value(const SQChar *v){ s = v; }
+ float f;
+ int i;
+ long int li;
+ const SQChar *s;
+ } val;
+};
+
+struct ScriptNamespaceDecl {
+ const SQChar *name;
+ const ScriptClassMemberDecl *members;
+ const ScriptConstantDecl *constants;
+ const ScriptClassMemberDecl *delegate;
+};
+
+#define _BEGIN_CLASS(classname) \
+ int __##classname##__typeof(HSQUIRRELVM v) \
+ { \
+ sq_pushstring(v,_SC(#classname),-1); \
+ return 1; \
+ } \
+ struct ScriptClassMemberDecl __##classname##_members[] = { \
+ {_SC("_typeof"),__##classname##__typeof,1,NULL},
+
+#define _BEGIN_NAMESPACE(xnamespace) struct ScriptClassMemberDecl __##xnamespace##_members[] = {
+#define _BEGIN_NAMESPACE_CONSTANTS(xnamespace) {NULL,NULL,0,NULL}}; \
+ struct ScriptConstantDecl __##xnamespace##_constants[] = {
+
+#define _BEGIN_DELEGATE(xnamespace) struct ScriptClassMemberDecl __##xnamespace##_delegate[] = {
+#define _DELEGATE(xnamespace) __##xnamespace##_delegate
+#define _END_DELEGATE(classname) {NULL,NULL,NULL,NULL}};
+
+#define _CONSTANT(name,type,val) {_SC(#name),type,val},
+#define _CONSTANT_IMPL(name,type) {_SC(#name),type,name},
+
+#define _MEMBER_FUNCTION(classname,name,nparams,typemask) \
+ {_SC(#name),__##classname##_##name,nparams,typemask},
+
+#define _END_NAMESPACE(classname,delegate) {NULL,OT_NULL,0}}; \
+struct ScriptNamespaceDecl __##classname##_decl = { \
+ _SC(#classname), __##classname##_members,__##classname##_constants,delegate };
+
+#define _END_CLASS(classname) {NULL,NULL,0,NULL}}; \
+struct SquirrelClassDecl __##classname##_decl = { \
+ _SC(#classname), NULL, __##classname##_members };
+
+
+#define _END_CLASS_INHERITANCE(classname,base) {NULL,NULL,NULL,NULL}}; \
+struct SquirrelClassDecl __##classname##_decl = { \
+ _SC(#classname), _SC(#base), __##classname##_members };
+
+#define _MEMBER_FUNCTION_IMPL(classname,name) \
+ int __##classname##_##name(HSQUIRRELVM v)
+
+#define _INIT_STATIC_NAMESPACE(classname) CreateStaticNamespace(SquirrelVM::GetVMPtr(),&__##classname##_decl);
+#define _INIT_CLASS(classname)CreateClass(SquirrelVM::GetVMPtr(),&__##classname##_decl);
+
+#define _DECL_STATIC_NAMESPACE(xnamespace) extern struct ScriptNamespaceDecl __##xnamespace##_decl;
+#define _DECL_CLASS(classname) extern struct SquirrelClassDecl __##classname##_decl;
+
+#define _CHECK_SELF(cppclass,scriptclass) \
+ cppclass *self = NULL; \
+ if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)&__##scriptclass##_decl))) { \
+ return sq_throwerror(v,_SC("invalid instance type"));\
+ }
+
+#define _CHECK_INST_PARAM(pname,idx,cppclass,scriptclass) \
+ cppclass *pname = NULL; \
+ if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&pname,(SQUserPointer)&__##scriptclass##_decl))) { \
+ return sq_throwerror(v,_SC("invalid instance type"));\
+ } \
+
+#define _CHECK_INST_PARAM_BREAK(pname,idx,cppclass,scriptclass) \
+ cppclass *pname = NULL; \
+ if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&pname,(SQUserPointer)&__##scriptclass##_decl))) { \
+ break; \
+ } \
+
+#define _CLASS_TAG(classname) ((unsigned int)&__##classname##_decl)
+
+
+#define _DECL_NATIVE_CONSTRUCTION(classname,cppclass) \
+ BOOL push_##classname(cppclass &quat); \
+ SquirrelObject new_##classname(cppclass &quat);
+
+#define _IMPL_NATIVE_CONSTRUCTION(classname,cppclass) \
+static int classname##_release_hook(SQUserPointer p, int size) \
+{ \
+ if(p) { \
+ cppclass *pv = (cppclass *)p; \
+ delete pv; \
+ } \
+ return 0; \
+} \
+BOOL push_##classname(cppclass &quat) \
+{ \
+ cppclass *newquat = new cppclass; \
+ *newquat = quat; \
+ if(!CreateNativeClassInstance(SquirrelVM::GetVMPtr(),_SC(#classname),newquat,classname##_release_hook)) { \
+ delete newquat; \
+ return FALSE; \
+ } \
+ return TRUE; \
+} \
+SquirrelObject new_##classname(cppclass &quat) \
+{ \
+ SquirrelObject ret; \
+ if(push_##classname(quat)) { \
+ ret.AttachToStackObject(-1); \
+ sq_pop(SquirrelVM::GetVMPtr(),1); \
+ } \
+ return ret; \
+} \
+int construct_##classname(cppclass *p) \
+{ \
+ sq_setinstanceup(SquirrelVM::GetVMPtr(),1,p); \
+ sq_setreleasehook(SquirrelVM::GetVMPtr(),1,classname##_release_hook); \
+ return 1; \
+}
+
+BOOL CreateStaticClass(HSQUIRRELVM v,SquirrelClassDecl *cd);
+BOOL CreateStaticNamespace(HSQUIRRELVM v,ScriptNamespaceDecl *sn);
+BOOL CreateClass(HSQUIRRELVM v,SquirrelClassDecl *cd);
+BOOL InitScriptClasses(HSQUIRRELVM v);
+BOOL CreateNativeClassInstance(HSQUIRRELVM v,const SQChar *classname,SQUserPointer ud,SQRELEASEHOOK hook);
+BOOL CreateConstructNativeClassInstance(HSQUIRRELVM v,const SQChar * className);
+
+#endif // SQUIRREL_BINDINGS_UTILS_H
+
diff --git a/squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtilsWin32.cpp b/squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtilsWin32.cpp
new file mode 100644
index 000000000..dd3f850ca
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtilsWin32.cpp
@@ -0,0 +1,31 @@
+#include "sqplus.h"
+
+//#include "SquirrelObject.h"
+//#include "SquirrelVM.h"
+#include "SquirrelBindingsUtilsWin32.h"
+
+int refcounted_release_hook(SQUserPointer p, int size)
+{
+ IUnknown *pRC = (IUnknown*)p;
+ pRC->Release();
+ return 0;
+}
+
+static BOOL __CreateRefCountedInstance(HSQUIRRELVM v,const SQChar *classname,IUnknown *pRC,SQRELEASEHOOK hook)
+{
+ if(!CreateNativeClassInstance(v,classname,pRC,hook)) return FALSE;
+ return TRUE;
+}
+
+int construct_RefCounted(IUnknown *p)
+{
+ sq_setinstanceup(SquirrelVM::GetVMPtr(),1,p);
+ sq_setreleasehook(SquirrelVM::GetVMPtr(),1,refcounted_release_hook);
+ return 1;
+}
+
+
+BOOL CreateRefCountedInstance(HSQUIRRELVM v,const SQChar *classname,IUnknown *pRC)
+{
+ return __CreateRefCountedInstance(v,classname,pRC,refcounted_release_hook);
+}
diff --git a/squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtilsWin32.h b/squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtilsWin32.h
new file mode 100644
index 000000000..3f3358422
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SquirrelBindingsUtilsWin32.h
@@ -0,0 +1,41 @@
+#ifndef SQUIRREL_BINDINGS_UTILS_WIN32_H
+#define SQUIRREL_BINDINGS_UTILS_WIN32_H
+
+#ifndef _INC_WINDOWS
+#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+// Windows Header Files:
+#include <windows.h>
+#endif
+#ifndef __IUnknown_INTERFACE_DEFINED__
+#include <unknwn.h>
+#endif
+
+#ifndef SQUIRREL_BINDINGS_UTILS_H
+#include "SquirrelBindingsUtils.h"
+#endif
+
+#define _DECLARE_REFCOUNTED_NEW(cppclass,classname) \
+ SquirrelObject new_##classname(cppclass *ptr) { \
+ if(CreateRefCountedInstance(SquirrelVM::GetVMPtr(),_SC(#classname),ptr)) { \
+ HSQOBJECT o; \
+ sq_getstackobj(SquirrelVM::GetVMPtr(),-1,&o); \
+ SquirrelObject tmp = o; \
+ sq_pop(SquirrelVM::GetVMPtr(),1); \
+ return tmp; \
+ } \
+ return SquirrelObject() ; \
+ }
+
+#define _RETURN_REFCOUNTED_INSTANCE(classname,ptr) \
+ if(!CreateRefCountedInstance(SquirrelVM::GetVMPtr(),_SC(#classname),ptr)) { \
+ return sa.ThrowError(_SC("cannot create the class instance")); \
+ } \
+ return 1;
+
+BOOL CreateRefCountedInstance(HSQUIRRELVM v,const SQChar *classname,IUnknown *pRC);
+BOOL CreateRefCountedInstanceChached(HSQUIRRELVM v,const SQChar *classname,IUnknown *pRC);
+int refcounted_release_hook(SQUserPointer p, int size);
+int construct_RefCounted(IUnknown *p);
+
+#endif // SQUIRREL_BINDINGS_UTILS_WIN32_H
+
diff --git a/squirrel_3_0_1_stable/sqplus/SquirrelObject.cpp b/squirrel_3_0_1_stable/sqplus/SquirrelObject.cpp
new file mode 100644
index 000000000..58d43bbed
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SquirrelObject.cpp
@@ -0,0 +1,702 @@
+#include "sqplus.h"
+
+SquirrelObject::SquirrelObject(void)
+{
+ sq_resetobject(&_o);
+}
+
+SquirrelObject::~SquirrelObject()
+{
+ Reset();
+}
+
+SquirrelObject::SquirrelObject(const SquirrelObject &o)
+{
+ _o = o._o;
+ sq_addref(SquirrelVM::_VM,&_o);
+}
+
+SquirrelObject::SquirrelObject(HSQOBJECT o)
+{
+ _o = o;
+ sq_addref(SquirrelVM::_VM,&_o);
+}
+
+void SquirrelObject::Reset(void) {
+ if(SquirrelVM::_VM)
+ sq_release(SquirrelVM::_VM,&_o);
+ else if( _o._type!=OT_NULL && _o._unVal.pRefCounted )
+ printf( "SquirrelObject::~SquirrelObject - Cannot release\n" );
+ sq_resetobject(&_o);
+} // SquirrelObject::Reset
+
+SquirrelObject SquirrelObject::Clone()
+{
+ SquirrelObject ret;
+ if(GetType() == OT_TABLE || GetType() == OT_ARRAY)
+ {
+ sq_pushobject(SquirrelVM::_VM,_o);
+ sq_clone(SquirrelVM::_VM,-1);
+ ret.AttachToStackObject(-1);
+ sq_pop(SquirrelVM::_VM,2);
+ }
+ return ret;
+
+}
+
+SquirrelObject & SquirrelObject::operator =(const SquirrelObject &o)
+{
+ //HSQOBJECT t;
+ //t = o._o;
+ //sq_addref(SquirrelVM::_VM,&t);
+ sq_addref(SquirrelVM::_VM, (HSQOBJECT*)&o._o);
+ sq_release(SquirrelVM::_VM,&_o);
+ //_o = t;
+ _o = o._o;
+ return *this;
+}
+
+SquirrelObject & SquirrelObject::operator =(HSQOBJECT ho)
+{
+ sq_addref(SquirrelVM::_VM,&ho);
+ sq_release(SquirrelVM::_VM,&_o);
+ _o = ho;
+ return *this;
+}
+
+SquirrelObject & SquirrelObject::operator =(int n)
+{
+ sq_pushinteger(SquirrelVM::_VM,n);
+ AttachToStackObject(-1);
+ sq_pop(SquirrelVM::_VM,1);
+ return *this;
+}
+
+#include <assert.h>
+#include "../squirrel/sqstate.h"
+#include "../squirrel/sqvm.h"
+
+SquirrelObject & SquirrelObject::operator =(HSQUIRRELVM v)
+{
+ if( v && SquirrelVM::_VM ){
+ SquirrelVM::_VM->Push(v);
+ AttachToStackObject(-1);
+ sq_poptop(SquirrelVM::_VM);
+ }
+ else Reset();
+ return *this;
+}
+
+bool SquirrelObject::operator == (const SquirrelObject &o)
+{
+ bool cmp = false;
+ HSQUIRRELVM v = SquirrelVM::GetVMPtr();
+ int oldtop = sq_gettop(v);
+
+ sq_pushobject(v, GetObjectHandle());
+ sq_pushobject(v, o.GetObjectHandle());
+ if(sq_cmp(v) == 0)
+ cmp = true;
+
+ sq_settop(v, oldtop);
+ return cmp;
+}
+
+bool SquirrelObject::CompareUserPointer( const SquirrelObject &o )
+{
+ if( _o._type == o.GetObjectHandle()._type )
+ if( _o._unVal.pUserPointer == o.GetObjectHandle()._unVal.pUserPointer )
+ return true;
+
+ return false;
+}
+
+void SquirrelObject::ArrayAppend(const SquirrelObject &o)
+{
+ if(sq_isarray(_o)) {
+ sq_pushobject(SquirrelVM::_VM,_o);
+ sq_pushobject(SquirrelVM::_VM,o._o);
+ sq_arrayappend(SquirrelVM::_VM,-2);
+ sq_pop(SquirrelVM::_VM,1);
+ }
+}
+
+void SquirrelObject::AttachToStackObject(int idx)
+{
+ HSQOBJECT t;
+ sq_getstackobj(SquirrelVM::_VM,idx,&t);
+ sq_addref(SquirrelVM::_VM,&t);
+ sq_release(SquirrelVM::_VM,&_o);
+ _o = t;
+}
+
+BOOL SquirrelObject::SetDelegate(SquirrelObject &obj)
+{
+ if(obj.GetType() == OT_TABLE ||
+ obj.GetType() == OT_NULL) {
+ switch(_o._type) {
+ case OT_USERDATA:
+ case OT_TABLE:
+ sq_pushobject(SquirrelVM::_VM,_o);
+ sq_pushobject(SquirrelVM::_VM,obj._o);
+ if(SQ_SUCCEEDED(sq_setdelegate(SquirrelVM::_VM,-2))) {
+ sq_pop(SquirrelVM::_VM,1);
+ return TRUE;
+ }
+ sq_pop(SquirrelVM::_VM,1);
+ break;
+ }
+ }
+ return FALSE;
+}
+
+SquirrelObject SquirrelObject::GetDelegate()
+{
+ SquirrelObject ret;
+ if(_o._type == OT_TABLE || _o._type == OT_USERDATA)
+ {
+ int top = sq_gettop(SquirrelVM::_VM);
+ sq_pushobject(SquirrelVM::_VM,_o);
+ sq_getdelegate(SquirrelVM::_VM,-1);
+ ret.AttachToStackObject(-1);
+ sq_settop(SquirrelVM::_VM,top);
+// sq_pop(SquirrelVM::_VM,2);
+ }
+ return ret;
+}
+
+BOOL SquirrelObject::IsNull() const
+{
+ return sq_isnull(_o);
+}
+
+BOOL SquirrelObject::IsNumeric() const
+{
+ return sq_isnumeric(_o);
+}
+
+int SquirrelObject::Len() const
+{
+ int ret = 0;
+ if(sq_isarray(_o) || sq_istable(_o) || sq_isstring(_o)) {
+ sq_pushobject(SquirrelVM::_VM,_o);
+ ret = sq_getsize(SquirrelVM::_VM,-1);
+ sq_pop(SquirrelVM::_VM,1);
+ }
+ return ret;
+}
+
+#define _SETVALUE_INT_BEGIN \
+ BOOL ret = FALSE; \
+ int top = sq_gettop(SquirrelVM::_VM); \
+ sq_pushobject(SquirrelVM::_VM,_o); \
+ sq_pushinteger(SquirrelVM::_VM,key);
+
+#define _SETVALUE_INT_END \
+ if(SQ_SUCCEEDED(sq_rawset(SquirrelVM::_VM,-3))) { \
+ ret = TRUE; \
+ } \
+ sq_settop(SquirrelVM::_VM,top); \
+ return ret;
+
+BOOL SquirrelObject::SetValue(INT key,const SquirrelObject &val)
+{
+ _SETVALUE_INT_BEGIN
+ sq_pushobject(SquirrelVM::_VM,val._o);
+ _SETVALUE_INT_END
+}
+
+BOOL SquirrelObject::SetValue(INT key,INT n)
+{
+ _SETVALUE_INT_BEGIN
+ sq_pushinteger(SquirrelVM::_VM,n);
+ _SETVALUE_INT_END
+}
+
+BOOL SquirrelObject::SetValue(INT key,FLOAT f)
+{
+ _SETVALUE_INT_BEGIN
+ sq_pushfloat(SquirrelVM::_VM,f);
+ _SETVALUE_INT_END
+}
+
+BOOL SquirrelObject::SetValue(INT key,const SQChar *s)
+{
+ _SETVALUE_INT_BEGIN
+ sq_pushstring(SquirrelVM::_VM,s,-1);
+ _SETVALUE_INT_END
+}
+
+BOOL SquirrelObject::SetValue(INT key,bool b)
+{
+ _SETVALUE_INT_BEGIN
+ sq_pushbool(SquirrelVM::_VM,b);
+ _SETVALUE_INT_END
+}
+
+BOOL SquirrelObject::SetValue(const SquirrelObject &key,const SquirrelObject &val)
+{
+ BOOL ret = FALSE;
+ int top = sq_gettop(SquirrelVM::_VM);
+ sq_pushobject(SquirrelVM::_VM,_o);
+ sq_pushobject(SquirrelVM::_VM,key._o);
+ sq_pushobject(SquirrelVM::_VM,val._o);
+ if(SQ_SUCCEEDED(sq_rawset(SquirrelVM::_VM,-3))) {
+ ret = TRUE;
+ }
+ sq_settop(SquirrelVM::_VM,top);
+ return ret;
+}
+
+#define _SETVALUE_STR_BEGIN \
+ BOOL ret = FALSE; \
+ int top = sq_gettop(SquirrelVM::_VM); \
+ sq_pushobject(SquirrelVM::_VM,_o); \
+ sq_pushstring(SquirrelVM::_VM,key,-1);
+
+#define _SETVALUE_STR_END \
+ if(SQ_SUCCEEDED(sq_rawset(SquirrelVM::_VM,-3))) { \
+ ret = TRUE; \
+ } \
+ sq_settop(SquirrelVM::_VM,top); \
+ return ret;
+
+BOOL SquirrelObject::SetValue(const SQChar *key,const SquirrelObject &val)
+{
+ _SETVALUE_STR_BEGIN
+ sq_pushobject(SquirrelVM::_VM,val._o);
+ _SETVALUE_STR_END
+}
+
+BOOL SquirrelObject::SetValue(const SQChar *key,INT n)
+{
+ _SETVALUE_STR_BEGIN
+ sq_pushinteger(SquirrelVM::_VM,n);
+ _SETVALUE_STR_END
+}
+
+BOOL SquirrelObject::SetValue(const SQChar *key,FLOAT f)
+{
+ _SETVALUE_STR_BEGIN
+ sq_pushfloat(SquirrelVM::_VM,f);
+ _SETVALUE_STR_END
+}
+
+BOOL SquirrelObject::SetValue(const SQChar *key,const SQChar *s)
+{
+ _SETVALUE_STR_BEGIN
+ sq_pushstring(SquirrelVM::_VM,s,-1);
+ _SETVALUE_STR_END
+}
+
+BOOL SquirrelObject::SetValue(const SQChar *key,bool b)
+{
+ _SETVALUE_STR_BEGIN
+ sq_pushbool(SquirrelVM::_VM,b);
+ _SETVALUE_STR_END
+}
+
+// === BEGIN User Pointer, User Data ===
+
+BOOL SquirrelObject::SetUserPointer(const SQChar * key,SQUserPointer up) {
+ _SETVALUE_STR_BEGIN
+ sq_pushuserpointer(SquirrelVM::_VM,up);
+ _SETVALUE_STR_END
+} // SquirrelObject::SetUserPointer
+
+SQUserPointer SquirrelObject::GetUserPointer(const SQChar * key) {
+ SQUserPointer ret = NULL;
+ if (GetSlot(key)) {
+ sq_getuserpointer(SquirrelVM::_VM,-1,&ret);
+ sq_pop(SquirrelVM::_VM,1);
+ } // if
+ sq_pop(SquirrelVM::_VM,1);
+ return ret;
+} // SquirrelObject::GetUserPointer
+
+BOOL SquirrelObject::SetUserPointer(INT key,SQUserPointer up) {
+ _SETVALUE_INT_BEGIN
+ sq_pushuserpointer(SquirrelVM::_VM,up);
+ _SETVALUE_INT_END
+} // SquirrelObject::SetUserPointer
+
+SQUserPointer SquirrelObject::GetUserPointer(INT key) {
+ SQUserPointer ret = NULL;
+ if (GetSlot(key)) {
+ sq_getuserpointer(SquirrelVM::_VM,-1,&ret);
+ sq_pop(SquirrelVM::_VM,1);
+ } // if
+ sq_pop(SquirrelVM::_VM,1);
+ return ret;
+} // SquirrelObject::GetUserPointer
+
+// === User Data ===
+
+BOOL SquirrelObject::NewUserData(const SQChar * key,INT size,SQUserPointer * typetag) {
+ _SETVALUE_STR_BEGIN
+ sq_newuserdata(SquirrelVM::_VM,size);
+ if (typetag) {
+ sq_settypetag(SquirrelVM::_VM,-1,typetag);
+ } // if
+ _SETVALUE_STR_END
+} // SquirrelObject::NewUserData
+
+BOOL SquirrelObject::GetUserData(const SQChar * key,SQUserPointer * data,SQUserPointer * typetag) {
+ BOOL ret = false;
+ if (GetSlot(key)) {
+ sq_getuserdata(SquirrelVM::_VM,-1,data,typetag);
+ sq_pop(SquirrelVM::_VM,1);
+ ret = true;
+ } // if
+ sq_pop(SquirrelVM::_VM,1);
+ return ret;
+} // SquirrelObject::GetUserData
+
+BOOL SquirrelObject::RawGetUserData(const SQChar * key,SQUserPointer * data,SQUserPointer * typetag) {
+ BOOL ret = false;
+ if (RawGetSlot(key)) {
+ sq_getuserdata(SquirrelVM::_VM,-1,data,typetag);
+ sq_pop(SquirrelVM::_VM,1);
+ ret = true;
+ } // if
+ sq_pop(SquirrelVM::_VM,1);
+ return ret;
+} // SquirrelObject::RawGetUserData
+
+// === END User Pointer ===
+
+// === BEGIN Arrays ===
+
+BOOL SquirrelObject::ArrayResize(INT newSize) {
+// int top = sq_gettop(SquirrelVM::_VM);
+ sq_pushobject(SquirrelVM::_VM,GetObjectHandle());
+ BOOL res = sq_arrayresize(SquirrelVM::_VM,-1,newSize) == SQ_OK;
+ sq_pop(SquirrelVM::_VM,1);
+// sq_settop(SquirrelVM::_VM,top);
+ return res;
+} // SquirrelObject::ArrayResize
+
+BOOL SquirrelObject::ArrayExtend(INT amount) {
+ int newLen = Len()+amount;
+ return ArrayResize(newLen);
+} // SquirrelObject::ArrayExtend
+
+BOOL SquirrelObject::ArrayReverse(void) {
+ sq_pushobject(SquirrelVM::_VM,GetObjectHandle());
+ BOOL res = sq_arrayreverse(SquirrelVM::_VM,-1) == SQ_OK;
+ sq_pop(SquirrelVM::_VM,1);
+ return res;
+} // SquirrelObject::ArrayReverse
+
+SquirrelObject SquirrelObject::ArrayPop(SQBool returnPoppedVal) {
+ SquirrelObject ret;
+ int top = sq_gettop(SquirrelVM::_VM);
+ sq_pushobject(SquirrelVM::_VM,GetObjectHandle());
+ if (sq_arraypop(SquirrelVM::_VM,-1,returnPoppedVal) == SQ_OK) {
+ if (returnPoppedVal) {
+ ret.AttachToStackObject(-1);
+ } // if
+ } // if
+ sq_settop(SquirrelVM::_VM,top);
+ return ret;
+} // SquirrelObject::ArrayPop
+
+// === END Arrays ===
+
+SQObjectType SquirrelObject::GetType()
+{
+ return _o._type;
+}
+
+BOOL SquirrelObject::GetSlot(INT key) const
+{
+ sq_pushobject(SquirrelVM::_VM,_o);
+ sq_pushinteger(SquirrelVM::_VM,key);
+ if(SQ_SUCCEEDED(sq_get(SquirrelVM::_VM,-2))) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+
+SquirrelObject SquirrelObject::GetValue(INT key)const
+{
+ SquirrelObject ret;
+ if(GetSlot(key)) {
+ ret.AttachToStackObject(-1);
+ sq_pop(SquirrelVM::_VM,1);
+ }
+ sq_pop(SquirrelVM::_VM,1);
+ return ret;
+}
+
+FLOAT SquirrelObject::GetFloat(INT key) const
+{
+ FLOAT ret = 0.0f;
+ if(GetSlot(key)) {
+ sq_getfloat(SquirrelVM::_VM,-1,&ret);
+ sq_pop(SquirrelVM::_VM,1);
+ }
+ sq_pop(SquirrelVM::_VM,1);
+ return ret;
+}
+
+INT SquirrelObject::GetInt(INT key) const
+{
+ INT ret = 0;
+ if(GetSlot(key)) {
+ sq_getinteger(SquirrelVM::_VM,-1,&ret);
+ sq_pop(SquirrelVM::_VM,1);
+ }
+ sq_pop(SquirrelVM::_VM,1);
+ return ret;
+}
+
+const SQChar *SquirrelObject::GetString(INT key) const
+{
+ const SQChar *ret = NULL;
+ if(GetSlot(key)) {
+ sq_getstring(SquirrelVM::_VM,-1,&ret);
+ sq_pop(SquirrelVM::_VM,1);
+ }
+ sq_pop(SquirrelVM::_VM,1);
+ return ret;
+}
+
+bool SquirrelObject::GetBool(INT key) const
+{
+ SQBool ret = FALSE;
+ if(GetSlot(key)) {
+ sq_getbool(SquirrelVM::_VM,-1,&ret);
+ sq_pop(SquirrelVM::_VM,1);
+ }
+ sq_pop(SquirrelVM::_VM,1);
+ return ret?true:false;
+}
+
+BOOL SquirrelObject::Exists(const SQChar *key) const
+{
+ if(GetSlot(key)) {
+ sq_pop(SquirrelVM::_VM,2);
+ return TRUE;
+ } else {
+ sq_pop(SquirrelVM::_VM,1);
+ return FALSE;
+ }
+}
+////////////////////////////////////////////////////////////////////////////////
+///////////////////////////////////////////////////////////////////////////////
+
+BOOL SquirrelObject::GetSlot(const SQChar *name) const
+{
+ sq_pushobject(SquirrelVM::_VM,_o);
+ sq_pushstring(SquirrelVM::_VM,name,-1);
+ if(SQ_SUCCEEDED(sq_get(SquirrelVM::_VM,-2))) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+BOOL SquirrelObject::RawGetSlot(const SQChar *name) const {
+ sq_pushobject(SquirrelVM::_VM,_o);
+ sq_pushstring(SquirrelVM::_VM,name,-1);
+ if(SQ_SUCCEEDED(sq_rawget(SquirrelVM::_VM,-2))) {
+ return TRUE;
+ }
+ return FALSE;
+} // SquirrelObject::RawGetSlot
+
+SquirrelObject SquirrelObject::GetValue(const SQChar *key)const
+{
+ SquirrelObject ret;
+ if(GetSlot(key)) {
+ ret.AttachToStackObject(-1);
+ sq_pop(SquirrelVM::_VM,1);
+ }
+ sq_pop(SquirrelVM::_VM,1);
+ return ret;
+}
+
+FLOAT SquirrelObject::GetFloat(const SQChar *key) const
+{
+ FLOAT ret = 0.0f;
+ if(GetSlot(key)) {
+ sq_getfloat(SquirrelVM::_VM,-1,&ret);
+ sq_pop(SquirrelVM::_VM,1);
+ }
+ sq_pop(SquirrelVM::_VM,1);
+ return ret;
+}
+
+INT SquirrelObject::GetInt(const SQChar *key) const
+{
+ INT ret = 0;
+ if(GetSlot(key)) {
+ sq_getinteger(SquirrelVM::_VM,-1,&ret);
+ sq_pop(SquirrelVM::_VM,1);
+ }
+ sq_pop(SquirrelVM::_VM,1);
+ return ret;
+}
+
+const SQChar *SquirrelObject::GetString(const SQChar *key) const
+{
+ const SQChar *ret = NULL;
+ if(GetSlot(key)) {
+ sq_getstring(SquirrelVM::_VM,-1,&ret);
+ sq_pop(SquirrelVM::_VM,1);
+ }
+ sq_pop(SquirrelVM::_VM,1);
+ return ret;
+}
+
+bool SquirrelObject::GetBool(const SQChar *key) const
+{
+ SQBool ret = FALSE;
+ if(GetSlot(key)) {
+ sq_getbool(SquirrelVM::_VM,-1,&ret);
+ sq_pop(SquirrelVM::_VM,1);
+ }
+ sq_pop(SquirrelVM::_VM,1);
+ return ret?true:false;
+}
+
+SQUserPointer SquirrelObject::GetInstanceUP(SQUserPointer tag) const
+{
+ SQUserPointer up;
+ sq_pushobject(SquirrelVM::_VM,_o);
+ if (SQ_FAILED(sq_getinstanceup(SquirrelVM::_VM,-1,(SQUserPointer*)&up,tag))) {
+ sq_reseterror(SquirrelVM::_VM);
+ up = NULL;
+ } // if
+ sq_pop(SquirrelVM::_VM,1);
+ return up;
+}
+
+BOOL SquirrelObject::SetInstanceUP(SQUserPointer up)
+{
+ if(!sq_isinstance(_o)) return FALSE;
+ sq_pushobject(SquirrelVM::_VM,_o);
+ sq_setinstanceup(SquirrelVM::_VM,-1,up);
+ sq_pop(SquirrelVM::_VM,1);
+ return TRUE;
+}
+
+SquirrelObject SquirrelObject::GetAttributes(const SQChar *key)
+{
+ SquirrelObject ret;
+ int top = sq_gettop(SquirrelVM::_VM);
+ sq_pushobject(SquirrelVM::_VM,_o);
+ if(key)
+ sq_pushstring(SquirrelVM::_VM,key,-1);
+ else
+ sq_pushnull(SquirrelVM::_VM);
+ if(SQ_SUCCEEDED(sq_getattributes(SquirrelVM::_VM,-2))) {
+ ret.AttachToStackObject(-1);
+ }
+ sq_settop(SquirrelVM::_VM,top);
+ return ret;
+}
+
+BOOL SquirrelObject::BeginIteration()
+{
+ if(!sq_istable(_o) && !sq_isarray(_o) && !sq_isclass(_o))
+ return FALSE;
+ sq_pushobject(SquirrelVM::_VM,_o);
+ sq_pushnull(SquirrelVM::_VM);
+ return TRUE;
+}
+
+BOOL SquirrelObject::Next(SquirrelObject &key,SquirrelObject &val)
+{
+ if(SQ_SUCCEEDED(sq_next(SquirrelVM::_VM,-2))) {
+ key.AttachToStackObject(-2);
+ val.AttachToStackObject(-1);
+ sq_pop(SquirrelVM::_VM,2);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL SquirrelObject::GetTypeTag(SQUserPointer * typeTag) {
+ if (SQ_SUCCEEDED(sq_getobjtypetag(&_o,typeTag))) {
+ return TRUE;
+ } // if
+ return FALSE;
+} // SquirrelObject::GetTypeTag
+
+const SQChar * SquirrelObject::GetTypeName(const SQChar * key) {
+#if 1
+ // This version will work even if SQ_SUPPORT_INSTANCE_TYPE_INFO is not enabled.
+ SqPlus::ScriptStringVar256 varNameTag;
+ SqPlus::getVarNameTag(varNameTag,sizeof(varNameTag),key);
+ SQUserPointer data=0;
+ if (!RawGetUserData(varNameTag,&data)) {
+ return NULL;
+ } // if
+ SqPlus::VarRefPtr vr = (SqPlus::VarRefPtr)data;
+ return vr->varType->GetTypeName();
+#else // This version will only work if SQ_SUPPORT_INSTANCE_TYPE_INFO is enabled.
+ SquirrelObject so = GetValue(key);
+ if (so.IsNull()) return NULL;
+ return so.GetTypeName();
+#endif
+} // SquirrelObject::GetTypeName
+
+const SQChar * SquirrelObject::GetTypeName(INT key) {
+ SquirrelObject so = GetValue(key);
+ if (so.IsNull()) return NULL;
+ return so.GetTypeName();
+} // SquirrelObject::GetTypeName
+
+const SQChar * SquirrelObject::GetTypeName(void) {
+ SQUserPointer typeTag=NULL;
+ if (SQ_SUCCEEDED(sq_getobjtypetag(&_o,&typeTag))) {
+ SquirrelObject typeTable = SquirrelVM::GetRootTable().GetValue(SQ_PLUS_TYPE_TABLE);
+ if (typeTable.IsNull()) {
+ return NULL; // Not compiled with SQ_SUPPORT_INSTANCE_TYPE_INFO enabled.
+ } // if
+ return typeTable.GetString(INT((size_t)typeTag));
+ } // if
+ return NULL;
+} // SquirrelObject::GetTypeName
+
+SquirrelObject SquirrelObject::GetBase(void)
+{
+ SquirrelObject ret;
+ sq_pushobject(SquirrelVM::_VM,_o);
+ sq_getbase(SquirrelVM::_VM,-1);
+ ret.AttachToStackObject(-1);
+ sq_pop(SquirrelVM::_VM,2);
+
+ return ret;
+}
+
+const SQChar* SquirrelObject::ToString()
+{
+ return sq_objtostring(&_o);
+}
+
+SQInteger SquirrelObject::ToInteger()
+{
+ return sq_objtointeger(&_o);
+}
+
+SQFloat SquirrelObject::ToFloat()
+{
+ return sq_objtofloat(&_o);
+}
+
+bool SquirrelObject::ToBool()
+{
+ //<<FIXME>>
+ return _o._unVal.nInteger?true:false;
+}
+
+void SquirrelObject::EndIteration()
+{
+ sq_pop(SquirrelVM::_VM,2);
+}
+
diff --git a/squirrel_3_0_1_stable/sqplus/SquirrelObject.h b/squirrel_3_0_1_stable/sqplus/SquirrelObject.h
new file mode 100644
index 000000000..647410a74
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SquirrelObject.h
@@ -0,0 +1,256 @@
+#ifndef _SQUIRREL_OBJECT_H_
+#define _SQUIRREL_OBJECT_H_
+
+class SquirrelObject
+{
+ friend class SquirrelVM;
+
+public:
+ SquirrelObject();
+ virtual ~SquirrelObject();
+ SquirrelObject(const SquirrelObject & o);
+ SquirrelObject(HSQOBJECT o);
+
+#if 1
+ template <typename _ty>
+ SquirrelObject(const _ty & val) { sq_resetobject(&_o); Set((_ty &)val); } // Cast away const to avoid compiler SqPlus::Push() match issue.
+ template <typename _ty>
+ SquirrelObject(_ty & val) { sq_resetobject(&_o); Set(val); }
+ template <typename _ty>
+ SquirrelObject(_ty * val) { sq_resetobject(&_o); SetByValue(val); } // Set() would also be OK here. SetByValue() to save potential compiler overhead.
+#endif
+
+ SquirrelObject & operator = (HSQOBJECT ho);
+ SquirrelObject & operator = (const SquirrelObject &o);
+ SquirrelObject & operator = (int n);
+ SquirrelObject & operator = (HSQUIRRELVM v);
+
+ operator HSQOBJECT& (){ return _o; }
+ bool operator ==(const SquirrelObject& o);
+ bool CompareUserPointer(const SquirrelObject& o);
+
+ void AttachToStackObject(int idx);
+ void Reset(void); // Release (any) reference and reset _o.
+ SquirrelObject Clone();
+ BOOL SetValue(const SquirrelObject &key,const SquirrelObject &val);
+
+ BOOL SetValue(SQInteger key,const SquirrelObject &val);
+ BOOL SetValue(INT key,bool b); // Compiler treats SQBool as INT.
+ BOOL SetValue(INT key,INT n);
+ BOOL SetValue(INT key,FLOAT f);
+ BOOL SetValue(INT key,const SQChar *s);
+
+ BOOL SetValue(const SQChar *key,const SquirrelObject &val);
+ BOOL SetValue(const SQChar *key,bool b);
+ BOOL SetValue(const SQChar *key,INT n);
+ BOOL SetValue(const SQChar *key,FLOAT f);
+ BOOL SetValue(const SQChar *key,const SQChar *s);
+
+ BOOL SetUserPointer(const SQChar * key,SQUserPointer up);
+ SQUserPointer GetUserPointer(const SQChar * key);
+ BOOL SetUserPointer(INT key,SQUserPointer up);
+ SQUserPointer GetUserPointer(INT key);
+
+ BOOL NewUserData(const SQChar * key,INT size,SQUserPointer * typetag=0);
+ BOOL GetUserData(const SQChar * key,SQUserPointer * data,SQUserPointer * typetag=0);
+ BOOL RawGetUserData(const SQChar * key,SQUserPointer * data,SQUserPointer * typetag=0);
+
+ // === BEGIN Arrays ===
+
+ BOOL ArrayResize(INT newSize);
+ BOOL ArrayExtend(INT amount);
+ BOOL ArrayReverse(void);
+ SquirrelObject ArrayPop(SQBool returnPoppedVal=SQTrue);
+
+ void ArrayAppend(const SquirrelObject &o);
+
+ template<typename T>
+ BOOL ArrayAppend(T item);
+
+ // === END Arrays ===
+
+ BOOL SetInstanceUP(SQUserPointer up);
+ BOOL IsNull() const;
+ int IsNumeric() const;
+ int Len() const;
+ BOOL SetDelegate(SquirrelObject &obj);
+ SquirrelObject GetDelegate();
+ const SQChar* ToString();
+ bool ToBool();
+ SQInteger ToInteger();
+ SQFloat ToFloat();
+ SQUserPointer GetInstanceUP(SQUserPointer tag) const;
+ SquirrelObject GetValue(const SQChar *key) const;
+ BOOL Exists(const SQChar *key) const;
+ FLOAT GetFloat(const SQChar *key) const;
+ INT GetInt(const SQChar *key) const;
+ const SQChar *GetString(const SQChar *key) const;
+ bool GetBool(const SQChar *key) const;
+ SquirrelObject GetValue(INT key) const;
+ FLOAT GetFloat(INT key) const;
+ INT GetInt(INT key) const;
+ const SQChar *GetString(INT key) const;
+ bool GetBool(INT key) const;
+ SquirrelObject GetAttributes(const SQChar *key = NULL);
+ SQObjectType GetType();
+ HSQOBJECT & GetObjectHandle() const {return *(HSQOBJECT*)&_o;}
+ BOOL BeginIteration();
+ BOOL Next(SquirrelObject &key,SquirrelObject &value);
+ void EndIteration();
+
+ BOOL GetTypeTag(SQUserPointer * typeTag);
+
+ // === Get the type name of item/object through string key in a table or class. Returns NULL if the type name is not set (not an SqPlus registered type).
+ const SQChar * GetTypeName(const SQChar * key);
+ // === Get the type name of item/object through INT key in a table or class. Returns NULL if the type name is not set (not an SqPlus registered type).
+ const SQChar * GetTypeName(INT key);
+ // === Get the type name of this object, else return NULL if not an SqPlus registered type.
+ const SQChar * GetTypeName(void);
+
+ // === Return base class of object using sq_getbase() ===
+ SquirrelObject GetBase();
+
+ // === BEGIN code suggestion from the Wiki ===
+ // Get any bound type from this SquirrelObject. Note that Squirrel's handling of references and pointers still holds here.
+ template<typename _ty>
+ _ty Get(void);
+
+ // Set any bound type to this SquirrelObject. Note that Squirrel's handling of references and pointers still holds here.
+ template<typename _ty>
+ SquirrelObject SetByValue(_ty val); // classes/structs should be passed by ref (below) to avoid an extra copy.
+
+ // Set any bound type to this SquirrelObject. Note that Squirrel's handling of references and pointers still holds here.
+ template<typename _ty>
+ SquirrelObject &Set(_ty & val);
+
+ // === END code suggestion from the Wiki ===
+
+private:
+ BOOL GetSlot(const SQChar *name) const;
+ BOOL RawGetSlot(const SQChar *name) const;
+ BOOL GetSlot(INT key) const;
+ HSQOBJECT _o;
+};
+
+struct StackHandler {
+ StackHandler(HSQUIRRELVM v) {
+ _top = sq_gettop(v);
+ this->v = v;
+ }
+ SQFloat GetFloat(int idx) {
+ SQFloat x = 0.0f;
+ if(idx > 0 && idx <= _top) {
+ sq_getfloat(v,idx,&x);
+ }
+ return x;
+ }
+ SQInteger GetInt(int idx) {
+ SQInteger x = 0;
+ if(idx > 0 && idx <= _top) {
+ sq_getinteger(v,idx,&x);
+ }
+ return x;
+ }
+ HSQOBJECT GetObjectHandle(int idx) {
+ HSQOBJECT x;
+ if(idx > 0 && idx <= _top) {
+ sq_resetobject(&x);
+ sq_getstackobj(v,idx,&x);
+ }
+ return x;
+ }
+ const SQChar *GetString(int idx)
+ {
+ const SQChar *x = NULL;
+ if(idx > 0 && idx <= _top) {
+ sq_getstring(v,idx,&x);
+ }
+ return x;
+ }
+ SQUserPointer GetUserPointer(int idx)
+ {
+ SQUserPointer x = 0;
+ if(idx > 0 && idx <= _top) {
+ sq_getuserpointer(v,idx,&x);
+ }
+ return x;
+ }
+ SQUserPointer GetInstanceUp(int idx,SQUserPointer tag)
+ {
+ SQUserPointer self;
+ if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer*)&self,tag)))
+ return NULL;
+ return self;
+ }
+ SQUserPointer GetUserData(int idx,SQUserPointer tag=0)
+ {
+ SQUserPointer otag;
+ SQUserPointer up;
+ if(idx > 0 && idx <= _top) {
+ if(SQ_SUCCEEDED(sq_getuserdata(v,idx,&up,&otag))) {
+ if(tag == otag)
+ return up;
+ }
+ }
+ return NULL;
+ }
+ BOOL GetBool(int idx)
+ {
+ SQBool ret;
+ if(idx > 0 && idx <= _top) {
+ if(SQ_SUCCEEDED(sq_getbool(v,idx,&ret)))
+ return ret;
+ }
+ return FALSE;
+ }
+ int GetType(int idx)
+ {
+ if(idx > 0 && idx <= _top) {
+ return sq_gettype(v,idx);
+ }
+ return -1;
+ }
+
+ int GetParamCount() {
+ return _top;
+ }
+ int Return(const SQChar *s)
+ {
+ sq_pushstring(v,s,-1);
+ return 1;
+ }
+ int Return(FLOAT f)
+ {
+ sq_pushfloat(v,f);
+ return 1;
+ }
+ int Return(INT i)
+ {
+ sq_pushinteger(v,i);
+ return 1;
+ }
+ int Return(bool b)
+ {
+ sq_pushbool(v,b);
+ return 1;
+ }
+ int Return(SQUserPointer p) {
+ sq_pushuserpointer(v,p);
+ return 1;
+ }
+ int Return(SquirrelObject &o)
+ {
+ sq_pushobject(v,o.GetObjectHandle());
+ return 1;
+ }
+ int Return() { return 0; }
+ int ThrowError(const SQChar *error) {
+ return sq_throwerror(v,error);
+ }
+ HSQUIRRELVM GetVMPtr() { return v; }
+private:
+ int _top;
+ HSQUIRRELVM v;
+};
+
+#endif //_SQUIRREL_OBJECT_H_
diff --git a/squirrel_3_0_1_stable/sqplus/SquirrelVM.cpp b/squirrel_3_0_1_stable/sqplus/SquirrelVM.cpp
new file mode 100644
index 000000000..2d506d700
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SquirrelVM.cpp
@@ -0,0 +1,505 @@
+#include <stdio.h>
+#include <stdarg.h>
+#include <assert.h>
+
+#define _DEBUG_DUMP
+
+#include "sqplus.h"
+
+#include <sqstdio.h>
+#include <sqstdmath.h>
+#include <sqstdstring.h>
+#include <sqstdaux.h>
+#include <sqstdblob.h>
+#include <sqstdsystem.h>
+
+
+HSQUIRRELVM SquirrelVM::_VM;
+bool SquirrelVM::_no_vm_ref;
+int SquirrelVM::_CallState = -1;
+SquirrelObject* SquirrelVM::_root;
+HSQUIRRELVM SquirrelVM::_sandboxVM;
+SquirrelObject SquirrelVM::_vm;
+
+
+// Helper struct to keep track of all SQSharedState:s created by SquirrelVM.
+#include "../squirrel/sqpcheader.h"
+#include "../squirrel/sqvm.h"
+struct SQSharedStateNode {
+ SQSharedStateNode( SQSharedState* ps );
+ ~SQSharedStateNode( );
+ SQSharedState* m_ps;
+ SQSharedStateNode* m_nxt;
+};
+
+// Linked list of shared states
+static SQSharedStateNode* g_sqss_fst;
+
+SQSharedStateNode::SQSharedStateNode( SQSharedState* ps ) : m_ps(ps), m_nxt(g_sqss_fst) {
+ g_sqss_fst = this;
+}
+
+SQSharedStateNode::~SQSharedStateNode() {
+ if(m_ps) sq_delete(m_ps,SQSharedState);
+ delete m_nxt;
+}
+
+static struct SquirrelVM_ModConstr {
+ ~SquirrelVM_ModConstr(){
+ // Delete any shared states we created
+ delete g_sqss_fst;
+ g_sqss_fst = NULL;
+ }
+} g_squirrelvm_mod_constr;
+
+
+
+SquirrelError::SquirrelError()
+{
+ const SQChar *s;
+ sq_getlasterror(SquirrelVM::_VM);
+ sq_getstring(SquirrelVM::_VM,-1,&s);
+ if(s) {
+ desc = s;
+ }
+ else {
+ desc = _SC("unknown error");
+ }
+}
+
+
+SquirrelVMSys::~SquirrelVMSys() {
+ // Must take care to release object with the 'ref' VM
+ PushRefVM( _vm.GetObjectHandle()._unVal.pThread );
+ _vm.Reset();
+ PopRefVM();
+}
+
+void SquirrelVMSys::Set( HSQUIRRELVM v ){
+ // Must take care to release object with the 'ref' VM
+ PushRefVM( v );
+ _vm = v;
+ PopRefVM( );
+}
+
+void SquirrelVMSys::Set( const SquirrelObject& ov ){
+ assert( ov.GetObjectHandle()._type==OT_THREAD );
+ // Must take care to release object with the 'ref' VM
+ PushRefVM( ov.GetObjectHandle()._unVal.pThread );
+ _vm = ov;
+ PopRefVM( );
+}
+
+SquirrelVMSys::operator HSQUIRRELVM () const {
+ // Avoid const madness
+ SquirrelObject *pvm = (SquirrelObject*)&_vm;
+ assert( pvm->GetObjectHandle()._type==OT_THREAD );
+ return pvm->GetObjectHandle()._unVal.pThread;
+}
+
+
+// When doing a SquirrelObject assignment, a reference using the current
+// VM is done.
+HSQUIRRELVM g_VM_pushed;
+void SquirrelVMSys::PushRefVM( HSQUIRRELVM v ){
+ assert( !g_VM_pushed );
+ g_VM_pushed = SquirrelVM::_VM;
+ SquirrelVM::_VM = v;
+}
+
+void SquirrelVMSys::PopRefVM( ){
+ SquirrelVM::_VM = g_VM_pushed;
+ g_VM_pushed = NULL;
+}
+
+
+bool SquirrelVM::Init( HSQUIRRELVM v ){
+ if( v && v==_VM )
+ return true;
+
+ // Do we have a previous state?
+ Release( );
+
+ bool created_new = false;
+ if( !v ){
+ // Create a new VM - a root VM with new SharedState.
+ v = sq_open(1024);
+ if( !v ) return false;
+ // Store the associated shared state in a linked list. The state will only
+ // be destroyed at app shutdown. Often that is fine, but if using many
+ // VM:s briefly, this allocation is not optimal.
+ new SQSharedStateNode( _ss(v) );
+ created_new = true;
+ sq_setprintfunc(v,SquirrelVM::PrintFunc, SquirrelVM::PrintFunc);
+ sq_pushroottable(v);
+ sqstd_register_iolib(v);
+ sqstd_register_bloblib(v);
+ sqstd_register_mathlib(v);
+ sqstd_register_stringlib(v);
+#ifdef SQPLUS_SQUIRRELVM_WITH_SYSTEMLIB
+ sqstd_register_systemlib(v);
+#endif
+ sqstd_seterrorhandlers(v);
+ //TODO error handler, compiler error handler
+ sq_pop(v,1);
+ }
+
+ // After this we hold a ref
+ _no_vm_ref = false;
+ _VM = v;
+ _vm = v;
+
+ // In the case where Squirrel is ref counted we currently
+ // hold two references to the VM (since it is created with
+ // a ref count of 1). In the GC case, it is outside of the
+ // chain of valid objects, so it is not referenced. Compensate
+ // in ref counted case.
+ if( created_new )
+ DropVMRefIfRefCounted( v );
+
+ return true;
+}
+
+bool SquirrelVM::InitNoRef( HSQUIRRELVM v ){
+ if( v && v==_VM )
+ return true;
+
+ // Do we have a previous state?
+ Release( );
+
+ // Set pointer to this VM, without referencing it
+ _no_vm_ref = true;
+ _VM = v;
+
+ return true;
+}
+
+/*
+void SquirrelVM::Init( HSQUIRRELVM v )
+{
+ if( v && v==_VM ) {
+ return;
+ }
+
+ // Do we have a previous state?
+ Release();
+
+ if( !v ){
+ // Create a new VM and own it
+ _VM = sq_open(1024);
+ sq_setprintfunc(_VM,SquirrelVM::PrintFunc);
+ sq_pushroottable(_VM);
+ sqstd_register_iolib(_VM);
+ sqstd_register_bloblib(_VM);
+ sqstd_register_mathlib(_VM);
+ sqstd_register_stringlib(_VM);
+ sqstd_seterrorhandlers(_VM);
+ //TODO error handler, compiler error handler
+ sq_pop(_VM,1);
+ }
+ else {
+ _VM = v;
+ }
+ // After this we hold a ref
+ _vm = _VM;
+}
+*/
+
+void SquirrelVM::Release() {
+ // Release root table object if we have one
+ if( _root ){
+ delete _root;
+ _root = NULL;
+ }
+
+ // Release our ref on VM - if we should
+ if( !_no_vm_ref )
+ _vm.Reset();
+
+ _VM = NULL;
+}
+
+void SquirrelVM::DropVMRefIfRefCounted( HSQUIRRELVM v ){
+#ifdef NO_GARBAGE_COLLECTOR
+ if( v ){
+ SQObject t;
+ t._unVal.pThread = v;
+ t._type = OT_THREAD;
+ sq_release( v, &t );
+ }
+#endif
+}
+
+BOOL SquirrelVM::Update()
+{
+ //update remote debugger
+ return TRUE;
+}
+
+void SquirrelVM::PrintFunc(HSQUIRRELVM v,const SQChar* s,...)
+{
+ static SQChar temp[2048];
+ va_list vl;
+ va_start(vl, s);
+ scvsprintf( temp,s, vl);
+ SCPUTS(temp);
+ va_end(vl);
+}
+
+SquirrelObject SquirrelVM::CompileScript(const SQChar *s)
+{
+ SquirrelObject ret;
+ if(SQ_SUCCEEDED(sqstd_loadfile(_VM,s,1))) {
+ ret.AttachToStackObject(-1);
+ sq_pop(_VM,1);
+ return ret;
+ }
+ throw SquirrelError();
+}
+
+SquirrelObject SquirrelVM::CompileBuffer(const SQChar *s,const SQChar * debugInfo)
+{
+ SquirrelObject ret;
+ if(SQ_SUCCEEDED(sq_compilebuffer(_VM,s,(int)scstrlen(s)*sizeof(SQChar),debugInfo,1))) {
+ ret.AttachToStackObject(-1);
+ sq_pop(_VM,1);
+ return ret;
+ }
+ throw SquirrelError();
+}
+
+SquirrelObject SquirrelVM::RunScript(const SquirrelObject &o,SquirrelObject *_this)
+{
+ SquirrelObject ret;
+ sq_pushobject(_VM,o._o);
+ if(_this) {
+ sq_pushobject(_VM,_this->_o);
+ }
+ else {
+ sq_pushroottable(_VM);
+ }
+ if(SQ_SUCCEEDED(sq_call(_VM,1,SQTrue,SQ_CALL_RAISE_ERROR))) {
+ ret.AttachToStackObject(-1);
+ sq_pop(_VM,2);
+ return ret;
+ }
+ sq_pop(_VM,1);
+ throw SquirrelError();
+
+}
+
+
+BOOL SquirrelVM::BeginCall(const SquirrelObject &func)
+{
+ if(_CallState != -1)
+ return FALSE;
+ _CallState = 1;
+ sq_pushobject(_VM,func._o);
+ sq_pushroottable(_VM);
+ return TRUE;
+}
+
+BOOL SquirrelVM::BeginCall(const SquirrelObject &func,SquirrelObject &_this)
+{
+ if(_CallState != -1)
+ throw SquirrelError(_SC("call already initialized"));
+ _CallState = 1;
+ sq_pushobject(_VM,func._o);
+ sq_pushobject(_VM,_this._o);
+ return TRUE;
+}
+
+#define _CHECK_CALL_STATE \
+ if(_CallState == -1) \
+ throw SquirrelError(_SC("call not initialized"));
+
+void SquirrelVM::PushParam(const SquirrelObject &o)
+{
+ _CHECK_CALL_STATE
+ sq_pushobject(_VM,o._o);
+ _CallState++;
+}
+
+void SquirrelVM::PushParam(const SQChar *s)
+{
+ _CHECK_CALL_STATE
+ sq_pushstring(_VM,s,-1);
+ _CallState++;
+}
+
+void SquirrelVM::PushParam(SQInteger n)
+{
+ _CHECK_CALL_STATE
+ sq_pushinteger(_VM,n);
+ _CallState++;
+}
+
+void SquirrelVM::PushParam(SQFloat f)
+{
+ _CHECK_CALL_STATE
+ sq_pushfloat(_VM,f);
+ _CallState++;
+}
+
+void SquirrelVM::PushParamNull()
+{
+ _CHECK_CALL_STATE
+ sq_pushnull(_VM);
+ _CallState++;
+}
+
+void SquirrelVM::PushParam(SQUserPointer up)
+{
+ _CHECK_CALL_STATE
+ sq_pushuserpointer(_VM,up);
+ _CallState++;
+}
+
+SquirrelObject SquirrelVM::EndCall()
+{
+ SquirrelObject ret;
+ if(_CallState >= 0) {
+ int oldtop = sq_gettop(_VM);
+ int nparams = _CallState;
+ _CallState = -1;
+ if(SQ_SUCCEEDED(sq_call(_VM,nparams,SQTrue,SQ_CALL_RAISE_ERROR))) {
+ ret.AttachToStackObject(-1);
+ sq_pop(_VM,2);
+ }else {
+ sq_settop(_VM,oldtop-(nparams+1));
+ throw SquirrelError();
+ }
+
+ }
+ return ret;
+}
+
+SquirrelObject SquirrelVM::CreateInstance(SquirrelObject &oclass)
+{
+ SquirrelObject ret;
+ int oldtop = sq_gettop(_VM);
+ sq_pushobject(_VM,oclass._o);
+ if(SQ_FAILED(sq_createinstance(_VM,-1))) {
+ sq_settop(_VM,oldtop);
+ throw SquirrelError();
+ }
+ ret.AttachToStackObject(-1);
+ sq_pop(_VM,2);
+ return ret;
+}
+
+SquirrelObject SquirrelVM::CreateTable()
+{
+ SquirrelObject ret;
+ sq_newtable(_VM);
+ ret.AttachToStackObject(-1);
+ sq_pop(_VM,1);
+ return ret;
+}
+
+SquirrelObject SquirrelVM::CreateString(const SQChar *s)
+{
+ SquirrelObject ret;
+ sq_pushstring(_VM,s,-1);
+ ret.AttachToStackObject(-1);
+ sq_pop(_VM,1);
+ return ret;
+}
+
+
+SquirrelObject SquirrelVM::CreateArray(int size)
+{
+ SquirrelObject ret;
+ sq_newarray(_VM,size);
+ ret.AttachToStackObject(-1);
+ sq_pop(_VM,1);
+ return ret;
+}
+
+SquirrelObject SquirrelVM::CreateFunction(SQFUNCTION func)
+{
+ SquirrelObject ret;
+ sq_newclosure(_VM,func,0);
+ ret.AttachToStackObject(-1);
+ sq_pop(_VM,1);
+ return ret;
+}
+
+SquirrelObject SquirrelVM::CreateUserData(int size) {
+ SquirrelObject ret;
+ sq_newuserdata(_VM,size);
+ ret.AttachToStackObject(-1);
+ sq_pop(_VM,1);
+ return ret;
+}
+
+const SquirrelObject &SquirrelVM::GetRootTable()
+{
+ if( !_root ){
+ sq_pushroottable(_VM);
+ _root = new SquirrelObject();
+ _root->AttachToStackObject(-1);
+ sq_pop(_VM,1);
+ }
+ return *_root;
+}
+
+void SquirrelVM::PushRootTable(void) {
+ sq_pushroottable(_VM);
+} // SquirrelVM::PushRootTable
+
+// Creates a function in the table or class currently on the stack.
+//void CreateFunction(HSQUIRRELVM v,const SQChar * scriptFuncName,SQFUNCTION func,int numParams=0,const SQChar * typeMask=0) {
+SquirrelObject SquirrelVM::CreateFunction(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask) {
+ sq_pushstring(_VM,scriptFuncName,-1);
+ sq_newclosure(_VM,func,0);
+ SquirrelObject ret;
+ ret.AttachToStackObject(-1);
+ SQChar tm[64];
+ SQChar * ptm = tm;
+ int numParams = SQ_MATCHTYPEMASKSTRING;
+ if (typeMask) {
+ if (typeMask[0] == '*') {
+ ptm = 0; // Variable args: don't check parameters.
+ numParams = 0; // Clear SQ_MATCHTYPEMASKSTRING (does not mean match 0 params. See sq_setparamscheck()).
+ } else {
+ if (SCSNPRINTF(tm,sizeof(tm),_SC("t|y|x%s"),typeMask) < 0) {
+// sq_throwerror(_VM,_SC("CreateFunction: typeMask string too long."));
+ throw SquirrelError(_SC("CreateFunction: typeMask string too long."));
+ } // if
+ } // if
+ } else { // <TODO> Need to check object type on stack: table, class, instance, etc.
+ SCSNPRINTF(tm,sizeof(tm),_SC("%s"),_SC("t|y|x")); // table, class, instance.
+// tm[0] = 't';
+// tm[1] = 0;
+ } // if
+#if 0
+ sq_setparamscheck(_VM,numParams+1,ptm); // Parameters are table+args (thus, the +1).
+#else
+ if (ptm) {
+ sq_setparamscheck(_VM,numParams,ptm); // Determine arg count from type string.
+ } // if
+#endif
+#ifdef _DEBUG
+ sq_setnativeclosurename(_VM,-1,scriptFuncName); // For debugging only.
+#endif
+ sq_createslot(_VM,-3); // Create slot in table or class (assigning function to slot at scriptNameFunc).
+ return ret;
+} // SquirrelVM::CreateFunction
+
+SquirrelObject SquirrelVM::CreateFunction(SquirrelObject & so,SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask) {
+ PushObject(so);
+ SquirrelObject ret = CreateFunction(func,scriptFuncName,typeMask);
+ Pop(1);
+ return ret;
+} // SquirrelVM::CreateFunction
+
+// Create a Global function on the root table.
+//void CreateFunctionGlobal(HSQUIRRELVM v,const SQChar * scriptFuncName,SQFUNCTION func,int numParams=0,const SQChar * typeMask=0) {
+SquirrelObject SquirrelVM::CreateFunctionGlobal(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask) {
+ PushRootTable(); // Push root table.
+ // CreateFunction(scriptFuncName,func,numParams,typeMask);
+ SquirrelObject ret = CreateFunction(func,scriptFuncName,typeMask);
+ Pop(1); // Pop root table.
+ return ret;
+} // SquirrelVM::CreateFunctionGlobal
diff --git a/squirrel_3_0_1_stable/sqplus/SquirrelVM.h b/squirrel_3_0_1_stable/sqplus/SquirrelVM.h
new file mode 100644
index 000000000..ee66a2b76
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/SquirrelVM.h
@@ -0,0 +1,179 @@
+#ifndef _SQUIRREL_VM_H_
+#define _SQUIRREL_VM_H_
+
+#include "SquirrelObject.h"
+
+struct SquirrelError {
+ SquirrelError();
+ SquirrelError(const SQChar* s):desc(s){}
+ const SQChar *desc;
+};
+
+// This class can hold a reference to a SquirrelVM. It keeps a Squirrel ref
+// to the VM to protect it from being deleted while held.
+struct SquirrelVMSys {
+ SquirrelVMSys() { }
+ ~SquirrelVMSys();
+
+ void Set( HSQUIRRELVM v );
+ void Set( const SquirrelObject& ov );
+ void Reset( ){ _vm.Reset(); }
+
+ SquirrelVMSys& operator = (HSQUIRRELVM v){ Set(v); return *this; }
+ operator HSQUIRRELVM () const;
+
+protected:
+ void PushRefVM(HSQUIRRELVM v);
+ void PopRefVM();
+ SquirrelObject _vm;
+ friend class SquirrelVM;
+};
+
+// Notes on creating / destroying SquirrelVM:s:
+//
+// VM:s created through sq_open are special since they create a new
+// SQSharedState. That shared state is later shared by any new thread
+// or friend VM. sq_close can be used for closing VM:s created through
+// sq_open (but not for friend VMs).
+//
+// Using squirrel references in SquirrelVMSys and SquirrelVM, one must
+// make sure that these are all reset if one calls sq_close manually.
+//
+// When there are no more references to a VM, it is destroyed automatically,
+// but the shared state is not! For VM:s created by SquirrelVM, it keeps
+// a list of shared states it has created and will destroy them all on
+// app shutdown.
+
+class SquirrelVM {
+ friend class SquirrelObject;
+ friend struct SquirrelError;
+ friend struct SquirrelVMSys;
+
+public:
+ // If a VM is passed as arg here, Init will not alter it. Otherwise
+ // a new VM is created and initialized. A squirrel reference is kept
+ // while it is the current VM.
+ static bool Init( HSQUIRRELVM v=NULL );
+
+ // Initialize with an externally created VM, without adding a ref
+ // on it. NOTE: This may not be compatible with Set/GetVMSys as
+ // we're just working with raw pointers here.
+ static bool InitNoRef( HSQUIRRELVM v );
+ static BOOL IsInitialized(){return _VM == NULL?FALSE:TRUE;}
+
+ static void Release(); // Release ref on VM and reset VM pointer
+ static void Shutdown(){ Release(); }
+ static void AppFinalShutdown(); // Call when finally shutting down app
+
+ static BOOL Update(); //debugger and maybe GC later
+
+ static SquirrelObject CompileScript(const SQChar *s);
+ static SquirrelObject CompileBuffer(const SQChar *s,const SQChar * debugInfo=_SC("console_buffer"));
+ static SquirrelObject RunScript(const SquirrelObject &o,SquirrelObject *_this = NULL);
+
+ static void PrintFunc(HSQUIRRELVM v,const SQChar* s,...);
+
+ static BOOL BeginCall(const SquirrelObject &func);
+ static BOOL BeginCall(const SquirrelObject &func,SquirrelObject &_this);
+
+ static void PushParam(const SquirrelObject &o);
+ static void PushParam(const SQChar *s);
+ static void PushParam(SQInteger n);
+ static void PushParam(SQFloat f);
+ static void PushParam(SQUserPointer up);
+ static void PushParamNull();
+
+ static SquirrelObject EndCall();
+ static SquirrelObject CreateString(const SQChar *s);
+ static SquirrelObject CreateTable();
+ static SquirrelObject CreateArray(int size);
+ static SquirrelObject CreateInstance(SquirrelObject &oclass); // oclass is an existing class. Create an 'instance' (OT_INSTANCE) of oclass.
+ static SquirrelObject CreateFunction(SQFUNCTION func);
+ static SquirrelObject CreateUserData(int size);
+
+ static const SquirrelObject &GetRootTable();
+ static HSQUIRRELVM GetVMPtr() { return _VM; }
+
+ // The sandbox VM ptr is one which cannot access functions bound with
+ // SqPlus. It is suitable for running non-trusted scripts that can only
+ // access basic functionality.
+ static void SetSandboxVMPtr(HSQUIRRELVM v) {
+ _sandboxVM = v;
+ } // SetSandboxVMPtr
+
+ static HSQUIRRELVM GetSandboxVMPtr() {
+ return _sandboxVM;
+ } // GetSandboxVMPtr
+
+ static void GetVMSys(SquirrelVMSys & vmSys) {
+ vmSys.Set( _vm );
+ } // GetVMSys
+
+ static void SetVMSys(const SquirrelVMSys & vmSys) {
+ Release();
+ HSQUIRRELVM v = (HSQUIRRELVM)vmSys;
+ if( v )
+ Init( v );
+ } // SetVMSys
+
+ static void PushValue(INT val) {
+ sq_pushinteger(_VM,val);
+ } // PushValue
+ static void PushValue(FLOAT val) {
+ sq_pushfloat(_VM,val);
+ } // PushValue
+ static void PushValue(bool val) { // Compiler treats SQBool as INT.
+ sq_pushbool(_VM,val);
+ } // PushValue
+ static void PushValue(SQChar * val) {
+ sq_pushstring(_VM,val,-1);
+ } // PushValue
+ static void PushValue(SQUserPointer val) {
+ sq_pushuserpointer(_VM,val);
+ } // PushValue
+ static void PushValue(const SQChar * val) {
+ sq_pushstring(_VM,val,-1);
+ } // PushValue
+ static void PushObject(SquirrelObject & so) {
+ sq_pushobject(_VM,so._o);
+ } // PushObject
+ static void Pop(SQInteger nelemstopop) {
+ sq_pop(_VM,nelemstopop);
+ } // Pop
+
+ static void PushRootTable(void);
+
+ // Create/bind a function on the table currently on the stack.
+ static SquirrelObject CreateFunction(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask=0);
+ // Create/bind a function on the table so. typeMask: standard Squirrel types plus: no typemask means no args, "*" means any type of args.
+ static SquirrelObject CreateFunction(SquirrelObject & so,SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask=0);
+ // Create/bind a function to the root table. typeMask: standard Squirrel types plus: no typemask means no args, "*" means any type of args.
+ static SquirrelObject CreateFunctionGlobal(SQFUNCTION func,const SQChar * scriptFuncName,const SQChar * typeMask=0);
+
+ // This is a helper to correct a difference in referncing new VM:s in
+ // ref counted versus garbage collected modes. NOTE: Only use after creating
+ // a VM with: 1 - sq_open() 2 - Creating a ref to the VM (SquirrelObject)
+ static void DropVMRefIfRefCounted( HSQUIRRELVM v );
+
+
+private:
+ static SquirrelObject _vm; // This is a Squirrel reference to the VM
+ static HSQUIRRELVM _VM; // The raw C++ pointer
+ static bool _no_vm_ref; // Set if we only keep the raw C++ pointer and no ref
+ static int _CallState;
+ static SquirrelObject * _root; // Cached root table if non NULL
+ static HSQUIRRELVM _sandboxVM; // The sandbox VM (that cannot use bound functions)
+};
+
+
+template<typename T>
+inline BOOL SquirrelObject::ArrayAppend(T item) {
+ sq_pushobject(SquirrelVM::_VM,GetObjectHandle());
+ SquirrelVM::PushValue(item);
+ BOOL res = sq_arrayappend(SquirrelVM::_VM,-2) == SQ_OK;
+ sq_pop(SquirrelVM::_VM,1);
+ return res;
+} // ArrayAppend
+
+#endif //_SQUIRREL_VM_H_
+
diff --git a/squirrel_3_0_1_stable/sqplus/changes.txt b/squirrel_3_0_1_stable/sqplus/changes.txt
new file mode 100644
index 000000000..a33f32c2f
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/changes.txt
@@ -0,0 +1,359 @@
+2008-07-13 "SQUIRREL2_1_1_sqplus_snapshot_20080713"
+
+ * Released as a snapshot
+
+
+2008-07-06 kawachi
+
+ * Removed testSqPlus2
+
+
+2008-06-26 arst@users.sf.net
+
+ * SquirrelVM.cpp / SqPlusSetup.h
+ - Added a new define SQPLUS_SQUIRRELVM_WITH_SYSTEMLIB
+ (Juggernaut, http://squirrel-lang.org/forums/2585/ShowThread.aspx#2585)
+
+ - Added a new function:
+ SQClassDefBase::scriptVar(const SQChar* name, int ival,
+ SQBool static_var=SQFalse)
+
+ It allows for creating either static or ordinary Squirrel class
+ members from C++ source code. Versions for int/double/const
+ SQChar*.
+
+ - SquirrelObject::GetBase() - retrieve base class.
+ (Juggernaut, http://squirrel-lang.org/forums/2585/ShowThread.aspx#2585)
+
+
+2008-06-14 Kazei
+
+ * Fixed memory leak in overloadConstructor
+ (http://squirrel-lang.org/forums/thread/2516.aspx)
+
+
+2008-05-10 Neimod
+
+ * Fixed for typesafe scripting
+ (http://squirrel-lang.org/forums/thread/2478.aspx)
+
+
+2008-05-08 arst@users.sf.net
+
+ * sqplus.h/.cpp
+
+ - SQ_USE_CLASS_INHERITANCE_SIMPLE is a new way of handling class
+ inheritence in SqPlus, relying on a template scheme (see ClassTypeBase
+ and ClassType<T>). It doesn't use any memory per instance and should
+ be a bit faster than previous scheme. SqClassDef has been given
+ a second template argument to account for this:
+
+ struct SQClassDef<MyClass, TheBaseClass> ...
+
+ - The name of the class (in SqClassDef) can be filled in by SqPlus now,
+ if Squirrel class name is same as C++ class name:
+
+ SQClasDef<Troll, Creature>("Troll", "Creature").func(...) =>
+ SQClasDef<Troll, Creature>().func(...)
+
+ - Code to handle class types (names, copy funcs, ID tag, ...) has been
+ collected in ClassTypeBase and ClassType<T>.
+
+ - A new macro to specify that classes should not be copied with default
+ C++ method: DECLARE_NONCOPY_TYPE(ClassThatCannotBeCopied).
+
+ - Reworked body of repetetive template functions, Moved to
+ SqPlusCallTemplates.h. Can be included with different qualifiers
+ (const, cdecl).
+
+ - Support for cdecl member functions (MSVC specific) through:
+
+ SQPLUS_ENABLE_CDECL_MEMBER_FUNCTIONS
+
+ cdecl functions are compatible across compilers, while thiscall
+ is not.
+
+ - Generic Push/Pop/Match handlers: SQPLUS_USE_GENERIC_HANDLERS
+ By default, Push/Get/Match handlers are for a single type. This
+ adds a fallback level, so that `hierarchy wide' handlers can
+ be used (define for base class and let all derived classes use
+ just that).
+
+ - For functions that return a pointer to a temporarary (such as
+ returning a SQDefCharBuf, a template mapper class:
+
+ Temporary<T>::type
+
+ was added. It can hold a temporary value while finishing a
+ SquirrelFunction call (before returning to C++).
+
+ - Suppressing horrible warnings from Visual C++ about sprintf and related
+ functions (_CRT_SECURE_NO_DEPRECATE).
+
+
+ * SquirrelVM.h/.cpp
+
+ - Changed SquirrelVM and SquirrelVMSys to make them hold a reference
+ on a SQVM so that ownership can be shared in a defined way.
+
+ - SquirrelVMSys can be used as before to swap the `active' VM.
+ Now it holds a ref to a VM so that a VM is closed automatically
+ when switched out and there are no refs to any longer. (To hold a
+ VM ref in the application, simply use an instance of SquirrelVMSys).
+
+ - NOTE: A VM created through sq_open() comes out with a reference
+ count of 1. A VM created with sq_newthread() arrives with a ref
+ count of 0. SquirrelVM will compensate for this.
+
+ - Possibility to store a `sandbox VM'. This VM is not allowed to
+ access functions / classes bound with SqPlus and so can run more
+ untrusted scripts.
+
+ - Hopefully these changes will not break current apps. (Note: creating
+ and keeping correct refs on SQVM involved some difficulties (with ref-
+ counting and garbage collected Squirrel). The scheme provided here is
+ (I hope) a working solution.)
+
+ * SquirrelObject.h/.cpp
+
+ - Added: operator = (HSQOBJECT)
+
+ - From forum: (http://squirrel-lang.org/forums/thread/2506.aspx)
+ (suggested by auron0)
+ - Added: operator == (const SquirrelObject& o)
+ - Added: CompareUserPointer(const SquirrelObject& o)
+
+ * SqPlusUTF8.h / .cpp
+
+ - New files for converting strings in arguments (UTF8 <-> wchar_t)
+
+ - Fix for conversion of UTF8 sequence of length 3+ bytes
+
+
+
+2008-02-17 PallavNawani
+
+ * BindVariable of std::string
+ (http://squirrel-lang.org/forums/2370/ShowThread.aspx)
+
+
+2007-10-14 "SQUIRREL2_1_1_sqplus_snapshot_20071014"
+
+ * Fixed const member function overloading by Tegan
+ (http://squirrel-lang.org/forums/thread/2160.aspx)
+
+ * Updates for missing inline in DECLARE_INSTANCE_TYPE_NAME
+ (http://squirrel-lang.org/forums/thread/2156.aspx)
+
+ * Fixed resolution in function overloading
+ (http://squirrel-lang.org/forums/thread/2179.aspx)
+
+ * Added support for operator overloading suggested by Tegan
+ (http://squirrel-lang.org/forums/thread/2160.aspx)
+
+
+2007-09-27 "SQUIRREL2_1_1_sqplus_snapshot_20070927"
+
+ * Added ats's extensions :
+ http://squirrel-lang.org/forums/1/2153/ShowThread.aspx
+
+ - GCC_INLINE_WORKAROUND (problems with inline functions with gcc)
+ - Set/get for short/char members
+ - Get for const SQChar*
+ - DECLARE_ENUM_TYPE - Allows enums to be used as arguments
+ - Support for more customized Push handlers
+ - SQPLUS_DISABLE_COPY_INSTANCES (disabling automatic use of copy
+ constructors)
+ - Support for automatically generate TypeMasks (a template
+ solution) on function registration
+
+
+2007-08-25 "SQUIRREL2_1_1_sqplus_snapshot_20070825"
+
+ * Added m0pey's smart pointer support :
+ http://squirrel-lang.org/forums/thread/1982.aspx
+
+
+2007-01-07 "SQUIRREL2_1_1_sqplus_snapshot_20070701"
+
+ * Fixed `returning a pointer of a derived class' problem with gcc
+ (http://squirrel-lang.org/forums/thread/1875.aspx) based on
+ http://wiki.squirrel-lang.org/default.aspx/SquirrelWiki/SqPlusNativeCreatedInstancesWithCorrectAncestry.html
+
+
+2007-06/02 "SQUIRREL2_1_1_sqplus_snapshot_20070602"
+
+ * Fix by Sebastien Frippiat:
+ http://squirrel-lang.org/forums/thread/507.aspx
+
+
+2007-05-27 "SQUIRREL2_1_1_sqplus_snapshot_20070527"
+
+ * Added sqplus/SqPlusOverload.h for function overloading. See
+ testSqPlus2unit/test_FunctionOverloading.cpp.
+
+
+2007-03-04 "SQUIRREL2_1_1_sqplus_snapshot_20070304"
+
+ * Fixed compilation problem on g++-3.4.4 (cygwin):
+ http://squirrel-lang.org/forums/thread/1753.aspx
+
+
+2007-02-25 "SQUIRREL2_1_1_sqplus_snapshot_20070225"
+
+ * Fix by Kamaitati: http://squirrel-lang.org/forums/thread/1748.aspx
+
+ * Modified sqplu.h (SquirrelObject::Set<>()) for gcc
+
+ * Added testSqPlus2unit directory for unit testing
+
+
+2006-10-09- "SQUIRREL2_1_1_sqplus_25"
+
+ * Fixed SqPlusConst.h:
+ http://squirrel-lang.org/forums/thread/1314.aspx, changed
+ SquirrelObject Get/Set to default to pass-by-reference, where
+ pass-by-copy requires extra parameter
+
+
+2006-10-08 "SQUIRREL2_1_1_sqplus_24"
+
+ * Added SQClassDefNoConstructor<>:
+ http://wiki.squirrel-lang.org/default.aspx/SquirrelWiki/SqPlusWithoutAutoDefaultConstructor.html
+ (allows binding abstract base classes/pure-virtual-interfaces)
+
+ * Added "Squirrel Set/Get objects"
+ http://wiki.squirrel-lang.org/default.aspx/SquirrelWiki/SqPlusGetSetObjects.html
+
+
+2006-09-30 "SQUIRREL2_1_1_sqplus_23"
+
+ * Fixed return type for sq_std_string Get()
+
+
+2006-08-21 "SQUIRREL2_1_0_sqplus_22"
+
+ * Merged in Squirrel 2.1.1 Stable
+
+
+2006-08-20 "SQUIRREL2_1_0_sqplus_21"
+
+ * Changed code order to be compatible with GCC 4.1.x.
+
+ * Added jflanglois' suggestion for std::basic_string<SQChar>
+
+
+2006-06-27 "SQUIRREL2_1_0_sqplus_20"
+
+ * Added Katsuaki Kawachi's GetInstance()/Match() changes
+ (http://www.squirrel-lang.org/forums/962/ShowPost.aspx)
+
+
+2006-02-06 "SQUIRREL2_1_0_sqplus_19"
+
+ * Added VS7.1 make/project files with 71 suffix: can be used
+ alongside VS8 without directory changes
+
+ * Added optional debug string argument to SquirrelVM::CompileBuffer()
+
+
+2006-05-28 "SQUIRREL2_1_0_sqplus_18"
+
+ * Added Kamaitati's changes: bug fix, C++ style inheritance support,
+ null instance argument support
+
+
+2006-04-25 "SQUIRREL2_1_0_sqplus_17"
+
+ * Changed SquirrelObject::GetInstanceUP() to return NULL and
+ clear internal error state on invalid instance type request
+
+ * Added SquirrelObject::GetTypeName(const "SQChar" * key),
+ SquirrelObject::GetTypeName("INT" key) and
+ SquirrelObject::GetTypeName().
+
+ * Added SQ_SUPPORT_INSTANCE_TYPE_INFO compile time option
+
+ * Added missing template arguments (7 argument case)
+
+ * Source changes to support VS7.1 and VS8 compilation (standard and
+ UNICODE builds)
+
+ * Added Code::Blocks project files
+
+
+2006-03-26 "SQUIRREL2_1_0_sqplus_11"
+
+ * Updated make/build files to VS8 (http://msdn.microsoft.com/vstudio/)
+
+ * Source changes for VS8 compilation
+
+
+2006-03-19 "SQUIRREL2_1_0_sqplus_10"
+
+ * Updated to Squirrel 2.1
+
+
+2006-02-27 "SQUIRREL2_0_5_sqplus_9"
+
+ * Added Ben's changes to implement DECLARE_INSTANCE_TYPE_NAME
+ (http://www.squirrel-lang.org/forums/635/ShowPost.aspx)
+
+
+2005-12-22 "SQUIRREL2_0_5_sqplus_8"
+
+ * Added GetVMSys() and SetVMSys() to better support multiple VM's
+
+
+2005-11-21 "SQUIRREL2_0_5_sqplus_7"
+
+ * Added modular support for const member functions. Defining
+ SQPLUS_CONST_OPT before including sqplus.h enables the added
+ functionality
+
+ * SqPlus tested on Mac OS-X
+
+
+2005-11-03 "SQUIRREL2_0_5_sqplus_6"
+
+ * Fixed inheritance issue: tables added to classes are not newly
+ created upon instantiation- they must be cloned during
+ construction (language design)
+
+ * Reworked projects build settings to better allow building all
+ projects types: Debug, Release, Debug - Unicode, Release - Unicode
+
+
+2005-11-01 "SQUIRREL2_0_5_sqplus_5"
+
+ * Added Unicode support
+
+
+2005-10-23 "SQUIRREL2_0_5_sqplus_4"
+
+ * Added gcc support:
+ - Added simple GNU Makefiles for gcc
+ - Minor code changes for gcc compilation
+ - Tested on RH Linux gcc 3.2.3, Cygwin gcc 3.4.4, and gcc on Sony PSP
+ (http://www.squirrel-lang.org/forums/420/ShowPost.aspx#420)
+
+ * Added ClassDef::enumInt() for registering enums as ints
+ (to replace ClassDef::constant((int)myEnum))
+
+
+2005-10-14 "SQUIRREL2_0_5_sqplus_3"
+
+ * Added support for SquirrelObject as a function argument and return
+ value. Tables and arrays can be directly accessed without using
+ the stack. This also makes it possible to return tables, arrays,
+ classes, and closures for later use at runtime, saving look-up
+ overhead
+
+ * Added GetRet() for SquirrelFunction<> to ensure proper stack
+ behavior
+
+ * Added additional error return info to help with debugging
+
+ * Removed unused code
+
+
diff --git a/squirrel_3_0_1_stable/sqplus/sqplus.cbp b/squirrel_3_0_1_stable/sqplus/sqplus.cbp
new file mode 100644
index 000000000..ba10ef105
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/sqplus.cbp
@@ -0,0 +1,190 @@
+<?xml version="1.0"?>
+<!DOCTYPE CodeBlocks_project_file>
+<CodeBlocks_project_file>
+ <FileVersion major="1" minor="1"/>
+ <Project>
+ <Option title="sqplus"/>
+ <Option makefile="Makefile"/>
+ <Option makefile_is_custom="0"/>
+ <Option default_target="-1"/>
+ <Option compiler="0"/>
+ <Build>
+ <Target title="Debug">
+ <Option output="..\lib\libsqplusD.a"/>
+ <Option working_dir=""/>
+ <Option object_output="Debug"/>
+ <Option deps_output=".deps"/>
+ <Option type="2"/>
+ <Option compiler="0"/>
+ <Option createDefFile="1"/>
+ <Option projectResourceIncludeDirsRelation="2"/>
+ <Compiler>
+ <Add option="-DWIN32"/>
+ <Add option="-D_DEBUG"/>
+ <Add option="-D_LIB"/>
+ <Add option="-D_CRT_SECURE_NO_DEPRECATE"/>
+ <Add option="-W"/>
+ <Add option="-O0"/>
+ <Add directory="..\include"/>
+ </Compiler>
+ </Target>
+ <Target title="Release">
+ <Option output="..\lib\libsqplus.a"/>
+ <Option working_dir=""/>
+ <Option object_output="Release"/>
+ <Option deps_output=".deps"/>
+ <Option type="2"/>
+ <Option compiler="0"/>
+ <Option createDefFile="1"/>
+ <Option projectResourceIncludeDirsRelation="2"/>
+ <Compiler>
+ <Add option="-DWIN32"/>
+ <Add option="-DNDEBUG"/>
+ <Add option="-D_LIB"/>
+ <Add option="-D_CRT_SECURE_NO_DEPRECATE"/>
+ <Add option="-W"/>
+ <Add option="-g"/>
+ <Add directory="..\include"/>
+ </Compiler>
+ </Target>
+ <Target title="Debug - Unicode">
+ <Option output="..\lib\libsqplusDU.a"/>
+ <Option working_dir=""/>
+ <Option object_output="Debug - Unicode"/>
+ <Option deps_output=".deps"/>
+ <Option type="2"/>
+ <Option compiler="0"/>
+ <Option createDefFile="1"/>
+ <Option projectResourceIncludeDirsRelation="2"/>
+ <Compiler>
+ <Add option="-DWIN32"/>
+ <Add option="-D_DEBUG"/>
+ <Add option="-D_LIB"/>
+ <Add option="-D_CRT_SECURE_NO_DEPRECATE"/>
+ <Add option="-D_CRT_NON_CONFORMING_SWPRINTFS"/>
+ <Add option="-W"/>
+ <Add option="-O0"/>
+ <Add directory="..\include"/>
+ </Compiler>
+ </Target>
+ <Target title="Release - Unicode">
+ <Option output="..\lib\libsqplusU.a"/>
+ <Option working_dir=""/>
+ <Option object_output="Release - Unicode"/>
+ <Option deps_output=".deps"/>
+ <Option type="2"/>
+ <Option compiler="0"/>
+ <Option createDefFile="1"/>
+ <Option projectResourceIncludeDirsRelation="2"/>
+ <Compiler>
+ <Add option="-DWIN32"/>
+ <Add option="-DNDEBUG"/>
+ <Add option="-D_LIB"/>
+ <Add option="-D_CRT_SECURE_NO_DEPRECATE"/>
+ <Add option="-D_CRT_NON_CONFORMING_SWPRINTFS"/>
+ <Add option="-W"/>
+ <Add option="-g"/>
+ <Add directory="..\include"/>
+ </Compiler>
+ </Target>
+ </Build>
+ <Unit filename="SqPlus.cpp">
+ <Option compilerVar="CPP"/>
+ <Option target="Debug"/>
+ <Option target="Release"/>
+ <Option target="Debug - Unicode"/>
+ <Option target="Release - Unicode"/>
+ </Unit>
+ <Unit filename="SqPlusConst.h">
+ <Option compilerVar=""/>
+ <Option compile="0"/>
+ <Option link="0"/>
+ <Option target="Debug"/>
+ <Option target="Release"/>
+ <Option target="Debug - Unicode"/>
+ <Option target="Release - Unicode"/>
+ </Unit>
+ <Unit filename="SquirrelBindingsUtils.cpp">
+ <Option compilerVar="CPP"/>
+ <Option target="Debug"/>
+ <Option target="Release"/>
+ <Option target="Debug - Unicode"/>
+ <Option target="Release - Unicode"/>
+ </Unit>
+ <Unit filename="SquirrelBindingsUtils.h">
+ <Option compilerVar=""/>
+ <Option compile="0"/>
+ <Option link="0"/>
+ <Option target="Debug"/>
+ <Option target="Release"/>
+ <Option target="Debug - Unicode"/>
+ <Option target="Release - Unicode"/>
+ </Unit>
+ <Unit filename="SquirrelBindingsUtilsWin32.cpp">
+ <Option compilerVar="CPP"/>
+ <Option target="Debug"/>
+ <Option target="Release"/>
+ <Option target="Debug - Unicode"/>
+ <Option target="Release - Unicode"/>
+ </Unit>
+ <Unit filename="SquirrelBindingsUtilsWin32.h">
+ <Option compilerVar=""/>
+ <Option compile="0"/>
+ <Option link="0"/>
+ <Option target="Debug"/>
+ <Option target="Release"/>
+ <Option target="Debug - Unicode"/>
+ <Option target="Release - Unicode"/>
+ </Unit>
+ <Unit filename="SquirrelObject.cpp">
+ <Option compilerVar="CPP"/>
+ <Option target="Debug"/>
+ <Option target="Release"/>
+ <Option target="Debug - Unicode"/>
+ <Option target="Release - Unicode"/>
+ </Unit>
+ <Unit filename="SquirrelObject.h">
+ <Option compilerVar=""/>
+ <Option compile="0"/>
+ <Option link="0"/>
+ <Option target="Debug"/>
+ <Option target="Release"/>
+ <Option target="Debug - Unicode"/>
+ <Option target="Release - Unicode"/>
+ </Unit>
+ <Unit filename="SquirrelVM.cpp">
+ <Option compilerVar="CPP"/>
+ <Option target="Debug"/>
+ <Option target="Release"/>
+ <Option target="Debug - Unicode"/>
+ <Option target="Release - Unicode"/>
+ </Unit>
+ <Unit filename="SquirrelVM.h">
+ <Option compilerVar=""/>
+ <Option compile="0"/>
+ <Option link="0"/>
+ <Option target="Debug"/>
+ <Option target="Release"/>
+ <Option target="Debug - Unicode"/>
+ <Option target="Release - Unicode"/>
+ </Unit>
+ <Unit filename="sqplus.h">
+ <Option compilerVar=""/>
+ <Option compile="0"/>
+ <Option link="0"/>
+ <Option target="Debug"/>
+ <Option target="Release"/>
+ <Option target="Debug - Unicode"/>
+ <Option target="Release - Unicode"/>
+ </Unit>
+ <Unit filename="sqplusWin32.h">
+ <Option compilerVar=""/>
+ <Option compile="0"/>
+ <Option link="0"/>
+ <Option target="Debug"/>
+ <Option target="Release"/>
+ <Option target="Debug - Unicode"/>
+ <Option target="Release - Unicode"/>
+ </Unit>
+ </Project>
+</CodeBlocks_project_file>
diff --git a/squirrel_3_0_1_stable/sqplus/sqplus.h b/squirrel_3_0_1_stable/sqplus/sqplus.h
new file mode 100644
index 000000000..6116d50ec
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/sqplus.h
@@ -0,0 +1,2327 @@
+// SqPlus.h
+// Created by John Schultz 9/05/05, major update 10/05/05.
+// Template function call design from LuaPlusCD by Joshua C. Jensen,
+// inspired by luabind which was inspired by boost::python.
+// Const argument, const member functions, and Mac OS-X changes by Simon Michelmore.
+// DECLARE_INSTANCE_TYPE_NAME changes by Ben (Project5) from http://www.squirrel-lang.org/forums/.
+// Added Kamaitati's changes 5/28/06.
+// Free for any use.
+
+#ifndef _SQ_PLUS_H_
+#define _SQ_PLUS_H_
+
+#include <stdlib.h>
+#include <assert.h>
+
+#ifdef __APPLE__
+ #include <malloc/malloc.h>
+#else
+ #include <malloc.h>
+#endif
+#include <memory.h>
+#include <memory>
+#include <limits.h> // For INT_MAX on GCC
+
+#include "squirrel.h" // Include to get SQUNICODE setting from here
+#ifndef _SC
+ #error No _SC macro - Usually defined in squirrel.h
+#endif
+// Provide a _sqT(...) macros also (same as _SC but easier to know its for Squirrel)
+#ifndef _sqT
+ #define _sqT _SC
+#endif
+
+// For backward compatibility, define _T if outside of Windows platform.
+// (really, _SC() or _sqT() are better, since that leaves us free to run
+// Squirrel in ASCII or wchar_t mode, regardless of the app being built).
+#if !defined(_WIN32) && !defined(_WIN64)
+ #ifndef _T
+ #define _T _SC
+ #endif
+#endif
+
+
+// A comment about strings. We let squirrel.h determine whether to use
+// char or wchar_t strings. So here we follow the define SQUNICODE. This
+// opens up for using Unicode system calls on Windows while having the script
+// engine in ASCII mode, or vice versa. To enable this, also the macro
+// _SC("some string") is used instead of _T("some string").
+//
+// To handle the case where function parameters are given in the opposite
+// character mode (char if SQChar is wchar_t and vice versa), such strings
+// can be converted on the fly to the other mode in the function call, if
+// the define SQPLUS_AUTOCONVERT_OTHER_CHAR is set below. Buffers are
+// allocated and kept around for the duration of the function call. The
+// same applies to returned strings of the opposite type.
+
+#if defined(_MSC_VER) || defined(__BORLANDC__)
+ #include <tchar.h>
+ #ifndef SQUNICODE
+ #define SCSNPRINTF _snprintf
+ #define SCPUTS puts
+ #else
+ #define SCSNPRINTF _snwprintf
+ #define SCPUTS _putws
+ #endif
+ #if defined(_MSC_VER)
+ #ifndef _CRT_SECURE_NO_DEPRECATE
+ #define _CRT_SECURE_NO_DEPRECATE // Disable warnings around various sprintf
+ #endif
+ #pragma warning(disable: 4996) // When above does not work
+ #endif
+#else
+ #ifdef SQUNICODE
+ #define SCSNPRINTF _snwprintf
+ #define SCPUTS _putws
+ #include <stdio.h> // for snprintf
+ #else
+ #define SCSNPRINTF snprintf
+ #include <stdio.h> // for snprintf
+ #define SCPUTS puts
+ #endif
+#endif
+
+
+#ifndef _WINDEF_
+ typedef int BOOL;
+ typedef int INT;
+ typedef float FLOAT;
+ #define TRUE 1
+ #define FALSE 0
+#endif
+
+#if 1
+#define SQ_CALL_RAISE_ERROR SQTrue
+#else
+#define SQ_CALL_RAISE_ERROR SQFalse
+#endif
+
+#include "SquirrelObject.h"
+#include "SquirrelVM.h"
+#include "SquirrelBindingsUtils.h"
+
+// All setup defines have moved to its own file
+#include "SqPlusSetup.h"
+
+#ifdef SQPLUS_AUTOCONVERT_OTHER_CHAR
+#define SQPLUS_AUTOCONVERT_MAX_INSTANCES 8 // In argument conversion, don't keep more than this alive
+#include "SqPlusOCharBuf.h"
+#endif
+
+#if defined(SQPLUS_SUPPORT_STD_STRING) && defined(SQUNICODE)
+ #ifdef _MSC_VER
+ #pragma message("std::string and SQChar as wchar_t is not compatible!")
+ #else
+ #warning std::string and SQChar as wchar_t is not compatible!
+ #endif
+#endif
+
+
+namespace SqPlus {
+
+template<class T> struct TypeWrapper {};
+struct SquirrelNull {};
+struct SQNoBaseClass {}; // For scripted classes with no base class (or no scripted base class)
+
+struct SQAnything { void * anything; }; // Needed for binding pointers to variables (cannot dereference void *).
+typedef SQAnything * SQAnythingPtr;
+typedef SQChar * SQCharPtr;
+
+// Helper struct to (sometimes) store a temporary return value as another type.
+// Useful when returning const char* and other types that require temp allocation.
+// For primitive types, it just maps onto itself.
+template<class T>
+struct Temporary {
+ typedef T type;
+};
+
+// References are tricky, but they should just be filtered out usually
+template<class T>
+struct SqAssignableRef {
+ SqAssignableRef( ) : m_pt(0) { }
+ void operator = (T& tr){ m_pt=&tr; }
+ operator T& () { return *m_pt; }
+ T *m_pt;
+};
+
+template<class T>
+struct Temporary<T&> {
+ typedef SqAssignableRef<T> type;
+};
+
+
+// === Do not use directly: use one of the predefined sizes below ===
+
+struct ScriptStringVarBase {
+ const unsigned char MaxLength; // Real length is MaxLength+1.
+ SQChar s[1];
+ ScriptStringVarBase(int _MaxLength) : MaxLength(_MaxLength) {}
+ operator SQChar * () { return &s[0]; }
+ operator void * () { return (void *)&s[0]; }
+ const SQChar * operator = (const SQChar * _s) {
+ return safeStringCopy(s,_s,MaxLength);
+ }
+ // Special safe string copy where MaxLength is 1 less than true buffer length.
+ // strncpy() pads out nulls for the full length of the buffer specified by MaxLength.
+ static inline SQChar * safeStringCopy(SQChar * d,const SQChar * s,int MaxLength) {
+ int i=0;
+ while (s[i]) {
+ d[i] = s[i];
+ i++;
+ if (i == MaxLength) break;
+ } // while
+ d[i] = 0; // Null terminate.
+ return d;
+ } // safeStringCopy
+};
+
+// === Do not use directly: use one of the predefined sizes below ===
+
+template<int MAXLENGTH> // MAXLENGTH is max printable characters (trailing NULL is accounted for in ScriptStringVarBase::s[1]).
+struct ScriptStringVar : ScriptStringVarBase {
+ SQChar ps[MAXLENGTH];
+ ScriptStringVar() : ScriptStringVarBase(MAXLENGTH) {
+ s[0] = 0;
+ }
+ ScriptStringVar(const SQChar * _s) : ScriptStringVarBase(MAXLENGTH) {
+ *this = _s;
+ }
+ const SQChar * operator = (const SQChar * _s) {
+ return safeStringCopy(s,_s,MaxLength);
+ }
+ const SQChar * operator = (const ScriptStringVar & _s) {
+ return safeStringCopy(s,_s.s,MaxLength);
+ }
+ bool operator == (const ScriptStringVar & _s) {
+ return _strcmp(s,_s.s) == 0;
+ }
+ bool compareCaseInsensitive(const ScriptStringVar & _s) {
+ return _stricmp(s,_s.s) == 0;
+ }
+};
+
+// === Fixed size strings for scripting ===
+
+typedef ScriptStringVar<8> ScriptStringVar8;
+typedef ScriptStringVar<16> ScriptStringVar16;
+typedef ScriptStringVar<32> ScriptStringVar32;
+typedef ScriptStringVar<64> ScriptStringVar64;
+typedef ScriptStringVar<128> ScriptStringVar128;
+typedef ScriptStringVar<256> ScriptStringVar256;
+
+// === Script Variable Types ===
+
+enum ScriptVarType {
+ VAR_TYPE_NONE = -1,
+ VAR_TYPE_INT = 0,
+ VAR_TYPE_UINT,
+ VAR_TYPE_FLOAT,
+ VAR_TYPE_BOOL,
+ VAR_TYPE_CONST_STRING,
+ VAR_TYPE_STRING,
+ VAR_TYPE_USER_POINTER,
+ VAR_TYPE_INSTANCE,
+#ifdef SQPLUS_SUPPORT_STD_STRING
+ VAR_TYPE_STD_STRING,
+#endif
+};
+
+template <typename T>
+struct TypeInfo {
+ const SQChar * typeName;
+ enum {TypeID=VAR_TYPE_NONE, Size=0, TypeMask='?', IsInstance=0};
+};
+
+// === Common Variable Types ===
+
+template<>
+struct TypeInfo<INT> {
+ const SQChar * typeName;
+ TypeInfo() : typeName(_SC("int")) {}
+ enum {TypeID=VAR_TYPE_INT,Size=sizeof(INT),TypeMask='i', IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+template<>
+struct TypeInfo<unsigned> {
+ const SQChar * typeName;
+ TypeInfo() : typeName(_SC("uint")) {}
+ enum {TypeID=VAR_TYPE_UINT,Size=sizeof(unsigned), IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+template<>
+struct TypeInfo<FLOAT> {
+ const SQChar * typeName;
+ TypeInfo() : typeName(_SC("float")) {}
+ enum {TypeID=VAR_TYPE_FLOAT,Size=sizeof(FLOAT),TypeMask='f', IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+template<>
+struct TypeInfo<bool> {
+ const SQChar * typeName;
+ TypeInfo() : typeName(_SC("bool")) {}
+ enum {TypeID=VAR_TYPE_BOOL,Size=sizeof(bool),TypeMask='b', IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+template<>
+struct TypeInfo<short> {
+ const SQChar * typeName;
+ TypeInfo() : typeName(_SC("short")) {}
+ enum {TypeID=VAR_TYPE_INT,Size=sizeof(short),TypeMask='i', IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+template<>
+struct TypeInfo<char> {
+ const SQChar * typeName;
+ TypeInfo() : typeName(_SC("char")) {}
+ enum {TypeID=VAR_TYPE_INT,Size=sizeof(char),TypeMask='i', IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+template<>
+struct TypeInfo<SQUserPointer> {
+ const SQChar * typeName;
+ TypeInfo() : typeName(_SC("SQUserPointer")) {}
+ enum {TypeID=VAR_TYPE_USER_POINTER,Size=sizeof(SQUserPointer),TypeMask='u', IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+template<>
+struct TypeInfo<SQAnything> {
+ const SQChar * typeName;
+ TypeInfo() : typeName(_SC("SQUserPointer")) {}
+ enum {TypeID=VAR_TYPE_USER_POINTER,Size=sizeof(SQUserPointer),TypeMask='u', IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+template<>
+struct TypeInfo<SQNoBaseClass> {
+ const SQChar * typeName;
+ TypeInfo() : typeName(0) {}
+ enum {TypeID=-1,Size=0,TypeMask=' ', IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+template<>
+struct TypeInfo<const SQChar *> {
+ const SQChar * typeName;
+ TypeInfo() : typeName(_SC("const SQChar *")) {}
+ enum {TypeID=VAR_TYPE_CONST_STRING,Size=sizeof(const SQChar *),TypeMask='s', IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+#ifdef SQPLUS_AUTOCONVERT_OTHER_CHAR
+template<>
+struct TypeInfo<const SQOtherChar *> {
+ const SQChar * typeName;
+ TypeInfo() : typeName(_SC("const SQOtherChar *")) {}
+ enum {TypeID=VAR_TYPE_CONST_STRING,Size=sizeof(const SQOtherChar *),TypeMask='s', IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+template<>
+struct Temporary<SQOtherChar*> {
+ typedef SQOthCharBuf type;
+};
+template<>
+struct Temporary<const SQOtherChar*> {
+ typedef SQOthCharBuf type;
+};
+#endif // SQPLUS_AUTOCONVERT_OTHER_CHAR
+
+// base case: raw pointer
+template<typename T, int is_inst>
+struct TypeInfoPtrBase {
+ const SQChar * typeName;
+ TypeInfoPtrBase() : typeName(TypeInfo<T>().typeName) {}
+ enum {TypeID=VAR_TYPE_USER_POINTER,Size=sizeof(T*),TypeMask='u'};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+template<typename T>
+struct TypeInfoPtrBase<T,1> : public TypeInfo<T> { };
+
+// Partial specialization for pointers (to access type without pointer / or instance typeinfo)
+template<class T>
+struct TypeInfo<T*> : public TypeInfoPtrBase<T,TypeInfo<T>::IsInstance> { };
+
+// Same thing for references
+template<class T>
+struct TypeInfo<T&> : public TypeInfoPtrBase<T,TypeInfo<T>::IsInstance> { };
+
+#ifdef SQPLUS_SUPPORT_STD_STRING
+template<>
+struct TypeInfo<std::string> {
+ const SQChar *typeName;
+ TypeInfo() : typeName(_SC("std::string")) {}
+ enum {TypeID=SqPlus::VAR_TYPE_STD_STRING,Size=sizeof(std::string),TypeMask='s'};
+ operator ScriptVarType() {return ScriptVarType(TypeID);}
+};
+#endif
+
+template<>
+struct TypeInfo<ScriptStringVarBase> {
+ const SQChar * typeName;
+ TypeInfo() : typeName(_SC("ScriptStringVarBase")) {}
+ enum {TypeID=VAR_TYPE_STRING,Size=sizeof(ScriptStringVarBase),TypeMask='s', IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+// === Fixed String Variants ===
+
+template<int N>
+struct TypeInfo<ScriptStringVar<N> > {
+ SQChar typeName[24];
+ TypeInfo() { scsprintf(typeName,_SC("ScriptStringVar<%d>"),N); }
+ enum {TypeID=VAR_TYPE_STRING,Size=N*sizeof(ScriptStringVar<N>),TypeMask='s', IsInstance=0};
+ operator ScriptVarType() { return ScriptVarType(TypeID); }
+};
+
+#ifdef SQPLUS_SMARTPOINTER_OPT
+ #define SQPLUS_SMARTPOINTER_ACCESSTYPE
+ #include "SqPlusSmartPointer.h"
+#else
+ enum VarAccessType {VAR_ACCESS_READ_WRITE=0,VAR_ACCESS_READ_ONLY=1<<0,VAR_ACCESS_CONSTANT=1<<1,VAR_ACCESS_STATIC=1<<2};
+#endif // SQPLUS_SMARTPOINTER_OPT
+
+// See VarRef and ClassType<> below: for instance assignment.
+typedef void (*CopyVarFunc)(void * dst,void * src);
+
+
+// === Class Type Helper class: returns an ID for each class type and provides base class pointer offset ===
+
+struct ClassTypeBase {
+ ClassTypeBase() : m_pbase(0), m_name(0), m_offset(0), m_may_have_offset(-1) { }
+ // Many types cannot have offset, since "this" is the same for all base classes of
+ // an instance. Detect this, to avoid sum up base offsets all the time.
+ int MayHaveOffset( ) {
+ if( m_may_have_offset<0 ){
+ if( m_offset ) m_may_have_offset = 1;
+ else m_may_have_offset = m_pbase ? m_pbase->MayHaveOffset() : 0;
+ }
+ return m_may_have_offset;
+ }
+ int GetOffsetTo( ClassTypeBase *pbase ){
+ if( !m_pbase ) { /*printf("ClassTypeBase::getOffsetTo - Warning - Base type pointer is NULL!\n" );*/ return 0; }
+ return m_pbase==pbase ? m_offset : m_offset+m_pbase->GetOffsetTo(pbase);
+ }
+ virtual CopyVarFunc vgetCopyFunc(void) = 0;
+ virtual const SQChar* GetTypeName() = 0;
+
+ ClassTypeBase *m_pbase;
+ const SQChar *m_name; // Name of type
+ int m_offset; // Adjustment of this pointer between this type and its base class
+ int m_may_have_offset; // Set to 0 for types that cannot possibly have offset
+};
+
+// This level handles instance copying in different ways
+template<typename T,bool copyable>
+struct ClassTypeCopyImpl;
+
+// Helper struct to decide if type is copyable or not
+template<typename T>
+struct IsCopyable { enum { value=true }; };
+
+#define DECLARE_NONCOPY_TYPE_INTERN(TYPE) \
+ template<> struct IsCopyable<TYPE> { enum { value=false }; };
+
+// Macro to declare a type that should _not_ be copied using ordinary
+// c++ copy expresssion: *(T*)pt1 = *(T*)pt2;
+#define DECLARE_NONCOPY_TYPE(TYPE) namespace SqPlus { \
+ template<> struct IsCopyable<TYPE> { enum { value=false }; }; \
+}
+
+// Base class to do copying in ordinary C++ way
+template<typename T>
+struct ClassTypeCopyImpl<T,true> : public ClassTypeBase {
+ static void copy(T * dst,T * src) {
+ *dst = *src; // This works types with copy ctor / assign operator
+ } // copy
+};
+
+// Base class to do copying with memcpy
+template<typename T>
+struct ClassTypeCopyImpl<T,false> : public ClassTypeBase {
+ static void copy(T * dst,T * src) {
+ memcpy(dst,src,sizeof(T)); // This works for raw data types
+ } // copy
+};
+
+// Base classes to do avoid copying altogether (void case)
+template<>
+struct ClassTypeCopyImpl<void,true> : public ClassTypeBase {
+ static void copy(void * dst,void * src) { } // copy
+};
+
+template<>
+struct ClassTypeCopyImpl<void,false> : public ClassTypeBase {
+ static void copy(void * dst,void * src) { } // copy
+};
+
+
+template<typename T>
+struct ClassType : public ClassTypeCopyImpl<T,IsCopyable<T>::value> {
+ typedef ClassTypeCopyImpl<T,IsCopyable<T>::value> ClassTypeBase;
+ ClassType( ) { this->m_name=stGetName(); }
+
+ virtual CopyVarFunc vgetCopyFunc(void) { return (CopyVarFunc)&ClassTypeBase::copy; }
+ virtual const SQChar* GetTypeName(){ return this->m_name; }
+
+ template<class BC>
+ void SetBase(TypeWrapper<BC>) {
+ this->m_pbase = ClassType<BC>::Get();
+ T* pt = reinterpret_cast<T*>(this);
+ this->m_offset = ((char*)pt)-((char*)static_cast<BC*>(pt));
+ }
+ static ClassType* Get(){ static ClassType<T> st_ct; return &st_ct; }
+ static ClassTypeBase* type() { return Get(); }
+ static CopyVarFunc getCopyFunc(void) { return (CopyVarFunc)&ClassTypeBase::copy; }
+ static const SQChar* stGetName(){ return TypeInfo<T>().typeName; }
+
+ #ifdef SQPLUS_OVERLOAD_OPT
+ #define SQPLUS_OVERLOAD_RELEASE_HOOK
+ #include "SqPlusOverload.h"
+ #endif
+};
+
+
+// === Variable references for script access ===
+
+#define SQ_PLUS_TYPE_TABLE _SC("__SqTypes")
+
+struct VarRef {
+ // In this case 'offsetOrAddrOrConst' is simpler than using an anonymous union.
+ void * offsetOrAddrOrConst; // Instance member variable offset from 'this' pointer base (as size_t), or address if static variable (void *), or constant value.
+ ScriptVarType m_type; // Variable type (from enum above).
+ ClassTypeBase* instanceType; // Class type of the containing class instance (for member vars only).
+ ClassTypeBase* varType; // The class type of the variable itself
+ short m_size; // ATS: Use for short and char support. For debugging only (size of item when pointer to item is dereferenced). Could be used for variable max string buffer length.
+ short m_access; // VarAccessType.
+
+ VarRef() : offsetOrAddrOrConst(0), m_type(VAR_TYPE_NONE), instanceType(0/*(SQUserPointer)-1*/), /*copyFunc(0),*/ m_size(0), m_access(VAR_ACCESS_READ_WRITE) {}
+ VarRef(void * _offsetOrAddrOrConst, ScriptVarType _type, ClassTypeBase* _instanceType, ClassTypeBase* _varType, int _size, VarAccessType _access) :
+ offsetOrAddrOrConst(_offsetOrAddrOrConst), m_type(_type), instanceType(_instanceType), varType(_varType), m_size(_size), m_access(_access) {
+#ifdef SQ_SUPPORT_INSTANCE_TYPE_INFO
+ SquirrelObject typeTable = SquirrelVM::GetRootTable().GetValue(SQ_PLUS_TYPE_TABLE);
+ if (typeTable.IsNull()) {
+ typeTable = SquirrelVM::CreateTable();
+ SquirrelObject root = SquirrelVM::GetRootTable();
+ root.SetValue(SQ_PLUS_TYPE_TABLE,typeTable);
+ } // if
+ typeTable.SetValue(INT((size_t)varType),varType->GetTypeName());
+#endif // SQ_SUPPORT_INSTANCE_TYPE_INFO
+ }
+};
+
+typedef VarRef * VarRefPtr;
+
+// Internal use only.
+inline void getVarNameTag(SQChar * buff,INT maxSize,const SQChar * scriptName) {
+// assert(maxSize > 3);
+#if 1
+ SQChar * d = buff;
+ d[0] = '_';
+ d[1] = 'v';
+ d = &d[2];
+ maxSize -= (2+1); // +1 = space for null.
+ int pos=0;
+ while (scriptName[pos] && pos < maxSize) {
+ d[pos] = scriptName[pos];
+ pos++;
+ } // while
+ d[pos] = 0; // null terminate.
+#else
+ SCSNPRINTF(buff,maxSize,_SC("_v%s"),scriptName);
+#endif
+} // getVarNameTag
+
+// Internal use only.
+int setVarFunc(HSQUIRRELVM v);
+int getVarFunc(HSQUIRRELVM v);
+int setInstanceVarFunc(HSQUIRRELVM v);
+int getInstanceVarFunc(HSQUIRRELVM v);
+
+// === BEGIN Helpers ===
+
+inline void createTableSetGetHandlers(SquirrelObject & so) {
+ SquirrelObject delegate = so.GetDelegate();
+ if (!delegate.Exists(_SC("_set"))) {
+ delegate = SquirrelVM::CreateTable();
+ SquirrelVM::CreateFunction(delegate,setVarFunc,_SC("_set"),_SC("sn|b|s")); // String var name = number(int or float) or bool or string.
+ SquirrelVM::CreateFunction(delegate,getVarFunc,_SC("_get"),_SC("s")); // String var name.
+ so.SetDelegate(delegate);
+ } // if
+} // createTableSetGetHandlers
+
+inline VarRefPtr createVarRef(SquirrelObject & so,const SQChar * scriptVarName) {
+ VarRefPtr pvr=0;
+ ScriptStringVar256 scriptVarTagName; getVarNameTag(scriptVarTagName,sizeof(scriptVarTagName),scriptVarName);
+ if (!so.GetUserData(scriptVarTagName,(SQUserPointer *)&pvr)) {
+ so.NewUserData(scriptVarTagName,sizeof(*pvr));
+ if (!so.GetUserData(scriptVarTagName,(SQUserPointer *)&pvr)) throw SquirrelError(_SC("Could not create UserData."));
+ } // if
+ return pvr;
+} // createVarRef
+
+template<typename T>
+void validateConstantType(T constant) {
+ switch(TypeInfo<T>()) {
+ case VAR_TYPE_INT:
+ case VAR_TYPE_FLOAT:
+ case VAR_TYPE_BOOL:
+ case VAR_TYPE_CONST_STRING:
+ break;
+ default:
+ throw SquirrelError(_SC("validateConstantType(): type must be INT, FLOAT, BOOL, or CONST CHAR *."));
+ } // case
+} // validateConstantType
+
+inline void createInstanceSetGetHandlers(SquirrelObject & so) {
+ if (!so.Exists(_SC("_set"))) {
+ SquirrelVM::CreateFunction(so,setInstanceVarFunc,_SC("_set"),_SC("sn|b|s|x")); // String var name = number(int or float) or bool or string or instance.
+ SquirrelVM::CreateFunction(so,getInstanceVarFunc,_SC("_get"),_SC("s")); // String var name.
+ } // if
+} // createInstanceSetGetHandlers
+
+// === END Helpers ===
+
+
+// Provide an overridable way of copying / deleting objects
+template<typename T>
+struct ObjectCloner {
+ static T* Clone(T* src){ return new T(src); }
+ static void Delete(T* dst){ if(dst) delete dst; }
+};
+
+// specialization for void type
+//template<> inline void ClassType<void>::copy(void *dst, void *src) {}
+DECLARE_NONCOPY_TYPE_INTERN(void)
+
+
+// === Bind a global or pre-allocated (not instance) class member variable or constant (for tables only (not classes)) ===
+
+template<typename T>
+void BindVariable(SquirrelObject & so,T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
+ VarRefPtr pvr = createVarRef(so,scriptVarName);
+ *pvr = VarRef(var,TypeInfo<T>(),NULL,ClassType<T>::type(),sizeof(*var),access);
+ createTableSetGetHandlers(so);
+} // BindVariable
+
+// === Bind a constant by value: INT, FLOAT, BOOL, or CONST CHAR * (for tables only (not classes)) ===
+
+template<typename T>
+void BindConstant(SquirrelObject & so,T constant,const SQChar * scriptVarName) {
+ validateConstantType(constant);
+ VarRefPtr pvr = createVarRef(so,scriptVarName);
+ struct CV {
+ T var;
+ } cv; // Cast Variable helper.
+ cv.var = constant;
+ *pvr = VarRef(*(void **)&cv,TypeInfo<T>(),NULL,ClassType<T>::type(),sizeof(constant),VAR_ACCESS_CONSTANT);
+ createTableSetGetHandlers(so);
+} // BindConstant
+
+template<typename T>
+void BindVariable(T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
+ SquirrelObject so = SquirrelVM::GetRootTable();
+ BindVariable(so,var,scriptVarName,access);
+} // BindVariable
+
+template<typename T>
+void BindConstant(T constant,const SQChar * scriptVarName) {
+ SquirrelObject so = SquirrelVM::GetRootTable();
+ BindConstant(so,constant,scriptVarName);
+} // BindConstant
+
+// === Register a class instance member variable or constant. var argument provides type and offset ( effectively &((ClassType *)0)->var ) ===
+
+// classType is the type of the member variable's containing class.
+ template<typename T>
+void RegisterInstanceVariable(SquirrelObject & so,ClassTypeBase* classType,T * var,const SQChar * scriptVarName,VarAccessType access=VAR_ACCESS_READ_WRITE) {
+ VarRef * pvr = createVarRef(so,scriptVarName);
+ void * offsetOrAddrOrConst = (void *)var; // var must be passed in as &obj->var, where obj = 0 (the address is the offset), or as static/global address.
+ *pvr = VarRef(offsetOrAddrOrConst,TypeInfo<T>(),classType,ClassType<T>::type(),sizeof(*var),access);
+ createInstanceSetGetHandlers(so);
+} // RegisterInstanceVariable
+
+#ifdef SQPLUS_SMARTPOINTER_OPT
+#define SQPLUS_SMARTPOINTER_REGISTER_VARIABLE
+#include "SqPlusSmartPointer.h"
+#endif
+
+template<typename T>
+void RegisterInstanceConstant(SquirrelObject & so,ClassTypeBase *classType,T constant,const SQChar * scriptVarName) {
+ validateConstantType(constant);
+ VarRef * pvr = createVarRef(so,scriptVarName);
+ struct CV {
+ T var;
+ size_t pad;
+ } cv; // Cast Variable helper.
+ cv.var = constant;
+ *pvr = VarRef(*(void **)&cv,TypeInfo<T>(),classType,ClassType<T>::type(),sizeof(constant),VAR_ACCESS_CONSTANT);
+ createInstanceSetGetHandlers(so);
+} // RegisterInstanceConstant
+
+//////////////////////////////////////////////////////////////////////////
+/////////// BEGIN Generalized Class/Struct Instance Support //////////////
+//////////////////////////////////////////////////////////////////////////
+
+// Was previously in SqPlus namespace
+//BOOL CreateNativeClassInstance(HSQUIRRELVM v,const SQChar * classname,SQUserPointer ud,SQRELEASEHOOK hook); // In SquirrelBindingUtils.cpp.
+
+// Create native class instance and leave on stack.
+//BOOL CreateConstructNativeClassInstance(HSQUIRRELVM v,const SQChar * className);
+
+// Create new instance, copy 'classToCopy', and store result on stack.
+template<typename T>
+inline BOOL CreateCopyInstance(HSQUIRRELVM v, const SQChar * className,const T & classToCopy) {
+#ifndef SQPLUS_DISABLE_COPY_INSTANCES
+ if (!CreateConstructNativeClassInstance(v,className)) {
+ return FALSE;
+ } // if
+ SQUserPointer up=0;
+ sq_getinstanceup(v,-1,&up,ClassType<T>::type());
+ if (!up) return FALSE;
+ T * newClass = (T *)up;
+ *newClass = classToCopy; // <TODO> Optimized version that uses the copy constructor.
+ return TRUE;
+#else
+ return FALSE;
+#endif
+} // CreateCopyInstance
+
+// Create a new copy of type 'className' and copy 'classToCopy', return result via SquirrelObject.
+template<typename T>
+inline SquirrelObject NewClassCopy(HSQUIRRELVM v, const SQChar * className,const T & classToCopy) {
+ if (CreateCopyInstance(v, className,classToCopy)) {
+ HSQOBJECT t;
+ sq_getstackobj(v,-1,&t);
+ SquirrelObject obj(t);
+ sq_poptop(v);
+ return obj;
+ } else {
+ throw SquirrelError(_SC("NewClassCopy(): could not create class"));
+ } // if
+ return SquirrelObject();
+} // NewClassCopy
+
+// Return a new class copy on the stack from a varArgs function call.
+template<typename T>
+inline int ReturnCopy(HSQUIRRELVM v,const T & classToCopy) {
+ SquirrelObject so(NewClassCopy(v,GetTypeName(classToCopy),classToCopy));
+ return StackHandler(v).Return(so);
+} // ReturnCopy
+
+// Katsuaki Kawachi's GetInstance<> exception change. 6/27/06 jcs
+
+// Get an instance of type T from the stack at idx (for function calls).
+template<typename T,bool ExceptionOnError>
+T * GetInstance(HSQUIRRELVM v,SQInteger idx) {
+ SQUserPointer up=0;
+ if (SQ_FAILED(sq_getinstanceup(v,idx,&up,ClassType<T>::type()))) {
+ up = 0;
+ }
+ if (ExceptionOnError) { // This code block should be compiled out when ExceptionOnError is false. In any case, the compiler should not generate a test condition (include or exclude the enclosed code block).
+ if (!up) {
+ throw SquirrelError(_SC("GetInstance: Invalid argument type"));
+ }
+ } // if
+ return (T *)up;
+} // GetInstance
+
+
+template<typename T> void Push(HSQUIRRELVM v, T* pt);
+template<typename T> void Push(HSQUIRRELVM v, T& t);
+template<typename T> bool Match(TypeWrapper<T&>, HSQUIRRELVM v, int ix);
+template<typename T> bool Match(TypeWrapper<T*>, HSQUIRRELVM v, int ix);
+template<typename T> T &Get(TypeWrapper<T&>, HSQUIRRELVM v, int ix);
+template<typename T> T *Get(TypeWrapper<T*>, HSQUIRRELVM v, int ix);
+
+
+#ifdef SQPLUS_USE_GENERIC_HANDLERS
+// With template specialization, we get Push handlers per 'precise type match'
+// This adds a fallback level after that, where we can delegate the work to
+// wider C-style functions that can do something for a whole class hierarchy.
+// (GenPush, GenGet, GenMatch).
+
+// This macro allows for a a last generic cast operation before giving control
+// to one of GenPush/GenMatch/GenGet.
+#ifndef SQPLUS_GEN_CAST
+ #define SQPLUS_GEN_CAST(TYPE,value) ((TYPE*)value)
+#endif
+
+template<typename T> void Push(HSQUIRRELVM v, T* pt){ GenPush(v,SQPLUS_GEN_CAST(T,pt)); }
+template<typename T> void Push(HSQUIRRELVM v, T& t){ GenPush(v,SQPLUS_GEN_CAST(T,&t)); }
+template<typename T> bool Match(TypeWrapper<T&>, HSQUIRRELVM v, int ix){
+ if((ScriptVarType)TypeInfo<T>::TypeID!=VAR_TYPE_NONE)
+ return GenMatch(SQPLUS_GEN_CAST(T*,0),TypeInfo<T>().typeName,v,ix);
+ else return false;
+}
+template<typename T> bool Match(TypeWrapper<T*>, HSQUIRRELVM v, int ix){
+ if((ScriptVarType)TypeInfo<T>::TypeID!=VAR_TYPE_NONE)
+ return GenMatch(SQPLUS_GEN_CAST(T*,0),TypeInfo<T>().typeName,v,ix);
+ else return false;
+}
+template<typename T> T &Get(TypeWrapper<T&>, HSQUIRRELVM v, int ix){
+ if((ScriptVarType)TypeInfo<T>::TypeID!=VAR_TYPE_NONE)
+ return *(T*)GenGet(SQPLUS_GEN_CAST(T*,0),TypeInfo<T>().typeName,v,ix);
+ else return *SQPLUS_GEN_CAST(T,0);
+}
+template<typename T> T *Get(TypeWrapper<T*>, HSQUIRRELVM v, int ix){
+ if((ScriptVarType)TypeInfo<T>::TypeID!=VAR_TYPE_NONE)
+ return (T*)GenGet(SQPLUS_GEN_CAST(T*,0),TypeInfo<T>().typeName,v,ix);
+ else return NULL;
+}
+#endif // SQPLUS_USE_GENERIC_HANDLERS
+
+
+// === BEGIN Function Call Handler Prototypes ===
+
+void Push(HSQUIRRELVM v, char value);
+void Push(HSQUIRRELVM v, unsigned char value);
+void Push(HSQUIRRELVM v, short value);
+void Push(HSQUIRRELVM v, unsigned short value);
+void Push(HSQUIRRELVM v, int value);
+void Push(HSQUIRRELVM v, unsigned int value);
+void Push(HSQUIRRELVM v, long value);
+void Push(HSQUIRRELVM v, unsigned long value);
+void Push(HSQUIRRELVM v, double value);
+void Push(HSQUIRRELVM v, float value);
+void Push(HSQUIRRELVM v, const SQChar *value);
+void Push(HSQUIRRELVM v, SQChar *value);
+void Push(HSQUIRRELVM v, const SquirrelNull &);
+void Push(HSQUIRRELVM v, SQFUNCTION value);
+void Push(HSQUIRRELVM v, SQAnythingPtr value); // Cast to SQAnythingPtr instead of void * if USE_ARGUMENT_DEPENDANT_OVERLOADS can't be used by your compiler.
+void Push(HSQUIRRELVM v, SquirrelObject &so);
+
+#define USE_ARGUMENT_DEPENDANT_OVERLOADS
+#ifdef USE_ARGUMENT_DEPENDANT_OVERLOADS
+#ifdef _MSC_VER
+#pragma warning(disable:4675) // Disable warning: "resolved overload was found by argument-dependent lookup" when class/struct pointers are used as function arguments.
+#endif
+// === BEGIN Argument Dependent Overloads ===
+void Push(HSQUIRRELVM v, bool value); // Pass bool as int if USE_ARGUMENT_DEPENDANT_OVERLOADS can't be used by your compiler.
+void Push(HSQUIRRELVM v, const void *value); // Pass SQAnythingPtr instead of void * " "
+void Push(HSQUIRRELVM v, const SQUserPointer &value);
+// === END Argument Dependent Overloads ===
+#endif
+
+#define SQPLUS_CHECK_GET(res) if (!SQ_SUCCEEDED(res)) throw SquirrelError(_SC("sq_get*() failed (type error)"))
+
+bool Match(TypeWrapper<bool>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<char>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<unsigned char>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<short>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<unsigned short>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<int>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<unsigned int>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<long>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<unsigned long>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<float>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<double>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<const SQChar *>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<SQChar *>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<HSQUIRRELVM>, HSQUIRRELVM v, int idx); // See Get() for HSQUIRRELVM below (v is always present).
+bool Match(TypeWrapper<void*>, HSQUIRRELVM v, int idx);
+bool Match(TypeWrapper<SquirrelObject>, HSQUIRRELVM v, int idx); // See sq_getstackobj(): always returns true.
+
+void Get(TypeWrapper<void>, HSQUIRRELVM v, int);
+bool Get(TypeWrapper<bool>, HSQUIRRELVM v, int idx);
+char Get(TypeWrapper<char>, HSQUIRRELVM v, int idx);
+unsigned char Get(TypeWrapper<unsigned char>, HSQUIRRELVM v, int idx);
+short Get(TypeWrapper<short>, HSQUIRRELVM v, int idx);
+unsigned short Get(TypeWrapper<unsigned short>, HSQUIRRELVM v, int idx);
+int Get(TypeWrapper<int>, HSQUIRRELVM v, int idx);
+unsigned int Get(TypeWrapper<unsigned int>, HSQUIRRELVM v, int idx);
+long Get(TypeWrapper<long>, HSQUIRRELVM v, int idx);
+unsigned long Get(TypeWrapper<unsigned long>, HSQUIRRELVM v, int idx);
+float Get(TypeWrapper<float>, HSQUIRRELVM v, int idx);
+double Get(TypeWrapper<double>, HSQUIRRELVM v, int idx);
+const SQChar *Get(TypeWrapper<const SQChar *>, HSQUIRRELVM v, int idx);
+SquirrelNull Get(TypeWrapper<SquirrelNull>, HSQUIRRELVM v, int idx);
+void *Get(TypeWrapper<void *>, HSQUIRRELVM v, int idx);
+HSQUIRRELVM Get(TypeWrapper<HSQUIRRELVM>, HSQUIRRELVM v, int /*idx*/); // sq_poptop(v): remove UserData from stack so GetParamCount() matches normal behavior.
+SquirrelObject Get(TypeWrapper<SquirrelObject>, HSQUIRRELVM v, int idx);
+
+#ifdef SQPLUS_AUTOCONVERT_OTHER_CHAR
+ void Push(HSQUIRRELVM v, const SQOtherChar *value);
+ void Push(HSQUIRRELVM v, SQOtherChar *value);
+ bool Match(TypeWrapper<const SQOtherChar *>, HSQUIRRELVM v, int idx);
+ bool Match(TypeWrapper<SQOtherChar *>, HSQUIRRELVM v, int idx);
+ SQOthCharBuf Get(TypeWrapper<const SQOtherChar *>, HSQUIRRELVM v, int idx);
+#endif // SQPLUS_AUTOCONVERT_OTHER_CHAR
+
+#ifdef SQPLUS_SUPPORT_STD_STRING
+void Push(HSQUIRRELVM v, const std::string& value);
+bool Match(TypeWrapper<const std::string&>, HSQUIRRELVM v, int idx);
+std::string Get(TypeWrapper<const std::string&>, HSQUIRRELVM v, int idx);
+#endif
+
+// Added jflanglois suggestion, 8/20/06. jcs
+#ifdef SQPLUS_SUPPORT_SQ_STD_STRING
+typedef std::basic_string<SQChar> sq_std_string;
+void Push(HSQUIRRELVM v,const sq_std_string & value);
+bool Match(TypeWrapper<const sq_std_string &>, HSQUIRRELVM v, int idx);
+sq_std_string Get(TypeWrapper<const sq_std_string &>, HSQUIRRELVM v, int idx);
+#endif
+
+// Specialization to support void return type.
+void GetRet(TypeWrapper<void>, HSQUIRRELVM v,int idx);
+
+// GetRet() restores the stack for SquirrelFunction<>() calls.
+// Hold on to a reference since return value might be temporary string/instance
+template<typename RT>
+inline RT GetRet(TypeWrapper<RT>,HSQUIRRELVM v,int idx) {
+ static SquirrelObject st_sq_ret;
+ static typename Temporary<RT>::type st_ret;
+ st_ret = Get(TypeWrapper<RT>(),v,idx);
+ st_sq_ret.AttachToStackObject(idx);
+ sq_pop(v,2); // restore stack after function call.
+ return st_ret; }
+
+#ifndef GCC_INLINE_WORKAROUND
+# include "SqPlusFunctionCallImpl.h"
+#endif // GCC_INLINE_WORKAROUND
+
+// === END Function Call Handlers ===
+
+
+// Helper, only implement function bodies
+#define IMPLEMENT_ENUM_TYPE(TYPE) namespace SqPlus { \
+ bool Match(TypeWrapper<TYPE>,HSQUIRRELVM v,int idx) { return Match(TypeWrapper<int>(),v,idx); } \
+ TYPE Get(TypeWrapper<TYPE>,HSQUIRRELVM v,int idx) { return (TYPE)Get(TypeWrapper<int>(),v,idx); } \
+ void Push(HSQUIRRELVM v,TYPE value) { sq_pushinteger(v,(int)value); } \
+} // nameSpace SqPlus
+
+// To register simple types (like enums) so they can be used as arguments
+// (however, this does not handle enums as return values correctly, since
+// we C++ gets problems with references to temporaries)
+#define DECLARE_ENUM_TYPE(TYPE) IMPLEMENT_ENUM_TYPE(TYPE) \
+namespace SqPlus { \
+ template<> struct TypeInfo<TYPE> : public TypeInfo<int> { }; \
+} // nameSpace SqPlus
+
+// As above but use when function bodies should not be generated
+// (for a header file).
+#define PROTOS_ENUM_TYPE(TYPE) namespace SqPlus { \
+ bool Match(TypeWrapper<TYPE>,HSQUIRRELVM v,int idx); \
+ TYPE Get(TypeWrapper<TYPE>,HSQUIRRELVM v,int idx); \
+ void Push(HSQUIRRELVM v,TYPE value); \
+ template<> struct TypeInfo<TYPE> : public TypeInfo<int> { }; \
+} // nameSpace SqPlus
+
+
+// NAME and macro changes from Ben's (Project5) forum post. 2/26/06 jcs
+// Kamaitati's NULL_INSTANCE support. 5/28/06 jcs
+
+// ATS: Splitting the macros in different parts to support custom Push implementation (covariant return type)
+
+#define DECLARE_INSTANCE_TYPEINFO_(TYPE,NAME) \
+ inline const SQChar * GetTypeName(const TYPE & n) { return _SC(#NAME); } \
+ template<> \
+ struct TypeInfo<TYPE> { \
+ const SQChar * typeName; \
+ TypeInfo() : typeName( _SC(#NAME)) {} \
+ enum {TypeID=VAR_TYPE_INSTANCE,Size=sizeof(TYPE),TypeMask='x', IsInstance=1}; \
+ operator ScriptVarType() { return ScriptVarType(TypeID); } \
+ };
+
+#define DECLARE_INSTANCE_TYPEINFO(TYPE) namespace SqPlus { \
+ DECLARE_INSTANCE_TYPEINFO_(TYPE,TYPE) \
+} // namespace SqPlus
+
+#define DECLARE_INSTANCE_TYPEINFO_NAME(TYPE,NAME) namespace SqPlus { \
+ DECLARE_INSTANCE_TYPEINFO_(TYPE,NAME) \
+} // namespace SqPlus
+
+
+#ifdef SQPLUS_SUPPORT_NULL_INSTANCES
+
+// Macro part shared by 'derived' macros
+#define DECLARE_INSTANCE_TYPE_BASE_(TYPE,NAME) \
+ DECLARE_INSTANCE_TYPEINFO_(TYPE,NAME) \
+ template<> inline bool Match(TypeWrapper<TYPE &>,HSQUIRRELVM v,int idx) { return GetInstance<TYPE,false>(v,idx) != NULL; } \
+ template<> inline bool Match(TypeWrapper<TYPE *>,HSQUIRRELVM v,int idx) { \
+ return (sq_gettype(v,idx)==OT_NULL) || (GetInstance<TYPE,false>(v,idx) != NULL); } \
+ template<> inline TYPE & Get(TypeWrapper<TYPE &>,HSQUIRRELVM v,int idx) { return *GetInstance<TYPE,true>(v,idx); } \
+ template<> inline TYPE * Get(TypeWrapper<TYPE *>,HSQUIRRELVM v,int idx) { \
+ if (sq_gettype(v,idx)==OT_NULL) return NULL; \
+ return GetInstance<TYPE,true>(v,idx); }
+
+// Ordinary case
+#define DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) namespace SqPlus { \
+ DECLARE_INSTANCE_TYPE_BASE_(TYPE,NAME) \
+ template<> inline void Push(HSQUIRRELVM v,TYPE * value) { \
+ if (!value) sq_pushnull(v); \
+ else if (!CreateNativeClassInstance(v,GetTypeName(*value),value,0)) \
+ throw SquirrelError( _SC( "Push(): could not create INSTANCE (check registration name)")); } \
+ template<> inline void Push(HSQUIRRELVM v,TYPE & value) { if (!CreateCopyInstance(v,GetTypeName(value),value)) throw SquirrelError( _SC( "Push(): could not create INSTANCE copy (check registration name)")); } \
+} // nameSpace SqPlus
+
+// Allows for providing custom Push handlers (protos here, impl must be provided by app)
+#define DECLARE_INSTANCE_TYPE_NAME_CUSTOM_(TYPE,NAME) namespace SqPlus { \
+ DECLARE_INSTANCE_TYPE_BASE_(TYPE,NAME) \
+ template<> void Push(HSQUIRRELVM v,TYPE * value); \
+ template<> void Push(HSQUIRRELVM v,TYPE & value); \
+} // nameSpace SqPlus
+
+
+#else
+
+#define DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME) namespace SqPlus { \
+ DECLARE_INSTANCE_TYPEINFO_(TYPE,NAME) \
+ template<> inline void Push(HSQUIRRELVM v,TYPE * value) { if (!CreateNativeClassInstance(v,GetTypeName(*value),value,0)) throw SquirrelError( _SC( "Push(): could not create INSTANCE (check registration name)")); } \
+ template<> inline void Push(HSQUIRRELVM v,TYPE & value) { if (!CreateCopyInstance(v,GetTypeName(value),value)) throw SquirrelError( _SC( "Push(): could not create INSTANCE copy (check registration name)")); } \
+ template<> inline bool Match(TypeWrapper<TYPE &>,HSQUIRRELVM v,int idx) { return GetInstance<TYPE,false>(v,idx) != NULL; } \
+ template<> inline bool Match(TypeWrapper<TYPE *>,HSQUIRRELVM v,int idx) { return GetInstance<TYPE,false>(v,idx) != NULL; } \
+ template<> inline TYPE & Get(TypeWrapper<TYPE &>,HSQUIRRELVM v,int idx) { return *GetInstance<TYPE,true>(v,idx); } \
+ template<> inline TYPE * Get(TypeWrapper<TYPE *>,HSQUIRRELVM v,int idx) { return GetInstance<TYPE,true>(v,idx); } \
+} // nameSpace SqPlus
+
+#endif
+
+// TYPE or NAME below must match the string name used in SQClassDef<>, otherwise name lookup won't match and Squirrel will throw a "can't create instance" error.
+#ifndef SQPLUS_CONST_OPT
+#define DECLARE_INSTANCE_TYPE(TYPE) DECLARE_INSTANCE_TYPE_NAME_(TYPE,TYPE)
+#define DECLARE_INSTANCE_TYPE_NAME(TYPE,NAME) DECLARE_INSTANCE_TYPE_NAME_(TYPE,NAME)
+#define DECLARE_INSTANCE_TYPE_CUSTOM(TYPE) DECLARE_INSTANCE_TYPE_NAME_CUSTOM_(TYPE,TYPE)
+#define DECLARE_INSTANCE_TYPE_NAME_CUSTOM(TYPE,NAME) DECLARE_INSTANCE_TYPE_NAME_CUSTOM_(TYPE,NAME)
+#else
+#define SQPLUS_DECLARE_INSTANCE_TYPE_CONST
+#include "SqPlusConst.h"
+#endif
+
+#ifdef SQPLUS_OVERLOAD_OPT
+#define SQPLUS_OVERLOAD_DECLARATION
+#include "SqPlusOverload.h"
+#endif
+
+// Versions of above for types that aren't copy constructable
+#define DECLARE_INSTANCE_TYPEINFO_NOCOPY(TYPE) \
+ DECLARE_INSTANCE_TYPEINFO(TYPE) \
+ DECLARE_NONCOPY_TYPE(TYPE)
+
+#define DECLARE_INSTANCE_TYPEINFO_NOCOPY_NAME(TYPE,NAME) namespace SqPlus { \
+ DECLARE_INSTANCE_TYPEINFO_(TYPE,NAME) \
+ DECLARE_NONCOPY_TYPE(TYPE)
+
+#define DECLARE_INSTANCE_TYPE_NOCOPY(TYPE) \
+ DECLARE_INSTANCE_TYPE(TYPE) \
+ DECLARE_NONCOPY_TYPE(TYPE)
+
+#define DECLARE_INSTANCE_TYPE_NOCOPY_NAME(TYPE,NAME) namespace SqPlus { \
+ DECLARE_INSTANCE_TYPEINFO_(TYPE,NAME) \
+ DECLARE_NONCOPY_TYPE(TYPE)
+
+
+//////////////////////////////////////////////////////////////////////////
+//////////// END Generalized Class/Struct Instance Support ///////////////
+//////////////////////////////////////////////////////////////////////////
+
+#ifndef SQ_SKIP_ARG_ASSERT
+ #define sq_argassert(arg,_index_) if (!Match(TypeWrapper<P##arg>(),v,_index_)) return sq_throwerror(v,_SC("Incorrect function argument"))
+#else
+ #define sq_argassert(arg,_index_)
+#endif
+
+// === Return value variants ===
+
+template<class RT>
+struct ReturnSpecialization {
+
+ // === Standard Function calls ===
+
+ static int Call(RT (*func)(),HSQUIRRELVM v,int /*index*/) {
+ RT ret = func();
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename P1>
+ static int Call(RT (*func)(P1),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ RT ret = func(
+ Get(TypeWrapper<P1>(),v,index + 0)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename P1,typename P2>
+ static int Call(RT (*func)(P1,P2),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ RT ret = func(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename P1,typename P2,typename P3>
+ static int Call(RT (*func)(P1,P2,P3),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ RT ret = func(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename P1,typename P2,typename P3,typename P4>
+ static int Call(RT (*func)(P1,P2,P3,P4),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ RT ret = func(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename P1,typename P2,typename P3,typename P4,typename P5>
+ static int Call(RT (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ sq_argassert(5,index + 4);
+ RT ret = func(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3),
+ Get(TypeWrapper<P5>(),v,index + 4)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
+ static int Call(RT (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ sq_argassert(5,index + 4);
+ sq_argassert(6,index + 5);
+ RT ret = func(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3),
+ Get(TypeWrapper<P5>(),v,index + 4),
+ Get(TypeWrapper<P6>(),v,index + 5)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
+ static int Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ sq_argassert(5,index + 4);
+ sq_argassert(6,index + 5);
+ sq_argassert(7,index + 6);
+ RT ret = func(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3),
+ Get(TypeWrapper<P5>(),v,index + 4),
+ Get(TypeWrapper<P6>(),v,index + 5),
+ Get(TypeWrapper<P7>(),v,index + 6)
+ );
+ Push(v,ret);
+ return 1;
+ }
+
+ // === Member Function calls ===
+
+
+#define SQPLUS_CALL_MFUNC_RET0
+#include "SqPlusCallTemplates.h"
+
+#ifdef SQPLUS_CONST_OPT
+#define SQPLUS_CALL_MFUNC_RET0
+#include "SqPlusConst.h"
+#endif
+};
+
+// === No return value variants ===
+
+template<>
+struct ReturnSpecialization<void> {
+
+ // === Standard function calls ===
+
+ static int Call(void (*func)(),HSQUIRRELVM v,int /*index*/) {
+ (void)v;
+ func();
+ return 0;
+ }
+
+ template<typename P1>
+ static int Call(void (*func)(P1),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ func(
+ Get(TypeWrapper<P1>(),v,index + 0)
+ );
+ return 0;
+ }
+
+ template<typename P1,typename P2>
+ static int Call(void (*func)(P1,P2),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ func(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1)
+ );
+ return 0;
+ }
+
+ template<typename P1,typename P2,typename P3>
+ static int Call(void (*func)(P1,P2,P3),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ func(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2)
+ );
+ return 0;
+ }
+
+ template<typename P1,typename P2,typename P3,typename P4>
+ static int Call(void (*func)(P1,P2,P3,P4),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ func(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3)
+ );
+ return 0;
+ }
+
+ template<typename P1,typename P2,typename P3,typename P4,typename P5>
+ static int Call(void (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ sq_argassert(5,index + 4);
+ func(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3),
+ Get(TypeWrapper<P5>(),v,index + 4)
+ );
+ return 0;
+ }
+
+ template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
+ static int Call(void (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ sq_argassert(5,index + 4);
+ sq_argassert(6,index + 5);
+ func(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3),
+ Get(TypeWrapper<P5>(),v,index + 4),
+ Get(TypeWrapper<P6>(),v,index + 5)
+ );
+ return 0;
+ }
+
+ template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
+ static int Call(void (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,int index) {
+ sq_argassert(1,index + 0);
+ sq_argassert(2,index + 1);
+ sq_argassert(3,index + 2);
+ sq_argassert(4,index + 3);
+ sq_argassert(5,index + 4);
+ sq_argassert(6,index + 5);
+ sq_argassert(7,index + 6);
+ func(
+ Get(TypeWrapper<P1>(),v,index + 0),
+ Get(TypeWrapper<P2>(),v,index + 1),
+ Get(TypeWrapper<P3>(),v,index + 2),
+ Get(TypeWrapper<P4>(),v,index + 3),
+ Get(TypeWrapper<P5>(),v,index + 4),
+ Get(TypeWrapper<P6>(),v,index + 5),
+ Get(TypeWrapper<P7>(),v,index + 6)
+ );
+ return 0;
+ }
+
+ // === Member function calls ===
+
+
+#define SQPLUS_CALL_MFUNC_NORET
+#include "SqPlusCallTemplates.h"
+
+#ifdef SQPLUS_CONST_OPT
+#define SQPLUS_CALL_MFUNC_NORET
+#include "SqPlusConst.h"
+#endif
+
+};
+
+// === STANDARD Function return value specialized call handlers ===
+
+template<typename RT>
+int Call(RT (*func)(),HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(func,v,index);
+}
+
+template<typename RT,typename P1>
+int Call(RT (*func)(P1),HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(func,v,index);
+}
+
+template<typename RT,typename P1,typename P2>
+int Call(RT (*func)(P1,P2),HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(func,v,index);
+}
+
+template<typename RT,typename P1,typename P2,typename P3>
+int Call(RT (*func)(P1,P2,P3),HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(func,v,index);
+}
+
+template<typename RT,typename P1,typename P2,typename P3,typename P4>
+int Call(RT (*func)(P1,P2,P3,P4),HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(func,v,index);
+}
+
+template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5>
+int Call(RT (*func)(P1,P2,P3,P4,P5),HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(func,v,index);
+}
+
+template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
+int Call(RT (*func)(P1,P2,P3,P4,P5,P6),HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(func,v,index);
+}
+
+template<typename RT,typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
+int Call(RT (*func)(P1,P2,P3,P4,P5,P6,P7),HSQUIRRELVM v,int index) {
+ return ReturnSpecialization<RT>::Call(func,v,index);
+}
+
+// === MEMBER Function return value specialized call handlers ===
+
+
+#define SQPLUS_CALL_MFUNC_RET1
+#include "SqPlusCallTemplates.h"
+
+#ifdef SQPLUS_CONST_OPT
+#define SQPLUS_CALL_MFUNC_RET1
+#include "SqPlusConst.h"
+#endif
+
+// === Direct Call Standard Function handler ===
+
+template<typename Func>
+struct DirectCallFunction {
+ static inline int Dispatch(HSQUIRRELVM v) {
+#ifdef SQPLUS_USE_SANDBOX_VM
+ if( v==SquirrelVM::GetSandboxVMPtr() ){
+ return sq_throwerror(v, _SC("SqPlus: Cannot exec function from sandbox VM"));
+ }
+#endif
+ StackHandler sa(v);
+ int paramCount = sa.GetParamCount();
+ Func * func = (Func *)sa.GetUserData(paramCount);
+ return Call(*func,v,2);
+ } // Dispatch
+};
+
+// === Direct Call Member Function handler ===
+
+template<typename Callee,typename Func>
+class DirectCallMemberFunction {
+public:
+ static inline int Dispatch(HSQUIRRELVM v) {
+#ifdef SQPLUS_USE_SANDBOX_VM
+ if( v==SquirrelVM::GetSandboxVMPtr() ){
+ return sq_throwerror(v, _SC("SqPlus: Cannot exec function from sandbox VM"));
+ }
+#endif
+ StackHandler sa(v);
+ int paramCount = sa.GetParamCount();
+ unsigned char * ud = (unsigned char *)sa.GetUserData(paramCount);
+ return Call(**(Callee**)ud,*(Func*)(ud + sizeof(Callee*)),v,2);
+ } // Dispatch
+};
+
+// === Direct Call Function handlers ===
+
+#define SQ_CLASS_OBJECT_TABLE_NAME _SC("__ot")
+#define SQ_CLASS_HIER_ARRAY _SC("__ca")
+
+template<typename Callee, typename Func>
+struct DirectCallInstanceFuncPicker {
+ Callee *instance;
+ Func *func;
+ DirectCallInstanceFuncPicker(HSQUIRRELVM v) {
+#ifdef SQPLUS_USE_SANDBOX_VM
+ if( v==SquirrelVM::GetSandboxVMPtr() ){
+ instance = NULL;
+ func = NULL;
+ return;
+ }
+#endif
+ StackHandler sa(v);
+ instance = static_cast<Callee*>(sa.GetInstanceUp(1, 0));
+ const int paramCount = sa.GetParamCount();
+ func = static_cast<Func*>(sa.GetUserData(paramCount));
+#ifdef SQ_USE_CLASS_INHERITANCE
+ SquirrelObject so(sa.GetObjectHandle(1)); // 'this'
+ SQUserPointer typetag; so.GetTypeTag(&typetag);
+ SQUserPointer calleeType = ClassType<Callee>::type();
+ if (typetag != calleeType) {
+ SquirrelObject typeTable = so.GetValue(SQ_CLASS_OBJECT_TABLE_NAME);
+ instance = static_cast<Callee*>(
+ // <TODO> 64-bit compatible version.
+ typeTable.GetUserPointer(INT((size_t)ClassType<Callee>::type()))
+ );
+ }
+#elif defined(SQ_USE_CLASS_INHERITANCE_SIMPLE)
+ SquirrelObject so(sa.GetObjectHandle(1)); // 'this'
+ ClassTypeBase *instType; so.GetTypeTag((SQUserPointer*)&instType);
+ ClassTypeBase *calleeType = ClassType<Callee>::type();
+ if (instType!=calleeType && instType->MayHaveOffset() ) {
+ // instance type is nore derived than callee, adjust pointer
+ int offset = instType->GetOffsetTo(calleeType);
+ instance = (Callee*)((char*)instance-offset);
+ }
+#endif
+ }
+};
+
+// === Direct Call Instance Member Function handler ===
+template<typename Callee,typename Func>
+class DirectCallInstanceMemberFunction {
+public:
+ static inline int Dispatch(HSQUIRRELVM v) {
+ DirectCallInstanceFuncPicker<Callee, Func> p(v);
+ return p.instance && p.func ?
+ Call(*(p.instance), *(p.func), v, 2) :
+ sq_throwerror(v, _SC("Invalid Instance Type"));
+ }
+};
+
+// === Direct Call Instance Global Function handler ===
+template<typename Callee,typename Func>
+class DirectCallInstanceGlobalFunction {
+public:
+ static inline int Dispatch(HSQUIRRELVM v) {
+ DirectCallInstanceFuncPicker<Callee, Func> p(v);
+ return p.func ?
+ Call(*(p.func), v, 1) :
+ sq_throwerror(v, _SC("Invalid Instance Type"));
+ }
+};
+
+// === Direct Call Instance Global Function Var Args handler ===
+template<typename Callee,typename Func>
+class DirectCallInstanceGlobalFunctionVarArgs {
+public:
+ static inline int Dispatch(HSQUIRRELVM v) {
+ DirectCallInstanceFuncPicker<Callee, Func> p(v);
+ return p.func && p.instance ?
+ (*p.func)(p.instance,v) :
+ sq_throwerror(v, _SC("Invalid Instance Type"));
+ }
+};
+
+// === Direct Call Instance Member Function Variable Argument handler ===
+template<typename Callee,typename Func>
+class DirectCallInstanceMemberFunctionVarArgs {
+public:
+ static inline int Dispatch(HSQUIRRELVM v) {
+ DirectCallInstanceFuncPicker<Callee, Func> p(v);
+ sq_poptop(v); // Remove UserData from stack: so sa.GetParamCount() returns actual param count.
+ return p.func && p.instance ?
+ (p.instance->*(*p.func))(v) :
+ sq_throwerror(v, _SC("Invalid Instance Type"));
+ }
+};
+
+#ifdef SQPLUS_SMARTPOINTER_OPT
+#define SQPLUS_SMARTPOINTER_DISPATCH
+#include "SqPlusSmartPointer.h"
+#endif
+
+
+// Code fragment useful for debugging new implementations.
+#if 0
+HSQOBJECT ho = sa.GetObjectHandle(paramCount);
+SquirrelObject so(ho);
+SQObjectType sot = so.GetType();
+#endif
+
+#ifdef SQPLUS_ENABLE_AUTO_TYPEMASK
+ #include "SqPlusTypeMask.h"
+#endif
+
+// === Standard function call ===
+
+template<typename Func>
+inline void sq_pushdirectclosure(HSQUIRRELVM v,Func func,SQUnsignedInteger nupvalues) {
+ SQUserPointer up = sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
+ memcpy(up,&func,sizeof(func));
+ sq_newclosure(v,DirectCallFunction<Func>::Dispatch,nupvalues+1);
+#ifdef SQPLUS_ENABLE_AUTO_TYPEMASK
+ sq_setparamscheck(v,0,sqTypeMask<Func>::Get());
+#endif
+} // sq_pushdirectclosure
+
+// === Fixed Class pointer call (always calls with object pointer that was registered) ===
+
+template<typename Callee,typename Func>
+inline void sq_pushdirectclosure(HSQUIRRELVM v,const Callee & callee,Func func,SQUnsignedInteger nupvalues) {
+ unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(Callee*)+sizeof(func)); // Also pushed on stack.
+ const SQUserPointer pCallee = (SQUserPointer)&callee;
+ memcpy(up,&pCallee,sizeof(Callee*));
+ memcpy(up + sizeof(Callee*),&func,sizeof(func));
+ sq_newclosure(v,DirectCallMemberFunction<Callee,Func>::Dispatch,nupvalues+1);
+#ifdef SQPLUS_ENABLE_AUTO_TYPEMASK
+ sq_setparamscheck(v,0,sqTypeMask<Func>::Get());
+#endif
+} // sq_pushdirectclosure
+
+#ifdef SQPLUS_SMARTPOINTER_OPT
+#define SQPLUS_SMARTPOINTER_DIRECT_CLOSURE
+#include "SqPlusSmartPointer.h"
+#endif
+
+// === Class Instance call: class pointer retrieved from script class instance ===
+
+template<typename Callee,typename Func>
+inline void sq_pushdirectinstanceclosure(HSQUIRRELVM v,const Callee & callee,Func func,SQUnsignedInteger nupvalues) {
+ unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
+ memcpy(up,&func,sizeof(func));
+ sq_newclosure(v,DirectCallInstanceMemberFunction<Callee,Func>::Dispatch,nupvalues+1);
+#ifdef SQPLUS_ENABLE_AUTO_TYPEMASK
+ sq_setparamscheck(v,0,sqTypeMask<Func>::Get());
+#endif
+} // sq_pushdirectinstanceclosure
+
+// === Global function using this: class pointer retrieved from script class instance ===
+
+template<typename Callee,typename Func>
+inline void sq_pushdirectinstanceclosureglobal(HSQUIRRELVM v,const Callee & callee,Func func,SQUnsignedInteger nupvalues) {
+ unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
+ memcpy(up,&func,sizeof(func));
+ // Could check that 1st arg of Func is a Callee
+ sq_newclosure(v,DirectCallInstanceGlobalFunction<Callee,Func>::Dispatch,nupvalues+1);
+#ifdef SQPLUS_ENABLE_AUTO_TYPEMASK
+ SQChar *tm = (SQChar*)sqTypeMask<Func>::Get();
+ if( tm ) {
+ // Censor out the 1st arg, since SqPlus adds that automatically
+ tm[1] = _SC('x'); //tm[0];
+ tm++;
+ }
+ sq_setparamscheck(v,0,tm?tm:_SC(""));
+#endif
+} // sq_pushdirectinstanceclosureglobal
+
+// === Global function using this: class pointer retrieved from script class instance ===
+
+template<typename Callee,typename Func>
+inline void sq_pushdirectinstanceclosureglobalvarargs(HSQUIRRELVM v,const Callee & callee,Func func,SQUnsignedInteger nupvalues) {
+ unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
+ memcpy(up,&func,sizeof(func));
+ // Could check that 1st arg of Func is a Callee
+ sq_newclosure(v,DirectCallInstanceGlobalFunctionVarArgs<Callee,Func>::Dispatch,nupvalues+1);
+#ifdef SQPLUS_ENABLE_AUTO_TYPEMASK
+ sq_setparamscheck(v,-1,_SC("x"));
+#endif
+} // sq_pushdirectinstanceclosureglobal
+
+// === Class Instance call: class pointer retrieved from script class instance (variable arguments) ===
+
+template<typename Callee>
+inline void sq_pushdirectinstanceclosurevarargs(HSQUIRRELVM v,const Callee & callee,int (Callee::*func)(HSQUIRRELVM),SQUnsignedInteger nupvalues) {
+ unsigned char * up = (unsigned char *)sq_newuserdata(v,sizeof(func)); // Also pushed on stack.
+ memcpy(up,&func,sizeof(func));
+ typedef int (Callee::*FuncType)(HSQUIRRELVM);
+ sq_newclosure(v,DirectCallInstanceMemberFunctionVarArgs<Callee, FuncType>::Dispatch,nupvalues+1);
+} // sq_pushdirectinstanceclosurevarargs
+
+// === Register a STANDARD function (table or class on stack) ===
+
+template<typename Func>
+inline void Register(HSQUIRRELVM v,Func func,const SQChar * name) {
+ sq_pushstring(v,name,-1);
+ sq_pushdirectclosure(v,func,0);
+ sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call).
+} // Register
+
+// === Register a MEMBER function (table or class on stack) ===
+
+template<typename Callee,typename Func>
+inline void Register(HSQUIRRELVM v,Callee & callee,Func func,const SQChar * name) {
+ sq_pushstring(v,name,-1);
+ sq_pushdirectclosure(v,callee,func,0);
+ sq_createslot(v,-3); // Stack is restored after this call (same state as before Register() call).
+} // Register
+
+// === Register a STANDARD global function (root table) ===
+
+template<typename Func>
+inline void RegisterGlobal(HSQUIRRELVM v,Func func,const SQChar * name) {
+ sq_pushroottable(v);
+ Register(v,func,name);
+ sq_poptop(v); // Remove root table.
+} // RegisterGlobal
+
+template<typename Func>
+inline void RegisterGlobal(Func func,const SQChar * name) {
+ RegisterGlobal(SquirrelVM::GetVMPtr(),func,name);
+} // RegisterGlobal
+
+// === Register a MEMBER global function (root table) ===
+
+template<typename Callee,typename Func>
+inline void RegisterGlobal(HSQUIRRELVM v,Callee & callee,Func func,const SQChar * name) {
+ sq_pushroottable(v);
+ Register(v,callee,func,name);
+ sq_poptop(v); // Remove root table.
+} // RegisterGlobal
+
+template<typename Callee,typename Func>
+inline void RegisterGlobal(Callee & callee,Func func,const SQChar * name) {
+ RegisterGlobal(SquirrelVM::GetVMPtr(),callee,func,name);
+} // RegisterGlobal
+
+// === Register a STANDARD function (hso is table or class) ===
+
+template<typename Func>
+inline void Register(HSQUIRRELVM v,HSQOBJECT hso,Func func,const SQChar * name) {
+ sq_pushobject(v,hso);
+ Register(v,func,name);
+ sq_poptop(v); // Remove hso.
+} // Register
+
+// === Register a MEMBER function (hso is table or class) ===
+// === Fixed Class pointer call (always calls with object pointer that was registered) ===
+
+template<typename Callee,typename Func>
+inline void Register(HSQUIRRELVM v,HSQOBJECT hso,Callee & callee,Func func,const SQChar * name) {
+ sq_pushobject(v,hso);
+ Register(v,callee,func,name);
+ sq_poptop(v); // Remove hso.
+} // Register
+
+// === Register an INSTANCE MEMBER function ===
+// === Class Instance call: class pointer retrieved from script class instance ===
+
+template<typename Callee,typename Func>
+inline void RegisterInstance(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,Func func,const SQChar * name) {
+ sq_pushobject(v,hclass);
+ sq_pushstring(v,name,-1);
+ sq_pushdirectinstanceclosure(v,callee,func,0);
+ sq_createslot(v,-3);
+ sq_poptop(v); // Remove hclass.
+} // RegisterInstance
+
+
+// === Register an INSTANCE GLOBAL MEMBER function ===
+// === Class Instance call: class pointer retrieved from script class instance ===
+// Allows embedding global func that takes Callee as 1st arg as a member func
+template<typename Callee,typename Func>
+inline void RegisterInstanceGlobalFunc(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,Func func,const SQChar * name) {
+ sq_pushobject(v,hclass);
+ sq_pushstring(v,name,-1);
+ sq_pushdirectinstanceclosureglobal(v,callee,func,0);
+ sq_createslot(v,-3);
+ sq_poptop(v); // Remove hclass.
+} // RegisterInstanceGlobaFunc
+
+// === Register an INSTANCE GLOBAL MEMBER WITH VAR ARGS function ===
+// === Class Instance call: class pointer retrieved from script class instance ===
+// Allows embedding global func that takes Callee as 1st arg as a member func
+template<typename Callee,typename Func>
+inline void RegisterInstanceGlobalFuncVarArgs(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,Func func,const SQChar * name) {
+ sq_pushobject(v,hclass);
+ sq_pushstring(v,name,-1);
+ sq_pushdirectinstanceclosureglobalvarargs(v,callee,func,0);
+ sq_createslot(v,-3);
+ sq_poptop(v); // Remove hclass.
+} // RegisterInstanceGlobaFunc
+
+#ifdef SQPLUS_SMARTPOINTER_OPT
+#define SQPLUS_SMARTPOINTER_REGISTER_INSTANCE
+#include "SqPlusSmartPointer.h"
+#endif
+
+#ifdef _MSC_VER
+#pragma warning(disable : 4995) // Deprecated _snprintf
+#endif
+
+// === Register an INSTANCE MEMBER function Variable Arguments ===
+// typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case).
+// All the other Squirrel type-masks are passed normally.
+
+template<typename Callee>
+inline void RegisterInstanceVarArgs(HSQUIRRELVM v,HSQOBJECT hclass,Callee & callee,int (Callee::*func)(HSQUIRRELVM),const SQChar * name,const SQChar * typeMask=_SC("*")) {
+ sq_pushobject(v,hclass);
+ sq_pushstring(v,name,-1);
+ sq_pushdirectinstanceclosurevarargs(v,callee,func,0);
+ SQChar tm[64];
+ SQChar * ptm = tm;
+ int numParams = SQ_MATCHTYPEMASKSTRING;
+ if (typeMask) {
+ if (typeMask[0] == '*') {
+ ptm = 0; // Variable args: don't check parameters.
+// numParams = 0; // Clear SQ_MATCHTYPEMASKSTRING (does not mean match 0 params. See sq_setparamscheck()).
+ } else {
+ if (SCSNPRINTF(tm,sizeof(tm),_SC("x%s"),typeMask) < 0) { // Must be an instance.
+ throw SquirrelError(_SC("RegisterInstanceVarArgs: typeMask string too long."));
+ } // if
+ } // if
+ } else { // <TODO> Need to check object type on stack: table, class, instance, etc.
+// _snprintf(tm,sizeof(tm),"x"); // instance.
+ tm[0] = 'x';
+ tm[1] = 0;
+ } // if
+ if (ptm) { // If ptm == 0, don't check type.
+ sq_setparamscheck(v,numParams,ptm); // Determine arg count from type string.
+ } // if
+#ifdef _DEBUG
+ sq_setnativeclosurename(v,-1,name); // For debugging only.
+#endif
+ sq_createslot(v,-3);
+ sq_poptop(v); // Remove hclass.
+} // RegisterInstanceVarArgs
+
+#ifdef _MSC_VER
+#pragma warning(default : 4995)
+#endif
+
+// === Call Squirrel Functions from C/C++ ===
+// No type checking is performed for Squirrel functions as Squirrel types are dynamic:
+// Incoming types are passed unchanged to Squirrel functions. The parameter count is checked: an exception is thrown if mismatched.
+// Return values must match the RT template argument type, else an exception can be thrown on return.
+
+template<typename RT>
+struct SquirrelFunction {
+ HSQUIRRELVM v;
+ SquirrelObject object; // Table or class.
+ SquirrelObject func;
+ SquirrelFunction() : v(0) {}
+ SquirrelFunction(HSQUIRRELVM _v,const SquirrelObject & _object,const SquirrelObject & _func) : v(_v), object(_object), func(_func) {}
+ SquirrelFunction(const SquirrelObject & _object,const SquirrelObject & _func) : v(SquirrelVM::GetVMPtr()), object(_object), func(_func) {}
+ SquirrelFunction(const SquirrelObject & _object,const SQChar * name) {
+ v = SquirrelVM::GetVMPtr();
+ object = _object;
+ func = object.GetValue(name);
+ }
+ SquirrelFunction(const SQChar * name) {
+ v = SquirrelVM::GetVMPtr();
+ object = SquirrelVM::GetRootTable();
+ func = object.GetValue(name);
+ }
+
+ // Release references and reset internal objects to null.
+ void reset(void) {
+ func.Reset();
+ object.Reset();
+ } // Reset
+
+#define SQPLUS_CHECK_FNCALL(res) if (!SQ_SUCCEEDED(res)) throw SquirrelError(_SC("SquirrelFunction<> call failed"))
+
+ RT operator()(void) {
+ sq_pushobject(v,func.GetObjectHandle());
+ sq_pushobject(v,object.GetObjectHandle());
+ SQPLUS_CHECK_FNCALL(sq_call(v,1,SQTrue,SQ_CALL_RAISE_ERROR));
+ return GetRet(TypeWrapper<RT>(),v,-1);
+ }
+
+ template<typename P1>
+ RT operator()(P1 p1) {
+ sq_pushobject(v,func.GetObjectHandle());
+ sq_pushobject(v,object.GetObjectHandle());
+ Push(v,p1);
+ SQPLUS_CHECK_FNCALL(sq_call(v,2,SQTrue,SQ_CALL_RAISE_ERROR));
+ return GetRet(TypeWrapper<RT>(),v,-1);
+ }
+
+ template<typename P1,typename P2>
+ RT operator()(P1 p1,P2 p2) {
+ sq_pushobject(v,func.GetObjectHandle());
+ sq_pushobject(v,object.GetObjectHandle());
+ Push(v,p1);
+ Push(v,p2);
+ SQPLUS_CHECK_FNCALL(sq_call(v,3,SQTrue,SQ_CALL_RAISE_ERROR));
+ return GetRet(TypeWrapper<RT>(),v,-1);
+ }
+
+ template<typename P1,typename P2,typename P3>
+ RT operator()(P1 p1,P2 p2,P3 p3) {
+ sq_pushobject(v,func.GetObjectHandle());
+ sq_pushobject(v,object.GetObjectHandle());
+ Push(v,p1);
+ Push(v,p2);
+ Push(v,p3);
+ SQPLUS_CHECK_FNCALL(sq_call(v,4,SQTrue,SQ_CALL_RAISE_ERROR));
+ return GetRet(TypeWrapper<RT>(),v,-1);
+ }
+
+ template<typename P1,typename P2,typename P3,typename P4>
+ RT operator()(P1 p1,P2 p2,P3 p3,P4 p4) {
+ sq_pushobject(v,func.GetObjectHandle());
+ sq_pushobject(v,object.GetObjectHandle());
+ Push(v,p1);
+ Push(v,p2);
+ Push(v,p3);
+ Push(v,p4);
+ SQPLUS_CHECK_FNCALL(sq_call(v,5,SQTrue,SQ_CALL_RAISE_ERROR));
+ return GetRet(TypeWrapper<RT>(),v,-1);
+ }
+
+ template<typename P1,typename P2,typename P3,typename P4,typename P5>
+ RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5) {
+ sq_pushobject(v,func.GetObjectHandle());
+ sq_pushobject(v,object.GetObjectHandle());
+ Push(v,p1);
+ Push(v,p2);
+ Push(v,p3);
+ Push(v,p4);
+ Push(v,p5);
+ SQPLUS_CHECK_FNCALL(sq_call(v,6,SQTrue,SQ_CALL_RAISE_ERROR));
+ return GetRet(TypeWrapper<RT>(),v,-1);
+ }
+
+ template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6>
+ RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6) {
+ sq_pushobject(v,func.GetObjectHandle());
+ sq_pushobject(v,object.GetObjectHandle());
+ Push(v,p1);
+ Push(v,p2);
+ Push(v,p3);
+ Push(v,p4);
+ Push(v,p5);
+ Push(v,p6);
+ SQPLUS_CHECK_FNCALL(sq_call(v,7,SQTrue,SQ_CALL_RAISE_ERROR));
+ return GetRet(TypeWrapper<RT>(),v,-1);
+ }
+
+ template<typename P1,typename P2,typename P3,typename P4,typename P5,typename P6,typename P7>
+ RT operator()(P1 p1,P2 p2,P3 p3,P4 p4,P5 p5,P6 p6,P7 p7) {
+ sq_pushobject(v,func.GetObjectHandle());
+ sq_pushobject(v,object.GetObjectHandle());
+ Push(v,p1);
+ Push(v,p2);
+ Push(v,p3);
+ Push(v,p4);
+ Push(v,p5);
+ Push(v,p6);
+ Push(v,p7);
+ SQPLUS_CHECK_FNCALL(sq_call(v,8,SQTrue,SQ_CALL_RAISE_ERROR));
+ return GetRet(TypeWrapper<RT>(),v,-1);
+ }
+
+};
+
+// === Class/Struct registration ===
+
+#define SQ_DELETE_CLASS(CLASSTYPE) if (up) { CLASSTYPE * self = (CLASSTYPE *)up; delete self;} return 0
+#define SQ_DECLARE_RELEASE(CLASSTYPE) \
+ static int release(SQUserPointer up,SQInteger size) { \
+ SQ_DELETE_CLASS(CLASSTYPE); \
+ }
+
+template<typename T>
+struct ReleaseClassPtrPtr {
+ static int release(SQUserPointer up,SQInteger size) {
+ if (up) {
+ T ** self = (T **)up;
+ delete *self;
+ } // if
+ return 0;
+ } // release
+};
+
+template<typename T>
+struct ReleaseClassPtr {
+ static int release(SQUserPointer up,SQInteger size) {
+ if (up) {
+ T * self = (T *)up;
+ delete self;
+ } // if
+ return 0;
+ } // release
+};
+
+BOOL CreateClass(HSQUIRRELVM v,SquirrelObject & newClass,SQUserPointer classType,const SQChar * name,const SQChar * baseName=0);
+
+
+template<typename T>
+inline void PopulateAncestry(HSQUIRRELVM v,
+ SquirrelObject &instance,
+ T *newClass)
+{
+ // 11/2/05: Create a new table for this instance.
+ SquirrelObject newObjectTable = SquirrelVM::CreateTable();
+ // <TODO> 64-bit compatible version.
+ newObjectTable.SetUserPointer(INT((size_t)ClassType<T>::type()), newClass);
+ instance.SetValue(SQ_CLASS_OBJECT_TABLE_NAME, newObjectTable);
+
+ SquirrelObject classHierArray = instance.GetValue(SQ_CLASS_HIER_ARRAY);
+ INT count = classHierArray.Len();
+
+ // This will be true when more than one C/C++ class is in the hierarchy.
+ if (count > 1) {
+ --count; // Skip the most-derived class.
+ for (INT i = 0; i < count; i++) {
+ // Kamaitati's changes for C++ inheritance support. jcs 5/28/06
+ SquirrelObject so = classHierArray.GetValue(i);
+ sq_pushobject(v,so.GetObjectHandle());
+ SQUserPointer typeTag;
+ sq_gettypetag(v,-1,&typeTag);
+ newObjectTable.SetUserPointer(INT(size_t(typeTag)),newClass);
+ sq_poptop(v);
+ }
+ }
+}
+
+
+// Call PostConstruct() at the end of custom constructors.
+template<typename T>
+inline int PostConstruct(HSQUIRRELVM v, T *newClass, SQRELEASEHOOK hook)
+{
+#ifdef SQ_USE_CLASS_INHERITANCE
+ StackHandler sa(v);
+ HSQOBJECT ho = sa.GetObjectHandle(1); // OT_INSTANCE
+ SquirrelObject instance(ho);
+ PopulateAncestry(v, instance, newClass);
+#endif // SQ_USE_CLASS_INHERITANCE
+
+ sq_setinstanceup(v, 1, newClass);
+ sq_setreleasehook(v, 1, hook);
+ return TRUE;
+} // PostConstruct
+
+inline int PostConstructSimple(HSQUIRRELVM v, void *newClass, SQRELEASEHOOK hook){
+ sq_setinstanceup(v, 1, newClass);
+ sq_setreleasehook(v, 1, hook);
+ return TRUE;
+} // PostConstructSimple
+
+
+template<typename T>
+struct ConstructReleaseClass {
+ static int construct(HSQUIRRELVM v) {
+ return PostConstruct<T>(v,new T(),release);
+ } // construct
+ SQ_DECLARE_RELEASE(T)
+};
+
+# ifdef SQPLUS_ENABLE_TYPEOF
+template<typename T>
+int sq_typeof(HSQUIRRELVM v) {
+ sq_pushstring(v,TypeInfo<T>().typeName,-1);
+ return 1;
+}
+# endif
+
+// === Helper for RegisterClassType*() ===
+inline void setupClassHierarchy(SquirrelObject newClass) {
+ // <NOTE> New member vars cannot be added to instances (OT_INSTANCE): additions must occur on the defining class (OT_CLASS), before any instances are instantiated.
+ if (!newClass.Exists(SQ_CLASS_OBJECT_TABLE_NAME)) { // Will always get table from most-derived registered class.
+ SquirrelObject objectTable = SquirrelVM::CreateTable();
+ newClass.SetValue(SQ_CLASS_OBJECT_TABLE_NAME,objectTable); // Constructors must add their 'this' pointer indexed by type to this table. See PostConstruct() above.
+ // 11/2/05: This table will behave as a static global for each instance unless overwritten during construction (see PostConstruct() above).
+ } // if
+ SquirrelObject classHierArray;
+ if (!newClass.Exists(SQ_CLASS_HIER_ARRAY)) { // Will always get table from most-derived registered class.
+ classHierArray = SquirrelVM::CreateArray(0); // The only constructor called will be the most-derived class: this array contains all classes in the hierarchy to be constructed.
+ newClass.SetValue(SQ_CLASS_HIER_ARRAY,classHierArray);
+ } else {
+ classHierArray = newClass.GetValue(SQ_CLASS_HIER_ARRAY);
+ } // if
+ classHierArray.ArrayAppend(newClass); // Add the class to the hierarchy array. The array values will be released and replaced with UserData to free created ancestor classes.
+} // setupClassHierarchy
+
+
+template<typename T>
+inline SquirrelObject RegisterClassType(HSQUIRRELVM v,const SQChar * scriptClassName,const SQChar * baseScriptClassName=0) {
+ int top = sq_gettop(v);
+ SquirrelObject newClass;
+ if (CreateClass(v,newClass,(SQUserPointer)ClassType<T>::type(),scriptClassName,baseScriptClassName)) {
+ SquirrelVM::CreateFunction(newClass,&ConstructReleaseClass<T>::construct,_SC("constructor"));
+# ifdef SQ_USE_CLASS_INHERITANCE
+ setupClassHierarchy(newClass);
+# endif
+# ifdef SQPLUS_ENABLE_TYPEOF
+ SquirrelVM::CreateFunction(newClass,&sq_typeof<T>,_SC("_typeof"));
+# endif
+ } // if
+ sq_settop(v,top);
+ return newClass;
+} // RegisterClassType
+
+template<typename T>
+inline SquirrelObject RegisterClassTypeNoConstructor(HSQUIRRELVM v,const SQChar * scriptClassName,const SQChar * baseScriptClassName=0) {
+ int top = sq_gettop(v);
+ SquirrelObject newClass;
+ if (CreateClass(v,newClass,(SQUserPointer)ClassType<T>::type(),scriptClassName,baseScriptClassName)) {
+# ifdef SQ_USE_CLASS_INHERITANCE
+ setupClassHierarchy(newClass);
+# endif
+# ifdef SQPLUS_ENABLE_TYPEOF
+ SquirrelVM::CreateFunction(newClass,&sq_typeof<T>,_SC("_typeof"));
+# endif
+ } // if
+ sq_settop(v,top);
+ return newClass;
+} // RegisterClassTypeNoConstructor
+
+
+// === Define and register a C++ class and its members for use with Squirrel ===
+// Constructors+destructors are automatically created. Custom constructors must use the
+// standard SQFUNCTION signature if variable argument types are required (overloads).
+// See testSqPlus2.cpp for examples.
+
+// <NOTE> Do not use SQClassDefBase<> directly, use SQClassDef<> or SQClassDefNoConstructor<>, below.
+template<typename TClassType, typename TClassBase>
+struct SQClassDefBase {
+ HSQUIRRELVM v;
+ const SQChar * name;
+ SquirrelObject newClass;
+
+#if defined(SQ_USE_CLASS_INHERITANCE) || defined(SQ_USE_CLASS_INHERITANCE_SIMPLE)
+ const SQChar * base;
+ // Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM).
+ SQClassDefBase(HSQUIRRELVM _v,const SQChar * _name=0,const SQChar * _base=0) : v(_v), name(_name), base(_base) {InitBase();}
+ // Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM).
+ SQClassDefBase(const SQChar * _name=0,const SQChar * _base=0) : v(SquirrelVM::GetVMPtr()), name(_name), base(_base) {InitBase(TypeWrapper<TClassBase>());}
+ template<class Base>
+ void InitBase(TypeWrapper<Base>){ /*assert(base);*/ ClassType<TClassType>::Get()->SetBase(TypeWrapper<Base>()); CheckInitDefaultNames(); }
+ void InitBase(TypeWrapper<SQNoBaseClass>){ /*assert(!base);*/ CheckInitDefaultNames(); }
+ void CheckInitDefaultNames(){ if( !name ) name=TypeInfo<TClassType>().typeName; if( !base ) base=TypeInfo<TClassBase>().typeName; }
+#else
+ SQClassDefBase(HSQUIRRELVM _v,const SQChar * _name=0) : v(_v), name(_name) { CheckInitDefaultName(); }
+ SQClassDefBase(const SQChar * _name=0) : v(SquirrelVM::GetVMPtr()), name(_name) { CheckInitDefaultName(); }
+ void CheckInitDefaultName(){ if( !name ) name=TypeInfo<TClassType>().typeName; }
+#endif
+
+ // Register a member function.
+ template<typename Func>
+ SQClassDefBase & func(Func pfunc,const SQChar * name) {
+ RegisterInstance(v,newClass.GetObjectHandle(),*(TClassType *)0,pfunc,name);
+ return *this;
+ } // func
+
+ // Register a global function as a member function (the global takes a Callee*/& as first arg).
+ template<typename Func>
+ SQClassDefBase & globMembFunc(Func pfunc,const SQChar * name) {
+ RegisterInstanceGlobalFunc(v,newClass.GetObjectHandle(),*(TClassType *)0,pfunc,name);
+ return *this;
+ } // globMemberFunc
+
+ // Register a global function as a member function (the global takes a Callee*/& as first arg and SQVM* as 2nd).
+ template<typename Func>
+ SQClassDefBase & globMembFuncVarArgs(Func pfunc,const SQChar * name) {
+ RegisterInstanceGlobalFuncVarArgs(v,newClass.GetObjectHandle(),*(TClassType *)0,pfunc,name);
+ return *this;
+ } // globMemberFuncVarArgs
+
+#ifdef SQPLUS_SMARTPOINTER_OPT
+#define SQPLUS_SMARTPOINTER_CLASS_DEF_FUNC
+#include "SqPlusSmartPointer.h"
+#endif
+
+ // Register a variable-argument member function (supports variable+multiple return values).
+ // typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case).
+ // All the other Squirrel type-masks are passed normally.
+ template<typename Func>
+ SQClassDefBase & funcVarArgs(Func pfunc,const SQChar * name,const SQChar * typeMask=_SC("*")) {
+ RegisterInstanceVarArgs(v,newClass.GetObjectHandle(),*(TClassType *)0,pfunc,name,typeMask);
+ return *this;
+ } // funcVarArgs
+
+ // === BEGIN static-member+global function registration ===
+
+ // === This version is for static member functions only, such as custom constructors where 'this' is not yet valid ===
+ // typeMask: "*" means don't check parameters, typeMask=0 means function takes no arguments (and is type checked for that case).
+ // All the other Squirrel type-masks are passed normally.
+
+ template<typename Func>
+ SQClassDefBase & staticFuncVarArgs(Func pfunc,const SQChar * name,const SQChar * typeMask=_SC("*")) {
+ SquirrelVM::PushObject(newClass);
+ SquirrelVM::CreateFunction(pfunc,name,typeMask);
+ SquirrelVM::Pop(1);
+ return *this;
+ } // staticFuncVarArgs
+
+ // Register a standard global function (effectively embedding a global function in TClassType's script namespace: does not need or use a 'this' pointer).
+ template<typename Func>
+ SQClassDefBase & staticFunc(Func pfunc,const SQChar * name) {
+ Register(v,newClass.GetObjectHandle(),pfunc,name);
+ return *this;
+ } // staticFunc
+
+ // Register a function to a pre-allocated class/struct member function: will use callee's 'this' (effectively embedding a global function in TClassType's script namespace).
+ template<typename Callee,typename Func>
+ SQClassDefBase & staticFunc(Callee & callee,Func pfunc,const SQChar * name) {
+ Register(v,newClass.GetObjectHandle(),callee,pfunc,name);
+ return *this;
+ } // staticFunc
+
+ // === END static+global function registration ===
+
+ // Register a member variable.
+ template<typename VarType>
+ SQClassDefBase & var(VarType TClassType::* pvar,const SQChar * name,VarAccessType access=VAR_ACCESS_READ_WRITE) {
+ struct CV {
+ VarType TClassType::* var;
+ } cv; // Cast Variable helper.
+ cv.var = pvar;
+ RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(VarType **)&cv,name,access);
+ return *this;
+ } // var
+
+ // Register a member variable as a UserPointer (read only).
+ template<typename VarType>
+ SQClassDefBase & varAsUserPointer(VarType TClassType::* pvar,const SQChar * name) {
+ struct CV {
+ VarType TClassType::* var;
+ } cv; // Cast Variable helper.
+ cv.var = pvar;
+ RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(SQAnything **)&cv,name,VAR_ACCESS_READ_ONLY);
+ return *this;
+ } // varAsUserPointer
+
+#ifdef SQPLUS_SMARTPOINTER_OPT
+#define SQPLUS_SMARTPOINTER_CLASS_DEF_VAR
+#include "SqPlusSmartPointer.h"
+#endif
+
+ template<typename VarType>
+ SQClassDefBase & staticVar(VarType * pvar,const SQChar * name,VarAccessType access=VAR_ACCESS_READ_WRITE) {
+ struct CV {
+ VarType * var;
+ } cv; // Cast Variable helper.
+ cv.var = pvar;
+ RegisterInstanceVariable(newClass,ClassType<TClassType>::type(),*(VarType **)&cv,name,VarAccessType(access|VAR_ACCESS_STATIC));
+ return *this;
+ } // staticVar
+
+#ifdef SQPLUS_CONST_OPT
+#define SQ_REG_CONST_STATIC_VAR
+#include "SqPlusConst.h"
+#endif
+
+ // Member / static member script vars (ordinary Squirrel vars)
+ SQClassDefBase & scriptVar( const SQChar* name, int ival, SQBool static_var=SQFalse ) {
+ HSQUIRRELVM v = SquirrelVM::GetVMPtr();
+ sq_pushobject(v,newClass.GetObjectHandle());
+ sq_pushstring(v,name,-1);
+ sq_pushinteger(v,ival);
+ sq_newslot(v,-3,static_var);
+ sq_pop(v,1);
+ return *this;
+ }
+
+ SQClassDefBase & scriptVar( const SQChar* name, double fval, SQBool static_var=SQFalse ) {
+ HSQUIRRELVM v = SquirrelVM::GetVMPtr();
+ sq_pushobject(v,newClass.GetObjectHandle());
+ sq_pushstring(v,name,-1);
+ sq_pushfloat(v,fval);
+ sq_newslot(v,-3,static_var);
+ sq_pop(v,1);
+ return *this;
+ }
+
+ SQClassDefBase & scriptVar( const SQChar* name, const SQChar* sval, SQBool static_var=SQFalse ) {
+ HSQUIRRELVM v = SquirrelVM::GetVMPtr();
+ sq_pushobject(v,newClass.GetObjectHandle());
+ sq_pushstring(v,name,-1);
+ sq_pushstring(v,sval,-1);
+ sq_newslot(v,-3,static_var);
+ sq_pop(v,1);
+ return *this;
+ }
+
+ // Register a constant (read-only in script, passed by value (only INT, FLOAT, or BOOL types)).
+ template<typename ConstantType>
+ SQClassDefBase & constant(ConstantType constant,const SQChar * name) {
+ RegisterInstanceConstant(newClass,ClassType<TClassType>::type(),constant,name);
+ return *this;
+ } // constant
+
+ // Register an enum as an integer (read-only in script).
+ SQClassDefBase & enumInt(int constant,const SQChar * name) {
+ RegisterInstanceConstant(newClass,ClassType<TClassType>::type(),constant,name);
+ return *this;
+ } // enumInt
+
+#ifdef SQPLUS_OVERLOAD_OPT
+#define SQPLUS_OVERLOAD_IMPLEMENTATION
+#include "SqPlusOverload.h"
+#endif
+};
+
+#ifdef SQPLUS_OVERLOAD_OPT
+#define SQPLUS_OVERLOAD_FUNCTIONS
+#include "SqPlusOverload.h"
+#endif
+
+template<typename TClassType, typename TClassBase=SQNoBaseClass>
+struct SQClassDef : public SQClassDefBase<TClassType,TClassBase> {
+
+#if defined(SQ_USE_CLASS_INHERITANCE) || defined(SQ_USE_CLASS_INHERITANCE_SIMPLE)
+ // Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM).
+ SQClassDef(HSQUIRRELVM _v,const SQChar * _name=0,const SQChar * _base=0) : SQClassDefBase<TClassType,TClassBase>(_v,_name,_base) {
+ SQClassDefBase<TClassType,TClassBase>::newClass =
+ RegisterClassType<TClassType>( SQClassDefBase<TClassType,TClassBase>::v,
+ SQClassDefBase<TClassType,TClassBase>::name,
+ SQClassDefBase<TClassType,TClassBase>::base );
+ }
+ // Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM).
+ SQClassDef(const SQChar * _name=0,const SQChar * _base=0) : SQClassDefBase<TClassType,TClassBase>(_name,_base) {
+ SQClassDefBase<TClassType,TClassBase>::newClass =
+ RegisterClassType< TClassType>( SQClassDefBase<TClassType,TClassBase>::v,
+ SQClassDefBase<TClassType,TClassBase>::name,
+ SQClassDefBase<TClassType,TClassBase>::base );
+ }
+#else
+ SQClassDef(HSQUIRRELVM _v,const SQChar * _name=0) : SQClassDefBase<TClassType,TClassBase>(_v,_name) {
+ SQClassDefBase<TClassType,TClassBase>::newClass =
+ RegisterClassType<TClassType>(SQClassDefBase<TClassType,TClassBase>::v,
+ SQClassDefBase<TClassType,TClassBase>::name );
+ }
+ SQClassDef(const SQChar * _name=0) : SQClassDefBase<TClassType,TClassBase>(_name) {
+ SQClassDefBase<TClassType,TClassBase>::newClass =
+ RegisterClassType<TClassType>(SQClassDefBase<TClassType,TClassBase>::v,
+ SQClassDefBase<TClassType,TClassBase>::name );
+ }
+#endif
+};
+
+template<typename TClassType, typename TClassBase=SQNoBaseClass>
+struct SQClassDefNoConstructor : public SQClassDefBase<TClassType,TClassBase> {
+#if defined(SQ_USE_CLASS_INHERITANCE) || defined(SQ_USE_CLASS_INHERITANCE_SIMPLE)
+ // Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM).
+ SQClassDefNoConstructor(HSQUIRRELVM _v,const SQChar * _name=0,const SQChar * _base=0) : SQClassDefBase<TClassType,TClassBase>(_v,_name,_base) {
+ SQClassDefBase<TClassType,TClassBase>::newClass = RegisterClassTypeNoConstructor<TClassType>(SQClassDefBase<TClassType,TClassBase>::v,SQClassDefBase<TClassType,TClassBase>::name,SQClassDefBase<TClassType,TClassBase>::base);
+ }
+ // Optional base arg is the name of a base class to inherit from (must already be defined in the Squirrel VM).
+ SQClassDefNoConstructor(const SQChar * _name=0,const SQChar * _base=0) : SQClassDefBase<TClassType,TClassBase>(_name,_base) {
+ SQClassDefBase<TClassType,TClassBase>::newClass = RegisterClassTypeNoConstructor<TClassType>(SQClassDefBase<TClassType,TClassBase>::v,SQClassDefBase<TClassType,TClassBase>::name,SQClassDefBase<TClassType,TClassBase>::base);
+ }
+#else
+ SQClassDefNoConstructor(HSQUIRRELVM _v,const SQChar * _name=0) : SQClassDefBase<TClassType,TClassBase>(_v,_name) {
+ SQClassDefBase<TClassType,TClassBase>::newClass = RegisterClassTypeNoConstructor<TClassType>(SQClassDefBase<TClassType,TClassBase>::v,SQClassDefBase<TClassType,TClassBase>::name);
+ }
+ SQClassDefNoConstructor(const SQChar * _name=0) : SQClassDefBase<TClassType,TClassBase>(_name) {
+ SQClassDefBase<TClassType,TClassBase>::newClass = RegisterClassTypeNoConstructor<TClassType>(SQClassDefBase<TClassType,TClassBase>::v,SQClassDefBase<TClassType,TClassBase>::name);
+ }
+#endif
+};
+
+
+// === Macros for old style registration. SQClassDef registration is now easier to use (SQ_DECLARE_CLASS() is not needed) ===
+
+#define SQ_DECLARE_CLASS(CLASSNAME) \
+static int _##CLASSNAME##_release(SQUserPointer up,SQInteger size) { \
+ if (up) { \
+ CLASSNAME * self = (CLASSNAME *)up; \
+ delete self; \
+ } \
+ return 0; \
+} \
+static int _##CLASSNAME##_constructor(HSQUIRRELVM v) { \
+ CLASSNAME * pc = new CLASSNAME(); \
+ sq_setinstanceup(v,1,pc); \
+ sq_setreleasehook(v,1,_##CLASSNAME##_release); \
+ return 1; \
+}
+
+#define SQ_REGISTER_CLASS(CLASSNAME) \
+ RegisterClassType(SquirrelVM::GetVMPtr(),_SC(#CLASSNAME),_##CLASSNAME##_constructor)
+
+#define SQ_REGISTER_INSTANCE(NEWSQCLASS,CCLASS,FUNCNAME) \
+ RegisterInstance(SquirrelVM::GetVMPtr(),NEWSQCLASS.GetObjectHandle(),*(CCLASS *)0,&CCLASS::FUNCNAME,_SC(#FUNCNAME));
+
+#define SQ_REGISTER_INSTANCE_VARARGS(NEWSQCLASS,CCLASS,FUNCNAME) \
+ RegisterInstanceVarArgs(SquirrelVM::GetVMPtr(),NEWSQCLASS.GetObjectHandle(),*(CCLASS *)0,&CCLASS::FUNCNAME,_SC(#FUNCNAME));
+
+#define SQ_REGISTER_INSTANCE_VARIABLE(NEWSQCLASS,CCLASS,VARNAME) \
+ RegisterInstanceVariable(NEWSQCLASS,&((CCLASS *)0)->VARNAME,_SC(#VARNAME));
+
+#if defined(USE_ARGUMENT_DEPENDANT_OVERLOADS) && defined(_MSC_VER)
+#pragma warning (default:4675)
+#endif
+
+}; // namespace SqPlus
+
+
+// === BEGIN code suggestion from the Wiki ===
+
+// Get any bound type from this SquirrelObject. Note that Squirrel's
+// handling of references and pointers still holds here.
+template<typename _ty>
+inline _ty SquirrelObject::Get(void) {
+ sq_pushobject(SquirrelVM::_VM,GetObjectHandle());
+ _ty val = SqPlus::Get(SqPlus::TypeWrapper<_ty>(),SquirrelVM::_VM,-1);
+ sq_poptop(SquirrelVM::_VM);
+ return val;
+}
+
+// Set any bound type to this SquirrelObject. Note that Squirrel's
+// handling of references and pointers still holds here.
+template<typename _ty>
+inline SquirrelObject SquirrelObject::SetByValue(_ty val) { // classes/structs should be passed by ref (below) to avoid an extra copy.
+ SqPlus::Push(SquirrelVM::_VM,val);
+ AttachToStackObject(-1);
+ sq_poptop(SquirrelVM::_VM);
+ return *this;
+}
+
+// Set any bound type to this SquirrelObject. Note that Squirrel's
+// handling of references and pointers still holds here.
+template<typename _ty>
+inline SquirrelObject &SquirrelObject::Set(_ty & val) {
+ SqPlus::Push(SquirrelVM::_VM,val);
+ AttachToStackObject(-1);
+ sq_poptop(SquirrelVM::_VM);
+ return *this;
+}
+
+// === END code suggestion from the Wiki ===
+
+#endif //_SQ_PLUS_H_
diff --git a/squirrel_3_0_1_stable/sqplus/sqplus.vcproj b/squirrel_3_0_1_stable/sqplus/sqplus.vcproj
new file mode 100644
index 000000000..fdc22e06b
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/sqplus.vcproj
@@ -0,0 +1,355 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="sqplus"
+ ProjectGUID="{F9811314-C694-49A4-BD87-BA2E7F30D358}"
+ RootNamespace="sqplus"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../lib/sqplusD.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../lib/sqplus.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Debug - Unicode|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../lib/sqplusDU.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release - Unicode|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../lib/sqplusU.lib"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\SqPlus.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SqPlusOCharBuf.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SqPlusUtf8.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SquirrelBindingsUtils.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SquirrelBindingsUtilsWin32.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SquirrelObject.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\SquirrelVM.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\sqplus.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SqPlusConst.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SqPlusOCharBuf.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SqPlusSetup.h"
+ >
+ </File>
+ <File
+ RelativePath=".\sqplusWin32.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SquirrelBindingsUtils.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SquirrelBindingsUtilsWin32.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SquirrelObject.h"
+ >
+ </File>
+ <File
+ RelativePath=".\SquirrelVM.h"
+ >
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/squirrel_3_0_1_stable/sqplus/sqplus.vcxproj b/squirrel_3_0_1_stable/sqplus/sqplus.vcxproj
new file mode 100644
index 000000000..fca6ce402
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/sqplus.vcxproj
@@ -0,0 +1,159 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup Label="ProjectConfigurations">
+ <ProjectConfiguration Include="Debug - Unicode|Win32">
+ <Configuration>Debug - Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Debug|Win32">
+ <Configuration>Debug</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release - Unicode|Win32">
+ <Configuration>Release - Unicode</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ <ProjectConfiguration Include="Release|Win32">
+ <Configuration>Release</Configuration>
+ <Platform>Win32</Platform>
+ </ProjectConfiguration>
+ </ItemGroup>
+ <PropertyGroup Label="Globals">
+ <ProjectGuid>{F9811314-C694-49A4-BD87-BA2E7F30D358}</ProjectGuid>
+ <RootNamespace>sqplus</RootNamespace>
+ <Keyword>Win32Proj</Keyword>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release - Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug - Unicode|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>Unicode</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
+ <ConfigurationType>StaticLibrary</ConfigurationType>
+ <CharacterSet>MultiByte</CharacterSet>
+ </PropertyGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
+ <ImportGroup Label="ExtensionSettings">
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release - Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug - Unicode|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
+ <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
+ <Import Project="$(VCTargetsPath)Microsoft.CPP.UpgradeFromVC71.props" />
+ </ImportGroup>
+ <PropertyGroup Label="UserMacros" />
+ <PropertyGroup>
+ <_ProjectFileVersion>10.0.30319.1</_ProjectFileVersion>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Configuration)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Configuration)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Debug - Unicode|Win32'">$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Debug - Unicode|Win32'">$(Configuration)\</IntDir>
+ <OutDir Condition="'$(Configuration)|$(Platform)'=='Release - Unicode|Win32'">$(Configuration)\</OutDir>
+ <IntDir Condition="'$(Configuration)|$(Platform)'=='Release - Unicode|Win32'">$(Configuration)\</IntDir>
+ </PropertyGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Lib>
+ <OutputFile>../lib/sqplusD.lib</OutputFile>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Lib>
+ <OutputFile>../lib/sqplus.lib</OutputFile>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug - Unicode|Win32'">
+ <ClCompile>
+ <Optimization>Disabled</Optimization>
+ <AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;_DEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <MinimalRebuild>true</MinimalRebuild>
+ <BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
+ <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>EditAndContinue</DebugInformationFormat>
+ </ClCompile>
+ <Lib>
+ <OutputFile>../lib/sqplusDU.lib</OutputFile>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release - Unicode|Win32'">
+ <ClCompile>
+ <AdditionalIncludeDirectories>..\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
+ <PreprocessorDefinitions>WIN32;NDEBUG;_LIB;_CRT_SECURE_NO_DEPRECATE;_CRT_NON_CONFORMING_SWPRINTFS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
+ <RuntimeLibrary>MultiThreaded</RuntimeLibrary>
+ <PrecompiledHeader>
+ </PrecompiledHeader>
+ <WarningLevel>Level3</WarningLevel>
+ <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
+ </ClCompile>
+ <Lib>
+ <OutputFile>../lib/sqplusU.lib</OutputFile>
+ </Lib>
+ </ItemDefinitionGroup>
+ <ItemGroup>
+ <ClCompile Include="SqPlus.cpp" />
+ <ClCompile Include="SqPlusOCharBuf.cpp" />
+ <ClCompile Include="SqPlusUtf8.cpp" />
+ <ClCompile Include="SquirrelBindingsUtils.cpp" />
+ <ClCompile Include="SquirrelBindingsUtilsWin32.cpp" />
+ <ClCompile Include="SquirrelObject.cpp" />
+ <ClCompile Include="SquirrelVM.cpp" />
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="sqplus.h" />
+ <ClInclude Include="SqPlusConst.h" />
+ <ClInclude Include="SqPlusOCharBuf.h" />
+ <ClInclude Include="SqPlusSetup.h" />
+ <ClInclude Include="sqplusWin32.h" />
+ <ClInclude Include="SquirrelBindingsUtils.h" />
+ <ClInclude Include="SquirrelBindingsUtilsWin32.h" />
+ <ClInclude Include="SquirrelObject.h" />
+ <ClInclude Include="SquirrelVM.h" />
+ </ItemGroup>
+ <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
+ <ImportGroup Label="ExtensionTargets">
+ </ImportGroup>
+</Project> \ No newline at end of file
diff --git a/squirrel_3_0_1_stable/sqplus/sqplus.vcxproj.filters b/squirrel_3_0_1_stable/sqplus/sqplus.vcxproj.filters
new file mode 100644
index 000000000..a61b1ca90
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/sqplus.vcxproj.filters
@@ -0,0 +1,65 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <ItemGroup>
+ <Filter Include="Source Files">
+ <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
+ <Extensions>cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
+ </Filter>
+ <Filter Include="Header Files">
+ <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
+ <Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
+ </Filter>
+ </ItemGroup>
+ <ItemGroup>
+ <ClCompile Include="SqPlus.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SqPlusOCharBuf.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SqPlusUtf8.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SquirrelBindingsUtils.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SquirrelBindingsUtilsWin32.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SquirrelObject.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ <ClCompile Include="SquirrelVM.cpp">
+ <Filter>Source Files</Filter>
+ </ClCompile>
+ </ItemGroup>
+ <ItemGroup>
+ <ClInclude Include="sqplus.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="SqPlusConst.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="SqPlusOCharBuf.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="SqPlusSetup.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="sqplusWin32.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="SquirrelBindingsUtils.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="SquirrelBindingsUtilsWin32.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="SquirrelObject.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ <ClInclude Include="SquirrelVM.h">
+ <Filter>Header Files</Filter>
+ </ClInclude>
+ </ItemGroup>
+</Project> \ No newline at end of file
diff --git a/squirrel_3_0_1_stable/sqplus/sqplus.vcxproj.user b/squirrel_3_0_1_stable/sqplus/sqplus.vcxproj.user
new file mode 100644
index 000000000..695b5c78b
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/sqplus.vcxproj.user
@@ -0,0 +1,3 @@
+<?xml version="1.0" encoding="utf-8"?>
+<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+</Project> \ No newline at end of file
diff --git a/squirrel_3_0_1_stable/sqplus/sqplus71.vcproj b/squirrel_3_0_1_stable/sqplus/sqplus71.vcproj
new file mode 100644
index 000000000..fc3ac5555
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/sqplus71.vcproj
@@ -0,0 +1,235 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="7.10"
+ Name="sqplus"
+ ProjectGUID="{F9811314-C694-49A4-BD87-BA2E7F30D358}"
+ RootNamespace="sqplus"
+ Keyword="Win32Proj">
+ <Platforms>
+ <Platform
+ Name="Win32"/>
+ </Platforms>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../lib/sqplusD.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="2">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../lib/sqplus.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Debug - Unicode|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1">
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="WIN32;_DEBUG;_LIB"
+ MinimalRebuild="TRUE"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="4"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../lib/sqplusDU.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ <Configuration
+ Name="Release - Unicode|Win32"
+ OutputDirectory="$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="4"
+ CharacterSet="1">
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\include"
+ PreprocessorDefinitions="WIN32;NDEBUG;_LIB"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="TRUE"
+ DebugInformationFormat="3"/>
+ <Tool
+ Name="VCCustomBuildTool"/>
+ <Tool
+ Name="VCLibrarianTool"
+ OutputFile="../lib/sqplusU.lib"/>
+ <Tool
+ Name="VCMIDLTool"/>
+ <Tool
+ Name="VCPostBuildEventTool"/>
+ <Tool
+ Name="VCPreBuildEventTool"/>
+ <Tool
+ Name="VCPreLinkEventTool"/>
+ <Tool
+ Name="VCResourceCompilerTool"/>
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"/>
+ <Tool
+ Name="VCXMLDataGeneratorTool"/>
+ <Tool
+ Name="VCManagedWrapperGeneratorTool"/>
+ <Tool
+ Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
+ <File
+ RelativePath=".\SqPlus.cpp">
+ </File>
+ <File
+ RelativePath=".\SqPlusOCharBuf.cpp">
+ </File>
+ <File
+ RelativePath=".\SqPlusUtf8.cpp">
+ </File>
+ <File
+ RelativePath=".\SquirrelBindingsUtils.cpp">
+ </File>
+ <File
+ RelativePath=".\SquirrelBindingsUtilsWin32.cpp">
+ </File>
+ <File
+ RelativePath=".\SquirrelObject.cpp">
+ </File>
+ <File
+ RelativePath=".\SquirrelVM.cpp">
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
+ <File
+ RelativePath=".\sqplus.h">
+ </File>
+ <File
+ RelativePath=".\SqPlusConst.h">
+ </File>
+ <File
+ RelativePath=".\sqplusWin32.h">
+ </File>
+ <File
+ RelativePath=".\SquirrelBindingsUtils.h">
+ </File>
+ <File
+ RelativePath=".\SquirrelBindingsUtilsWin32.h">
+ </File>
+ <File
+ RelativePath=".\SquirrelObject.h">
+ </File>
+ <File
+ RelativePath=".\SquirrelVM.h">
+ </File>
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/squirrel_3_0_1_stable/sqplus/sqplusWin32.h b/squirrel_3_0_1_stable/sqplus/sqplusWin32.h
new file mode 100644
index 000000000..bf46fd6cf
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqplus/sqplusWin32.h
@@ -0,0 +1,7 @@
+#ifndef _SQ_PLUS_WIN32_H_
+#define _SQ_PLUS_WIN32_H_
+
+#include "sqplus.h"
+#include "SquirrelBindingsUtilsWin32.h"
+
+#endif //_SQ_PLUS_WIN32_H_ \ No newline at end of file
diff --git a/squirrel_3_0_1_stable/sqstdlib/Makefile b/squirrel_3_0_1_stable/sqstdlib/Makefile
new file mode 100644
index 000000000..10f6384ea
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqstdlib/Makefile
@@ -0,0 +1,41 @@
+SQUIRREL= ..
+
+
+OUT= $(SQUIRREL)/lib/libsqstdlib.a
+INCZ= -I$(SQUIRREL)/include -I. -Iinclude
+
+OBJS= \
+ sqstdblob.o \
+ sqstdio.o \
+ sqstdstream.o \
+ sqstdmath.o \
+ sqstdsystem.o \
+ sqstdstring.o \
+ sqstdaux.o \
+ sqstdrex.o
+
+SRCS= \
+ sqstdblob.cpp \
+ sqstdio.cpp \
+ sqstdstream.cpp \
+ sqstdmath.cpp \
+ sqstdsystem.cpp \
+ sqstdstring.cpp \
+ sqstdaux.cpp \
+ sqstdrex.cpp
+
+
+sq32:
+ gcc -O2 -fno-exceptions -fno-rtti -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ)
+ ar rc $(OUT) *.o
+ rm *.o
+
+sqprof:
+ gcc -O2 -pg -fno-exceptions -fno-rtti -pie -gstabs -g3 -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ)
+ ar rc $(OUT) *.o
+ rm *.o
+
+sq64:
+ gcc -O2 -m64 -fno-exceptions -D_SQ64 -fno-rtti -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ)
+ ar rc $(OUT) *.o
+ rm *.o
diff --git a/squirrel_3_0_1_stable/sqstdlib/sqstdaux.cpp b/squirrel_3_0_1_stable/sqstdlib/sqstdaux.cpp
new file mode 100644
index 000000000..e115770a8
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqstdlib/sqstdaux.cpp
@@ -0,0 +1,129 @@
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <sqstdaux.h>
+#include <assert.h>
+
+void sqstd_printcallstack(HSQUIRRELVM v)
+{
+ SQPRINTFUNCTION pf = sq_geterrorfunc(v);
+ if(pf) {
+ SQStackInfos si;
+ SQInteger i;
+ 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_getinteger(v,-1,&i);
+ pf(v,_SC("[%s] %s\n"),name,i?_SC("true"):_SC("false"));
+ }
+ break;
+ default: assert(0); break;
+ }
+ sq_pop(v,1);
+ }
+ }
+ }
+}
+
+static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v)
+{
+ SQPRINTFUNCTION pf = sq_geterrorfunc(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_geterrorfunc(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);
+}
diff --git a/squirrel_3_0_1_stable/sqstdlib/sqstdblob.cpp b/squirrel_3_0_1_stable/sqstdlib/sqstdblob.cpp
new file mode 100644
index 000000000..11b593306
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqstdlib/sqstdblob.cpp
@@ -0,0 +1,275 @@
+/* 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;
+ self->~SQBlob();
+ sq_free(self,sizeof(SQBlob));
+ 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);
+
+ SQBlob *b = new (sq_malloc(sizeof(SQBlob)))SQBlob(size);
+ if(SQ_FAILED(sq_setinstanceup(v,1,b))) {
+ b->~SQBlob();
+ sq_free(b,sizeof(SQBlob));
+ return sq_throwerror(v, _SC("cannot create blob"));
+ }
+ sq_setreleasehook(v,1,_blob_releasehook);
+ return 0;
+}
+
+static SQInteger _blob__cloned(HSQUIRRELVM v)
+{
+ SQBlob *other = NULL;
+ {
+ if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
+ return SQ_ERROR;
+ }
+ //SQBlob *thisone = new SQBlob(other->Len());
+ SQBlob *thisone = new (sq_malloc(sizeof(SQBlob)))SQBlob(other->Len());
+ memcpy(thisone->GetBuf(),other->GetBuf(),thisone->Len());
+ if(SQ_FAILED(sq_setinstanceup(v,1,thisone))) {
+ thisone->~SQBlob();
+ sq_free(thisone,sizeof(SQBlob));
+ return sq_throwerror(v, _SC("cannot clone blob"));
+ }
+ 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")),
+ _DECL_BLOB_FUNC(_cloned,2,_SC("xx")),
+ {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);
+}
+
diff --git a/squirrel_3_0_1_stable/sqstdlib/sqstdblobimpl.h b/squirrel_3_0_1_stable/sqstdlib/sqstdblobimpl.h
new file mode 100644
index 000000000..b2291b73c
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqstdlib/sqstdblobimpl.h
@@ -0,0 +1,108 @@
+/* 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_
diff --git a/squirrel_3_0_1_stable/sqstdlib/sqstdio.cpp b/squirrel_3_0_1_stable/sqstdlib/sqstdio.cpp
new file mode 100644
index 000000000..241864bb2
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqstdlib/sqstdio.cpp
@@ -0,0 +1,419 @@
+/* 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;
+ self->~SQFile();
+ sq_free(self,sizeof(SQFile));
+ 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 (sq_malloc(sizeof(SQFile)))SQFile(newf,owns);
+ if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
+ f->~SQFile();
+ sq_free(f,sizeof(SQFile));
+ 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_PLAIN(SQUserPointer file)
+{
+ SQInteger ret;
+ char c;
+ if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) )
+ return c;
+ return 0;
+}
+
+#ifdef SQUNICODE
+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;
+}
+#endif
+
+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_PLAIN;
+ 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"));
+ }
+#ifdef SQUNICODE
+ func = _io_file_lexfeed_UTF8;
+#else
+ func = _io_file_lexfeed_PLAIN;
+#endif
+ 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_newslot(v,-3,SQFalse);
+ sq_pushstring(v,_SC("stdin"),-1);
+ sqstd_createfile(v,stdin,SQFalse);
+ sq_newslot(v,-3,SQFalse);
+ sq_pushstring(v,_SC("stderr"),-1);
+ sqstd_createfile(v,stderr,SQFalse);
+ sq_newslot(v,-3,SQFalse);
+ sq_settop(v,top);
+ return SQ_OK;
+}
diff --git a/squirrel_3_0_1_stable/sqstdlib/sqstdlib.dsp b/squirrel_3_0_1_stable/sqstdlib/sqstdlib.dsp
new file mode 100644
index 000000000..7453243fe
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqstdlib/sqstdlib.dsp
@@ -0,0 +1,131 @@
+# Microsoft Developer Studio Project File - Name="sqstdlib" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=sqstdlib - Win32 Release
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "sqstdlib.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "sqstdlib.mak" CFG="sqstdlib - Win32 Release"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "sqstdlib - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "sqstdlib - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "sqstdlib - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD BASE RSC /l 0x410 /d "NDEBUG"
+# ADD RSC /l 0x410 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"
+
+!ELSEIF "$(CFG)" == "sqstdlib - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x410 /d "_DEBUG"
+# ADD RSC /l 0x410 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\sqstdlib.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "sqstdlib - Win32 Release"
+# Name "sqstdlib - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\sqstdblob.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdio.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdmath.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdrex.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdstream.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdstring.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdaux.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdsystem.cpp
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\sqstdblobimpl.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstdstream.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/squirrel_3_0_1_stable/sqstdlib/sqstdmath.cpp b/squirrel_3_0_1_stable/sqstdlib/sqstdmath.cpp
new file mode 100644
index 000000000..ef50359bd
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqstdlib/sqstdmath.cpp
@@ -0,0 +1,107 @@
+/* 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},
+};
+#undef _DECL_FUNC
+
+#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_newslot(v,-3,SQFalse);
+ i++;
+ }
+ sq_pushstring(v,_SC("RAND_MAX"),-1);
+ sq_pushinteger(v,RAND_MAX);
+ sq_newslot(v,-3,SQFalse);
+ sq_pushstring(v,_SC("PI"),-1);
+ sq_pushfloat(v,(SQFloat)M_PI);
+ sq_newslot(v,-3,SQFalse);
+ return SQ_OK;
+}
diff --git a/squirrel_3_0_1_stable/sqstdlib/sqstdrex.cpp b/squirrel_3_0_1_stable/sqstdlib/sqstdrex.cpp
new file mode 100644
index 000000000..921597fed
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqstdlib/sqstdrex.cpp
@@ -0,0 +1,638 @@
+/* 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(exp->_nodes[first].type>*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++;
+ }
+ int tempcap = 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]));
+
+ exp->_currsubexp = tempcap;
+ 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;
+}
+
diff --git a/squirrel_3_0_1_stable/sqstdlib/sqstdstream.cpp b/squirrel_3_0_1_stable/sqstdlib/sqstdstream.cpp
new file mode 100644
index 000000000..29fbdd601
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqstdlib/sqstdstream.cpp
@@ -0,0 +1,336 @@
+/* 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;
+}
+
+ SQInteger _stream__cloned(HSQUIRRELVM v)
+ {
+ return sq_throwerror(v,_SC("this object cannot be cloned"));
+ }
+
+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")),
+ _DECL_STREAM_FUNC(_cloned,0,NULL),
+ {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_newslot(v,-3,SQFalse);
+ i++;
+ }
+ sq_newslot(v,-3,SQFalse);
+ sq_pushroottable(v);
+ sq_pushstring(v,_SC("stream"),-1);
+ sq_pushstring(v,_SC("std_stream"),-1);
+ sq_get(v,-4);
+ sq_newslot(v,-3,SQFalse);
+ 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_newslot(v,-3,SQFalse);
+ i++;
+ }
+ sq_newslot(v,-3,SQFalse);
+ 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_newslot(v,-3,SQFalse);
+ 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_newslot(v,-3,SQFalse);
+
+ sq_settop(v,top);
+ return SQ_OK;
+ }
+ sq_settop(v,top);
+ return SQ_ERROR;
+}
diff --git a/squirrel_3_0_1_stable/sqstdlib/sqstdstream.h b/squirrel_3_0_1_stable/sqstdlib/sqstdstream.h
new file mode 100644
index 000000000..1595251e7
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqstdlib/sqstdstream.h
@@ -0,0 +1,18 @@
+/* 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_*/
diff --git a/squirrel_3_0_1_stable/sqstdlib/sqstdstring.cpp b/squirrel_3_0_1_stable/sqstdlib/sqstdstring.cpp
new file mode 100644
index 000000000..aaa37dfde
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqstdlib/sqstdstring.cpp
@@ -0,0 +1,378 @@
+/* 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 'o': case 'u': case 'x': case 'X':
+#ifdef _SQ64
+ {
+ size_t flen = scstrlen(fmt);
+ SQInteger fpos = flen - 1;
+ SQChar f = fmt[fpos];
+ SQChar *prec = (SQChar *)_PRINT_INT_PREC;
+ while(*prec != _SC('\0')) {
+ fmt[fpos++] = *prec++;
+ }
+ fmt[fpos++] = f;
+ fmt[fpos++] = _SC('\0');
+ }
+#endif
+ case 'c':
+ 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}
+};
+#undef _DECL_REX_FUNC
+
+#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}
+};
+#undef _DECL_FUNC
+
+
+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_newslot(v,-3,SQFalse);
+ i++;
+ }
+ sq_newslot(v,-3,SQFalse);
+
+ 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_newslot(v,-3,SQFalse);
+ i++;
+ }
+ return 1;
+}
diff --git a/squirrel_3_0_1_stable/sqstdlib/sqstdsystem.cpp b/squirrel_3_0_1_stable/sqstdlib/sqstdsystem.cpp
new file mode 100644
index 000000000..40f78d785
--- /dev/null
+++ b/squirrel_3_0_1_stable/sqstdlib/sqstdsystem.cpp
@@ -0,0 +1,147 @@
+/* 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,0,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}
+};
+#undef _DECL_FUNC
+
+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_newslot(v,-3,SQFalse);
+ i++;
+ }
+ return 1;
+}
diff --git a/squirrel_3_0_1_stable/squirrel.dsw b/squirrel_3_0_1_stable/squirrel.dsw
new file mode 100644
index 000000000..db43df68e
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel.dsw
@@ -0,0 +1,77 @@
+Microsoft Developer Studio Workspace File, Format Version 6.00
+# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
+
+###############################################################################
+
+Project: "sq"=.\sq\sq.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ .
+ end source code control
+}}}
+
+Package=<4>
+{{{
+ Begin Project Dependency
+ Project_Dep_Name sqlibs
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name squirrel
+ End Project Dependency
+ Begin Project Dependency
+ Project_Dep_Name sqstdlib
+ End Project Dependency
+}}}
+
+###############################################################################
+
+Project: "sqstdlib"=.\sqstdlib\sqstdlib.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ "$/squirrel", HAAAAAAA
+ .
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "squirrel"=.\squirrel\squirrel.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+ begin source code control
+ "$/squirrel", HAAAAAAA
+ .
+ end source code control
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Global:
+
+Package=<5>
+{{{
+ begin source code control
+ "$/squirrel", HAAAAAAA
+ .
+ end source code control
+}}}
+
+Package=<3>
+{{{
+}}}
+
+###############################################################################
+
diff --git a/squirrel_3_0_1_stable/squirrel/Makefile b/squirrel_3_0_1_stable/squirrel/Makefile
new file mode 100644
index 000000000..d5de81a96
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/Makefile
@@ -0,0 +1,52 @@
+SQUIRREL= ..
+
+
+OUT= $(SQUIRREL)/lib/libsquirrel.a
+INCZ= -I$(SQUIRREL)/include -I. -Iinclude
+DEFS=
+LIB=
+
+OBJS= \
+ sqapi.o \
+ sqbaselib.o \
+ sqfuncstate.o \
+ sqdebug.o \
+ sqlexer.o \
+ sqobject.o \
+ sqcompiler.o \
+ sqstate.o \
+ sqtable.o \
+ sqmem.o \
+ sqvm.o \
+ sqclass.o
+
+SRCS= \
+ sqapi.cpp \
+ sqbaselib.cpp \
+ sqfuncstate.cpp \
+ sqdebug.cpp \
+ sqlexer.cpp \
+ sqobject.cpp \
+ sqcompiler.cpp \
+ sqstate.cpp \
+ sqtable.cpp \
+ sqmem.cpp \
+ sqvm.cpp \
+ sqclass.cpp
+
+
+
+sq32:
+ gcc -O2 -fno-exceptions -fno-rtti -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ) $(DEFS)
+ ar rc $(OUT) *.o
+ rm *.o
+
+sqprof:
+ gcc -O2 -pg -fno-exceptions -fno-rtti -pie -gstabs -g3 -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ) $(DEFS)
+ ar rc $(OUT) *.o
+ rm *.o
+
+sq64:
+ gcc -O2 -m64 -D_SQ64 -fno-exceptions -fno-rtti -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ) $(DEFS)
+ ar rc $(OUT) *.o
+ rm *.o
diff --git a/squirrel_3_0_1_stable/squirrel/sqapi.cpp b/squirrel_3_0_1_stable/squirrel/sqapi.cpp
new file mode 100644
index 000000000..05338ce23
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqapi.cpp
@@ -0,0 +1,1456 @@
+/*
+ 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_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_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook)
+{
+ v->_debughook_native = hook;
+ v->_debughook_closure.Null();
+ v->_debughook = hook?true:false;
+}
+
+void sq_setdebughook(HSQUIRRELVM v)
+{
+ SQObject o = stack_get(v,-1);
+ if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
+ v->_debughook_closure = o;
+ v->_debughook_native = NULL;
+ v->_debughook = !sq_isnull(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;
+#ifndef NO_COMPILER
+ 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;
+#else
+ return sq_throwerror(v,_SC("this is a no compiler build"));
+#endif
+}
+
+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
+}
+
+SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po)
+{
+ if(!ISREFCOUNTED(type(*po))) return 0;
+#ifdef NO_GARBAGE_COLLECTOR
+ return po->_unVal.pRefCounted->_uiRef;
+#else
+ return _ss(v)->_refs_table.GetRefCount(*po);
+#endif
+}
+
+SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)
+{
+ if(!ISREFCOUNTED(type(*po))) return SQTrue;
+#ifdef NO_GARBAGE_COLLECTOR
+ bool ret = (po->_unVal.pRefCounted->_uiRef <= 1) ? SQTrue : SQFalse;
+ __Release(po->_type,po->_unVal);
+ return ret; //the ret val doesn't work(and cannot be fixed)
+#else
+ return _ss(v)->_refs_table.Release(*po);
+#endif
+}
+
+const SQChar *sq_objtostring(const HSQOBJECT *o)
+{
+ if(sq_type(*o) == OT_STRING) {
+ return _stringval(*o);
+ }
+ return NULL;
+}
+
+SQInteger sq_objtointeger(const HSQOBJECT *o)
+{
+ if(sq_isnumeric(*o)) {
+ return tointeger(*o);
+ }
+ return 0;
+}
+
+SQFloat sq_objtofloat(const HSQOBJECT *o)
+{
+ if(sq_isnumeric(*o)) {
+ return tofloat(*o);
+ }
+ return 0;
+}
+
+SQBool sq_objtobool(const HSQOBJECT *o)
+{
+ if(sq_isbool(*o)) {
+ return _integer(*o);
+ }
+ return SQFalse;
+}
+
+SQUserPointer sq_objtouserpointer(const HSQOBJECT *o)
+{
+ if(sq_isuserpointer(*o)) {
+ return _userpointer(*o);
+ }
+ return 0;
+}
+
+void sq_pushnull(HSQUIRRELVM v)
+{
+ v->PushNull();
+}
+
+void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len)
+{
+ if(s)
+ v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len)));
+ else v->PushNull();
+}
+
+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 (SQUserPointer)sq_aligning(ud + 1);
+}
+
+void sq_newtable(HSQUIRRELVM v)
+{
+ v->Push(SQTable::Create(_ss(v), 0));
+}
+
+void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity)
+{
+ v->Push(SQTable::Create(_ss(v), initialcapacity));
+}
+
+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();
+ 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,nfreevars);
+ nc->_nparamscheck = 0;
+ for(SQUnsignedInteger i = 0; i < nfreevars; i++) {
+ nc->_outervalues[i] = 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(type(o) == OT_CLOSURE) {
+ SQClosure *c = _closure(o);
+ SQFunctionProto *proto = c->_function;
+ *nparams = (SQUnsignedInteger)proto->_nparameters;
+ *nfreevars = (SQUnsignedInteger)proto->_noutervalues;
+ return SQ_OK;
+ }
+ else if(type(o) == OT_NATIVECLOSURE)
+ {
+ SQNativeClosure *c = _nativeclosure(o);
+ *nparams = (SQUnsignedInteger)c->_nparamscheck;
+ *nfreevars = c->_noutervalues;
+ 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"));
+ SQWeakRef *w = _refcounted(env)->GetWeakRef(type(env));
+ SQObjectPtr ret;
+ if(sq_isclosure(o)) {
+ SQClosure *c = _closure(o)->Clone();
+ __ObjRelease(c->_env);
+ c->_env = w;
+ __ObjAddRef(c->_env);
+ if(_closure(o)->_base) {
+ c->_base = _closure(o)->_base;
+ __ObjAddRef(c->_base);
+ }
+ ret = c;
+ }
+ else { //then must be a native closure
+ SQNativeClosure *c = _nativeclosure(o)->Clone();
+ __ObjRelease(c->_env);
+ c->_env = w;
+ __ObjAddRef(c->_env);
+ 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));
+}
+
+
+SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx)
+{
+ SQObjectPtr &o = stack_get(v, idx);
+ SQObjectPtr res;
+ if(!v->ToString(o,res)) {
+ return SQ_ERROR;
+ }
+ v->Push(res);
+ return SQ_OK;
+}
+
+void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b)
+{
+ SQObjectPtr &o = stack_get(v, idx);
+ *b = SQVM::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->PushNull();
+ if(!v->Clone(o, stack_get(v, -1))){
+ v->Pop();
+ return SQ_ERROR;
+ }
+ 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;
+ case OT_INSTANCE: return _instance(o)->_class->_udsize;
+ case OT_CLASS: return _class(o)->_udsize;
+ 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(const 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();
+ 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),DONT_FALL_BACK)) {
+ v->Pop(2);
+ return SQ_OK;
+ }
+ 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)
+ v->GetUp(-1) = t;
+ else
+ v->Pop();
+ 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->PushNull();
+ 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,DONT_FALL_BACK))
+ return SQ_OK;
+ v->Pop();
+ return SQ_ERROR;
+}
+
+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:{
+ SQObjectPtr& key = v->GetUp(-1);
+ if(sq_isnumeric(key)){
+ if(_array(self)->Get(tointeger(key),v->GetUp(-1))) {
+ return SQ_OK;
+ }
+ }
+ else {
+ v->Pop();
+ return sq_throwerror(v,_SC("invalid index type for an array"));
+ }
+ }
+ break;
+ default:
+ v->Pop();
+ return sq_throwerror(v,_SC("rawget works only on array/table/instance and class"));
+ }
+ v->Pop();
+ 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=c->_function;
+ if(func->_noutervalues > (SQInteger)idx) {
+ v->Push(*_outer(c->_outervalues[idx])->_valptr);
+ 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 SQ_ERROR;
+}
+
+SQRESULT sq_throwobject(HSQUIRRELVM v)
+{
+ v->_lasterror = v->GetUp(-1);
+ v->Pop();
+ return SQ_ERROR;
+}
+
+
+void sq_reseterror(HSQUIRRELVM v)
+{
+ v->_lasterror.Null();
+}
+
+void sq_getlasterror(HSQUIRRELVM v)
+{
+ v->Push(v->_lasterror);
+}
+
+SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize)
+{
+ if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) {
+ if(v->_nmetamethodscall) {
+ return sq_throwerror(v,_SC("cannot resize stack while in a metamethod"));
+ }
+ v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size()));
+ }
+ return SQ_OK;
+}
+
+SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror)
+{
+ if(type(v->GetUp(-1))==OT_GENERATOR){
+ v->PushNull(); //retval
+ if(!v->Execute(v->GetUp(-2),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"));
+ SQInteger target = v->_suspended_target;
+ if(wakeupret) {
+ if(target != -1) {
+ v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval
+ }
+ v->Pop();
+ } else if(target != -1) { v->GetAt(v->_stackbase+v->_suspended_target).Null(); }
+ SQObjectPtr dummy;
+ if(!v->Execute(dummy,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM)) {
+ return SQ_ERROR;
+ }
+ 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);
+}
+
+SQRESULT sq_resurrectunreachable(HSQUIRRELVM v)
+{
+#ifndef NO_GARBAGE_COLLECTOR
+ _ss(v)->ResurrectUnreachable(v);
+ return SQ_OK;
+#else
+ return sq_throwerror(v,_SC("sq_resurrectunreachable requires a garbage collector build"));
+#endif
+}
+
+SQInteger sq_collectgarbage(HSQUIRRELVM v)
+{
+#ifndef NO_GARBAGE_COLLECTOR
+ return _ss(v)->CollectGarbage(v);
+#else
+ return -1;
+#endif
+}
+
+SQRESULT sq_getcallee(HSQUIRRELVM v)
+{
+ if(v->_callsstacksize > 1)
+ {
+ v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);
+ return SQ_OK;
+ }
+ return sq_throwerror(v,_SC("no closure in the calls stack"));
+}
+
+const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
+{
+ SQObjectPtr &self=stack_get(v,idx);
+ const SQChar *name = NULL;
+ switch(type(self))
+ {
+ case OT_CLOSURE:{
+ SQClosure *clo = _closure(self);
+ SQFunctionProto *fp = clo->_function;
+ if(((SQUnsignedInteger)fp->_noutervalues) > nval) {
+ v->Push(*(_outer(clo->_outervalues[nval])->_valptr));
+ SQOuterVar &ov = fp->_outervalues[nval];
+ name = _stringval(ov._name);
+ }
+ }
+ break;
+ case OT_NATIVECLOSURE:{
+ SQNativeClosure *clo = _nativeclosure(self);
+ if(clo->_noutervalues > nval) {
+ v->Push(clo->_outervalues[nval]);
+ name = _SC("@NATIVE");
+ }
+ }
+ break;
+ default: break; //shutup compiler
+ }
+ return name;
+}
+
+SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
+{
+ SQObjectPtr &self=stack_get(v,idx);
+ switch(type(self))
+ {
+ case OT_CLOSURE:{
+ SQFunctionProto *fp = _closure(self)->_function;
+ if(((SQUnsignedInteger)fp->_noutervalues) > nval){
+ *(_outer(_closure(self)->_outervalues[nval])->_valptr) = stack_get(v,-1);
+ }
+ else return sq_throwerror(v,_SC("invalid free var index"));
+ }
+ break;
+ case OT_NATIVECLOSURE:
+ if(_nativeclosure(self)->_noutervalues > 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();
+ 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_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle)
+{
+ SQObjectPtr *o = NULL;
+ _GETSAFE_OBJ(v, idx, OT_CLASS,o);
+ SQObjectPtr &key = stack_get(v,-1);
+ SQTable *m = _class(*o)->_members;
+ SQObjectPtr val;
+ if(m->Get(key,val)) {
+ handle->_static = _isfield(val) ? SQFalse : SQTrue;
+ handle->_index = _member_idx(val);
+ v->Pop();
+ return SQ_OK;
+ }
+ return sq_throwerror(v,_SC("wrong index"));
+}
+
+SQRESULT _getmemberbyhandle(HSQUIRRELVM v,SQObjectPtr &self,HSQMEMBERHANDLE *handle,SQObjectPtr *&val)
+{
+ switch(type(self)) {
+ case OT_INSTANCE: {
+ SQInstance *i = _instance(self);
+ if(handle->_static) {
+ SQClass *c = i->_class;
+ val = &c->_methods[handle->_index].val;
+ }
+ else {
+ val = &i->_values[handle->_index];
+
+ }
+ }
+ break;
+ case OT_CLASS: {
+ SQClass *c = _class(self);
+ if(handle->_static) {
+ val = &c->_methods[handle->_index].val;
+ }
+ else {
+ val = &c->_defaultvalues[handle->_index].val;
+ }
+ }
+ break;
+ default:
+ return sq_throwerror(v,_SC("wrong type(expected class or instance)"));
+ }
+ return SQ_OK;
+}
+
+SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle)
+{
+ SQObjectPtr &self = stack_get(v,idx);
+ SQObjectPtr *val = NULL;
+ if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) {
+ return SQ_ERROR;
+ }
+ v->Push(_realval(*val));
+ return SQ_OK;
+}
+
+SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle)
+{
+ SQObjectPtr &self = stack_get(v,idx);
+ SQObjectPtr &newval = stack_get(v,-1);
+ SQObjectPtr *val = NULL;
+ if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) {
+ return SQ_ERROR;
+ }
+ *val = newval;
+ v->Pop();
+ return SQ_OK;
+}
+
+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->PushNull();
+ 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,SQPRINTFUNCTION errfunc)
+{
+ _ss(v)->_printfunc = printfunc;
+ _ss(v)->_errorfunc = errfunc;
+}
+
+SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)
+{
+ return _ss(v)->_printfunc;
+}
+
+SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v)
+{
+ return _ss(v)->_errorfunc;
+}
+
+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);
+}
diff --git a/squirrel_3_0_1_stable/squirrel/sqarray.h b/squirrel_3_0_1_stable/squirrel/sqarray.h
new file mode 100644
index 000000000..c3a57abcc
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqarray.h
@@ -0,0 +1,94 @@
+/* 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);
+ SQObjectType GetType() {return OT_ARRAY;}
+#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),0); anew->_values.copy(_values); return anew; }
+ SQInteger Size() const {return _values.size();}
+ void Resize(SQInteger size)
+ {
+ SQObjectPtr _null;
+ Resize(size,_null);
+ }
+ void Resize(SQInteger size,SQObjectPtr &fill) { _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_
diff --git a/squirrel_3_0_1_stable/squirrel/sqbaselib.cpp b/squirrel_3_0_1_stable/squirrel/sqbaselib.cpp
new file mode 100644
index 000000000..1e9ae1445
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqbaselib.cpp
@@ -0,0 +1,1110 @@
+/*
+ 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;
+}
+static SQInteger base_resurectureachable(HSQUIRRELVM v)
+{
+ sq_resurrectunreachable(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 = v->_roottable;
+ if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR;
+ v->Push(o);
+ return 1;
+}
+
+static SQInteger base_setconsttable(HSQUIRRELVM v)
+{
+ SQObjectPtr o = _ss(v)->_consts;
+ 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,SQVM::IsFalse(o)?SQFalse:SQTrue);
+ return 0;
+}
+
+static SQInteger __getcallstackinfos(HSQUIRRELVM v,SQInteger level)
+{
+ SQStackInfos si;
+ SQInteger seq = 0;
+ const SQChar *name = NULL;
+
+ 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_newslot(v, -3, SQFalse);
+ sq_pushstring(v, _SC("src"), -1);
+ sq_pushstring(v, src, -1);
+ sq_newslot(v, -3, SQFalse);
+ sq_pushstring(v, _SC("line"), -1);
+ sq_pushinteger(v, si.line);
+ sq_newslot(v, -3, SQFalse);
+ 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_newslot(v, -4, SQFalse);
+ sq_pop(v, 1);
+ seq++;
+ }
+ sq_newslot(v, -3, SQFalse);
+ return 1;
+ }
+
+ return 0;
+}
+static SQInteger base_getstackinfos(HSQUIRRELVM v)
+{
+ SQInteger level;
+ sq_getinteger(v, -1, &level);
+ return __getcallstackinfos(v,level);
+}
+
+static SQInteger base_assert(HSQUIRRELVM v)
+{
+ if(SQVM::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_error(HSQUIRRELVM v)
+{
+ const SQChar *str;
+ sq_tostring(v,2);
+ sq_getstring(v,-1,&str);
+ if(_ss(v)->_errorfunc) _ss(v)->_errorfunc(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 = (_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 SQInteger base_callee(HSQUIRRELVM v)
+{
+ if(v->_callsstacksize > 1)
+ {
+ v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);
+ return 1;
+ }
+ return sq_throwerror(v,_SC("no closure in the calls stack"));
+}
+
+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("error"),base_error,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("callee"),base_callee,0,NULL},
+ {_SC("dummy"),base_dummy,0,NULL},
+#ifndef NO_GARBAGE_COLLECTOR
+ {_SC("collectgarbage"),base_collectgarbage,0, NULL},
+ {_SC("resurrectunreachable"),base_resurectureachable,0, NULL},
+#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_newslot(v,-3, SQFalse);
+ i++;
+ }
+
+ sq_pushstring(v,_SC("_versionnumber_"),-1);
+ sq_pushinteger(v,SQUIRREL_VERSION_NUMBER);
+ sq_newslot(v,-3, SQFalse);
+ sq_pushstring(v,_SC("_version_"),-1);
+ sq_pushstring(v,SQUIRREL_VERSION,-1);
+ sq_newslot(v,-3, SQFalse);
+ sq_pushstring(v,_SC("_charsize_"),-1);
+ sq_pushinteger(v,sizeof(SQChar));
+ sq_newslot(v,-3, SQFalse);
+ sq_pushstring(v,_SC("_intsize_"),-1);
+ sq_pushinteger(v,sizeof(SQInteger));
+ sq_newslot(v,-3, SQFalse);
+ sq_pushstring(v,_SC("_floatsize_"),-1);
+ sq_pushinteger(v,sizeof(SQFloat));
+ sq_newslot(v,-3, SQFalse);
+ 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->PushNull();
+ 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->PushNull();
+ 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 container_rawset(HSQUIRRELVM v)
+{
+ return sq_rawset(v,-3);
+}
+
+
+static SQInteger container_rawget(HSQUIRRELVM v)
+{
+ return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;
+}
+
+static SQInteger table_setdelegate(HSQUIRRELVM v)
+{
+ if(SQ_FAILED(sq_setdelegate(v,-2)))
+ return SQ_ERROR;
+ sq_push(v,-1); // -1 because sq_setdelegate pops 1
+ return 1;
+}
+
+static SQInteger table_getdelegate(HSQUIRRELVM v)
+{
+ return SQ_SUCCEEDED(sq_getdelegate(v,-1))?1:SQ_ERROR;
+}
+
+SQRegFunction SQSharedState::_table_default_delegate_funcz[]={
+ {_SC("len"),default_delegate_len,1, _SC("t")},
+ {_SC("rawget"),container_rawget,2, _SC("t")},
+ {_SC("rawset"),container_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(".")},
+ {_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")},
+ {_SC("getdelegate"),table_getdelegate,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"));
+}
+
+static SQInteger __map_array(SQArray *dest,SQArray *src,HSQUIRRELVM v) {
+ SQObjectPtr temp;
+ SQInteger size = src->Size();
+ for(SQInteger n = 0; n < size; n++) {
+ src->Get(n,temp);
+ v->Push(src);
+ v->Push(temp);
+ if(SQ_FAILED(sq_call(v,2,SQTrue,SQFalse))) {
+ return SQ_ERROR;
+ }
+ dest->Set(n,v->GetUp(-1));
+ v->Pop();
+ }
+ return 0;
+}
+
+static SQInteger array_map(HSQUIRRELVM v)
+{
+ SQObject &o = stack_get(v,1);
+ SQInteger size = _array(o)->Size();
+ SQObjectPtr ret = SQArray::Create(_ss(v),size);
+ if(SQ_FAILED(__map_array(_array(ret),_array(o),v)))
+ return SQ_ERROR;
+ v->Push(ret);
+ return 1;
+}
+
+static SQInteger array_apply(HSQUIRRELVM v)
+{
+ SQObject &o = stack_get(v,1);
+ if(SQ_FAILED(__map_array(_array(o),_array(o),v)))
+ return SQ_ERROR;
+ return 0;
+}
+
+static SQInteger array_reduce(HSQUIRRELVM v)
+{
+ SQObject &o = stack_get(v,1);
+ SQArray *a = _array(o);
+ SQInteger size = a->Size();
+ if(size == 0) {
+ return 0;
+ }
+ SQObjectPtr res;
+ a->Get(0,res);
+ if(size > 1) {
+ SQObjectPtr other;
+ for(SQInteger n = 1; n < size; n++) {
+ a->Get(n,other);
+ v->Push(o);
+ v->Push(res);
+ v->Push(other);
+ if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {
+ return SQ_ERROR;
+ }
+ res = v->GetUp(-1);
+ v->Pop();
+ }
+ }
+ v->Push(res);
+ return 1;
+}
+
+static SQInteger array_filter(HSQUIRRELVM v)
+{
+ SQObject &o = stack_get(v,1);
+ SQArray *a = _array(o);
+ SQObjectPtr ret = SQArray::Create(_ss(v),0);
+ SQInteger size = a->Size();
+ SQObjectPtr val;
+ for(SQInteger n = 0; n < size; n++) {
+ a->Get(n,val);
+ v->Push(o);
+ v->Push(n);
+ v->Push(val);
+ if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {
+ return SQ_ERROR;
+ }
+ if(!SQVM::IsFalse(v->GetUp(-1))) {
+ _array(ret)->Append(val);
+ }
+ v->Pop();
+ }
+ v->Push(ret);
+ return 1;
+}
+
+static SQInteger array_find(HSQUIRRELVM v)
+{
+ SQObject &o = stack_get(v,1);
+ SQObjectPtr &val = stack_get(v,2);
+ SQArray *a = _array(o);
+ SQInteger size = a->Size();
+ SQObjectPtr temp;
+ for(SQInteger n = 0; n < size; n++) {
+ bool res = false;
+ a->Get(n,temp);
+ if(SQVM::IsEqual(temp,val,res) && res) {
+ v->Push(n);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+//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(sq_gettop(v) == 2 /*&& 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(".")},
+ {_SC("map"),array_map,2, _SC("ac")},
+ {_SC("apply"),array_apply,2, _SC("ac")},
+ {_SC("reduce"),array_reduce,2, _SC("ac")},
+ {_SC("filter"),array_filter,2, _SC("ac")},
+ {_SC("find"),array_find,2, _SC("a.")},
+ {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 = _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;
+}
+
+static SQInteger thread_getstackinfos(HSQUIRRELVM v)
+{
+ SQObjectPtr o = stack_get(v,1);
+ if(type(o) == OT_THREAD) {
+ SQVM *thread = _thread(o);
+ SQInteger threadtop = sq_gettop(thread);
+ SQInteger level;
+ sq_getinteger(v,-1,&level);
+ SQRESULT res = __getcallstackinfos(thread,level);
+ if(SQ_FAILED(res))
+ {
+ sq_settop(thread,threadtop);
+ if(type(thread->_lasterror) == OT_STRING) {
+ sq_throwerror(v,_stringval(thread->_lasterror));
+ }
+ else {
+ sq_throwerror(v,_SC("unknown error"));
+ }
+ }
+ if(res > 0) {
+ //some result
+ sq_move(v,thread,-1);
+ sq_settop(thread,threadtop);
+ return 1;
+ }
+ //no result
+ sq_settop(thread,threadtop);
+ return 0;
+
+ }
+ return sq_throwerror(v,_SC("wrong parameter"));
+}
+
+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("getstackinfos"),thread_getstackinfos,2, _SC("vn")},
+ {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
+ {0,0},
+};
+
+static SQInteger class_getattributes(HSQUIRRELVM v)
+{
+ return SQ_SUCCEEDED(sq_getattributes(v,-2))?1:SQ_ERROR;
+}
+
+static SQInteger class_setattributes(HSQUIRRELVM v)
+{
+ return SQ_SUCCEEDED(sq_setattributes(v,-3))?1:SQ_ERROR;
+}
+
+static SQInteger class_instance(HSQUIRRELVM v)
+{
+ return SQ_SUCCEEDED(sq_createinstance(v,-1))?1:SQ_ERROR;
+}
+
+static SQInteger class_getbase(HSQUIRRELVM v)
+{
+ return SQ_SUCCEEDED(sq_getbase(v,-1))?1:SQ_ERROR;
+}
+
+SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {
+ {_SC("getattributes"), class_getattributes, 2, _SC("y.")},
+ {_SC("setattributes"), class_setattributes, 3, _SC("y..")},
+ {_SC("rawget"),container_rawget,2, _SC("y")},
+ {_SC("rawset"),container_rawset,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")},
+ {_SC("getbase"),class_getbase,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("rawget"),container_rawget,2, _SC("x")},
+ {_SC("rawset"),container_rawset,3, _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}
+};
+
diff --git a/squirrel_3_0_1_stable/squirrel/sqclass.cpp b/squirrel_3_0_1_stable/squirrel/sqclass.cpp
new file mode 100644
index 000000000..1f26cc92f
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqclass.cpp
@@ -0,0 +1,213 @@
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqvm.h"
+#include "sqtable.h"
+#include "sqclass.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+
+
+
+SQClass::SQClass(SQSharedState *ss,SQClass *base)
+{
+ _base = base;
+ _typetag = 0;
+ _hook = NULL;
+ _udsize = 0;
+ _locked = false;
+ _constructoridx = -1;
+ if(_base) {
+ _constructoridx = _base->_constructoridx;
+ _udsize = _base->_udsize;
+ _defaultvalues.copy(base->_defaultvalues);
+ _methods.copy(base->_methods);
+ _COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST);
+ __ObjAddRef(_base);
+ }
+ _members = base?base->_members->Clone() : SQTable::Create(ss,0);
+ __ObjAddRef(_members);
+
+ INIT_CHAIN();
+ ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
+}
+
+void SQClass::Finalize() {
+ _attributes.Null();
+ _defaultvalues.resize(0);
+ _methods.resize(0);
+ _NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST);
+ __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;
+ bool belongs_to_static_table = type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic;
+ if(_locked && !belongs_to_static_table)
+ 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(belongs_to_static_table) {
+ SQInteger mmidx;
+ if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) &&
+ (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
+ _metamethods[mmidx] = val;
+ }
+ else {
+ SQObjectPtr theval = val;
+ if(_base && type(val) == OT_CLOSURE) {
+ theval = _closure(val)->Clone();
+ _closure(theval)->_base = _base;
+ __ObjAddRef(_base); //ref for the closure
+ }
+ if(type(temp) == OT_NULL) {
+ bool isconstructor;
+ SQVM::IsEqual(ss->_constructoridx, key, isconstructor);
+ if(isconstructor) {
+ _constructoridx = (SQInteger)_methods.size();
+ }
+ SQClassMember m;
+ m.val = theval;
+ _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));
+ _methods.push_back(m);
+ }
+ else {
+ _methods[_member_idx(temp)].val = theval;
+ }
+ }
+ 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);
+ _NULL_SQOBJECT_VECTOR(_values,nvalues);
+ //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;
+}
diff --git a/squirrel_3_0_1_stable/squirrel/sqclass.h b/squirrel_3_0_1_stable/squirrel/sqclass.h
new file mode 100644
index 000000000..996a3df70
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqclass.h
@@ -0,0 +1,158 @@
+/* see copyright notice in squirrel.h */
+#ifndef _SQCLASS_H_
+#define _SQCLASS_H_
+
+struct SQInstance;
+
+struct SQClassMember {
+ 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 GetConstructor(SQObjectPtr &ctor)
+ {
+ if(_constructoridx != -1) {
+ ctor = _methods[_constructoridx].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 ** );
+ SQObjectType GetType() {return OT_CLASS;}
+#endif
+ SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
+ SQInstance *CreateInstance();
+ SQTable *_members;
+ SQClass *_base;
+ SQClassMemberVec _defaultvalues;
+ SQClassMemberVec _methods;
+ SQObjectPtr _metamethods[MT_LAST];
+ SQObjectPtr _attributes;
+ SQUserPointer _typetag;
+ SQRELEASEHOOK _hook;
+ bool _locked;
+ SQInteger _constructoridx;
+ SQInteger _udsize;
+};
+
+#define calcinstancesize(_theclass_) \
+ (_theclass_->_udsize + sq_aligning(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 ** );
+ SQObjectType GetType() {return OT_INSTANCE;}
+#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_
diff --git a/squirrel_3_0_1_stable/squirrel/sqclosure.h b/squirrel_3_0_1_stable/squirrel/sqclosure.h
new file mode 100644
index 000000000..07b3efcfe
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqclosure.h
@@ -0,0 +1,193 @@
+/* see copyright notice in squirrel.h */
+#ifndef _SQCLOSURE_H_
+#define _SQCLOSURE_H_
+
+
+#define _CALC_CLOSURE_SIZE(func) (sizeof(SQClosure) + (func->_noutervalues*sizeof(SQObjectPtr)) + (func->_ndefaultparams*sizeof(SQObjectPtr)))
+
+struct SQFunctionProto;
+struct SQClass;
+struct SQClosure : public CHAINABLE_OBJ
+{
+private:
+ SQClosure(SQSharedState *ss,SQFunctionProto *func){_function = func; __ObjAddRef(_function); _base = NULL; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;}
+public:
+ static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){
+ SQInteger size = _CALC_CLOSURE_SIZE(func);
+ SQClosure *nc=(SQClosure*)SQ_MALLOC(size);
+ new (nc) SQClosure(ss,func);
+ nc->_outervalues = (SQObjectPtr *)(nc + 1);
+ nc->_defaultparams = &nc->_outervalues[func->_noutervalues];
+ _CONSTRUCT_VECTOR(SQObjectPtr,func->_noutervalues,nc->_outervalues);
+ _CONSTRUCT_VECTOR(SQObjectPtr,func->_ndefaultparams,nc->_defaultparams);
+ return nc;
+ }
+ void Release(){
+ SQFunctionProto *f = _function;
+ SQInteger size = _CALC_CLOSURE_SIZE(f);
+ _DESTRUCT_VECTOR(SQObjectPtr,f->_noutervalues,_outervalues);
+ _DESTRUCT_VECTOR(SQObjectPtr,f->_ndefaultparams,_defaultparams);
+ __ObjRelease(_function);
+ this->~SQClosure();
+ sq_vm_free(this,size);
+ }
+
+ SQClosure *Clone()
+ {
+ SQFunctionProto *f = _function;
+ SQClosure * ret = SQClosure::Create(_opt_ss(this),f);
+ ret->_env = _env;
+ if(ret->_env) __ObjAddRef(ret->_env);
+ _COPY_VECTOR(ret->_outervalues,_outervalues,f->_noutervalues);
+ _COPY_VECTOR(ret->_defaultparams,_defaultparams,f->_ndefaultparams);
+ return ret;
+ }
+ ~SQClosure();
+
+ 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(){
+ SQFunctionProto *f = _function;
+ _NULL_SQOBJECT_VECTOR(_outervalues,f->_noutervalues);
+ _NULL_SQOBJECT_VECTOR(_defaultparams,f->_ndefaultparams);
+ }
+ SQObjectType GetType() {return OT_CLOSURE;}
+#endif
+ SQWeakRef *_env;
+ SQClass *_base;
+ SQFunctionProto *_function;
+ SQObjectPtr *_outervalues;
+ SQObjectPtr *_defaultparams;
+};
+
+//////////////////////////////////////////////
+struct SQOuter : public CHAINABLE_OBJ
+{
+
+private:
+ SQOuter(SQSharedState *ss, SQObjectPtr *outer){_valptr = outer; _next = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); }
+
+public:
+ static SQOuter *Create(SQSharedState *ss, SQObjectPtr *outer)
+ {
+ SQOuter *nc = (SQOuter*)SQ_MALLOC(sizeof(SQOuter));
+ new (nc) SQOuter(ss, outer);
+ return nc;
+ }
+ ~SQOuter() { REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); }
+
+ void Release()
+ {
+ this->~SQOuter();
+ sq_vm_free(this,sizeof(SQOuter));
+ }
+
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+ void Finalize() { _value.Null(); }
+ SQObjectType GetType() {return OT_OUTER;}
+#endif
+
+ SQObjectPtr *_valptr; /* pointer to value on stack, or _value below */
+ SQInteger _idx; /* idx in stack array, for relocation */
+ SQObjectPtr _value; /* value of outer after stack frame is closed */
+ SQOuter *_next; /* pointer to next outer when frame is open */
+};
+
+//////////////////////////////////////////////
+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,SQInteger target);
+ bool Resume(SQVM *v,SQObjectPtr &dest);
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+ void Finalize(){_stack.resize(0);_closure.Null();}
+ SQObjectType GetType() {return OT_GENERATOR;}
+#endif
+ SQObjectPtr _closure;
+ SQObjectPtrVec _stack;
+ SQVM::CallInfo _ci;
+ ExceptionsTraps _etraps;
+ SQGeneratorState _state;
+};
+
+#define _CALC_NATVIVECLOSURE_SIZE(noutervalues) (sizeof(SQNativeClosure) + (noutervalues*sizeof(SQObjectPtr)))
+
+struct SQNativeClosure : public CHAINABLE_OBJ
+{
+private:
+ SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;}
+public:
+ static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func,SQInteger nouters)
+ {
+ SQInteger size = _CALC_NATVIVECLOSURE_SIZE(nouters);
+ SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(size);
+ new (nc) SQNativeClosure(ss,func);
+ nc->_outervalues = (SQObjectPtr *)(nc + 1);
+ nc->_noutervalues = nouters;
+ _CONSTRUCT_VECTOR(SQObjectPtr,nc->_noutervalues,nc->_outervalues);
+ return nc;
+ }
+ SQNativeClosure *Clone()
+ {
+ SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function,_noutervalues);
+ ret->_env = _env;
+ if(ret->_env) __ObjAddRef(ret->_env);
+ ret->_name = _name;
+ _COPY_VECTOR(ret->_outervalues,_outervalues,_noutervalues);
+ ret->_typecheck.copy(_typecheck);
+ ret->_nparamscheck = _nparamscheck;
+ return ret;
+ }
+ ~SQNativeClosure()
+ {
+ __ObjRelease(_env);
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+ }
+ void Release(){
+ SQInteger size = _CALC_NATVIVECLOSURE_SIZE(_noutervalues);
+ _DESTRUCT_VECTOR(SQObjectPtr,_noutervalues,_outervalues);
+ this->~SQNativeClosure();
+ sq_free(this,size);
+ }
+
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+ void Finalize() { _NULL_SQOBJECT_VECTOR(_outervalues,_noutervalues); }
+ SQObjectType GetType() {return OT_NATIVECLOSURE;}
+#endif
+ SQInteger _nparamscheck;
+ SQIntVec _typecheck;
+ SQObjectPtr *_outervalues;
+ SQUnsignedInteger _noutervalues;
+ SQWeakRef *_env;
+ SQFUNCTION _function;
+ SQObjectPtr _name;
+};
+
+
+
+#endif //_SQCLOSURE_H_
diff --git a/squirrel_3_0_1_stable/squirrel/sqcompiler.cpp b/squirrel_3_0_1_stable/squirrel/sqcompiler.cpp
new file mode 100644
index 000000000..e8c1496c9
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqcompiler.cpp
@@ -0,0 +1,1504 @@
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#ifndef NO_COMPILER
+#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 EXPR 1
+#define OBJECT 2
+#define BASE 3
+#define LOCAL 4
+#define OUTER 5
+
+struct SQExpState {
+ SQInteger etype; /* expr. type; one of EXPR, OBJECT, BASE, OUTER or LOCAL */
+ SQInteger epos; /* expr. location on stack; -1 for OBJECT and BASE */
+ bool donot_get; /* signal not to deref the next value */
+};
+
+struct SQScope {
+ SQInteger outers;
+ SQInteger stacksize;
+};
+
+#define BEGIN_SCOPE() SQScope __oldscope__ = _scope; \
+ _scope.outers = _fs->_outers; \
+ _scope.stacksize = _fs->GetStackSize();
+
+#define RESOLVE_OUTERS() if(_fs->GetStackSize() != _scope.stacksize) { \
+ if(_fs->CountOuters(_scope.stacksize)) { \
+ _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \
+ } \
+ }
+
+#define END_SCOPE_NO_CLOSE() { if(_fs->GetStackSize() != _scope.stacksize) { \
+ _fs->SetStackSize(_scope.stacksize); \
+ } \
+ _scope = __oldscope__; \
+ }
+
+#define END_SCOPE() { SQInteger oldouters = _fs->_outers;\
+ if(_fs->GetStackSize() != _scope.stacksize) { \
+ _fs->SetStackSize(_scope.stacksize); \
+ if(oldouters != _fs->_outers) { \
+ _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \
+ } \
+ } \
+ _scope = __oldscope__; \
+ }
+
+#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;
+ _scope.outers = 0;
+ _scope.stacksize = 0;
+ 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();}
+ SQObject Expect(SQInteger tok)
+ {
+
+ if(_token != tok) {
+ if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {
+ //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->AddParameter(_fs->CreateString(_SC("vargv")));
+ _fs->_varparams = true;
+ _fs->_sourcename = _sourcename;
+ SQInteger stacksize = _fs->GetStackSize();
+ if(setjmp(_errorjmp) == 0) {
+ Lex();
+ while(_token > 0){
+ Statement();
+ if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
+ }
+ _fs->SetStackSize(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(bool closeframe = true)
+ {
+ _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(),_fs->GetStackSize());
+ }
+ else{
+ if(op == _OP_RETURN && _fs->_traps > 0)
+ _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);
+ _fs->_returnexp = -1;
+ _fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize());
+ }
+ 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);
+ }
+ RESOLVE_OUTERS();
+ _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);
+ }
+ RESOLVE_OUTERS();
+ _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('{'):{
+ BEGIN_SCOPE();
+ Lex();
+ Statements();
+ Expect(_SC('}'));
+ if(closeframe) {
+ END_SCOPE();
+ }
+ else {
+ END_SCOPE_NO_CLOSE();
+ }
+ }
+ 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->DiscardTarget();
+ //_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, SQInteger etype, SQInteger pos)
+ {
+ /* Generate code depending on the expression type */
+ switch(etype) {
+ case LOCAL:{
+ SQInteger p2 = _fs->PopTarget(); //src in OP_GET
+ SQInteger p1 = _fs->PopTarget(); //key in OP_GET
+ _fs->PushTarget(p1);
+ //EmitCompArithLocal(tok, p1, p1, p2);
+ _fs->AddInstruction(ChooseArithOpByToken(tok),p1, p2, p1, 0);
+ }
+ break;
+ case OBJECT:
+ case BASE:
+ {
+ SQInteger val = _fs->PopTarget();
+ SQInteger key = _fs->PopTarget();
+ SQInteger src = _fs->PopTarget();
+ /* _OP_COMPARITH mixes dest obj and source val in the arg1 */
+ _fs->AddInstruction(_OP_COMPARITH, _fs->PushTarget(), (src<<16)|val, key, ChooseCompArithCharByToken(tok));
+ }
+ break;
+ case OUTER:
+ {
+ SQInteger val = _fs->TopTarget();
+ SQInteger tmp = _fs->PushTarget();
+ _fs->AddInstruction(_OP_GETOUTER, tmp, pos);
+ _fs->AddInstruction(ChooseArithOpByToken(tok), tmp, val, tmp, 0);
+ _fs->AddInstruction(_OP_SETOUTER, tmp, pos, tmp);
+ }
+ break;
+ }
+ }
+ void CommaExpr()
+ {
+ for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr());
+ }
+ void Expression()
+ {
+ SQExpState es = _es;
+ _es.etype = EXPR;
+ _es.epos = -1;
+ _es.donot_get = false;
+ 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 = _es.etype;
+ SQInteger pos = _es.epos;
+ if(ds == EXPR) Error(_SC("can't assign expression"));
+ Lex(); Expression();
+
+ switch(op){
+ case TK_NEWSLOT:
+ if(ds == OBJECT || ds == BASE)
+ 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
+ switch(ds) {
+ case LOCAL:
+ {
+ SQInteger src = _fs->PopTarget();
+ SQInteger dst = _fs->TopTarget();
+ _fs->AddInstruction(_OP_MOVE, dst, src);
+ }
+ break;
+ case OBJECT:
+ case BASE:
+ EmitDerefOp(_OP_SET);
+ break;
+ case OUTER:
+ {
+ SQInteger src = _fs->PopTarget();
+ SQInteger dst = _fs->PushTarget();
+ _fs->AddInstruction(_OP_SETOUTER, dst, pos, src);
+ }
+ }
+ break;
+ case TK_MINUSEQ:
+ case TK_PLUSEQ:
+ case TK_MULEQ:
+ case TK_DIVEQ:
+ case TK_MODEQ:
+ EmitCompoundArith(op, ds, pos);
+ 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;
+ }
+ _es = es;
+ }
+ template<typename T> void BIN_EXP(SQOpcode op, T f,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()
+ {
+ EqExp();
+ for(;;) if(_token == _SC('&'))
+ {BIN_EXP(_OP_BITW, &SQCompiler::EqExp,BW_AND);
+ }else return;
+ }
+ void EqExp()
+ {
+ CompExp();
+ for(;;) switch(_token) {
+ case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::CompExp); break;
+ case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::CompExp); break;
+ case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQCompiler::CompExp,CMP_3W); break;
+ default: return;
+ }
+ }
+ void CompExp()
+ {
+ ShiftExp();
+ for(;;) switch(_token) {
+ 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;
+ 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;
+ }
+ }
+ SQOpcode ChooseArithOpByToken(SQInteger tok)
+ {
+ switch(tok) {
+ case TK_PLUSEQ: case '+': return _OP_ADD;
+ case TK_MINUSEQ: case '-': return _OP_SUB;
+ case TK_MULEQ: case '*': return _OP_MUL;
+ case TK_DIVEQ: case '/': return _OP_DIV;
+ case TK_MODEQ: case '%': return _OP_MOD;
+ default: assert(0);
+ }
+ return _OP_ADD;
+ }
+ SQInteger ChooseCompArithCharByToken(SQInteger tok)
+ {
+ 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;
+ };
+ return oper;
+ }
+ void PlusExp()
+ {
+ MultExp();
+ for(;;) switch(_token) {
+ case _SC('+'): case _SC('-'):
+ BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::MultExp); break;
+ default: return;
+ }
+ }
+
+ void MultExp()
+ {
+ PrefixedExpr();
+ for(;;) switch(_token) {
+ case _SC('*'): case _SC('/'): case _SC('%'):
+ BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::PrefixedExpr); 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();
+
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
+ if(_es.etype==BASE) {
+ Emit2ArgsOP(_OP_GET);
+ pos = _fs->TopTarget();
+ _es.etype = EXPR;
+ _es.epos = pos;
+ }
+ else {
+ if(NeedGet()) {
+ Emit2ArgsOP(_OP_GET);
+ }
+ _es.etype = OBJECT;
+ }
+ 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(_es.etype==BASE) {
+ Emit2ArgsOP(_OP_GET);
+ pos = _fs->TopTarget();
+ _es.etype = EXPR;
+ _es.epos = pos;
+ }
+ else {
+ if(NeedGet()) {
+ Emit2ArgsOP(_OP_GET);
+ }
+ _es.etype = OBJECT;
+ }
+ break;
+ case TK_MINUSMINUS:
+ case TK_PLUSPLUS:
+ {
+ if(IsEndOfStatement()) return;
+ SQInteger diff = (_token==TK_MINUSMINUS) ? -1 : 1;
+ Lex();
+ switch(_es.etype)
+ {
+ case EXPR: Error(_SC("can't '++' or '--' an expression")); break;
+ case OBJECT:
+ case BASE:
+ Emit2ArgsOP(_OP_PINC, diff);
+ break;
+ case LOCAL: {
+ SQInteger src = _fs->PopTarget();
+ _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, diff);
+ }
+ break;
+ case OUTER: {
+ SQInteger tmp1 = _fs->PushTarget();
+ SQInteger tmp2 = _fs->PushTarget();
+ _fs->AddInstruction(_OP_GETOUTER, tmp2, _es.epos);
+ _fs->AddInstruction(_OP_PINCL, tmp1, tmp2, 0, diff);
+ _fs->AddInstruction(_OP_SETOUTER, tmp2, _es.epos, tmp2);
+ _fs->PopTarget();
+ }
+ }
+ }
+ return;
+ break;
+ case _SC('('):
+ switch(_es.etype) {
+ case OBJECT: {
+ SQInteger key = _fs->PopTarget(); /* location of the key */
+ SQInteger table = _fs->PopTarget(); /* location of the object */
+ SQInteger closure = _fs->PushTarget(); /* location for the closure */
+ SQInteger ttarget = _fs->PushTarget(); /* location for 'this' pointer */
+ _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);
+ }
+ break;
+ case BASE:
+ //Emit2ArgsOP(_OP_GET);
+ _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
+ break;
+ case OUTER:
+ _fs->AddInstruction(_OP_GETOUTER, _fs->PushTarget(), _es.epos);
+ _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
+ break;
+ default:
+ _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
+ }
+ _es.etype = EXPR;
+ Lex();
+ FunctionCallArgs();
+ break;
+ default: return;
+ }
+ }
+ }
+ SQInteger Factor()
+ {
+ _es.etype = EXPR;
+ switch(_token)
+ {
+ case TK_STRING_LITERAL:
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
+ Lex();
+ break;
+ case TK_BASE:
+ Lex();
+ _fs->AddInstruction(_OP_GETBASE, _fs->PushTarget());
+ _es.etype = BASE;
+ _es.epos = _fs->TopTarget();
+ return (_es.epos);
+ break;
+ case TK_IDENTIFIER:
+ case TK_CONSTRUCTOR:
+ case TK_THIS:{
+ 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) {
+ /* Handle a local variable (includes 'this') */
+ _fs->PushTarget(pos);
+ _es.etype = LOCAL;
+ _es.epos = pos;
+ }
+
+ else if((pos = _fs->GetOuterVariable(id)) != -1) {
+ /* Handle a free var */
+ if(NeedGet()) {
+ _es.epos = _fs->PushTarget();
+ _fs->AddInstruction(_OP_GETOUTER, _es.epos, pos);
+ /* _es.etype = EXPR; already default value */
+ }
+ else {
+ _es.etype = OUTER;
+ _es.epos = pos;
+ }
+ }
+
+ else if(_fs->IsConstant(id, constant)) {
+ /* Handle named constant */
+ 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;
+ }
+ _es.epos = _fs->PushTarget();
+
+ /* generate direct or literal function depending on size */
+ SQObjectType ctype = type(constval);
+ switch(ctype) {
+ case OT_INTEGER: EmitLoadConstInt(_integer(constval),_es.epos); break;
+ case OT_FLOAT: EmitLoadConstFloat(_float(constval),_es.epos); break;
+ default: _fs->AddInstruction(_OP_LOAD,_es.epos,_fs->GetConstant(constval)); break;
+ }
+ _es.etype = EXPR;
+ }
+ else {
+ /* Handle a non-local variable, aka a field. Push the 'this' pointer on
+ * the virtual stack (always found in offset 0, so no instruction needs to
+ * be generated), and push the key next. Generate an _OP_LOAD instruction
+ * for the latter. If we are not using the variable as a dref expr, generate
+ * the _OP_GET instruction.
+ */
+ _fs->PushTarget(0);
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
+ if(NeedGet()) {
+ Emit2ArgsOP(_OP_GET);
+ }
+ _es.etype = OBJECT;
+ }
+ return _es.epos;
+ }
+ break;
+ case TK_DOUBLE_COLON: // "::"
+ _fs->AddInstruction(_OP_LOADROOT, _fs->PushTarget());
+ _es.etype = OBJECT;
+ _token = _SC('.'); /* hack: drop into PrefixExpr, case '.'*/
+ _es.epos = -1;
+ return _es.epos;
+ break;
+ case TK_NULL:
+ _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
+ Lex();
+ break;
+ case TK_INTEGER: EmitLoadConstInt(_lex._nvalue,-1); Lex(); break;
+ case TK_FLOAT: EmitLoadConstFloat(_lex._fvalue,-1); 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_NEWOBJ, _fs->PushTarget(),0,0,NOT_ARRAY);
+ 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, AAT_STACK);
+ key++;
+ }
+ _fs->SetIntructionParam(apos, 1, key);
+ Lex();
+ }
+ break;
+ case _SC('{'):
+ _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
+ Lex();ParseTableOrClass(_SC(','),_SC('}'));
+ break;
+ case TK_FUNCTION: FunctionExp(_token);break;
+ case _SC('@'): FunctionExp(_token,true);break;
+ case TK_CLASS: Lex(); ClassExp();break;
+ case _SC('-'):
+ Lex();
+ switch(_token) {
+ case TK_INTEGER: EmitLoadConstInt(-_lex._nvalue,-1); Lex(); break;
+ case TK_FLOAT: EmitLoadConstFloat(-_lex._fvalue,-1); Lex(); break;
+ default: UnaryOP(_OP_NEG);
+ }
+ break;
+ case _SC('!'): Lex(); UnaryOP(_OP_NOT); break;
+ case _SC('~'):
+ Lex();
+ if(_token == TK_INTEGER) { EmitLoadConstInt(~_lex._nvalue,-1); Lex(); break; }
+ UnaryOP(_OP_BWNOT);
+ break;
+ case TK_TYPEOF : Lex() ;UnaryOP(_OP_TYPEOF); break;
+ case TK_RESUME : Lex(); UnaryOP(_OP_RESUME); break;
+ case TK_CLONE : Lex(); UnaryOP(_OP_CLONE); break;
+ case TK_MINUSMINUS :
+ case TK_PLUSPLUS :PrefixIncDec(_token); break;
+ case TK_DELETE : DeleteExpr(); break;
+ case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));
+ break;
+ default: Error(_SC("expression expected"));
+ }
+ return -1;
+ }
+ void EmitLoadConstInt(SQInteger value,SQInteger target)
+ {
+ if(target < 0) {
+ target = _fs->PushTarget();
+ }
+ if((value & (~((SQInteger)0xFFFFFFFF))) == 0) { //does it fit in 32 bits?
+ _fs->AddInstruction(_OP_LOADINT, target,value);
+ }
+ else {
+ _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));
+ }
+ }
+ void EmitLoadConstFloat(SQFloat value,SQInteger target)
+ {
+ if(target < 0) {
+ target = _fs->PushTarget();
+ }
+ if(sizeof(SQFloat) == sizeof(SQInt32)) {
+ _fs->AddInstruction(_OP_LOADFLOAT, target,*((SQInt32 *)&value));
+ }
+ else {
+ _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));
+ }
+ }
+ void UnaryOP(SQOpcode op)
+ {
+ PrefixedExpr();
+ SQInteger src = _fs->PopTarget();
+ _fs->AddInstruction(op, _fs->PushTarget(), src);
+ }
+ bool NeedGet()
+ {
+ switch(_token) {
+ 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 false;
+ }
+ return (!_es.donot_get || ( _es.donot_get && (_token == _SC('.') || _token == _SC('['))));
+ }
+ void FunctionCallArgs()
+ {
+ SQInteger nargs = 1;//this
+ while(_token != _SC(')')) {
+ Expression();
+ 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_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); 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;
+ case TK_STRING_LITERAL: //JSON
+ if(separator == ',') { //only works for tables
+ _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_STRING_LITERAL)));
+ 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
+ if(separator == _SC(',')) { //hack recognizes a table from the separator
+ _fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val);
+ }
+ else {
+ _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val); //this for classes only as it invokes _newmember
+ }
+ }
+ if(separator == _SC(',')) //hack recognizes a table from the separator
+ _fs->SetIntructionParam(tpos, 1, nkeys);
+ Lex();
+ }
+ void LocalDeclStatement()
+ {
+ SQObject varname;
+ Lex();
+ if( _token == TK_FUNCTION) {
+ Lex();
+ varname = Expect(TK_IDENTIFIER);
+ Expect(_SC('('));
+ CreateFunction(varname,false);
+ _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
+ _fs->PopTarget();
+ _fs->PushLocalVariable(varname);
+ return;
+ }
+
+ do {
+ 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);
+ if(_token == _SC(',')) Lex(); else break;
+ } while(1);
+ }
+ void IfStatement()
+ {
+ SQInteger jmppos;
+ bool haselse = false;
+ Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+ _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
+ SQInteger jnepos = _fs->GetCurrentPos();
+ BEGIN_SCOPE();
+
+ Statement();
+ //
+ if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon();
+
+ END_SCOPE();
+ SQInteger endifblock = _fs->GetCurrentPos();
+ if(_token == TK_ELSE){
+ haselse = true;
+ BEGIN_SCOPE();
+ _fs->AddInstruction(_OP_JMP);
+ jmppos = _fs->GetCurrentPos();
+ Lex();
+ Statement(); OptionalSemicolon();
+ END_SCOPE();
+ _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
+ }
+ _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));
+ }
+ void WhileStatement()
+ {
+ SQInteger jzpos, jmppos;
+ jmppos = _fs->GetCurrentPos();
+ Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+
+ BEGIN_BREAKBLE_BLOCK();
+ _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
+ jzpos = _fs->GetCurrentPos();
+ BEGIN_SCOPE();
+
+ Statement();
+
+ END_SCOPE();
+ _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
+ _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
+
+ END_BREAKBLE_BLOCK(jmppos);
+ }
+ void DoWhileStatement()
+ {
+ Lex();
+ SQInteger jmptrg = _fs->GetCurrentPos();
+ BEGIN_BREAKBLE_BLOCK()
+ BEGIN_SCOPE();
+ Statement();
+ END_SCOPE();
+ Expect(TK_WHILE);
+ SQInteger continuetrg = _fs->GetCurrentPos();
+ Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+ _fs->AddInstruction(_OP_JZ, _fs->PopTarget(), 1);
+ _fs->AddInstruction(_OP_JMP, 0, jmptrg - _fs->GetCurrentPos() - 1);
+ END_BREAKBLE_BLOCK(continuetrg);
+ }
+ void ForStatement()
+ {
+ Lex();
+ BEGIN_SCOPE();
+ 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);
+ END_SCOPE();
+
+ 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
+ BEGIN_SCOPE();
+ //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);
+ END_BREAKBLE_BLOCK(foreachpos - 1);
+ //restore the local variable stack(remove index,val and ref idx)
+ END_SCOPE();
+ }
+ 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) {
+ 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();
+ BEGIN_SCOPE();
+ Statements();
+ END_SCOPE();
+ bfirst = false;
+ }
+ if(tonextcondjmp != -1)
+ _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
+ if(_token == TK_DEFAULT) {
+ Lex(); Expect(_SC(':'));
+ BEGIN_SCOPE();
+ Statements();
+ END_SCOPE();
+ }
+ 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()
+ {
+ SQExpState es;
+ Lex();
+ es = _es;
+ _es.donot_get = true;
+ PrefixedExpr();
+ if(_es.etype == EXPR) {
+ Error(_SC("invalid class name"));
+ }
+ else if(_es.etype == OBJECT || _es.etype == BASE) {
+ ClassExp();
+ EmitDerefOp(_OP_NEWSLOT);
+ _fs->PopTarget();
+ }
+ else {
+ Error(_SC("cannot create a class in a local with the syntax(class <local>)"));
+ }
+ _es = es;
+ }
+ SQObject ExpectScalar()
+ {
+ SQObject val;
+ val._type = OT_NULL; val._unVal.nInteger = 0; //shut up GCC 4.x
+ 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;
+ 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();
+ {
+ BEGIN_SCOPE();
+ Statement();
+ END_SCOPE();
+ }
+ _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(')'));
+ {
+ BEGIN_SCOPE();
+ SQInteger ex_target = _fs->PushLocalVariable(exid);
+ _fs->SetIntructionParam(trappos, 0, ex_target);
+ Statement();
+ _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);
+ END_SCOPE();
+ }
+ }
+ void FunctionExp(SQInteger ftype,bool lambda = false)
+ {
+ Lex(); Expect(_SC('('));
+ SQObjectPtr dummy;
+ CreateFunction(dummy,lambda);
+ _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_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
+ ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);
+ attrs = _fs->TopTarget();
+ }
+ Expect(_SC('{'));
+ if(attrs != -1) _fs->PopTarget();
+ if(base != -1) _fs->PopTarget();
+ _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS);
+ ParseTableOrClass(_SC(';'),_SC('}'));
+ }
+ void DeleteExpr()
+ {
+ SQExpState es;
+ Lex();
+ es = _es;
+ _es.donot_get = true;
+ PrefixedExpr();
+ if(_es.etype==EXPR) Error(_SC("can't delete an expression"));
+ if(_es.etype==OBJECT || _es.etype==BASE) {
+ Emit2ArgsOP(_OP_DELETE);
+ }
+ else {
+ Error(_SC("cannot delete an (outer) local"));
+ }
+ _es = es;
+ }
+ void PrefixIncDec(SQInteger token)
+ {
+ SQExpState es;
+ SQInteger diff = (token==TK_MINUSMINUS) ? -1 : 1;
+ Lex();
+ es = _es;
+ _es.donot_get = true;
+ PrefixedExpr();
+ if(_es.etype==EXPR) {
+ Error(_SC("can't '++' or '--' an expression"));
+ }
+ else if(_es.etype==OBJECT || _es.etype==BASE) {
+ Emit2ArgsOP(_OP_INC, diff);
+ }
+ else if(_es.etype==LOCAL) {
+ SQInteger src = _fs->TopTarget();
+ _fs->AddInstruction(_OP_INCL, src, src, 0, diff);
+
+ }
+ else if(_es.etype==OUTER) {
+ SQInteger tmp = _fs->PushTarget();
+ _fs->AddInstruction(_OP_GETOUTER, tmp, _es.epos);
+ _fs->AddInstruction(_OP_INCL, tmp, tmp, 0, diff);
+ _fs->AddInstruction(_OP_SETOUTER, tmp, _es.epos, tmp);
+ }
+ _es = es;
+ }
+ void CreateFunction(SQObject &name,bool lambda = false)
+ {
+ 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->AddParameter(_fs->CreateString(_SC("vargv")));
+ 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();
+ }
+
+ SQFuncState *currchunk = _fs;
+ _fs = funcstate;
+ if(lambda) {
+ Expression();
+ _fs->AddInstruction(_OP_RETURN, 1, _fs->PopTarget());}
+ else {
+ Statement(false);
+ }
+ funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);
+ funcstate->AddInstruction(_OP_RETURN, -1);
+ funcstate->SetStackSize(0);
+
+ SQFunctionProto *func = funcstate->BuildProto();
+#ifdef _DEBUG_DUMP
+ funcstate->Dump(func);
+#endif
+ _fs = currchunk;
+ _fs->_functions.push_back(func);
+ _fs->PopChildState();
+ }
+ 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;
+ SQExpState _es;
+ SQScope _scope;
+ 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);
+}
+
+#endif
diff --git a/squirrel_3_0_1_stable/squirrel/sqcompiler.h b/squirrel_3_0_1_stable/squirrel/sqcompiler.h
new file mode 100644
index 000000000..fcfd46a99
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqcompiler.h
@@ -0,0 +1,77 @@
+/* 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_BASE 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_3WAYSCMP 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_
diff --git a/squirrel_3_0_1_stable/squirrel/sqdebug.cpp b/squirrel_3_0_1_stable/squirrel/sqdebug.cpp
new file mode 100644
index 000000000..3cb7b71cd
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqdebug.cpp
@@ -0,0 +1,116 @@
+/*
+ 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 = 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 = _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(const SQObjectPtr &desc)
+{
+ _lasterror = desc;
+}
+
+SQString *SQVM::PrintObjVal(const SQObjectPtr &o)
+{
+ switch(type(o)) {
+ case OT_STRING: return _string(o);
+ case OT_INTEGER:
+ scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _PRINT_INT_FMT, _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(const SQObjectPtr &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));
+}
diff --git a/squirrel_3_0_1_stable/squirrel/sqfuncproto.h b/squirrel_3_0_1_stable/squirrel/sqfuncproto.h
new file mode 100644
index 000000000..cd48aa6df
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqfuncproto.h
@@ -0,0 +1,154 @@
+/* see copyright notice in squirrel.h */
+#ifndef _SQFUNCTION_H_
+#define _SQFUNCTION_H_
+
+#include "sqopcodes.h"
+
+enum SQOuterType {
+ otLOCAL = 0,
+ otOUTER = 1
+};
+
+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),_pos(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)))
+
+
+struct SQFunctionProto : public CHAINABLE_OBJ
+{
+private:
+ SQFunctionProto(SQSharedState *ss);
+ ~SQFunctionProto();
+
+public:
+ static SQFunctionProto *Create(SQSharedState *ss,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(ss);
+ 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);
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+ void Finalize(){ _NULL_SQOBJECT_VECTOR(_literals,_nliterals); }
+ SQObjectType GetType() {return OT_FUNCPROTO;}
+#endif
+ SQObjectPtr _sourcename;
+ SQObjectPtr _name;
+ SQInteger _stacksize;
+ bool _bgenerator;
+ SQInteger _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_
diff --git a/squirrel_3_0_1_stable/squirrel/sqfuncstate.cpp b/squirrel_3_0_1_stable/squirrel/sqfuncstate.cpp
new file mode 100644
index 000000000..9e236c7e7
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqfuncstate.cpp
@@ -0,0 +1,652 @@
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#ifndef NO_COMPILER
+#include "sqcompiler.h"
+#include "sqstring.h"
+#include "sqfuncproto.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_ADD")},
+ {_SC("_OP_SUB")},
+ {_SC("_OP_MUL")},
+ {_SC("_OP_DIV")},
+ {_SC("_OP_MOD")},
+ {_SC("_OP_BITW")},
+ {_SC("_OP_RETURN")},
+ {_SC("_OP_LOADNULLS")},
+ {_SC("_OP_LOADROOT")},
+ {_SC("_OP_LOADBOOL")},
+ {_SC("_OP_DMOVE")},
+ {_SC("_OP_JMP")},
+ {_SC("_OP_JCMP")},
+ {_SC("_OP_JZ")},
+ {_SC("_OP_SETOUTER")},
+ {_SC("_OP_GETOUTER")},
+ {_SC("_OP_NEWOBJ")},
+ {_SC("_OP_APPENDARRAY")},
+ {_SC("_OP_COMPARITH")},
+ {_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_CLONE")},
+ {_SC("_OP_TYPEOF")},
+ {_SC("_OP_PUSHTRAP")},
+ {_SC("_OP_POPTRAP")},
+ {_SC("_OP_THROW")},
+ {_SC("_OP_NEWSLOTA")},
+ {_SC("_OP_GETBASE")},
+ {_SC("_OP_CLOSE")},
+ {_SC("_OP_JCMP")}
+};
+#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("{") _PRINT_INT_FMT _SC("}"),_integer(o));break;
+ case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
+ default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_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;
+ _outers = 0;
+ _ss = ss;
+
+}
+
+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();
+}
+
+SQInteger SQFuncState::CountOuters(SQInteger stacksize)
+{
+ SQInteger outers = 0;
+ SQInteger k = _vlocals.size() - 1;
+ while(k >= stacksize) {
+ SQLocalVarInfo &lvi = _vlocals[k];
+ k--;
+ if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
+ outers++;
+ }
+ }
+ return outers;
+}
+
+void SQFuncState::SetStackSize(SQInteger n)
+{
+ SQInteger size=_vlocals.size();
+ while(size>n){
+ size--;
+ SQLocalVarInfo lvi = _vlocals.back();
+ if(type(lvi._name)!=OT_NULL){
+ if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
+ _outers--;
+ }
+ 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){
+ SQLocalVarInfo &lvi = _vlocals[locals-1];
+ if(type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){
+ return locals-1;
+ }
+ locals--;
+ }
+ return -1;
+}
+
+void SQFuncState::MarkLocalAsOuter(SQInteger pos)
+{
+ SQLocalVarInfo &lvi = _vlocals[pos];
+ lvi._end_op = UINT_MINUS_ONE;
+ _outers++;
+}
+
+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;
+ }
+ 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 _outervalues.size() - 1;
+ }
+ }
+ else {
+ _parent->MarkLocalAsOuter(pos);
+ _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
+ return _outervalues.size() - 1;
+
+
+ }
+ }
+ return -1;
+}
+
+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);
+ if(_lastline!=line) {
+ _lineinfos.push_back(li);
+ }
+ _lastline=line;
+ }
+}
+
+void SQFuncState::DiscardTarget()
+{
+ SQInteger discardedtarget = PopTarget();
+ SQInteger size = _instructions.size();
+ if(size > 0 && _optimization){
+ SQInstruction &pi = _instructions[size-1];//previous instruction
+ switch(pi.op) {
+ case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL:
+ if(pi._arg0 == discardedtarget) {
+ pi._arg0 = 0xFF;
+ }
+ }
+ }
+}
+
+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_JZ:
+ if( pi.op == _OP_CMP && pi._arg1 < 0xFF) {
+ pi.op = _OP_JCMP;
+ pi._arg0 = (unsigned char)pi._arg1;
+ pi._arg1 = i._arg1;
+ return;
+ }
+ case _OP_SET:
+ case _OP_NEWSLOT:
+ if(i._arg0 == i._arg3) {
+ i._arg0 = 0xFF;
+ }
+ break;
+ case _OP_SETOUTER:
+ if(i._arg0 == i._arg2) {
+ i._arg0 = 0xFF;
+ }
+ break;
+ case _OP_RETURN:
+ if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
+ pi.op = _OP_TAILCALL;
+ } else if(pi.op == _OP_CLOSE){
+ pi = i;
+ return;
+ }
+ 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: {
+ SQInteger aat = -1;
+ switch(pi.op) {
+ case _OP_LOAD: aat = AAT_LITERAL; break;
+ case _OP_LOADINT: aat = AAT_INT; break;
+ case _OP_LOADBOOL: aat = AAT_BOOL; break;
+ case _OP_LOADFLOAT: aat = AAT_FLOAT; break;
+ default: break;
+ }
+ if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
+ pi.op = _OP_APPENDARRAY;
+ pi._arg0 = i._arg0;
+ pi._arg1 = pi._arg1;
+ pi._arg2 = (unsigned char)aat;
+ pi._arg3 = MAX_FUNC_STACKSIZE;
+ return;
+ }
+ }
+ break;
+ case _OP_MOVE:
+ switch(pi.op) {
+ case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW:
+ case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD:
+
+ if(pi._arg0 == i._arg1)
+ {
+ pi._arg0 = i._arg0;
+ _optimization = false;
+ //_result_elimination = 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(_ss,_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 nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl];
+ for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni];
+ for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd];
+
+ 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();
+ }
+}
+
+#endif
diff --git a/squirrel_3_0_1_stable/squirrel/sqfuncstate.h b/squirrel_3_0_1_stable/squirrel/sqfuncstate.h
new file mode 100644
index 000000000..1da13212a
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqfuncstate.h
@@ -0,0 +1,91 @@
+/* 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);
+ SQInteger CountOuters(SQInteger stacksize);
+ 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);
+ void MarkLocalAsOuter(SQInteger pos);
+ 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);
+ void DiscardTarget();
+ 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 _scope_blocks;
+ SQIntVec _breaktargets;
+ SQIntVec _continuetargets;
+ SQIntVec _defaultparams;
+ SQInteger _lastline;
+ SQInteger _traps; //contains number of nested exception traps
+ SQInteger _outers;
+ bool _optimization;
+ SQSharedState *_sharedstate;
+ sqvector<SQFuncState*> _childstates;
+ SQInteger GetConstant(const SQObject &cons);
+private:
+ CompilerErrorFunc _errfunc;
+ void *_errtarget;
+ SQSharedState *_ss;
+};
+
+
+#endif //_SQFUNCSTATE_H_
+
diff --git a/squirrel_3_0_1_stable/squirrel/sqlexer.cpp b/squirrel_3_0_1_stable/squirrel/sqlexer.cpp
new file mode 100644
index 000000000..ab17ba619
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqlexer.cpp
@@ -0,0 +1,489 @@
+/*
+ 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(base, TK_BASE);
+ 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(class,TK_CLASS);
+ ADD_KEYWORD(extends,TK_EXTENDS);
+ ADD_KEYWORD(constructor,TK_CONSTRUCTOR);
+ ADD_KEYWORD(instanceof,TK_INSTANCEOF);
+ 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;
+ _reached_eof = SQFalse;
+ 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;
+ _reached_eof = SQTrue;
+}
+
+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();
+ }
+ }
+}
+void SQLexer::LexLineComment()
+{
+ do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));
+}
+
+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('#'): LexLineComment(); continue;
+ case _SC('/'):
+ NEXT();
+ switch(CUR_CHAR){
+ case _SC('*'):
+ NEXT();
+ LexBlockComment();
+ continue;
+ case _SC('/'):
+ LexLineComment();
+ 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();
+ switch(CUR_CHAR) {
+ case _SC('='):
+ NEXT();
+ if(CUR_CHAR == _SC('>')) {
+ NEXT();
+ RETURN_TOKEN(TK_3WAYSCMP);
+ }
+ RETURN_TOKEN(TK_LE)
+ break;
+ case _SC('-'): NEXT(); RETURN_TOKEN(TK_NEWSLOT); break;
+ case _SC('<'): NEXT(); RETURN_TOKEN(TK_SHIFTL); break;
+ case _SC('/'): NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); break;
+ }
+ 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('"')) {
+ RETURN_TOKEN('@');
+ }
+ 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;
+}
diff --git a/squirrel_3_0_1_stable/squirrel/sqlexer.h b/squirrel_3_0_1_stable/squirrel/sqlexer.h
new file mode 100644
index 000000000..d3283c6f7
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqlexer.h
@@ -0,0 +1,47 @@
+/* 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();
+ void LexLineComment();
+ SQInteger ReadID();
+ void Next();
+ SQInteger _curtoken;
+ SQTable *_keywords;
+ SQBool _reached_eof;
+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
diff --git a/squirrel_3_0_1_stable/squirrel/sqmem.cpp b/squirrel_3_0_1_stable/squirrel/sqmem.cpp
new file mode 100644
index 000000000..520f7eb76
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqmem.cpp
@@ -0,0 +1,9 @@
+/*
+ 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); }
diff --git a/squirrel_3_0_1_stable/squirrel/sqobject.cpp b/squirrel_3_0_1_stable/squirrel/sqobject.cpp
new file mode 100644
index 000000000..418a6d656
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqobject.cpp
@@ -0,0 +1,655 @@
+/*
+ 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");
+ case _RT_OUTER: return _SC("outer");
+ 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);
+ 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,SQInteger target)
+{
+ 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;
+
+ _stack.resize(size);
+ SQObject _this = v->_stack[v->_stackbase];
+ _stack._vals[0] = ISREFCOUNTED(type(_this)) ? SQObjectPtr(_refcounted(_this)->GetWeakRef(type(_this))) : _this;
+ for(SQInteger n =1; n<target; n++) {
+ _stack._vals[n] = v->_stack[v->_stackbase+n];
+ }
+ for(SQInteger j =0; j < size; j++)
+ {
+ v->_stack[v->_stackbase+j].Null();
+ }
+
+ _ci = *v->ci;
+ _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,SQObjectPtr &dest)
+{
+ 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 size = _stack.size();
+ SQInteger target = &dest - &(v->_stack._vals[v->_stackbase]);
+ assert(target>=0 && target<=255);
+ if(!v->EnterFrame(v->_top, v->_top + size, false))
+ return false;
+ v->ci->_generator = this;
+ v->ci->_target = (SQInt32)target;
+ v->ci->_closure = _ci._closure;
+ v->ci->_ip = _ci._ip;
+ v->ci->_literals = _ci._literals;
+ v->ci->_ncalls = _ci._ncalls;
+ v->ci->_etraps = _ci._etraps;
+ v->ci->_root = _ci._root;
+
+
+ for(SQInteger i=0;i<_ci._etraps;i++) {
+ v->_etraps.push_back(_etraps.top());
+ _etraps.pop_back();
+ }
+ SQObject _this = _stack._vals[0];
+ v->_stack[v->_stackbase] = type(_this) == OT_WEAKREF ? _weakref(_this)->_obj : _this;
+
+ for(SQInteger n = 1; n<size; n++) {
+ v->_stack[v->_stackbase+n] = _stack._vals[n];
+ _stack._vals[n].Null();
+ }
+
+ _state=eRunning;
+ if (v->_debughook)
+ 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;
+ SQInteger low = 0;
+ SQInteger high = _nlineinfos - 1;
+ SQInteger mid = 0;
+ while(low <= high)
+ {
+ mid = low + ((high - low) >> 1);
+ SQInteger curop = _lineinfos[mid]._op;
+ if(curop > op)
+ {
+ high = mid - 1;
+ }
+ else if(curop < op) {
+ if(mid < (_nlineinfos - 1)
+ && _lineinfos[mid + 1]._op >= op) {
+ break;
+ }
+ low = mid + 1;
+ }
+ else { //equal
+ break;
+ }
+ }
+
+ line = _lineinfos[mid]._line;
+ return line;
+}
+
+SQClosure::~SQClosure()
+{
+ __ObjRelease(_env);
+ __ObjRelease(_base);
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+}
+
+#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,SQUnsignedInteger32 tag)
+{
+ return SafeWrite(v,write,up,&tag,sizeof(tag));
+}
+
+bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUnsignedInteger32 tag)
+{
+ SQUnsignedInteger32 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)
+{
+ SQUnsignedInteger32 _type = (SQUnsignedInteger32)type(o);
+ _CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type)));
+ 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)
+{
+ SQUnsignedInteger32 _type;
+ _CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type)));
+ SQObjectType t = (SQObjectType)_type;
+ 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(WriteTag(v,write,up,sizeof(SQInteger)));
+ _CHECK_IO(WriteTag(v,write,up,sizeof(SQFloat)));
+ _CHECK_IO(_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)));
+ _CHECK_IO(CheckTag(v,read,up,sizeof(SQInteger)));
+ _CHECK_IO(CheckTag(v,read,up,sizeof(SQFloat)));
+ 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;
+}
+
+SQFunctionProto::SQFunctionProto(SQSharedState *ss)
+{
+ _stacksize=0;
+ _bgenerator=false;
+ INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);
+}
+
+SQFunctionProto::~SQFunctionProto()
+{
+ REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+}
+
+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(_opt_ss(v),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_closure,chain);
+ SQSharedState::MarkObject(_roottable, chain);
+ SQSharedState::MarkObject(temp_reg, chain);
+ for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], 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< MT_LAST; 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);
+ SQSharedState::MarkObject(_closure, chain);
+ END_MARK()
+}
+
+void SQFunctionProto::Mark(SQCollectable **chain)
+{
+ START_MARK()
+ for(SQInteger i = 0; i < _nliterals; i++) SQSharedState::MarkObject(_literals[i], chain);
+ for(SQInteger k = 0; k < _nfunctions; k++) SQSharedState::MarkObject(_functions[k], chain);
+ END_MARK()
+}
+
+void SQClosure::Mark(SQCollectable **chain)
+{
+ START_MARK()
+ if(_base) _base->Mark(chain);
+ SQFunctionProto *fp = _function;
+ fp->Mark(chain);
+ for(SQInteger i = 0; i < fp->_noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain);
+ for(SQInteger k = 0; k < fp->_ndefaultparams; k++) SQSharedState::MarkObject(_defaultparams[k], chain);
+ END_MARK()
+}
+
+void SQNativeClosure::Mark(SQCollectable **chain)
+{
+ START_MARK()
+ for(SQUnsignedInteger i = 0; i < _noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain);
+ END_MARK()
+}
+
+void SQOuter::Mark(SQCollectable **chain)
+{
+ START_MARK()
+ /* If the valptr points to a closed value, that value is alive */
+ if(_valptr == &_value) {
+ SQSharedState::MarkObject(_value, chain);
+ }
+ END_MARK()
+}
+
+void SQUserData::Mark(SQCollectable **chain){
+ START_MARK()
+ if(_delegate) _delegate->Mark(chain);
+ END_MARK()
+}
+
+void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; }
+
+#endif
+
diff --git a/squirrel_3_0_1_stable/squirrel/sqobject.h b/squirrel_3_0_1_stable/squirrel/sqobject.h
new file mode 100644
index 000000000..a7d1e1ed3
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqobject.h
@@ -0,0 +1,354 @@
+/* see copyright notice in squirrel.h */
+#ifndef _SQOBJECT_H_
+#define _SQOBJECT_H_
+
+#include "squtils.h"
+
+#ifdef _SQ64
+#define UINT_MINUS_ONE (0xFFFFFFFFFFFFFFFF)
+#else
+#define UINT_MINUS_ONE (0xFFFFFFFF)
+#endif
+
+#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 _CONSTRUCT_VECTOR(type,size,ptr) { \
+ for(SQInteger n = 0; n < ((SQInteger)size); n++) { \
+ new (&ptr[n]) type(); \
+ } \
+}
+
+#define _DESTRUCT_VECTOR(type,size,ptr) { \
+ for(SQInteger nl = 0; nl < ((SQInteger)size); nl++) { \
+ ptr[nl].~type(); \
+ } \
+}
+
+#define _COPY_VECTOR(dest,src,size) { \
+ for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \
+ dest[_n_] = src[_n_]; \
+ } \
+}
+
+#define _NULL_SQOBJECT_VECTOR(vec,size) { \
+ for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \
+ vec[_n_].Null(); \
+ } \
+}
+
+#define MINPOWER2 4
+
+struct SQRefCounted
+{
+ SQUnsignedInteger _uiRef;
+ struct SQWeakRef *_weakref;
+ SQRefCounted() { _uiRef = 0; _weakref = NULL; }
+ virtual ~SQRefCounted();
+ SQWeakRef *GetWeakRef(SQObjectType type);
+ 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 _outer(obj) ((obj)._unVal.pOuter)
+#define _refcounted(obj) ((obj)._unVal.pRefCounted)
+#define _rawval(obj) ((obj)._unVal.raw)
+
+#define _stringval(obj) (obj)._unVal.pString->_val
+#define _userdataval(obj) ((SQUserPointer)sq_aligning((obj)._unVal.pUserData + 1))
+
+#define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num))
+#define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num))
+/////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+#if defined(SQUSEDOUBLE) && !defined(_SQ64) || !defined(SQUSEDOUBLE) && defined(_SQ64)
+#define SQ_REFOBJECT_INIT() SQ_OBJECT_RAWINIT()
+#else
+#define SQ_REFOBJECT_INIT()
+#endif
+
+#define _REF_TYPE_DECL(type,_class,sym) \
+ SQObjectPtr(_class * x) \
+ { \
+ SQ_OBJECT_RAWINIT() \
+ _type=type; \
+ _unVal.sym = x; \
+ assert(_unVal.pTable); \
+ _unVal.pRefCounted->_uiRef++; \
+ } \
+ inline SQObjectPtr& operator=(_class *x) \
+ { \
+ SQObjectType tOldType; \
+ SQObjectValue unOldVal; \
+ tOldType=_type; \
+ unOldVal=_unVal; \
+ _type = type; \
+ SQ_REFOBJECT_INIT() \
+ _unVal.sym = x; \
+ _unVal.pRefCounted->_uiRef++; \
+ __Release(tOldType,unOldVal); \
+ return *this; \
+ }
+
+#define _SCALAR_TYPE_DECL(type,_class,sym) \
+ SQObjectPtr(_class x) \
+ { \
+ SQ_OBJECT_RAWINIT() \
+ _type=type; \
+ _unVal.sym = x; \
+ } \
+ inline SQObjectPtr& operator=(_class x) \
+ { \
+ __Release(_type,_unVal); \
+ _type = type; \
+ SQ_OBJECT_RAWINIT() \
+ _unVal.sym = x; \
+ return *this; \
+ }
+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);
+ }
+ _REF_TYPE_DECL(OT_TABLE,SQTable,pTable)
+ _REF_TYPE_DECL(OT_CLASS,SQClass,pClass)
+ _REF_TYPE_DECL(OT_INSTANCE,SQInstance,pInstance)
+ _REF_TYPE_DECL(OT_ARRAY,SQArray,pArray)
+ _REF_TYPE_DECL(OT_CLOSURE,SQClosure,pClosure)
+ _REF_TYPE_DECL(OT_NATIVECLOSURE,SQNativeClosure,pNativeClosure)
+ _REF_TYPE_DECL(OT_OUTER,SQOuter,pOuter)
+ _REF_TYPE_DECL(OT_GENERATOR,SQGenerator,pGenerator)
+ _REF_TYPE_DECL(OT_STRING,SQString,pString)
+ _REF_TYPE_DECL(OT_USERDATA,SQUserData,pUserData)
+ _REF_TYPE_DECL(OT_WEAKREF,SQWeakRef,pWeakRef)
+ _REF_TYPE_DECL(OT_THREAD,SQVM,pThread)
+ _REF_TYPE_DECL(OT_FUNCPROTO,SQFunctionProto,pFunctionProto)
+
+ _SCALAR_TYPE_DECL(OT_INTEGER,SQInteger,nInteger)
+ _SCALAR_TYPE_DECL(OT_FLOAT,SQFloat,fFloat)
+ _SCALAR_TYPE_DECL(OT_USERPOINTER,SQUserPointer,pUserPointer)
+
+ SQObjectPtr(bool bBool)
+ {
+ SQ_OBJECT_RAWINIT()
+ _type = OT_BOOL;
+ _unVal.nInteger = bBool?1:0;
+ }
+ inline SQObjectPtr& operator=(bool b)
+ {
+ __Release(_type,_unVal);
+ SQ_OBJECT_RAWINIT()
+ _type = OT_BOOL;
+ _unVal.nInteger = b?1:0;
+ return *this;
+ }
+
+ ~SQObjectPtr()
+ {
+ __Release(_type,_unVal);
+ }
+
+ 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;
+ }
+ inline void Null()
+ {
+ __Release(_type ,_unVal);
+ _type = OT_NULL;
+ _unVal.raw = NULL;
+ }
+ private:
+ SQObjectPtr(const SQChar *){} //safety
+};
+
+
+inline void _Swap(SQObject &a,SQObject &b)
+{
+ SQObjectType tOldType = a._type;
+ SQObjectValue unOldVal = a._unVal;
+ a._type = b._type;
+ a._unVal = b._unVal;
+ b._type = tOldType;
+ b._unVal = unOldVal;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+#ifndef NO_GARBAGE_COLLECTOR
+#define MARK_FLAG 0x80000000
+struct SQCollectable : public SQRefCounted {
+ SQCollectable *_next;
+ SQCollectable *_prev;
+ SQSharedState *_sharedstate;
+ virtual SQObjectType GetType()=0;
+ 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_
diff --git a/squirrel_3_0_1_stable/squirrel/sqopcodes.h b/squirrel_3_0_1_stable/squirrel/sqopcodes.h
new file mode 100644
index 000000000..4d179812f
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqopcodes.h
@@ -0,0 +1,132 @@
+/* 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,
+ CMP_3W = 5
+};
+
+enum NewObjectType {
+ NOT_TABLE = 0,
+ NOT_ARRAY = 1,
+ NOT_CLASS = 2
+};
+
+enum AppendArrayType {
+ AAT_STACK = 0,
+ AAT_LITERAL = 1,
+ AAT_INT = 2,
+ AAT_FLOAT = 3,
+ AAT_BOOL = 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_ADD= 0x11,
+ _OP_SUB= 0x12,
+ _OP_MUL= 0x13,
+ _OP_DIV= 0x14,
+ _OP_MOD= 0x15,
+ _OP_BITW= 0x16,
+ _OP_RETURN= 0x17,
+ _OP_LOADNULLS= 0x18,
+ _OP_LOADROOT= 0x19,
+ _OP_LOADBOOL= 0x1A,
+ _OP_DMOVE= 0x1B,
+ _OP_JMP= 0x1C,
+ //_OP_JNZ= 0x1D,
+ _OP_JCMP= 0x1D,
+ _OP_JZ= 0x1E,
+ _OP_SETOUTER= 0x1F,
+ _OP_GETOUTER= 0x20,
+ _OP_NEWOBJ= 0x21,
+ _OP_APPENDARRAY= 0x22,
+ _OP_COMPARITH= 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_CLONE= 0x35,
+ _OP_TYPEOF= 0x36,
+ _OP_PUSHTRAP= 0x37,
+ _OP_POPTRAP= 0x38,
+ _OP_THROW= 0x39,
+ _OP_NEWSLOTA= 0x3A,
+ _OP_GETBASE= 0x3B,
+ _OP_CLOSE= 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_
diff --git a/squirrel_3_0_1_stable/squirrel/sqpcheader.h b/squirrel_3_0_1_stable/squirrel/sqpcheader.h
new file mode 100644
index 000000000..f0e5cf2df
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqpcheader.h
@@ -0,0 +1,19 @@
+/* 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_
diff --git a/squirrel_3_0_1_stable/squirrel/sqstate.cpp b/squirrel_3_0_1_stable/squirrel/sqstate.cpp
new file mode 100644
index 000000000..0bee40661
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqstate.cpp
@@ -0,0 +1,648 @@
+/*
+ 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;
+ _errorfunc = 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,0);
+ 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
+ _stringtable = (SQStringTable*)SQ_MALLOC(sizeof(SQStringTable));
+ new (_stringtable) SQStringTable(this);
+ 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,SQStringTable);
+ 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;
+ case OT_OUTER:_outer(o)->Mark(chain);break;
+ case OT_FUNCPROTO:_funcproto(o)->Mark(chain);break;
+ default: break; //shutup compiler
+ }
+}
+
+
+void SQSharedState::RunMark(SQVM *vm,SQCollectable **tchain)
+{
+ SQVM *vms = _thread(_root_vm);
+
+ vms->Mark(tchain);
+
+ _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);
+
+}
+
+SQInteger SQSharedState::ResurrectUnreachable(SQVM *vm)
+{
+ SQInteger n=0;
+ SQCollectable *tchain=NULL;
+
+ RunMark(vm,&tchain);
+
+ SQCollectable *resurrected = _gc_chain;
+ SQCollectable *t = resurrected;
+ //SQCollectable *nx = NULL;
+
+ _gc_chain = tchain;
+
+ SQArray *ret = NULL;
+ if(resurrected) {
+ ret = SQArray::Create(this,0);
+ SQCollectable *rlast = NULL;
+ while(t) {
+ rlast = t;
+ SQObjectType type = t->GetType();
+ if(type != OT_FUNCPROTO && type != OT_OUTER) {
+ SQObject sqo;
+ sqo._type = type;
+ sqo._unVal.pRefCounted = t;
+ ret->Append(sqo);
+ }
+ t = t->_next;
+ n++;
+ }
+
+ assert(rlast->_next == NULL);
+ rlast->_next = _gc_chain;
+ if(_gc_chain)
+ {
+ _gc_chain->_prev = rlast;
+ }
+ _gc_chain = resurrected;
+ }
+
+ t = _gc_chain;
+ while(t) {
+ t->UnMark();
+ t = t->_next;
+ }
+
+ if(ret) {
+ SQObjectPtr temp = ret;
+ vm->Push(temp);
+ }
+ else {
+ vm->PushNull();
+ }
+ return n;
+}
+
+SQInteger SQSharedState::CollectGarbage(SQVM *vm)
+{
+ SQInteger n=0;
+ SQCollectable *tchain=NULL;
+
+ RunMark(vm,&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;
+
+ 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++;
+}
+
+SQUnsignedInteger RefTable::GetRefCount(SQObject &obj)
+{
+ SQHash mainpos;
+ RefNode *prev;
+ RefNode *ref = Get(obj,mainpos,&prev,true);
+ return 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;
+}
+//////////////////////////////////////////////////////////////////////////
+//SQStringTable
+/*
+* 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
+*/
+
+SQStringTable::SQStringTable(SQSharedState *ss)
+{
+ _sharedstate = ss;
+ AllocNodes(4);
+ _slotused = 0;
+}
+
+SQStringTable::~SQStringTable()
+{
+ SQ_FREE(_strings,sizeof(SQString*)*_numofslots);
+ _strings = NULL;
+}
+
+void SQStringTable::AllocNodes(SQInteger size)
+{
+ _numofslots = size;
+ _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
+ memset(_strings,0,sizeof(SQString*)*_numofslots);
+}
+
+SQString *SQStringTable::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;
+ t->_sharedstate = _sharedstate;
+ 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 SQStringTable::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 SQStringTable::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
+}
diff --git a/squirrel_3_0_1_stable/squirrel/sqstate.h b/squirrel_3_0_1_stable/squirrel/sqstate.h
new file mode 100644
index 000000000..3ed3307d7
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqstate.h
@@ -0,0 +1,144 @@
+/* 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 SQStringTable
+{
+ SQStringTable(SQSharedState*ss);
+ ~SQStringTable();
+ SQString *Add(const SQChar *,SQInteger len);
+ void Remove(SQString *);
+private:
+ void Resize(SQInteger size);
+ void AllocNodes(SQInteger size);
+ SQString **_strings;
+ SQUnsignedInteger _numofslots;
+ SQUnsignedInteger _slotused;
+ SQSharedState *_sharedstate;
+};
+
+struct RefTable {
+ struct RefNode {
+ SQObjectPtr obj;
+ SQUnsignedInteger refs;
+ struct RefNode *next;
+ };
+ RefTable();
+ ~RefTable();
+ void AddRef(SQObject &obj);
+ SQBool Release(SQObject &obj);
+ SQUnsignedInteger GetRefCount(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);
+ void RunMark(SQVM *vm,SQCollectable **tchain);
+ SQInteger ResurrectUnreachable(SQVM *vm);
+ static void MarkObject(SQObjectPtr &o,SQCollectable **chain);
+#endif
+ SQObjectPtrVec *_metamethods;
+ SQObjectPtr _metamethodsmap;
+ SQObjectPtrVec *_systemstrings;
+ SQObjectPtrVec *_types;
+ SQStringTable *_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;
+ SQPRINTFUNCTION _errorfunc;
+ 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_;
+
+bool CompileTypemask(SQIntVec &res,const SQChar *typemask);
+
+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 //_SQSTATE_H_
diff --git a/squirrel_3_0_1_stable/squirrel/sqstring.h b/squirrel_3_0_1_stable/squirrel/sqstring.h
new file mode 100644
index 000000000..235d19059
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqstring.h
@@ -0,0 +1,31 @@
+/* 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_
diff --git a/squirrel_3_0_1_stable/squirrel/sqtable.cpp b/squirrel_3_0_1_stable/squirrel/sqtable.cpp
new file mode 100644
index 000000000..fe3d5f2a1
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqtable.cpp
@@ -0,0 +1,220 @@
+/*
+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.Null();
+ 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++){
+ _HashNode &n = nodes[i];
+ new (&n) _HashNode;
+ n.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);
+#ifdef _FAST_CLONE
+ _HashNode *basesrc = _nodes;
+ _HashNode *basedst = nt->_nodes;
+ _HashNode *src = _nodes;
+ _HashNode *dst = nt->_nodes;
+ SQInteger n = 0;
+ for(n = 0; n < _numofnodes; n++) {
+ dst->key = src->key;
+ dst->val = src->val;
+ if(src->next) {
+ assert(src->next > basesrc);
+ dst->next = basedst + (src->next - basesrc);
+ assert(dst != dst->next);
+ }
+ dst++;
+ src++;
+ }
+ assert(_firstfree > basesrc);
+ assert(_firstfree != NULL);
+ nt->_firstfree = basedst + (_firstfree - basesrc);
+#else
+ SQInteger ridx=0;
+ SQObjectPtr key,val;
+ while((ridx=Next(true,ridx,key,val))!=-1){
+ nt->NewSlot(key,val);
+ }
+#endif
+ 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++) { _HashNode &n = _nodes[i]; n.key.Null(); n.val.Null(); }
+}
+
+void SQTable::Finalize()
+{
+ _ClearNodes();
+ SetDelegate(NULL);
+}
+
+void SQTable::Clear()
+{
+ _ClearNodes();
+ _usednodes = 0;
+ Rehash(true);
+}
diff --git a/squirrel_3_0_1_stable/squirrel/sqtable.h b/squirrel_3_0_1_stable/squirrel/sqtable.h
new file mode 100644
index 000000000..2f6487023
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqtable.h
@@ -0,0 +1,92 @@
+/* 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);
+ SQObjectType GetType() {return OT_TABLE;}
+#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_
diff --git a/squirrel_3_0_1_stable/squirrel/squirrel.dsp b/squirrel_3_0_1_stable/squirrel/squirrel.dsp
new file mode 100644
index 000000000..4778b6963
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/squirrel.dsp
@@ -0,0 +1,302 @@
+# Microsoft Developer Studio Project File - Name="squirrel" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Static Library" 0x0104
+
+CFG=squirrel - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "squirrel.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "squirrel.mak" CFG="squirrel - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "squirrel - Win32 Release" (based on "Win32 (x86) Static Library")
+!MESSAGE "squirrel - Win32 Debug" (based on "Win32 (x86) Static Library")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_LocalPath ".."
+CPP=cl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "squirrel - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c
+# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /D "GARBAGE_COLLECTOR" /YX /FD /c
+# ADD BASE RSC /l 0x410 /d "NDEBUG"
+# ADD RSC /l 0x410 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\squirrel.lib"
+
+!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c
+# ADD BASE RSC /l 0x410 /d "_DEBUG"
+# ADD RSC /l 0x410 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LIB32=link.exe -lib
+# ADD BASE LIB32 /nologo
+# ADD LIB32 /nologo /out:"..\lib\squirrel.lib"
+
+!ENDIF
+
+# Begin Target
+
+# Name "squirrel - Win32 Release"
+# Name "squirrel - Win32 Debug"
+# Begin Group "Source Files"
+
+# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
+# Begin Source File
+
+SOURCE=.\sqapi.cpp
+
+!IF "$(CFG)" == "squirrel - Win32 Release"
+
+!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
+
+# ADD CPP /YX"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqbaselib.cpp
+
+!IF "$(CFG)" == "squirrel - Win32 Release"
+
+!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
+
+# ADD CPP /YX"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqcompiler.cpp
+
+!IF "$(CFG)" == "squirrel - Win32 Release"
+
+!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
+
+# ADD CPP /YX"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqdebug.cpp
+
+!IF "$(CFG)" == "squirrel - Win32 Release"
+
+!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
+
+# ADD CPP /YX"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqfuncstate.cpp
+
+!IF "$(CFG)" == "squirrel - Win32 Release"
+
+!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
+
+# ADD CPP /YX"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqlexer.cpp
+
+!IF "$(CFG)" == "squirrel - Win32 Release"
+
+!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
+
+# ADD CPP /YX"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqmem.cpp
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqobject.cpp
+
+!IF "$(CFG)" == "squirrel - Win32 Release"
+
+!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
+
+# ADD CPP /YX"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstate.cpp
+
+!IF "$(CFG)" == "squirrel - Win32 Release"
+
+!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
+
+# ADD CPP /YX"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqtable.cpp
+
+!IF "$(CFG)" == "squirrel - Win32 Release"
+
+!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
+
+# ADD CPP /YX"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqclass.cpp
+
+!IF "$(CFG)" == "squirrel - Win32 Release"
+
+!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
+
+# ADD CPP /YX"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqvm.cpp
+
+!IF "$(CFG)" == "squirrel - Win32 Release"
+
+!ELSEIF "$(CFG)" == "squirrel - Win32 Debug"
+
+# ADD CPP /YX"stdafx.h"
+
+!ENDIF
+
+# End Source File
+# End Group
+# Begin Group "Header Files"
+
+# PROP Default_Filter "h;hpp;hxx;hm;inl"
+# Begin Source File
+
+SOURCE=.\sqarray.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqclosure.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqcompiler.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqfuncproto.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqfuncstate.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqlexer.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqobject.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqopcodes.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqpcheader.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstate.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqstring.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqtable.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\squserdata.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\squtils.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqclass.h
+# End Source File
+# Begin Source File
+
+SOURCE=.\sqvm.h
+# End Source File
+# End Group
+# End Target
+# End Project
diff --git a/squirrel_3_0_1_stable/squirrel/squserdata.h b/squirrel_3_0_1_stable/squirrel/squserdata.h
new file mode 100644
index 000000000..dea27ae78
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/squserdata.h
@@ -0,0 +1,40 @@
+/* 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(sq_aligning(sizeof(SQUserData))+size);
+ new (ud) SQUserData(ss);
+ ud->_size = size;
+ ud->_typetag = 0;
+ return ud;
+ }
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+ void Finalize(){SetDelegate(NULL);}
+ SQObjectType GetType(){ return OT_USERDATA;}
+#endif
+ void Release() {
+ if (_hook) _hook((SQUserPointer)sq_aligning(this + 1),_size);
+ SQInteger tsize = _size;
+ this->~SQUserData();
+ SQ_FREE(this, sq_aligning(sizeof(SQUserData)) + tsize);
+ }
+
+
+ SQInteger _size;
+ SQRELEASEHOOK _hook;
+ SQUserPointer _typetag;
+ //SQChar _val[1];
+};
+
+#endif //_SQUSERDATA_H_
diff --git a/squirrel_3_0_1_stable/squirrel/squtils.h b/squirrel_3_0_1_stable/squirrel/squtils.h
new file mode 100644
index 000000000..bff7d24bb
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/squtils.h
@@ -0,0 +1,112 @@
+/* see copyright notice in squirrel.h */
+#ifndef _SQUTILS_H_
+#define _SQUTILS_H_
+
+#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;}
+#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));}
+#define SQ_MALLOC(__size) sq_vm_malloc((__size));
+#define SQ_FREE(__ptr,__size) sq_vm_free((__ptr),(__size));
+#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc((__ptr),(__oldsize),(__size));
+
+#define sq_aligning(v) (((size_t)(v) + (SQ_ALIGNMENT-1)) & (~(SQ_ALIGNMENT-1)))
+
+//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)
+ {
+ if(_size) {
+ resize(0); //destroys all previous stuff
+ }
+ //resize(v._size);
+ if(v._size > _allocated) {
+ _realloc(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)) {
+ memcpy(&_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_
diff --git a/squirrel_3_0_1_stable/squirrel/sqvm.cpp b/squirrel_3_0_1_stable/squirrel/sqvm.cpp
new file mode 100644
index 000000000..bd8ebcc1a
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqvm.cpp
@@ -0,0 +1,1714 @@
+/*
+ see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include <math.h>
+#include <stdlib.h>
+#include "sqopcodes.h"
+#include "sqvm.h"
+#include "sqfuncproto.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])
+
+bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)
+{
+ SQInteger res;
+ if((type(o1)|type(o2)) == OT_INTEGER)
+ {
+ SQInteger i1 = _integer(o1), i2 = _integer(o2);
+ 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;
+}
+
+#define _ARITH_(op,trg,o1,o2) \
+{ \
+ SQInteger tmask = type(o1)|type(o2); \
+ switch(tmask) { \
+ case OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \
+ case (OT_FLOAT|OT_INTEGER): \
+ case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\
+ default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\
+ } \
+}
+
+#define _ARITH_NOZERO(op,trg,o1,o2,err) \
+{ \
+ SQInteger tmask = type(o1)|type(o2); \
+ switch(tmask) { \
+ case OT_INTEGER: { SQInteger i2 = _integer(o2); if(i2 == 0) { Raise_Error(err); SQ_THROW(); } trg = _integer(o1) op i2; } break;\
+ case (OT_FLOAT|OT_INTEGER): \
+ case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\
+ default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\
+ } \
+}
+
+bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)
+{
+ SQInteger tmask = type(o1)|type(o2);
+ switch(tmask) {
+ case 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; }
+ break;
+ case (OT_FLOAT|OT_INTEGER):
+ case (OT_FLOAT):{
+ 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; }
+ break;
+ default:
+ if(op == '+' && (tmask & _RT_STRING)){
+ if(!StringCat(o1, o2, trg)) return false;
+ }
+ else if(!ArithMetaMethod(op,o1,o2,trg)) {
+ 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;
+ _nmetamethodscall = 0;
+ _lasterror.Null();
+ _errorhandler.Null();
+ _debughook = false;
+ _debughook_native = NULL;
+ _debughook_closure.Null();
+ _openouters = NULL;
+ ci = NULL;
+ INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);
+}
+
+void SQVM::Finalize()
+{
+ if(_openouters) CloseOuters(&_stack._vals[0]);
+ _roottable.Null();
+ _lasterror.Null();
+ _errorhandler.Null();
+ _debughook = false;
+ _debughook_native = NULL;
+ _debughook_closure.Null();
+ temp_reg.Null();
+ _callstackdata.resize(0);
+ SQInteger size=_stack.size();
+ for(SQInteger i=0;i<size;i++)
+ _stack[i].Null();
+}
+
+SQVM::~SQVM()
+{
+ Finalize();
+ 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) {
+
+ SQObjectPtr closure;
+ if(_delegable(o1)->GetMetaMethod(this, mm, closure)) {
+ Push(o1);Push(o2);
+ return CallMetaMethod(closure,mm,2,dest);
+ }
+ }
+ Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2));
+ 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) {
+ SQObjectPtr closure;
+ if(_delegable(o)->GetMetaMethod(this, MT_UNM, closure)) {
+ Push(o);
+ if(!CallMetaMethod(closure, MT_UNM, 1, temp_reg)) return false;
+ _Swap(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)
+{
+ SQObjectType t1 = type(o1), t2 = type(o2);
+ if(t1 == t2){
+ if(_rawval(o1)==_rawval(o2))_RET_SUCCEED(0);
+ SQObjectPtr res;
+ switch(t1){
+ 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) {
+ SQObjectPtr closure;
+ if(_delegable(o1)->GetMetaMethod(this, MT_CMP, closure)) {
+ Push(o1);Push(o2);
+ if(!CallMetaMethod(closure,MT_CMP,2,res)) return false;
+ }
+ 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((t1==OT_INTEGER) && (t2==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(t1==OT_NULL) {_RET_SUCCEED(-1);}
+ else if(t2==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); return true;
+ case CMP_GE: res = (r >= 0); return true;
+ case CMP_L: res = (r < 0); return true;
+ case CMP_LE: res = (r <= 0); return true;
+ case CMP_3W: res = r; return true;
+ }
+ assert(0);
+ }
+ return false;
+}
+
+bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
+{
+ switch(type(o)) {
+ case OT_STRING:
+ res = o;
+ return true;
+ 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)),_PRINT_INT_FMT,_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) {
+ SQObjectPtr closure;
+ if(_delegable(o)->GetMetaMethod(this, MT_TOSTRING, closure)) {
+ Push(o);
+ if(CallMetaMethod(closure,MT_TOSTRING,1,res)) {;
+ if(type(res) == OT_STRING)
+ return true;
+ }
+ else {
+ return false;
+ }
+ }
+ }
+ default:
+ scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o));
+ }
+ res = SQString::Create(_ss(this),_spval);
+ return true;
+}
+
+
+bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)
+{
+ SQObjectPtr a, b;
+ if(!ToString(str, a)) return false;
+ if(!ToString(obj, b)) return false;
+ 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;
+}
+
+bool SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest)
+{
+ if(is_delegable(obj1) && _delegable(obj1)->_delegate) {
+ SQObjectPtr closure;
+ if(_delegable(obj1)->GetMetaMethod(this, MT_TYPEOF, closure)) {
+ Push(obj1);
+ return CallMetaMethod(closure,MT_TYPEOF,1,dest);
+ }
+ }
+ dest = SQString::Create(_ss(this),GetTypeName(obj1));
+ return true;
+}
+
+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;
+ _debughook_native = friendvm->_debughook_native;
+ _debughook_closure = friendvm->_debughook_closure;
+ }
+
+ sq_base_register(this);
+ return true;
+}
+
+
+bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall)
+{
+ SQFunctionProto *func = closure->_function;
+
+ SQInteger paramssize = func->_nparameters;
+ const SQInteger newtop = stackbase + func->_stacksize;
+ SQInteger nargs = args;
+ if(func->_varparams)
+ {
+ paramssize--;
+ if (nargs < paramssize) {
+ Raise_Error(_SC("wrong number of parameters"));
+ return false;
+ }
+
+ //dumpstack(stackbase);
+ SQInteger nvargs = nargs - paramssize;
+ SQArray *arr = SQArray::Create(_ss(this),nvargs);
+ SQInteger pbase = stackbase+paramssize;
+ for(SQInteger n = 0; n < nvargs; n++) {
+ arr->_values[n] = _stack._vals[pbase];
+ _stack._vals[pbase].Null();
+ pbase++;
+
+ }
+ _stack._vals[stackbase+paramssize] = arr;
+ //dumpstack(stackbase);
+ }
+ else 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 {
+ Raise_Error(_SC("wrong number of parameters"));
+ return false;
+ }
+ }
+
+ if(closure->_env) {
+ _stack._vals[stackbase] = closure->_env->_obj;
+ }
+
+ if(!EnterFrame(stackbase, newtop, tailcall)) return false;
+
+ ci->_closure = closure;
+ ci->_literals = func->_literals;
+ ci->_ip = func->_instructions;
+ ci->_target = (SQInt32)target;
+
+ if (_debughook) {
+ CallDebugHook(_SC('c'));
+ }
+
+ if (closure->_function->_bgenerator) {
+ SQFunctionProto *f = closure->_function;
+ SQGenerator *gen = SQGenerator::Create(_ss(this), closure);
+ if(!gen->Yield(this,f->_stacksize))
+ return false;
+ SQObjectPtr temp;
+ Return(1, target, temp);
+ STK(target) = gen;
+ }
+
+
+ return true;
+}
+
+bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval)
+{
+ SQBool _isroot = ci->_root;
+ SQInteger callerbase = _stackbase - ci->_prevstkbase;
+
+ if (_debughook) {
+ for(SQInteger i=0; i<ci->_ncalls; i++) {
+ CallDebugHook(_SC('r'));
+ }
+ }
+
+ SQObjectPtr *dest;
+ if (_isroot) {
+ dest = &(retval);
+ } else if (ci->_target == -1) {
+ dest = NULL;
+ } else {
+ dest = &_stack._vals[callerbase + ci->_target];
+ }
+ if (dest) {
+ if(_arg0 != 0xFF) {
+ *dest = _stack._vals[_stackbase+_arg1];
+ }
+ else {
+ dest->Null();
+ }
+ //*dest = (_arg0 != 0xFF) ? _stack._vals[_stackbase+_arg1] : _null_;
+ }
+ LeaveFrame();
+ return _isroot ? true : false;
+}
+
+#define _RET_ON_FAIL(exp) { if(!exp) return false; }
+
+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,SQInteger selfidx)
+{
+ SQObjectPtr tmp, tself = self, tkey = key;
+ if (!Get(tself, tkey, tmp, false, selfidx)) { return false; }
+ _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr))
+ if (!Set(tself, tkey, target,selfidx)) { return false; }
+ if (postfix) target = tmp;
+ return true;
+}
+
+#define arg0 (_i_._arg0)
+#define sarg0 ((SQInteger)*((signed char *)&_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;
+}
+
+
+#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;
+ SQObjectPtr closure;
+ if(_delegable(o1)->GetMetaMethod(this, MT_NEXTI, closure)) {
+ Push(o1);
+ Push(o4);
+ if(CallMetaMethod(closure, MT_NEXTI, 2, itr)) {
+ o4 = o2 = itr;
+ if(type(itr) == OT_NULL) _FINISH(exitpos);
+ if(!Get(o1, itr, o3, false, DONT_FALL_BACK)) {
+ Raise_Error(_SC("_nexti returned an invalid idx")); // cloud be changed
+ return false;
+ }
+ _FINISH(1);
+ }
+ else {
+ return false;
+ }
+ }
+ 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, o3);
+ _FINISH(0);
+ }
+ default:
+ Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));
+ }
+ return false; //cannot be hit(just to avoid warnings)
+}
+
+#define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1))
+
+#define SQ_THROW() { goto exception_trap; }
+
+#define _GUARD(exp) { if(!exp) { SQ_THROW();} }
+
+bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)
+{
+ SQInteger nouters;
+ SQClosure *closure = SQClosure::Create(_ss(this), func);
+ if((nouters = func->_noutervalues)) {
+ for(SQInteger i = 0; i<nouters; i++) {
+ SQOuterVar &v = func->_outervalues[i];
+ switch(v._type){
+ case otLOCAL:
+ FindOuter(closure->_outervalues[i], &STK(_integer(v._src)));
+ break;
+ case otOUTER:
+ closure->_outervalues[i] = _closure(ci->_closure)->_outervalues[_integer(v._src)];
+ break;
+ }
+ }
+ }
+ SQInteger ndefparams;
+ if((ndefparams = func->_ndefaultparams)) {
+ for(SQInteger i = 0; i < ndefparams; i++) {
+ SQInteger spos = func->_defaultparams[i];
+ closure->_defaultparams[i] = _stack._vals[_stackbase + spos];
+ }
+ }
+ target = closure;
+ 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(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res)
+{
+ if(type(o1) == type(o2)) {
+ res = (_rawval(o1) == _rawval(o2));
+ }
+ else {
+ if(sq_isnumeric(o1) && sq_isnumeric(o2)) {
+ res = (tofloat(o1) == tofloat(o2));
+ }
+ else {
+ res = false;
+ }
+ }
+ return true;
+}
+
+bool SQVM::IsFalse(SQObjectPtr &o)
+{
+ if(((type(o) & SQOBJECT_CANBEFALSE)
+ && ( ((type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) ))
+#if !defined(SQUSEDOUBLE) || (defined(SQUSEDOUBLE) && defined(_SQ64))
+ || (_integer(o) == 0) ) //OT_NULL|OT_INTEGER|OT_BOOL
+#else
+ || (((type(o) != OT_FLOAT) && (_integer(o) == 0))) ) //OT_NULL|OT_INTEGER|OT_BOOL
+#endif
+ {
+ return true;
+ }
+ return false;
+}
+
+bool SQVM::Execute(SQObjectPtr &closure, 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;
+ CallInfo *prevci = ci;
+
+ switch(et) {
+ case ET_CALL: {
+ 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(ci == prevci) {
+ outres = STK(_top-nargs);
+ return true;
+ }
+ ci->_root = SQTrue;
+ }
+ break;
+ case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = SQTrue; traps += ci->_etraps; break;
+ case ET_RESUME_VM:
+ case ET_RESUME_THROW_VM:
+ traps = _suspended_traps;
+ ci->_root = _suspended_root;
+ _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 (_debughook) CallDebugHook(_SC('l'),arg1); continue;
+ case _OP_LOAD: TARGET = ci->_literals[arg1]; continue;
+ case _OP_LOADINT:
+#ifndef _SQ64
+ TARGET = (SQInteger)arg1; continue;
+#else
+ TARGET = (SQInteger)((SQUnsignedInteger32)arg1); continue;
+#endif
+ case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue;
+ case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;
+ case _OP_TAILCALL:{
+ SQObjectPtr &t = STK(arg1);
+ if (type(t) == OT_CLOSURE
+ && (!_closure(t)->_function->_bgenerator)){
+ SQObjectPtr clo = t;
+ if(_openouters) CloseOuters(&(_stack._vals[_stackbase]));
+ for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);
+ _GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true));
+ continue;
+ }
+ }
+ case _OP_CALL: {
+ SQObjectPtr clo = STK(arg1);
+ switch (type(clo)) {
+ case OT_CLOSURE:
+ _GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false));
+ continue;
+ case OT_NATIVECLOSURE: {
+ bool suspend;
+ _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo,suspend));
+ if(suspend){
+ _suspended = SQTrue;
+ _suspended_target = sarg0;
+ _suspended_root = ci->_root;
+ _suspended_traps = traps;
+ outres = clo;
+ return true;
+ }
+ if(sarg0 != -1) {
+ STK(arg0) = clo;
+ }
+ }
+ continue;
+ case OT_CLASS:{
+ SQObjectPtr inst;
+ _GUARD(CreateClassInstance(_class(clo),inst,clo));
+ if(sarg0 != -1) {
+ STK(arg0) = inst;
+ }
+ SQInteger stkbase;
+ switch(type(clo)) {
+ case OT_CLOSURE:
+ stkbase = _stackbase+arg2;
+ _stack._vals[stkbase] = inst;
+ _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false));
+ break;
+ case OT_NATIVECLOSURE:
+ bool suspend;
+ stkbase = _stackbase+arg2;
+ _stack._vals[stkbase] = inst;
+ _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend));
+ break;
+ default: break; //shutup GCC 4.x
+ }
+ }
+ break;
+ case OT_TABLE:
+ case OT_USERDATA:
+ case OT_INSTANCE:{
+ SQObjectPtr closure;
+ if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) {
+ Push(clo);
+ for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i));
+ if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) SQ_THROW();
+ if(sarg0 != -1) {
+ STK(arg0) = 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,arg2)) {
+ SQ_THROW();
+ }
+ STK(arg3) = o;
+ _Swap(TARGET,temp_reg);//TARGET = temp_reg;
+ }
+ continue;
+ case _OP_GETK:
+ if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,arg2)) { SQ_THROW();}
+ _Swap(TARGET,temp_reg);//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 != 0xFF) 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),arg1)) { SQ_THROW(); }
+ if (arg0 != 0xFF) TARGET = STK(arg3);
+ continue;
+ case _OP_GET:
+ if (!Get(STK(arg1), STK(arg2), temp_reg, false,arg1)) { SQ_THROW(); }
+ _Swap(TARGET,temp_reg);//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_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue;
+ case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue;
+ case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue;
+ case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue;
+ case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); 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;
+ _Swap(outres,temp_reg);
+ return true;
+ }
+ continue;
+ case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue;
+ case _OP_LOADROOT: 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_JCMP:
+ _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg));
+ if(IsFalse(temp_reg)) ci->_ip+=(sarg1);
+ continue;
+ case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
+ case _OP_GETOUTER: {
+ SQClosure *cur_cls = _closure(ci->_closure);
+ SQOuter *otr = _outer(cur_cls->_outervalues[arg1]);
+ TARGET = *(otr->_valptr);
+ }
+ continue;
+ case _OP_SETOUTER: {
+ SQClosure *cur_cls = _closure(ci->_closure);
+ SQOuter *otr = _outer(cur_cls->_outervalues[arg1]);
+ *(otr->_valptr) = STK(arg2);
+ if(arg0 != 0xFF) {
+ TARGET = STK(arg2);
+ }
+ }
+ continue;
+ case _OP_NEWOBJ:
+ switch(arg3) {
+ case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;
+ case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;
+ case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;
+ default: assert(0); continue;
+ }
+ case _OP_APPENDARRAY:
+ {
+ SQObject val;
+ val._unVal.raw = 0;
+ switch(arg2) {
+ case AAT_STACK:
+ val = STK(arg1); break;
+ case AAT_LITERAL:
+ val = ci->_literals[arg1]; break;
+ case AAT_INT:
+ val._type = OT_INTEGER;
+#ifndef _SQ64
+ val._unVal.nInteger = (SQInteger)arg1;
+#else
+ val._unVal.nInteger = (SQInteger)((SQUnsignedInteger32)arg1);
+#endif
+ break;
+ case AAT_FLOAT:
+ val._type = OT_FLOAT;
+ val._unVal.fFloat = *((SQFloat *)&arg1);
+ break;
+ case AAT_BOOL:
+ val._type = OT_BOOL;
+ val._unVal.nInteger = arg1;
+ break;
+ default: assert(0); break;
+
+ }
+ _array(STK(arg0))->Append(val); continue;
+ }
+ case _OP_COMPARITH: {
+ SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16);
+ _GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx));
+ }
+ continue;
+ case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue;
+ case _OP_INCL: {
+ SQObjectPtr &a = STK(arg1);
+ if(type(a) == OT_INTEGER) {
+ a._unVal.nInteger = _integer(a) + sarg3;
+ }
+ else {
+ SQObjectPtr o(sarg3); //_GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));
+ _ARITH_(+,a,a,o);
+ }
+ } continue;
+ case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue;
+ case _OP_PINCL: {
+ SQObjectPtr &a = STK(arg1);
+ if(type(a) == OT_INTEGER) {
+ TARGET = a;
+ a._unVal.nInteger = _integer(a) + sarg3;
+ }
+ else {
+ 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,DONT_FALL_BACK)?true:false;continue;
+ case _OP_INSTANCEOF:
+ if(type(STK(arg1)) != OT_CLASS)
+ {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();}
+ TARGET = (type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : 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)); 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;
+ 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,arg2));
+ traps -= ci->_etraps;
+ if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);//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, TARGET));
+ 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_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue;
+ case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue;
+ case _OP_PUSHTRAP:{
+ SQInstruction *_iv = _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_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) : SQObjectPtr());
+ Push(bstatic);
+ int nparams = 5;
+ if(Call(_class(STK(arg1))->_metamethods[MT_NEWMEMBER], nparams, _top - nparams, temp_reg,SQFalse)) {
+ Pop(nparams);
+ continue;
+ }
+ else {
+ SQ_THROW();
+ }
+ }
+ }
+ _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;
+ case _OP_GETBASE:{
+ SQClosure *clo = _closure(ci->_closure);
+ if(clo->_base) {
+ TARGET = clo->_base;
+ }
+ else {
+ TARGET.Null();
+ }
+ continue;
+ }
+ case _OP_CLOSE:
+ if(_openouters) CloseOuters(&(STK(arg1)));
+ continue;
+ }
+
+ }
+ }
+exception_trap:
+ {
+ SQObjectPtr currerror = _lasterror;
+// dumpstack(_stackbase);
+// SQInteger n = 0;
+ SQInteger last_top = _top;
+
+ if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror);
+
+ while( ci ) {
+ 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--;
+ while(last_top >= _top) _stack._vals[last_top--].Null();
+ goto exception_restore;
+ }
+ else if (_debughook) {
+ //notify debugger of a "return"
+ //even if it really an exception unwinding the stack
+ for(SQInteger i = 0; i < ci->_ncalls; i++) {
+ CallDebugHook(_SC('r'));
+ }
+ }
+ if(ci->_generator) ci->_generator->Kill();
+ bool mustbreak = ci && ci->_root;
+ LeaveFrame();
+ if(mustbreak) break;
+ }
+
+ _lasterror = currerror;
+ return false;
+ }
+ assert(0);
+}
+
+bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor)
+{
+ inst = theclass->CreateInstance();
+ if(!theclass->GetConstructor(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)
+{
+ _debughook = false;
+ SQFunctionProto *func=_closure(ci->_closure)->_function;
+ if(_debughook_native) {
+ const SQChar *src = type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL;
+ const SQChar *fname = type(func->_name) == OT_STRING?_stringval(func->_name):NULL;
+ SQInteger line = forcedline?forcedline:func->GetLine(ci->_ip);
+ _debughook_native(this,type,src,line,fname);
+ }
+ else {
+ SQObjectPtr temp_reg;
+ SQInteger nparams=5;
+ Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);
+ Call(_debughook_closure,nparams,_top-nparams,temp_reg,SQFalse);
+ Pop(nparams);
+ }
+ _debughook = true;
+}
+
+bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, bool &suspend)
+{
+ SQInteger nparamscheck = nclosure->_nparamscheck;
+ SQInteger newtop = newbase + nargs + nclosure->_noutervalues;
+
+ if (_nnativecalls + 1 > MAX_NATIVE_CALLS) {
+ Raise_Error(_SC("Native stack overflow"));
+ return false;
+ }
+
+ if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) ||
+ ((nparamscheck < 0) && (nargs < (-nparamscheck)))))
+ {
+ Raise_Error(_SC("wrong number of parameters"));
+ return false;
+ }
+
+ SQInteger tcs;
+ SQIntVec &tc = nclosure->_typecheck;
+ if((tcs = tc.size())) {
+ for(SQInteger i = 0; i < nargs && i < tcs; i++) {
+ if((tc._vals[i] != -1) && !(type(_stack._vals[newbase+i]) & tc._vals[i])) {
+ Raise_ParamTypeError(i,tc._vals[i],type(_stack._vals[newbase+i]));
+ return false;
+ }
+ }
+ }
+
+ if(!EnterFrame(newbase, newtop, false)) return false;
+ ci->_closure = nclosure;
+
+ SQInteger outers = nclosure->_noutervalues;
+ for (SQInteger i = 0; i < outers; i++) {
+ _stack._vals[newbase+nargs+i] = nclosure->_outervalues[i];
+ }
+ if(nclosure->_env) {
+ _stack._vals[newbase] = nclosure->_env->_obj;
+ }
+
+ _nnativecalls++;
+ SQInteger ret = (nclosure->_function)(this);
+ _nnativecalls--;
+
+ suspend = false;
+ if (ret == SQ_SUSPEND_FLAG) {
+ suspend = true;
+ }
+ else if (ret < 0) {
+ LeaveFrame();
+ Raise_Error(_lasterror);
+ return false;
+ }
+ if(ret) {
+ retval = _stack._vals[_top-1];
+ }
+ else {
+ retval.Null();
+ }
+ //retval = ret ? _stack._vals[_top-1] : _null_;
+ LeaveFrame();
+ return true;
+}
+
+#define FALLBACK_OK 0
+#define FALLBACK_NO_MATCH 1
+#define FALLBACK_ERROR 2
+
+bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, SQInteger selfidx)
+{
+ switch(type(self)){
+ case OT_TABLE:
+ if(_table(self)->Get(key,dest))return true;
+ break;
+ case OT_ARRAY:
+ if(sq_isnumeric(key)) { if(_array(self)->Get(tointeger(key),dest)) { return true; } Raise_IdxError(key); return false; }
+ break;
+ case OT_INSTANCE:
+ if(_instance(self)->Get(key,dest)) return true;
+ break;
+ case OT_CLASS:
+ if(_class(self)->Get(key,dest)) return true;
+ break;
+ 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;
+ }
+ Raise_IdxError(key);
+ return false;
+ }
+ break;
+ default:break; //shut up compiler
+ }
+ if(!raw) {
+ switch(FallBackGet(self,key,dest)) {
+ case FALLBACK_OK: return true; //okie
+ case FALLBACK_NO_MATCH: break; //keep falling back
+ case FALLBACK_ERROR: return false; // the metamethod failed
+ }
+ if(InvokeDefaultDelegate(self,key,dest)) {
+ return true;
+ }
+ }
+//#ifdef ROOT_FALLBACK
+ if(selfidx == 0) {
+ if(_table(_roottable)->Get(key,dest)) return true;
+ }
+//#endif
+ Raise_IdxError(key);
+ return false;
+}
+
+bool SQVM::InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest)
+{
+ SQTable *ddel = NULL;
+ switch(type(self)) {
+ case OT_CLASS: ddel = _class_ddel; break;
+ case OT_TABLE: ddel = _table_ddel; break;
+ case OT_ARRAY: ddel = _array_ddel; break;
+ case OT_STRING: ddel = _string_ddel; break;
+ case OT_INSTANCE: ddel = _instance_ddel; break;
+ case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break;
+ case OT_GENERATOR: ddel = _generator_ddel; break;
+ case OT_CLOSURE: case OT_NATIVECLOSURE: ddel = _closure_ddel; break;
+ case OT_THREAD: ddel = _thread_ddel; break;
+ case OT_WEAKREF: ddel = _weakref_ddel; break;
+ default: return false;
+ }
+ return ddel->Get(key,dest);
+}
+
+
+SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest)
+{
+ switch(type(self)){
+ case OT_TABLE:
+ case OT_USERDATA:
+ //delegation
+ if(_delegable(self)->_delegate) {
+ if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,false,DONT_FALL_BACK)) return FALLBACK_OK;
+ }
+ else {
+ return FALLBACK_NO_MATCH;
+ }
+ //go through
+ case OT_INSTANCE: {
+ SQObjectPtr closure;
+ if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) {
+ Push(self);Push(key);
+ _nmetamethodscall++;
+ AutoDec ad(&_nmetamethodscall);
+ if(Call(closure, 2, _top - 2, dest, SQFalse)) {
+ Pop(2);
+ return FALLBACK_OK;
+ }
+ else {
+ if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found)
+ //error
+ Pop(2);
+ return FALLBACK_ERROR;
+ }
+ }
+ }
+ }
+ break;
+ default: break;//shutup GCC 4.x
+ }
+ // no metamethod or no fallback type
+ return FALLBACK_NO_MATCH;
+}
+
+bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,SQInteger selfidx)
+{
+ switch(type(self)){
+ case OT_TABLE:
+ if(_table(self)->Set(key,val)) return true;
+ break;
+ case OT_INSTANCE:
+ if(_instance(self)->Set(key,val)) return true;
+ break;
+ case OT_ARRAY:
+ if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; }
+ if(!_array(self)->Set(tointeger(key),val)) {
+ Raise_IdxError(key);
+ return false;
+ }
+ return true;
+ default:
+ Raise_Error(_SC("trying to set '%s'"),GetTypeName(self));
+ return false;
+ }
+
+ switch(FallBackSet(self,key,val)) {
+ case FALLBACK_OK: return true; //okie
+ case FALLBACK_NO_MATCH: break; //keep falling back
+ case FALLBACK_ERROR: return false; // the metamethod failed
+ }
+ if(selfidx == 0) {
+ if(_table(_roottable)->Set(key,val))
+ return true;
+ }
+ Raise_IdxError(key);
+ return false;
+}
+
+SQInteger SQVM::FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val)
+{
+ switch(type(self)) {
+ case OT_TABLE:
+ if(_table(self)->_delegate) {
+ if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK)) return FALLBACK_OK;
+ }
+ //keps on going
+ case OT_INSTANCE:
+ case OT_USERDATA:{
+ SQObjectPtr closure;
+ SQObjectPtr t;
+ if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) {
+ Push(self);Push(key);Push(val);
+ _nmetamethodscall++;
+ AutoDec ad(&_nmetamethodscall);
+ if(Call(closure, 3, _top - 3, t, SQFalse)) {
+ Pop(3);
+ return FALLBACK_OK;
+ }
+ else {
+ if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found)
+ //error
+ Pop(3);
+ return FALLBACK_ERROR;
+ }
+ }
+ }
+ }
+ break;
+ default: break;//shutup GCC 4.x
+ }
+ // no metamethod or no fallback type
+ return FALLBACK_NO_MATCH;
+}
+
+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:
+ SQObjectPtr closure;
+ if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) {
+ Push(newobj);
+ Push(self);
+ if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg))
+ return false;
+ }
+ }
+ target = newobj;
+ return true;
+ case OT_ARRAY:
+ target = _array(self)->Clone();
+ return true;
+ default:
+ Raise_Error(_SC("cloning a %s"), GetTypeName(self));
+ 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)) {
+ SQObjectPtr closure;
+ if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {
+ Push(self);Push(key);Push(val);
+ if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {
+ return false;
+ }
+ rawcall = false;
+ }
+ else {
+ rawcall = true;
+ }
+ }
+ }
+ if(rawcall) _table(self)->NewSlot(key,val); //cannot fail
+
+ break;}
+ case OT_INSTANCE: {
+ SQObjectPtr res;
+ SQObjectPtr closure;
+ if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {
+ Push(self);Push(key);Push(val);
+ if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {
+ return false;
+ }
+ break;
+ }
+ 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;
+ SQObjectPtr closure;
+ if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) {
+ Push(self);Push(key);
+ return CallMetaMethod(closure,MT_DELSLOT,2,res);
+ }
+ else {
+ 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, 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(SQObjectPtr &closure,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres)
+{
+ //SQObjectPtr closure;
+
+ _nmetamethodscall++;
+ if(Call(closure, nparams, _top - nparams, outres, SQFalse)) {
+ _nmetamethodscall--;
+ Pop(nparams);
+ return true;
+ }
+ _nmetamethodscall--;
+ //}
+ Pop(nparams);
+ return false;
+}
+
+void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex)
+{
+ SQOuter **pp = &_openouters;
+ SQOuter *p;
+ SQOuter *otr;
+
+ while ((p = *pp) != NULL && p->_valptr >= stackindex) {
+ if (p->_valptr == stackindex) {
+ target = SQObjectPtr(p);
+ return;
+ }
+ pp = &p->_next;
+ }
+ otr = SQOuter::Create(_ss(this), stackindex);
+ otr->_next = *pp;
+ otr->_idx = (stackindex - _stack._vals);
+ __ObjAddRef(otr);
+ *pp = otr;
+ target = SQObjectPtr(otr);
+}
+
+bool SQVM::EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall)
+{
+ if( !tailcall ) {
+ if( _callsstacksize == _alloccallsstacksize ) {
+ GrowCallStack();
+ }
+ ci = &_callsstack[_callsstacksize++];
+ ci->_prevstkbase = (SQInt32)(newbase - _stackbase);
+ ci->_prevtop = (SQInt32)(_top - _stackbase);
+ ci->_etraps = 0;
+ ci->_ncalls = 1;
+ ci->_generator = NULL;
+ ci->_root = SQFalse;
+ }
+ else {
+ ci->_ncalls++;
+ }
+
+ _stackbase = newbase;
+ _top = newtop;
+ if(newtop + MIN_STACK_OVERHEAD > (SQInteger)_stack.size()) {
+ if(_nmetamethodscall) {
+ Raise_Error(_SC("stack overflow, cannot resize stack while in a metamethod"));
+ return false;
+ }
+ _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD << 2));
+ RelocateOuters();
+ }
+ return true;
+}
+
+void SQVM::LeaveFrame() {
+ SQInteger last_top = _top;
+ SQInteger last_stackbase = _stackbase;
+ SQInteger css = --_callsstacksize;
+
+ /* First clean out the call stack frame */
+ ci->_closure.Null();
+ _stackbase -= ci->_prevstkbase;
+ _top = _stackbase + ci->_prevtop;
+ ci = (css) ? &_callsstack[css-1] : NULL;
+
+ if(_openouters) CloseOuters(&(_stack._vals[last_stackbase]));
+ while (last_top >= _top) {
+ _stack._vals[last_top--].Null();
+ }
+}
+
+void SQVM::RelocateOuters()
+{
+ SQOuter *p = _openouters;
+ while (p) {
+ p->_valptr = _stack._vals + p->_idx;
+ p = p->_next;
+ }
+}
+
+void SQVM::CloseOuters(SQObjectPtr *stackindex) {
+ SQOuter *p;
+ while ((p = _openouters) != NULL && p->_valptr >= stackindex) {
+ p->_value = *(p->_valptr);
+ p->_valptr = &p->_value;
+ _openouters = p->_next;
+ __ObjRelease(p);
+ }
+}
+
+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::PushNull() { _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
diff --git a/squirrel_3_0_1_stable/squirrel/sqvm.h b/squirrel_3_0_1_stable/squirrel/sqvm.h
new file mode 100644
index 000000000..397dcd9c1
--- /dev/null
+++ b/squirrel_3_0_1_stable/squirrel/sqvm.h
@@ -0,0 +1,208 @@
+/* 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 15
+
+#define SQ_SUSPEND_FLAG -666
+#define DONT_FALL_BACK 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 CallInfo{
+ //CallInfo() { _generator = NULL;}
+ SQInstruction *_ip;
+ SQObjectPtr *_literals;
+ SQObjectPtr _closure;
+ SQGenerator *_generator;
+ SQInt32 _etraps;
+ SQInt32 _prevstkbase;
+ SQInt32 _prevtop;
+ SQInt32 _target;
+ SQInt32 _ncalls;
+ SQBool _root;
+ };
+
+typedef sqvector<CallInfo> CallInfoVec;
+public:
+ void DebugHookProxy(SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname);
+ static void _DebugHookProxy(HSQUIRRELVM v, SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname);
+ 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 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 newbase, 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, SQInteger selfidx);
+ SQInteger FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);
+ bool InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);
+ bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, SQInteger selfidx);
+ SQInteger FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val);
+ 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);
+ static bool IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res);
+ bool ToString(const SQObjectPtr &o,SQObjectPtr &res);
+ SQString *PrintObjVal(const SQObjectPtr &o);
+
+
+ void Raise_Error(const SQChar *s, ...);
+ void Raise_Error(const SQObjectPtr &desc);
+ void Raise_IdxError(const SQObjectPtr &o);
+ void Raise_CompareError(const SQObject &o1, const SQObject &o2);
+ void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type);
+
+ void FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex);
+ void RelocateOuters();
+ void CloseOuters(SQObjectPtr *stackindex);
+
+ bool TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);
+ bool CallMetaMethod(SQObjectPtr &closure, 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 CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs);
+ //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);
+ //_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,SQInteger arg0);
+#ifdef _DEBUG_DUMP
+ void dumpstack(SQInteger stackbase=-1, bool dumpall = false);
+#endif
+
+#ifndef NO_GARBAGE_COLLECTOR
+ void Mark(SQCollectable **chain);
+ SQObjectType GetType() {return OT_THREAD;}
+#endif
+ void Finalize();
+ void GrowCallStack() {
+ SQInteger newsize = _alloccallsstacksize*2;
+ _callstackdata.resize(newsize);
+ _callsstack = &_callstackdata[0];
+ _alloccallsstacksize = newsize;
+ }
+ bool EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall);
+ void LeaveFrame();
+ void Release(){ sq_delete(this,SQVM); }
+////////////////////////////////////////////////////////////////////////////
+ //stack functions for the api
+ void Remove(SQInteger n);
+
+ static bool IsFalse(SQObjectPtr &o);
+
+ void Pop();
+ void Pop(SQInteger n);
+ void Push(const SQObjectPtr &o);
+ void PushNull();
+ SQObjectPtr &Top();
+ SQObjectPtr &PopGet();
+ SQObjectPtr &GetUp(SQInteger n);
+ SQObjectPtr &GetAt(SQInteger n);
+
+ SQObjectPtrVec _stack;
+
+ SQInteger _top;
+ SQInteger _stackbase;
+ SQOuter *_openouters;
+ SQObjectPtr _roottable;
+ SQObjectPtr _lasterror;
+ SQObjectPtr _errorhandler;
+
+ bool _debughook;
+ SQDEBUGHOOK _debughook_native;
+ SQObjectPtr _debughook_closure;
+
+ 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;
+ SQInteger _nmetamethodscall;
+ //suspend infos
+ SQBool _suspended;
+ SQBool _suspended_root;
+ SQInteger _suspended_target;
+ SQInteger _suspended_traps;
+};
+
+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){ \
+ SQInteger css = v->_callsstacksize; \
+ if(css == v->_alloccallsstacksize) { \
+ v->GrowCallStack(); \
+ } \
+ v->ci = &v->_callsstack[css]; \
+ *(v->ci) = nci; \
+ v->_callsstacksize++; \
+}
+
+#define POP_CALLINFO(v){ \
+ SQInteger css = --v->_callsstacksize; \
+ v->ci->_closure.Null(); \
+ v->ci = css?&v->_callsstack[css-1]:NULL; \
+}
+#endif //_SQVM_H_