From 1ad50ce4e6ed74c8eeb89a1f2780e6ed58a72b2b Mon Sep 17 00:00:00 2001 From: rubidium Date: Wed, 25 Feb 2009 01:21:50 +0000 Subject: [PATCH] (svn r15578) -Change: unexternalise squirrel. --- readme.txt | 1 + src/3rdparty/squirrel/COMPILE | 41 + src/3rdparty/squirrel/COPYRIGHT | 29 + src/3rdparty/squirrel/HISTORY | 327 ++++ src/3rdparty/squirrel/Makefile | 23 + src/3rdparty/squirrel/README | 22 + src/3rdparty/squirrel/README.OpenTTD | 4 + src/3rdparty/squirrel/doc/sqstdlib2.chm | Bin 0 -> 36148 bytes src/3rdparty/squirrel/doc/squirrel2.chm | Bin 0 -> 118745 bytes src/3rdparty/squirrel/etc/minimal.c | 63 + src/3rdparty/squirrel/etc/test.nut | 4 + src/3rdparty/squirrel/include/sqstdaux.h | 16 + src/3rdparty/squirrel/include/sqstdblob.h | 20 + src/3rdparty/squirrel/include/sqstdio.h | 54 + src/3rdparty/squirrel/include/sqstdmath.h | 15 + src/3rdparty/squirrel/include/sqstdstring.h | 31 + src/3rdparty/squirrel/include/sqstdsystem.h | 15 + src/3rdparty/squirrel/include/squirrel.h | 450 +++++ src/3rdparty/squirrel/samples/ackermann.nut | 22 + src/3rdparty/squirrel/samples/array.nut | 28 + src/3rdparty/squirrel/samples/class.nut | 49 + .../squirrel/samples/classattributes.nut | 35 + src/3rdparty/squirrel/samples/coroutines.nut | 25 + src/3rdparty/squirrel/samples/delegation.nut | 52 + src/3rdparty/squirrel/samples/fibonacci.nut | 15 + src/3rdparty/squirrel/samples/flow.nut | 33 + src/3rdparty/squirrel/samples/generators.nut | 42 + src/3rdparty/squirrel/samples/hello.nut | 1 + src/3rdparty/squirrel/samples/list.nut | 39 + src/3rdparty/squirrel/samples/loops.nut | 32 + src/3rdparty/squirrel/samples/matrix.nut | 44 + src/3rdparty/squirrel/samples/metamethods.nut | 115 ++ src/3rdparty/squirrel/samples/methcall.nut | 61 + src/3rdparty/squirrel/samples/tailstate.nut | 24 + src/3rdparty/squirrel/sq/Makefile | 24 + src/3rdparty/squirrel/sq/sq.c | 321 ++++ src/3rdparty/squirrel/sq/sq.dsp | 101 ++ src/3rdparty/squirrel/sqstdlib/Makefile | 31 + src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp | 129 ++ src/3rdparty/squirrel/sqstdlib/sqstdblob.cpp | 251 +++ .../squirrel/sqstdlib/sqstdblobimpl.h | 108 ++ src/3rdparty/squirrel/sqstdlib/sqstdio.cpp | 410 +++++ src/3rdparty/squirrel/sqstdlib/sqstdlib.dsp | 131 ++ src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp | 106 ++ src/3rdparty/squirrel/sqstdlib/sqstdrex.cpp | 635 +++++++ .../squirrel/sqstdlib/sqstdstream.cpp | 330 ++++ src/3rdparty/squirrel/sqstdlib/sqstdstream.h | 18 + .../squirrel/sqstdlib/sqstdstring.cpp | 364 ++++ .../squirrel/sqstdlib/sqstdsystem.cpp | 147 ++ src/3rdparty/squirrel/squirrel.dsw | 77 + src/3rdparty/squirrel/squirrel/Makefile | 52 + src/3rdparty/squirrel/squirrel/sqapi.cpp | 1282 ++++++++++++++ src/3rdparty/squirrel/squirrel/sqarray.h | 87 + src/3rdparty/squirrel/squirrel/sqbaselib.cpp | 921 ++++++++++ src/3rdparty/squirrel/squirrel/sqclass.cpp | 194 +++ src/3rdparty/squirrel/squirrel/sqclass.h | 152 ++ src/3rdparty/squirrel/squirrel/sqclosure.h | 122 ++ src/3rdparty/squirrel/squirrel/sqcompiler.cpp | 1347 +++++++++++++++ src/3rdparty/squirrel/squirrel/sqcompiler.h | 77 + src/3rdparty/squirrel/squirrel/sqdebug.cpp | 104 ++ src/3rdparty/squirrel/squirrel/sqfuncproto.h | 160 ++ .../squirrel/squirrel/sqfuncstate.cpp | 572 ++++++ src/3rdparty/squirrel/squirrel/sqfuncstate.h | 85 + src/3rdparty/squirrel/squirrel/sqlexer.cpp | 476 +++++ src/3rdparty/squirrel/squirrel/sqlexer.h | 45 + src/3rdparty/squirrel/squirrel/sqmem.cpp | 9 + src/3rdparty/squirrel/squirrel/sqobject.cpp | 587 +++++++ src/3rdparty/squirrel/squirrel/sqobject.h | 352 ++++ src/3rdparty/squirrel/squirrel/sqopcodes.h | 116 ++ src/3rdparty/squirrel/squirrel/sqpcheader.h | 19 + src/3rdparty/squirrel/squirrel/sqstate.cpp | 572 ++++++ src/3rdparty/squirrel/squirrel/sqstate.h | 143 ++ src/3rdparty/squirrel/squirrel/sqstring.h | 31 + src/3rdparty/squirrel/squirrel/sqtable.cpp | 196 +++ src/3rdparty/squirrel/squirrel/sqtable.h | 91 + src/3rdparty/squirrel/squirrel/squirrel.dsp | 302 ++++ src/3rdparty/squirrel/squirrel/squserdata.h | 38 + src/3rdparty/squirrel/squirrel/squtils.h | 104 ++ src/3rdparty/squirrel/squirrel/sqvm.cpp | 1537 +++++++++++++++++ src/3rdparty/squirrel/squirrel/sqvm.h | 217 +++ src/misc_gui.cpp | 1 + 81 files changed, 14906 insertions(+) create mode 100644 src/3rdparty/squirrel/COMPILE create mode 100644 src/3rdparty/squirrel/COPYRIGHT create mode 100644 src/3rdparty/squirrel/HISTORY create mode 100644 src/3rdparty/squirrel/Makefile create mode 100644 src/3rdparty/squirrel/README create mode 100644 src/3rdparty/squirrel/README.OpenTTD create mode 100644 src/3rdparty/squirrel/doc/sqstdlib2.chm create mode 100644 src/3rdparty/squirrel/doc/squirrel2.chm create mode 100644 src/3rdparty/squirrel/etc/minimal.c create mode 100644 src/3rdparty/squirrel/etc/test.nut create mode 100644 src/3rdparty/squirrel/include/sqstdaux.h create mode 100644 src/3rdparty/squirrel/include/sqstdblob.h create mode 100644 src/3rdparty/squirrel/include/sqstdio.h create mode 100644 src/3rdparty/squirrel/include/sqstdmath.h create mode 100644 src/3rdparty/squirrel/include/sqstdstring.h create mode 100644 src/3rdparty/squirrel/include/sqstdsystem.h create mode 100644 src/3rdparty/squirrel/include/squirrel.h create mode 100644 src/3rdparty/squirrel/samples/ackermann.nut create mode 100644 src/3rdparty/squirrel/samples/array.nut create mode 100644 src/3rdparty/squirrel/samples/class.nut create mode 100644 src/3rdparty/squirrel/samples/classattributes.nut create mode 100644 src/3rdparty/squirrel/samples/coroutines.nut create mode 100644 src/3rdparty/squirrel/samples/delegation.nut create mode 100644 src/3rdparty/squirrel/samples/fibonacci.nut create mode 100644 src/3rdparty/squirrel/samples/flow.nut create mode 100644 src/3rdparty/squirrel/samples/generators.nut create mode 100644 src/3rdparty/squirrel/samples/hello.nut create mode 100644 src/3rdparty/squirrel/samples/list.nut create mode 100644 src/3rdparty/squirrel/samples/loops.nut create mode 100644 src/3rdparty/squirrel/samples/matrix.nut create mode 100644 src/3rdparty/squirrel/samples/metamethods.nut create mode 100644 src/3rdparty/squirrel/samples/methcall.nut create mode 100644 src/3rdparty/squirrel/samples/tailstate.nut create mode 100644 src/3rdparty/squirrel/sq/Makefile create mode 100644 src/3rdparty/squirrel/sq/sq.c create mode 100644 src/3rdparty/squirrel/sq/sq.dsp create mode 100644 src/3rdparty/squirrel/sqstdlib/Makefile create mode 100644 src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp create mode 100644 src/3rdparty/squirrel/sqstdlib/sqstdblob.cpp create mode 100644 src/3rdparty/squirrel/sqstdlib/sqstdblobimpl.h create mode 100644 src/3rdparty/squirrel/sqstdlib/sqstdio.cpp create mode 100644 src/3rdparty/squirrel/sqstdlib/sqstdlib.dsp create mode 100644 src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp create mode 100644 src/3rdparty/squirrel/sqstdlib/sqstdrex.cpp create mode 100644 src/3rdparty/squirrel/sqstdlib/sqstdstream.cpp create mode 100644 src/3rdparty/squirrel/sqstdlib/sqstdstream.h create mode 100644 src/3rdparty/squirrel/sqstdlib/sqstdstring.cpp create mode 100644 src/3rdparty/squirrel/sqstdlib/sqstdsystem.cpp create mode 100644 src/3rdparty/squirrel/squirrel.dsw create mode 100644 src/3rdparty/squirrel/squirrel/Makefile create mode 100644 src/3rdparty/squirrel/squirrel/sqapi.cpp create mode 100644 src/3rdparty/squirrel/squirrel/sqarray.h create mode 100644 src/3rdparty/squirrel/squirrel/sqbaselib.cpp create mode 100644 src/3rdparty/squirrel/squirrel/sqclass.cpp create mode 100644 src/3rdparty/squirrel/squirrel/sqclass.h create mode 100644 src/3rdparty/squirrel/squirrel/sqclosure.h create mode 100644 src/3rdparty/squirrel/squirrel/sqcompiler.cpp create mode 100644 src/3rdparty/squirrel/squirrel/sqcompiler.h create mode 100644 src/3rdparty/squirrel/squirrel/sqdebug.cpp create mode 100644 src/3rdparty/squirrel/squirrel/sqfuncproto.h create mode 100644 src/3rdparty/squirrel/squirrel/sqfuncstate.cpp create mode 100644 src/3rdparty/squirrel/squirrel/sqfuncstate.h create mode 100644 src/3rdparty/squirrel/squirrel/sqlexer.cpp create mode 100644 src/3rdparty/squirrel/squirrel/sqlexer.h create mode 100644 src/3rdparty/squirrel/squirrel/sqmem.cpp create mode 100644 src/3rdparty/squirrel/squirrel/sqobject.cpp create mode 100644 src/3rdparty/squirrel/squirrel/sqobject.h create mode 100644 src/3rdparty/squirrel/squirrel/sqopcodes.h create mode 100644 src/3rdparty/squirrel/squirrel/sqpcheader.h create mode 100644 src/3rdparty/squirrel/squirrel/sqstate.cpp create mode 100644 src/3rdparty/squirrel/squirrel/sqstate.h create mode 100644 src/3rdparty/squirrel/squirrel/sqstring.h create mode 100644 src/3rdparty/squirrel/squirrel/sqtable.cpp create mode 100644 src/3rdparty/squirrel/squirrel/sqtable.h create mode 100644 src/3rdparty/squirrel/squirrel/squirrel.dsp create mode 100644 src/3rdparty/squirrel/squirrel/squserdata.h create mode 100644 src/3rdparty/squirrel/squirrel/squtils.h create mode 100644 src/3rdparty/squirrel/squirrel/sqvm.cpp create mode 100644 src/3rdparty/squirrel/squirrel/sqvm.h diff --git a/readme.txt b/readme.txt index 8ffd456005..338a5b2aa2 100644 --- a/readme.txt +++ b/readme.txt @@ -498,6 +498,7 @@ Thanks to: Cian Duffy (MYOB) - BeOS port / manual writing Christian Rosentreter (tokai) - MorphOS / AmigaOS port Richard Kempton (RichK67) - Additional airports, initial TGP implementation + Alberto Demichelis - Squirrel scripting language Michael Blunck - For revolutionizing TTD with awesome graphics George - Canal graphics David Dallaston (Pikka) - Tram tracks diff --git a/src/3rdparty/squirrel/COMPILE b/src/3rdparty/squirrel/COMPILE new file mode 100644 index 0000000000..53022f4c8e --- /dev/null +++ b/src/3rdparty/squirrel/COMPILE @@ -0,0 +1,41 @@ +Squirrel 2.2.1 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!) diff --git a/src/3rdparty/squirrel/COPYRIGHT b/src/3rdparty/squirrel/COPYRIGHT new file mode 100644 index 0000000000..03a73fc568 --- /dev/null +++ b/src/3rdparty/squirrel/COPYRIGHT @@ -0,0 +1,29 @@ +Copyright (c) 2003-2008 Alberto Demichelis + +This software is provided 'as-is', without any +express or implied warranty. In no event will the +authors be held liable for any damages arising from +the use of this software. + +Permission is granted to anyone to use this software +for any purpose, including commercial applications, +and to alter it and redistribute it freely, subject +to the following restrictions: + + 1. The origin of this software must not be + misrepresented; you must not claim that + you wrote the original software. If you + use this software in a product, an + acknowledgment in the product + documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly + marked as such, and must not be + misrepresented as being the original + software. + + 3. This notice may not be removed or + altered from any source distribution. +----------------------------------------------------- +END OF COPYRIGHT diff --git a/src/3rdparty/squirrel/HISTORY b/src/3rdparty/squirrel/HISTORY new file mode 100644 index 0000000000..3717ae4451 --- /dev/null +++ b/src/3rdparty/squirrel/HISTORY @@ -0,0 +1,327 @@ +***version 2.2.2 stable*** +-fixed some behaviour inconsistencies in thread.call() and thread.wakeup() (thx Mr.Accident) +-fixed coroutine error propagation +-fixed lingering return value from native function (thx Tom Leonard) +-fixed a bug if array.sort() is given a bad sort function (thx Tom Leonard) +-fixed some minor api bug +-added sq_arrayremove() and sq_arrayinsert() + +***2008-05-16 *** +***version 2.2.1 stable*** +-fixed a tailcall bug + +***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 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 +-improoved 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) +-improoved 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/src/3rdparty/squirrel/Makefile b/src/3rdparty/squirrel/Makefile new file mode 100644 index 0000000000..594ec8b1c2 --- /dev/null +++ b/src/3rdparty/squirrel/Makefile @@ -0,0 +1,23 @@ + +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 + +clean: + $(MAKE) -C squirrel clean + $(MAKE) -C sqstdlib clean + $(MAKE) -C sq clean diff --git a/src/3rdparty/squirrel/README b/src/3rdparty/squirrel/README new file mode 100644 index 0000000000..e48108f51a --- /dev/null +++ b/src/3rdparty/squirrel/README @@ -0,0 +1,22 @@ +The programming language SQUIRREL 2.2.1 stable + +-------------------------------------------------- +The project has been compiled and run on Windows(Windows XP/2000 on Intel x86 Windows XP Pro on AMD x64) and +Linux(Slackware 9.0 on Intel x86, Fedora Core 4 on AMD x64). + +Has been tested with the following compilers: + MS Visual C++ 6.0,7.0,7.1 and 8.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) + + +Feedback and suggestions are appreciated +project page - http://www.squirrel-lang.org +community forums - http://www.squirrel-lang.org/Forums +wiki - http://wiki.squirrel-lang.org +author - alberto@demichelis.net + +END OF README + diff --git a/src/3rdparty/squirrel/README.OpenTTD b/src/3rdparty/squirrel/README.OpenTTD new file mode 100644 index 0000000000..34e4d7723e --- /dev/null +++ b/src/3rdparty/squirrel/README.OpenTTD @@ -0,0 +1,4 @@ +This folder contains a modified version of Squirrel that is tailored to meet +the needs of OpenTTD. +We have based this modification on the version as described in: +include/squirrel.h diff --git a/src/3rdparty/squirrel/doc/sqstdlib2.chm b/src/3rdparty/squirrel/doc/sqstdlib2.chm new file mode 100644 index 0000000000000000000000000000000000000000..606bec7202c13264dc503f17933a8f5fefc6dae6 GIT binary patch literal 36148 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 bXSb5Yj)g)s<(3-6>VNg||6lLmApQRj4^;b= literal 0 HcmV?d00001 diff --git a/src/3rdparty/squirrel/doc/squirrel2.chm b/src/3rdparty/squirrel/doc/squirrel2.chm new file mode 100644 index 0000000000000000000000000000000000000000..99bbf0687c0dbb00f4b46341d6c47cd6b792499a GIT binary patch literal 118745 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

FT3bQk4td< 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 RKHyI2{Sf|Nz#{;q{}1S5-Ms(+ literal 0 HcmV?d00001 diff --git a/src/3rdparty/squirrel/etc/minimal.c b/src/3rdparty/squirrel/etc/minimal.c new file mode 100644 index 0000000000..fc59859f87 --- /dev/null +++ b/src/3rdparty/squirrel/etc/minimal.c @@ -0,0 +1,63 @@ +#include +#include + +#include +#include +#include + +#ifdef _MSC_VER +#pragma comment (lib ,"squirrel.lib") +#pragma comment (lib ,"sqstdlib.lib") +#endif + +#ifdef SQUNICODE +#define scvprintf vwprintf +#else +#define scvprintf vprintf +#endif + +void printfunc(HSQUIRRELVM v, const SQChar *s, ...) +{ +va_list arglist; +va_start(arglist, s); +scvprintf(s, arglist); +va_end(arglist); +} + +void call_foo(HSQUIRRELVM v, int n,float f,const SQChar *s) +{ + SQInteger top = sq_gettop(v); //saves the stack size before the call + sq_pushroottable(v); //pushes the global table + sq_pushstring(v,_SC("foo"),-1); + if(SQ_SUCCEEDED(sq_get(v,-2))) { //gets the field 'foo' from the global table + sq_pushroottable(v); //push the 'this' (in this case is the global table) + sq_pushinteger(v,n); + sq_pushfloat(v,f); + sq_pushstring(v,s,-1); + sq_call(v,4,SQFalse,SQTrue); //calls the function + } + sq_settop(v,top); //restores the original stack size +} + +int main(int argc, char* argv[]) +{ + HSQUIRRELVM v; + v = sq_open(1024); // creates a VM with initial stack size 1024 + + //sq_pushroottable(v); //push the root table were to register the lib function + //sqstd_register_iolib(v); + sqstd_seterrorhandlers(v); //registers the default error handlers + + sq_setprintfunc(v, printfunc); //sets the print function + + sq_pushroottable(v); //push the root table(were the globals of the script will be stored) + if(SQ_SUCCEEDED(sqstd_dofile(v, _SC("test.nut"), SQFalse, SQTrue))) // also prints syntax errors if any + { + call_foo(v,1,2.5,_SC("teststring")); + } + + sq_pop(v,1); //pops the root table + sq_close(v); + + return 0; +} diff --git a/src/3rdparty/squirrel/etc/test.nut b/src/3rdparty/squirrel/etc/test.nut new file mode 100644 index 0000000000..125df32cd8 --- /dev/null +++ b/src/3rdparty/squirrel/etc/test.nut @@ -0,0 +1,4 @@ +function foo(i, f, s) +{ + print("Called foo(), i="+i+", f="+f+", s='"+s+"'\n"); +} diff --git a/src/3rdparty/squirrel/include/sqstdaux.h b/src/3rdparty/squirrel/include/sqstdaux.h new file mode 100644 index 0000000000..c16b04373b --- /dev/null +++ b/src/3rdparty/squirrel/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/src/3rdparty/squirrel/include/sqstdblob.h b/src/3rdparty/squirrel/include/sqstdblob.h new file mode 100644 index 0000000000..1d9a4cdc38 --- /dev/null +++ b/src/3rdparty/squirrel/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/src/3rdparty/squirrel/include/sqstdio.h b/src/3rdparty/squirrel/include/sqstdio.h new file mode 100644 index 0000000000..5eaec31c6d --- /dev/null +++ b/src/3rdparty/squirrel/include/sqstdio.h @@ -0,0 +1,54 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQSTDIO_H_ +#define _SQSTDIO_H_ + +#ifdef __cplusplus + +#define SQSTD_STREAM_TYPE_TAG 0x80000000 + +struct SQStream { + virtual ~SQStream() {} + virtual SQInteger Read(void *buffer, SQInteger size) = 0; + virtual SQInteger Write(void *buffer, SQInteger size) = 0; + virtual SQInteger Flush() = 0; + virtual SQInteger Tell() = 0; + virtual SQInteger Len() = 0; + virtual SQInteger Seek(SQInteger offset, SQInteger origin) = 0; + virtual bool IsValid() = 0; + virtual bool EOS() = 0; +}; + +extern "C" { +#endif + +#define SQ_SEEK_CUR 0 +#define SQ_SEEK_END 1 +#define SQ_SEEK_SET 2 + +typedef void* SQFILE; + +SQUIRREL_API SQFILE sqstd_fopen(const SQChar *,const SQChar *); +SQUIRREL_API SQInteger sqstd_fread(SQUserPointer, SQInteger, SQInteger, SQFILE); +SQUIRREL_API SQInteger sqstd_fwrite(const SQUserPointer, SQInteger, SQInteger, SQFILE); +SQUIRREL_API SQInteger sqstd_fseek(SQFILE , SQInteger , SQInteger); +SQUIRREL_API SQInteger sqstd_ftell(SQFILE); +SQUIRREL_API SQInteger sqstd_fflush(SQFILE); +SQUIRREL_API SQInteger sqstd_fclose(SQFILE); +SQUIRREL_API SQInteger sqstd_feof(SQFILE); + +SQUIRREL_API SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own); +SQUIRREL_API SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file); + +//compiler helpers +SQUIRREL_API SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror); +SQUIRREL_API SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror); +SQUIRREL_API SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename); + +SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*_SQSTDIO_H_*/ + diff --git a/src/3rdparty/squirrel/include/sqstdmath.h b/src/3rdparty/squirrel/include/sqstdmath.h new file mode 100644 index 0000000000..65de6fd72d --- /dev/null +++ b/src/3rdparty/squirrel/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/src/3rdparty/squirrel/include/sqstdstring.h b/src/3rdparty/squirrel/include/sqstdstring.h new file mode 100644 index 0000000000..72f30b4adf --- /dev/null +++ b/src/3rdparty/squirrel/include/sqstdstring.h @@ -0,0 +1,31 @@ +/* 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_register_stringlib(HSQUIRRELVM v); + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*_SQSTD_STRING_H_*/ diff --git a/src/3rdparty/squirrel/include/sqstdsystem.h b/src/3rdparty/squirrel/include/sqstdsystem.h new file mode 100644 index 0000000000..b155a91f8b --- /dev/null +++ b/src/3rdparty/squirrel/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/src/3rdparty/squirrel/include/squirrel.h b/src/3rdparty/squirrel/include/squirrel.h new file mode 100644 index 0000000000..e611d0853b --- /dev/null +++ b/src/3rdparty/squirrel/include/squirrel.h @@ -0,0 +1,450 @@ +/* +Copyright (c) 2003-2008 Alberto Demichelis + +This software is provided 'as-is', without any +express or implied warranty. In no event will the +authors be held liable for any damages arising from +the use of this software. + +Permission is granted to anyone to use this software +for any purpose, including commercial applications, +and to alter it and redistribute it freely, subject +to the following restrictions: + + 1. The origin of this software must not be + misrepresented; you must not claim that + you wrote the original software. If you + use this software in a product, an + acknowledgment in the product + documentation would be appreciated but is + not required. + + 2. Altered source versions must be plainly + marked as such, and must not be + misrepresented as being the original + software. + + 3. This notice may not be removed or + altered from any source distribution. + +*/ +#ifndef _SQUIRREL_H_ +#define _SQUIRREL_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(_MSC_VER) && _MSC_VER >= 1400 // MSVC 2005 safety checks +# pragma warning(disable: 4996) // '_wfopen' was declared deprecated +# define _CRT_SECURE_NO_DEPRECATE // all deprecated 'unsafe string functions +# define _CRT_NON_CONFORMING_SWPRINTFS // another deprecated stuff +#endif /* _MSC_VER >= 1400 */ + +#ifndef SQUIRREL_API +#define SQUIRREL_API extern +#endif + +#if (defined(_WIN64) || defined(_LP64)) && !defined(_SQ64) +#define _SQ64 +#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 SQInteger; +typedef unsigned long SQUnsignedInteger; +typedef unsigned long SQHash; /*should be the same size of a pointer*/ +#endif +typedef int SQInt32; +#else +typedef int SQInteger; +typedef int SQInt32; /*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 + + +typedef float SQFloat; +typedef void* SQUserPointer; +typedef SQUnsignedInteger SQBool; +typedef SQInteger SQRESULT; + +#define SQTrue (1) +#define SQFalse (0) + +struct SQVM; +struct SQTable; +struct SQArray; +struct SQString; +struct SQClosure; +struct SQGenerator; +struct SQNativeClosure; +struct SQUserData; +struct SQFunctionProto; +struct SQRefCounted; +struct SQClass; +struct SQInstance; +struct SQDelegable; + +#ifdef _UNICODE +#define SQUNICODE +#endif + +#ifdef SQUNICODE +#if (defined(_MSC_VER) && _MSC_VER >= 1400) // 1400 = VS8 + +#ifndef _WCHAR_T_DEFINED //this is if the compiler considers wchar_t as native type +typedef unsigned short wchar_t; +#endif +#endif + +typedef wchar_t SQChar; +#define _SC(a) L##a +#define scstrcmp wcscmp +#define scsprintf swprintf +#define scsnprintf _snwprintf +#define scstrlen wcslen +#define scstrtod wcstod +#define scstrtol wcstol +#define scatoi _wtoi +#define scstrtoul wcstoul +#define scvsprintf vswprintf +#define scstrstr wcsstr +#define scisspace iswspace +#define scisdigit iswdigit +#define scisxdigit iswxdigit +#define scisalpha iswalpha +#define sciscntrl iswcntrl +#define scisalnum iswalnum +#define scprintf wprintf +#define scfprintf fwprintf +#define scvprintf vwprintf +#define scvfprintf vfwprintf +#define scvsnprintf _vsnwprintf +#define scstrdup _wcsdup +#define scstrrchr wcsrchr +#define scstrcat wcscat +#define MAX_CHAR 0xFFFF +#else +typedef char SQChar; +#define _SC(a) a +#define scstrcmp strcmp +#define scsprintf sprintf +#define scsnprintf snprintf +#define scstrlen strlen +#define scstrtod strtod +#define scstrtol strtol +#define scatoi atoi +#define scstrtoul strtoul +#define scvsprintf vsprintf +#define scstrstr strstr +#define scisspace isspace +#define scisdigit isdigit +#define scisxdigit isxdigit +#define sciscntrl iscntrl +#define scisalpha isalpha +#define scisalnum isalnum +#define scprintf printf +#define scfprintf fprintf +#define scvprintf vprintf +#define scvfprintf vfprintf +#define scvsnprintf vsnprintf +#define scstrdup strdup +#define scstrrchr strrchr +#define scstrcat strcat +#define MAX_CHAR 0xFF +#endif + +#define SQUIRREL_VERSION _SC("Squirrel 2.2.2 stable - With custom OpenTTD modifications") +#define SQUIRREL_COPYRIGHT _SC("Copyright (C) 2003-2008 Alberto Demichelis") +#define SQUIRREL_AUTHOR _SC("Alberto Demichelis") + +#define SQ_VMSTATE_IDLE 0 +#define SQ_VMSTATE_RUNNING 1 +#define SQ_VMSTATE_SUSPENDED 2 + +#define SQUIRREL_EOB 0 +#define SQ_BYTECODE_STREAM_TAG 0xFAFA + +#define SQOBJECT_REF_COUNTED 0x08000000 +#define SQOBJECT_NUMERIC 0x04000000 +#define SQOBJECT_DELEGABLE 0x02000000 +#define SQOBJECT_CANBEFALSE 0x01000000 + +#define SQ_MATCHTYPEMASKSTRING (-99999) + +#define _RT_MASK 0x00FFFFFF +#define _RAW_TYPE(type) (type&_RT_MASK) + +#define _RT_NULL 0x00000001 +#define _RT_INTEGER 0x00000002 +#define _RT_FLOAT 0x00000004 +#define _RT_BOOL 0x00000008 +#define _RT_STRING 0x00000010 +#define _RT_TABLE 0x00000020 +#define _RT_ARRAY 0x00000040 +#define _RT_USERDATA 0x00000080 +#define _RT_CLOSURE 0x00000100 +#define _RT_NATIVECLOSURE 0x00000200 +#define _RT_GENERATOR 0x00000400 +#define _RT_USERPOINTER 0x00000800 +#define _RT_THREAD 0x00001000 +#define _RT_FUNCPROTO 0x00002000 +#define _RT_CLASS 0x00004000 +#define _RT_INSTANCE 0x00008000 +#define _RT_WEAKREF 0x00010000 + +typedef enum tagSQObjectType{ + OT_NULL = (_RT_NULL|SQOBJECT_CANBEFALSE), + OT_INTEGER = (_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE), + OT_FLOAT = (_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE), + OT_BOOL = (_RT_BOOL|SQOBJECT_CANBEFALSE), + OT_STRING = (_RT_STRING|SQOBJECT_REF_COUNTED), + OT_TABLE = (_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), + OT_ARRAY = (_RT_ARRAY|SQOBJECT_REF_COUNTED), + OT_USERDATA = (_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), + OT_CLOSURE = (_RT_CLOSURE|SQOBJECT_REF_COUNTED), + OT_NATIVECLOSURE = (_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED), + OT_GENERATOR = (_RT_GENERATOR|SQOBJECT_REF_COUNTED), + OT_USERPOINTER = _RT_USERPOINTER, + OT_THREAD = (_RT_THREAD|SQOBJECT_REF_COUNTED) , + OT_FUNCPROTO = (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only + OT_CLASS = (_RT_CLASS|SQOBJECT_REF_COUNTED), + OT_INSTANCE = (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE), + OT_WEAKREF = (_RT_WEAKREF|SQOBJECT_REF_COUNTED) +}SQObjectType; + +#define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED) + + +typedef union tagSQObjectValue +{ + struct SQTable *pTable; + struct SQArray *pArray; + struct SQClosure *pClosure; + struct SQGenerator *pGenerator; + struct SQNativeClosure *pNativeClosure; + struct SQString *pString; + struct SQUserData *pUserData; + SQInteger nInteger; + SQFloat fFloat; + SQUserPointer pUserPointer; + struct SQFunctionProto *pFunctionProto; + struct SQRefCounted *pRefCounted; + struct SQDelegable *pDelegable; + struct SQVM *pThread; + struct SQClass *pClass; + struct SQInstance *pInstance; + struct SQWeakRef *pWeakRef; +}SQObjectValue; + + +typedef struct tagSQObject +{ + SQObjectType _type; + SQObjectValue _unVal; +}SQObject; + +typedef struct tagSQStackInfos{ + const SQChar* funcname; + const SQChar* source; + SQInteger line; +}SQStackInfos; + +typedef struct SQVM* HSQUIRRELVM; +typedef SQObject HSQOBJECT; +typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM); +typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size); +typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/); +typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...); + +typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger); +typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger); + +typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer); + +typedef struct tagSQRegFunction{ + const SQChar *name; + SQFUNCTION f; + SQInteger nparamscheck; + const SQChar *typemask; +}SQRegFunction; + +/*vm*/ +SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize); +SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize); +SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v); +SQUIRREL_API void sq_close(HSQUIRRELVM v); +SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p); +SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v); +SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc); +SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v); +SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v); +SQUIRREL_API bool sq_resumecatch(HSQUIRRELVM v, int suspend = -1); +SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval,SQBool raiseerror); +SQUIRREL_API SQInteger sq_getvmstate(HSQUIRRELVM v); + +/*compiler*/ +SQUIRREL_API SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror); +SQUIRREL_API SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror); +SQUIRREL_API void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable); +SQUIRREL_API void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable); +SQUIRREL_API void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f); + +/*stack operations*/ +SQUIRREL_API void sq_push(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API void sq_pop(HSQUIRRELVM v,SQInteger nelemstopop); +SQUIRREL_API void sq_poptop(HSQUIRRELVM v); +SQUIRREL_API void sq_remove(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQInteger sq_gettop(HSQUIRRELVM v); +SQUIRREL_API void sq_settop(HSQUIRRELVM v,SQInteger newtop); +SQUIRREL_API void sq_reservestack(HSQUIRRELVM v,SQInteger nsize); +SQUIRREL_API SQInteger sq_cmp(HSQUIRRELVM v); +SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx); + +/*object creation handling*/ +SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size); +SQUIRREL_API void sq_newtable(HSQUIRRELVM v); +SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size); +SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars); +SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask); +SQUIRREL_API SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len); +SQUIRREL_API void sq_pushfloat(HSQUIRRELVM v,SQFloat f); +SQUIRREL_API void sq_pushinteger(HSQUIRRELVM v,SQInteger n); +SQUIRREL_API void sq_pushbool(HSQUIRRELVM v,SQBool b); +SQUIRREL_API void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p); +SQUIRREL_API void sq_pushnull(HSQUIRRELVM v); +SQUIRREL_API SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQBool sq_instanceof(HSQUIRRELVM v); +SQUIRREL_API void sq_tostring(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b); +SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c); +SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i); +SQUIRREL_API SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f); +SQUIRREL_API SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b); +SQUIRREL_API SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread); +SQUIRREL_API SQRESULT sq_getuserpointer(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p); +SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag); +SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag); +SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag); +SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook); +SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize); +SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars); +SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name); +SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p); +SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag); +SQUIRREL_API SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize); +SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase); +SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API void sq_weakref(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t); + +/*object manipulation*/ +SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v); +SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v); +SQUIRREL_API void sq_pushconsttable(HSQUIRRELVM v); +SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v); +SQUIRREL_API SQRESULT sq_setconsttable(HSQUIRRELVM v); +SQUIRREL_API SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic); +SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval); +SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval); +SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval); +SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize); +SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx); +SQUIRREL_API SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos); +SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval); +SQUIRREL_API SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx); +SQUIRREL_API SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx); + +/*calls*/ +SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror, int suspend = -1); +SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror); +SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx); +SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval); +SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err); +SQUIRREL_API void sq_reseterror(HSQUIRRELVM v); +SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v); + +/*raw object handling*/ +SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po); +SQUIRREL_API void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj); +SQUIRREL_API void sq_addref(HSQUIRRELVM v,HSQOBJECT *po); +SQUIRREL_API SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po); +SQUIRREL_API void sq_resetobject(HSQOBJECT *po); +SQUIRREL_API const SQChar *sq_objtostring(HSQOBJECT *o); +SQUIRREL_API SQBool sq_objtobool(HSQOBJECT *o); +SQUIRREL_API SQInteger sq_objtointeger(HSQOBJECT *o); +SQUIRREL_API SQFloat sq_objtofloat(HSQOBJECT *o); +SQUIRREL_API SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag); + +/*GC*/ +SQUIRREL_API SQInteger sq_collectgarbage(HSQUIRRELVM v); + +/*serialization*/ +SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up); +SQUIRREL_API SQRESULT sq_readclosure(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up); + +/*mem allocation*/ +SQUIRREL_API void *sq_malloc(SQUnsignedInteger size); +SQUIRREL_API void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize); +SQUIRREL_API void sq_free(void *p,SQUnsignedInteger size); + +/*debug*/ +SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,SQInteger level,SQStackInfos *si); +SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v); + +/*UTILITY MACRO*/ +#define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC) +#define sq_istable(o) ((o)._type==OT_TABLE) +#define sq_isarray(o) ((o)._type==OT_ARRAY) +#define sq_isfunction(o) ((o)._type==OT_FUNCPROTO) +#define sq_isclosure(o) ((o)._type==OT_CLOSURE) +#define sq_isgenerator(o) ((o)._type==OT_GENERATOR) +#define sq_isnativeclosure(o) ((o)._type==OT_NATIVECLOSURE) +#define sq_isstring(o) ((o)._type==OT_STRING) +#define sq_isinteger(o) ((o)._type==OT_INTEGER) +#define sq_isfloat(o) ((o)._type==OT_FLOAT) +#define sq_isuserpointer(o) ((o)._type==OT_USERPOINTER) +#define sq_isuserdata(o) ((o)._type==OT_USERDATA) +#define sq_isthread(o) ((o)._type==OT_THREAD) +#define sq_isnull(o) ((o)._type==OT_NULL) +#define sq_isclass(o) ((o)._type==OT_CLASS) +#define sq_isinstance(o) ((o)._type==OT_INSTANCE) +#define sq_isbool(o) ((o)._type==OT_BOOL) +#define sq_isweakref(o) ((o)._type==OT_WEAKREF) +#define sq_type(o) ((o)._type) + +/* deprecated */ +#define sq_createslot(v,n) sq_newslot(v,n,SQFalse) + +#define SQ_OK (0) +#define SQ_ERROR (-1) + +#define SQ_FAILED(res) (res<0) +#define SQ_SUCCEEDED(res) (res>=0) + +#ifdef __cplusplus +} /*extern "C"*/ +#endif + +#endif /*_SQUIRREL_H_*/ diff --git a/src/3rdparty/squirrel/samples/ackermann.nut b/src/3rdparty/squirrel/samples/ackermann.nut new file mode 100644 index 0000000000..c8d056082c --- /dev/null +++ b/src/3rdparty/squirrel/samples/ackermann.nut @@ -0,0 +1,22 @@ +/* +* +* Original Javascript version by David Hedbor(http://www.bagley.org/~doug/shootout/) +* +*/ + +function Ack(M, N) { + if (M == 0) return( N + 1 ); + if (N == 0) return( Ack(M - 1, 1) ); + return( Ack(M - 1, Ack(M, (N - 1))) ); +} + +local n; + +if(ARGS.len()!=0) { + n = ARGS[0].tointeger(); + if(n < 1) n = 1; +} else { + n = 1; +} +print("n="+n+"\n"); +print("Ack(3,"+ n+ "):"+ Ack(3, n)); diff --git a/src/3rdparty/squirrel/samples/array.nut b/src/3rdparty/squirrel/samples/array.nut new file mode 100644 index 0000000000..58f160b12d --- /dev/null +++ b/src/3rdparty/squirrel/samples/array.nut @@ -0,0 +1,28 @@ +/* +* +* Original Javascript version by David Hedbor(http://www.bagley.org/~doug/shootout/) +* +*/ +local n, i, k; + +if(ARGS.len()!=0) { + n = ARGS[0].tointeger(); + if(n < 1) n = 1; +} else { + n = 1; +} + +local x = []; x.resize(n); +local y = []; y.resize(n); + +for (i = 0; i < n; i+=1) { + x[i] = i + 1; + y[i] = 0; +} + +for (k = 0 ; k < n; k+=1) { + for (i = n-1; i >= 0; i-=1) { + y[i] = y[i]+ x[i]; + } +} +print(y[0].tostring()+" "+y[n-1]); diff --git a/src/3rdparty/squirrel/samples/class.nut b/src/3rdparty/squirrel/samples/class.nut new file mode 100644 index 0000000000..babe54f0b3 --- /dev/null +++ b/src/3rdparty/squirrel/samples/class.nut @@ -0,0 +1,49 @@ +////////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////////// +class BaseVector { + constructor(...) + { + if(vargc >= 3) { + x = vargv[0]; + y = vargv[1]; + z = vargv[2]; + } + } + + + x = 0; + y = 0; + z = 0; +} + +class Vector3 extends BaseVector { + function _add(other) + { + if(other instanceof this.getclass()) + return ::Vector3(x+other.x,y+other.y,z+other.z); + else + throw "wrong parameter"; + } + function Print() + { + ::print(x+","+y+","+z+"\n"); + } +} + +local v0 = Vector3(1,2,3) +local v1 = Vector3(11,12,13) +local v2 = v0 + v1; +v2.Print(); + +FakeNamespace <- { + Utils = {} +} + +class FakeNamespace.Utils.SuperClass { + constructor() + { + ::print("FakeNamespace.Utils.SuperClass") + } +} + +local testy = FakeNamespace.Utils.SuperClass(); diff --git a/src/3rdparty/squirrel/samples/classattributes.nut b/src/3rdparty/squirrel/samples/classattributes.nut new file mode 100644 index 0000000000..01232002c2 --- /dev/null +++ b/src/3rdparty/squirrel/samples/classattributes.nut @@ -0,0 +1,35 @@ +class Foo { + //constructor + constructor(a) + { + testy = ["stuff",1,2,3]; + } + //attributes of PrintTesty + + function PrintTesty() + { + foreach(i,val in testy) + { + ::print("idx = "+i+" = "+val+" \n"); + } + } + //attributes of testy + + testy = null; + +} + +foreach(member,val in Foo) +{ + ::print(member+"\n"); + local attr; + if((attr = Foo.getattributes(member)) != null) { + foreach(i,v in attr) + { + ::print("\t"+i+" = "+(typeof v)+"\n"); + } + } + else { + ::print("\t\n") + } +} diff --git a/src/3rdparty/squirrel/samples/coroutines.nut b/src/3rdparty/squirrel/samples/coroutines.nut new file mode 100644 index 0000000000..c7e4583c19 --- /dev/null +++ b/src/3rdparty/squirrel/samples/coroutines.nut @@ -0,0 +1,25 @@ +function coroutine_test(a,b) +{ + ::print(a+" "+b+"\n"); + local ret = ::suspend("suspend 1"); + ::print("the coroutine says "+ret+"\n"); + ret = ::suspend("suspend 2"); + ::print("the coroutine says "+ret+"\n"); + ret = ::suspend("suspend 3"); + ::print("the coroutine says "+ret+"\n"); + return "I'm done" +} + +local coro = ::newthread(coroutine_test); + +local susparam = coro.call("test","coroutine"); //starts the coroutine + +local i = 1; +do +{ + ::print("suspend passed ["+susparam+"]\n") + susparam = coro.wakeup("ciao "+i); + ++i; +}while(coro.getstatus()=="suspended") + +::print("return passed ["+susparam+"]\n") diff --git a/src/3rdparty/squirrel/samples/delegation.nut b/src/3rdparty/squirrel/samples/delegation.nut new file mode 100644 index 0000000000..e9e86ca9a5 --- /dev/null +++ b/src/3rdparty/squirrel/samples/delegation.nut @@ -0,0 +1,52 @@ + +PEntity <- { + name="noname" + pos={x=0,y=0,z=0} + type="entity" + //methamethod + _typeof=function() + { + return type; + } +} + +function PEntity::PrintPos() +{ + ::print("x="+pos.x+" y="+pos.y+" z="+pos.z+"\n"); +} + +function PEntity::new(name,pos) +{ + local newentity=clone ::PEntity; + if(name) + newentity.name=name; + if(pos) + newentity.pos=pos; + return newentity; +} + +PPlayer <- { + model="warrior.mdl" + weapon="fist" + health=100 + armor=0 + //overrides the parent type + type="player" +} + +function PPlayer::new(name,pos) +{ + local newplayer=delegate ::PEntity.new(name,pos) : clone ::PPlayer; + return newplayer; +} + +local player=PPlayer.new("godzilla",{x=10,y=20,z=30}); + +::print("PLAYER NAME"+player.name+"\n"); +::print("ENTITY TYPE"+typeof player+"\n"); + +player.PrintPos(); + +player.pos.x=123; + +player.PrintPos(); diff --git a/src/3rdparty/squirrel/samples/fibonacci.nut b/src/3rdparty/squirrel/samples/fibonacci.nut new file mode 100644 index 0000000000..1db79423e5 --- /dev/null +++ b/src/3rdparty/squirrel/samples/fibonacci.nut @@ -0,0 +1,15 @@ +/* +* +* Original Javascript version by David Hedbor(http://www.bagley.org/~doug/shootout/) +* +*/ + +function fib(n) +{ + if (n < 2) return 1 + return fib(n-2) + fib(n-1) +} + +local n = ARGS.len()!=0?ARGS[0].tointeger():1 + +print(fib(n)+"\n") diff --git a/src/3rdparty/squirrel/samples/flow.nut b/src/3rdparty/squirrel/samples/flow.nut new file mode 100644 index 0000000000..1cd7cfcf4b --- /dev/null +++ b/src/3rdparty/squirrel/samples/flow.nut @@ -0,0 +1,33 @@ +function min(x,y) + return xy?x:y; + +if(min(100,200)>max(50,20)) + print("I'm useless statement just to show up the if/else\n"); +else + print("squirrel!!\n"); + +print("\n") + +function typy(obj) +{ + switch(typeof obj) + { + case "integer": + case "float": + return "is a number"; + case "table": + case "array": + return "is a container"; + default: + return "is other stuff" + } +} + +local a=1,b={},c=function(a,b){return a+b;} + +print("a "+typy(a)+"\n"); +print("b "+typy(b)+"\n"); +print("c "+typy(c)+"\n"); diff --git a/src/3rdparty/squirrel/samples/generators.nut b/src/3rdparty/squirrel/samples/generators.nut new file mode 100644 index 0000000000..9853e09640 --- /dev/null +++ b/src/3rdparty/squirrel/samples/generators.nut @@ -0,0 +1,42 @@ +/* +*Random number function from The Great Computer Language shootout +*converted to a generator func +*/ + +function gen_random(max) { + local last=42 + local IM = 139968; + local IA = 3877; + local IC = 29573; + for(;;){ //loops forever + yield (max * (last = (last * IA + IC) % IM) / IM); + } +} + +local randtor=gen_random(100); + +print("RAND NUMBERS \n") + +for(local i=0;i<10;i+=1) + print(">"+resume randtor+"\n"); + +print("FIBONACCI \n") +function fiboz(n) +{ + local prev=0; + local curr=1; + yield 1; + + for(local i=0;i"+val+"\n"); +} diff --git a/src/3rdparty/squirrel/samples/hello.nut b/src/3rdparty/squirrel/samples/hello.nut new file mode 100644 index 0000000000..1dc45ac136 --- /dev/null +++ b/src/3rdparty/squirrel/samples/hello.nut @@ -0,0 +1 @@ +print("Hello World!") \ No newline at end of file diff --git a/src/3rdparty/squirrel/samples/list.nut b/src/3rdparty/squirrel/samples/list.nut new file mode 100644 index 0000000000..8ab1ab517b --- /dev/null +++ b/src/3rdparty/squirrel/samples/list.nut @@ -0,0 +1,39 @@ +/*translation of the list test from The Great Computer Language Shootout +*/ + +function compare_arr(a1,a2) +{ + foreach(i,val in a1) + if(val!=a2[i])return null; + return 1; +} + +function test() +{ + local size=10000 + local l1=[]; l1.resize(size); + for(local i=0;i0) + l3.append(l2.pop()); + while(l3.len()>0) + l2.append(l3.pop()); + l1.reverse(); + + if(compare_arr(l1,l2)) + return l1.len(); + return null; +} + +local n = ARGS.len()!=0?ARGS[0].tointeger():1 +for(local i=0;i\n"); +else + print("\n"); diff --git a/src/3rdparty/squirrel/samples/methcall.nut b/src/3rdparty/squirrel/samples/methcall.nut new file mode 100644 index 0000000000..131d262288 --- /dev/null +++ b/src/3rdparty/squirrel/samples/methcall.nut @@ -0,0 +1,61 @@ +/*translation of the methcall test from The Great Computer Language Shootout +*/ + +Toggle <- { + bool=null +} + +function Toggle::value() { + return bool; +} + +function Toggle::activate() { + bool = !bool; + return this; +} + +function Toggle::new(startstate) { + local newo=clone this; + newo.bool = startstate; + return newo; +} + +NthToggle <- { + count_max=null + count=0 +} + +function NthToggle::new(start_state,max_counter) +{ + local newo=delegate ::Toggle.new(start_state) : clone this; + newo.count_max <- max_counter + return newo; +} + +function NthToggle::activate () +{ + count+=1 + if (count >= count_max) { + bool = !bool; + count = 0; + } + return this; +} + + +local n = ARGS.len()!=0?ARGS[0].tointeger():1 + +local val = 1; +local toggle = Toggle.new(val); +for (local i=0; i +#include +#include +#include + +#if defined(_MSC_VER) && defined(_DEBUG) +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#ifdef SQUNICODE +#define scfprintf fwprintf +#define scfopen _wfopen +#define scvprintf vwprintf +#else +#define scfprintf fprintf +#define scfopen fopen +#define scvprintf vprintf +#endif + + +void PrintVersionInfos(); + +#if defined(_MSC_VER) && defined(_DEBUG) +int MemAllocHook( int allocType, void *userData, size_t size, int blockType, + long requestNumber, const unsigned char *filename, int lineNumber) +{ +// if(requestNumber==585)_asm int 3; + return 1; +} +#endif + + +SQInteger quit(HSQUIRRELVM v) +{ + int *done; + sq_getuserpointer(v,-1,(SQUserPointer*)&done); + *done=1; + return 0; +} + +void printfunc(HSQUIRRELVM v,const SQChar *s,...) +{ + va_list vl; + va_start(vl, s); + scvprintf( s, vl); + va_end(vl); +} + +void PrintVersionInfos() +{ + scfprintf(stdout,_SC("%s %s (%d bits)\n"),SQUIRREL_VERSION,SQUIRREL_COPYRIGHT,sizeof(SQInteger)*8); +} + +void PrintUsage() +{ + scfprintf(stderr,_SC("usage: sq .\n") + _SC("Available options are:\n") + _SC(" -c compiles the file to bytecode(default output 'out.cnut')\n") + _SC(" -o specifies output file for the -c option\n") + _SC(" -c compiles only\n") + _SC(" -d generates debug infos\n") + _SC(" -v displays version infos\n") + _SC(" -h prints help\n")); +} + +#define _INTERACTIVE 0 +#define _DONE 2 +//<> this func is a mess +int getargs(HSQUIRRELVM v,int argc, char* argv[]) +{ + int i; + int compiles_only = 0; + static SQChar temp[500]; + const SQChar *ret=NULL; + char * output = NULL; + int lineinfo=0; + if(argc>1) + { + int arg=1,exitloop=0; + while(arg < argc && !exitloop) + { + + if(argv[arg][0]=='-') + { + switch(argv[arg][1]) + { + case 'd': //DEBUG(debug infos) + sq_enabledebuginfo(v,1); + break; + case 'c': + compiles_only = 1; + break; + case 'o': + if(arg < argc) { + arg++; + output = argv[arg]; + } + break; + case 'v': + PrintVersionInfos(); + return _DONE; + + case 'h': + PrintVersionInfos(); + PrintUsage(); + return _DONE; + default: + PrintVersionInfos(); + scprintf(_SC("unknown prameter '-%c'\n"),argv[arg][1]); + PrintUsage(); + return _DONE; + } + }else break; + arg++; + } + + // src file + + if(arg")); + for(;;) { + int c; + if(done)return; + c = getchar(); + if (c == _SC('\n')) { + if (i>0 && buffer[i-1] == _SC('\\')) + { + buffer[i-1] = _SC('\n'); + } + else if(blocks==0)break; + buffer[i++] = _SC('\n'); + } + else if (c==_SC('}')) {blocks--; buffer[i++] = (SQChar)c;} + else if(c==_SC('{') && !string){ + blocks++; + buffer[i++] = (SQChar)c; + } + else if(c==_SC('"') || c==_SC('\'')){ + string=!string; + buffer[i++] = (SQChar)c; + } + else if (i >= MAXINPUT-1) { + scfprintf(stderr, _SC("sq : input line too long\n")); + break; + } + else{ + buffer[i++] = (SQChar)c; + } + } + buffer[i] = _SC('\0'); + + if(buffer[0]==_SC('=')){ + scsprintf(sq_getscratchpad(v,MAXINPUT),_SC("return (%s)"),&buffer[1]); + memcpy(buffer,sq_getscratchpad(v,-1),(scstrlen(sq_getscratchpad(v,-1))+1)*sizeof(SQChar)); + retval=1; + } + i=scstrlen(buffer); + if(i>0){ + SQInteger oldtop=sq_gettop(v); + if(SQ_SUCCEEDED(sq_compilebuffer(v,buffer,i,_SC("interactive console"),SQTrue))){ + sq_pushroottable(v); + if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue)) && retval){ + scprintf(_SC("\n")); + sq_pushroottable(v); + sq_pushstring(v,_SC("print"),-1); + sq_get(v,-2); + sq_pushroottable(v); + sq_push(v,-4); + sq_call(v,2,SQFalse,SQTrue); + retval=0; + scprintf(_SC("\n")); + } + } + + sq_settop(v,oldtop); + } + } +} + +int main(int argc, char* argv[]) +{ + HSQUIRRELVM v; + + const SQChar *filename=NULL; +#if defined(_MSC_VER) && defined(_DEBUG) + _CrtSetAllocHook(MemAllocHook); +#endif + + v=sq_open(1024); + sq_setprintfunc(v,printfunc); + + sq_pushroottable(v); + + sqstd_register_bloblib(v); + sqstd_register_iolib(v); + sqstd_register_systemlib(v); + sqstd_register_mathlib(v); + sqstd_register_stringlib(v); + + //aux library + //sets error handlers + sqstd_seterrorhandlers(v); + + //gets arguments + switch(getargs(v,argc,argv)) + { + case _INTERACTIVE: + Interactive(v); + break; + case _DONE: + default: + break; + } + + sq_close(v); + +#if defined(_MSC_VER) && defined(_DEBUG) + _getch(); + _CrtMemDumpAllObjectsSince( NULL ); +#endif + return 0; +} + diff --git a/src/3rdparty/squirrel/sq/sq.dsp b/src/3rdparty/squirrel/sq/sq.dsp new file mode 100644 index 0000000000..77887d0644 --- /dev/null +++ b/src/3rdparty/squirrel/sq/sq.dsp @@ -0,0 +1,101 @@ +# Microsoft Developer Studio Project File - Name="sq" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Console Application" 0x0103 + +CFG=sq - 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 "sq.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 "sq.mak" CFG="sq - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "sq - Win32 Release" (based on "Win32 (x86) Console Application") +!MESSAGE "sq - Win32 Debug" (based on "Win32 (x86) Console Application") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_LocalPath ".." +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "sq - 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 Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "..\include" /I "..\sqstdlib" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /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 +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 +# ADD LINK32 squirrel.lib sqstdlib.lib /nologo /subsystem:console /machine:I386 /out:"../bin/sq.exe" /libpath:"../lib" + +!ELSEIF "$(CFG)" == "sq - 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 Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "..\include" /I "..\sqstdlib" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /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 +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept +# ADD LINK32 squirrel.lib sqstdlib.lib /nologo /subsystem:console /debug /machine:I386 /out:"../bin/sq.exe" /pdbtype:sept /libpath:"../lib" + +!ENDIF + +# Begin Target + +# Name "sq - Win32 Release" +# Name "sq - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\sq.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# End Group +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# End Group +# End Target +# End Project diff --git a/src/3rdparty/squirrel/sqstdlib/Makefile b/src/3rdparty/squirrel/sqstdlib/Makefile new file mode 100644 index 0000000000..d2c33c54a0 --- /dev/null +++ b/src/3rdparty/squirrel/sqstdlib/Makefile @@ -0,0 +1,31 @@ +SQUIRREL= .. + + +OUT= $(SQUIRREL)/lib/libsqstdlib.a +INCZ= -I$(SQUIRREL)/include -I. -Iinclude + +SRCS= \ + sqstdblob.cpp \ + sqstdio.cpp \ + sqstdstream.cpp \ + sqstdmath.cpp \ + sqstdsystem.cpp \ + sqstdstring.cpp \ + sqstdaux.cpp \ + sqstdrex.cpp + + +sq32: + gcc -O2 -fno-rtti -Wall -c $(SRCS) $(INCZ) + ar rc $(OUT) *.o + +sqprof: + gcc -O2 -pg -fno-rtti -pie -gstabs -g3 -Wall -c $(SRCS) $(INCZ) + ar rc $(OUT) *.o + +sq64: + gcc -O2 -D_SQ64 -fno-rtti -Wall -c $(SRCS) $(INCZ) + ar rc $(OUT) *.o + +clean: + rm -f $(OUT) $(SRCS:%.cpp=%.o) diff --git a/src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp new file mode 100644 index 0000000000..65c9070b35 --- /dev/null +++ b/src/3rdparty/squirrel/sqstdlib/sqstdaux.cpp @@ -0,0 +1,129 @@ +/* see copyright notice in squirrel.h */ +#include +#include +#include + +void sqstd_printcallstack(HSQUIRRELVM v) +{ + SQPRINTFUNCTION pf = sq_getprintfunc(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_getprintfunc(v); + if(pf) { + const SQChar *sErr = 0; + if(sq_gettop(v)>=1) { + if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr))) { + pf(v,_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr); + } + else{ + pf(v,_SC("\nAN ERROR HAS OCCURED [unknown]\n")); + } + sqstd_printcallstack(v); + } + } + return 0; +} + +void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSource,SQInteger line,SQInteger column) +{ + SQPRINTFUNCTION pf = sq_getprintfunc(v); + if(pf) { + pf(v,_SC("%s line = (%d) column = (%d) : error %s\n"),sSource,line,column,sErr); + } +} + +void sqstd_seterrorhandlers(HSQUIRRELVM v) +{ + sq_setcompilererrorhandler(v,_sqstd_compiler_error); + sq_newclosure(v,_sqstd_aux_printerror,0); + sq_seterrorhandler(v); +} diff --git a/src/3rdparty/squirrel/sqstdlib/sqstdblob.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdblob.cpp new file mode 100644 index 0000000000..23842ba6fd --- /dev/null +++ b/src/3rdparty/squirrel/sqstdlib/sqstdblob.cpp @@ -0,0 +1,251 @@ +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include +#include +#include "sqstdstream.h" +#include "sqstdblobimpl.h" + +#define SQSTD_BLOB_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000002) + +//Blob + + +#define SETUP_BLOB(v) \ + SQBlob *self = NULL; \ + { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \ + return SQ_ERROR; } + + +static SQInteger _blob_resize(HSQUIRRELVM v) +{ + SETUP_BLOB(v); + SQInteger size; + sq_getinteger(v,2,&size); + if(!self->Resize(size)) + return sq_throwerror(v,_SC("resize failed")); + return 0; +} + +static void __swap_dword(unsigned int *n) +{ + *n=(unsigned int)(((*n&0xFF000000)>>24) | + ((*n&0x00FF0000)>>8) | + ((*n&0x0000FF00)<<8) | + ((*n&0x000000FF)<<24)); +} + +static void __swap_word(unsigned short *n) +{ + *n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00); +} + +static SQInteger _blob_swap4(HSQUIRRELVM v) +{ + SETUP_BLOB(v); + SQInteger num=(self->Len()-(self->Len()%4))>>2; + unsigned int *t=(unsigned int *)self->GetBuf(); + for(SQInteger i = 0; i < num; i++) { + __swap_dword(&t[i]); + } + return 0; +} + +static SQInteger _blob_swap2(HSQUIRRELVM v) +{ + SETUP_BLOB(v); + SQInteger num=(self->Len()-(self->Len()%2))>>1; + unsigned short *t = (unsigned short *)self->GetBuf(); + for(SQInteger i = 0; i < num; i++) { + __swap_word(&t[i]); + } + return 0; +} + +static SQInteger _blob__set(HSQUIRRELVM v) +{ + SETUP_BLOB(v); + SQInteger idx,val; + sq_getinteger(v,2,&idx); + sq_getinteger(v,3,&val); + if(idx < 0 || idx >= self->Len()) + return sq_throwerror(v,_SC("index out of range")); + ((unsigned char *)self->GetBuf())[idx] = (unsigned char) val; + sq_push(v,3); + return 1; +} + +static SQInteger _blob__get(HSQUIRRELVM v) +{ + SETUP_BLOB(v); + SQInteger idx; + sq_getinteger(v,2,&idx); + if(idx < 0 || idx >= self->Len()) + return sq_throwerror(v,_SC("index out of range")); + sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]); + return 1; +} + +static SQInteger _blob__nexti(HSQUIRRELVM v) +{ + SETUP_BLOB(v); + if(sq_gettype(v,2) == OT_NULL) { + sq_pushinteger(v, 0); + return 1; + } + SQInteger idx; + if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) { + if(idx+1 < self->Len()) { + sq_pushinteger(v, idx+1); + return 1; + } + sq_pushnull(v); + return 1; + } + return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type")); +} + +static SQInteger _blob__typeof(HSQUIRRELVM v) +{ + sq_pushstring(v,_SC("blob"),-1); + return 1; +} + +static SQInteger _blob_releasehook(SQUserPointer p, SQInteger size) +{ + SQBlob *self = (SQBlob*)p; + delete self; + return 1; +} + +static SQInteger _blob_constructor(HSQUIRRELVM v) +{ + SQInteger nparam = sq_gettop(v); + SQInteger size = 0; + if(nparam == 2) { + sq_getinteger(v, 2, &size); + } + if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size")); + SQBlob *b = new SQBlob(size); + if(SQ_FAILED(sq_setinstanceup(v,1,b))) { + delete b; + return sq_throwerror(v, _SC("cannot create blob with negative size")); + } + sq_setreleasehook(v,1,_blob_releasehook); + return 0; +} + +#define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck} +static SQRegFunction _blob_methods[] = { + _DECL_BLOB_FUNC(constructor,-1,_SC("xn")), + _DECL_BLOB_FUNC(resize,2,_SC("xn")), + _DECL_BLOB_FUNC(swap2,1,_SC("x")), + _DECL_BLOB_FUNC(swap4,1,_SC("x")), + _DECL_BLOB_FUNC(_set,3,_SC("xnn")), + _DECL_BLOB_FUNC(_get,2,_SC("xn")), + _DECL_BLOB_FUNC(_typeof,1,_SC("x")), + _DECL_BLOB_FUNC(_nexti,2,_SC("x")), + {0,0,0,0} +}; + + + +//GLOBAL FUNCTIONS + +static SQInteger _g_blob_casti2f(HSQUIRRELVM v) +{ + SQInteger i; + sq_getinteger(v,2,&i); + sq_pushfloat(v,*((SQFloat *)&i)); + return 1; +} + +static SQInteger _g_blob_castf2i(HSQUIRRELVM v) +{ + SQFloat f; + sq_getfloat(v,2,&f); + sq_pushinteger(v,*((SQInteger *)&f)); + return 1; +} + +static SQInteger _g_blob_swap2(HSQUIRRELVM v) +{ + SQInteger i; + sq_getinteger(v,2,&i); + short s=(short)i; + sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF)); + return 1; +} + +static SQInteger _g_blob_swap4(HSQUIRRELVM v) +{ + SQInteger i; + sq_getinteger(v,2,&i); + unsigned int t4 = (unsigned int)i; + __swap_dword(&t4); + sq_pushinteger(v,(SQInteger)t4); + return 1; +} + +static SQInteger _g_blob_swapfloat(HSQUIRRELVM v) +{ + SQFloat f; + sq_getfloat(v,2,&f); + __swap_dword((unsigned int *)&f); + sq_pushfloat(v,f); + return 1; +} + +#define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck} +static SQRegFunction bloblib_funcs[]={ + _DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")), + _DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")), + _DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")), + _DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")), + _DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")), + {0,0,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/src/3rdparty/squirrel/sqstdlib/sqstdblobimpl.h b/src/3rdparty/squirrel/sqstdlib/sqstdblobimpl.h new file mode 100644 index 0000000000..9f22c0ae2d --- /dev/null +++ b/src/3rdparty/squirrel/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/src/3rdparty/squirrel/sqstdlib/sqstdio.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdio.cpp new file mode 100644 index 0000000000..217205e5c9 --- /dev/null +++ b/src/3rdparty/squirrel/sqstdlib/sqstdio.cpp @@ -0,0 +1,410 @@ +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include +#include "sqstdstream.h" + +#define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001) +//basic API +SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode) +{ +#ifndef SQUNICODE + return (SQFILE)fopen(filename,mode); +#else + return (SQFILE)_wfopen(filename,mode); +#endif +} + +SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file) +{ + return (SQInteger)fread(buffer,size,count,(FILE *)file); +} + +SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file) +{ + return (SQInteger)fwrite(buffer,size,count,(FILE *)file); +} + +SQInteger sqstd_fseek(SQFILE file, SQInteger offset, SQInteger origin) +{ + SQInteger realorigin; + switch(origin) { + case SQ_SEEK_CUR: realorigin = SEEK_CUR; break; + case SQ_SEEK_END: realorigin = SEEK_END; break; + case SQ_SEEK_SET: realorigin = SEEK_SET; break; + default: return -1; //failed + } + return fseek((FILE *)file,(long)offset,(int)realorigin); +} + +SQInteger sqstd_ftell(SQFILE file) +{ + return ftell((FILE *)file); +} + +SQInteger sqstd_fflush(SQFILE file) +{ + return fflush((FILE *)file); +} + +SQInteger sqstd_fclose(SQFILE file) +{ + return fclose((FILE *)file); +} + +SQInteger sqstd_feof(SQFILE file) +{ + return feof((FILE *)file); +} + +//File +struct SQFile : public SQStream { + SQFile() { _handle = NULL; _owns = false;} + SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;} + virtual ~SQFile() { Close(); } + bool Open(const SQChar *filename ,const SQChar *mode) { + Close(); + if( (_handle = sqstd_fopen(filename,mode)) ) { + _owns = true; + return true; + } + return false; + } + void Close() { + if(_handle && _owns) { + sqstd_fclose(_handle); + _handle = NULL; + _owns = false; + } + } + SQInteger Read(void *buffer,SQInteger size) { + return sqstd_fread(buffer,1,size,_handle); + } + SQInteger Write(void *buffer,SQInteger size) { + return sqstd_fwrite(buffer,1,size,_handle); + } + SQInteger Flush() { + return sqstd_fflush(_handle); + } + SQInteger Tell() { + return sqstd_ftell(_handle); + } + SQInteger Len() { + SQInteger prevpos=Tell(); + Seek(0,SQ_SEEK_END); + SQInteger size=Tell(); + Seek(prevpos,SQ_SEEK_SET); + return size; + } + SQInteger Seek(SQInteger offset, SQInteger origin) { + return sqstd_fseek(_handle,offset,origin); + } + bool IsValid() { return _handle?true:false; } + bool EOS() { return Tell()==Len()?true:false;} + SQFILE GetHandle() {return _handle;} +private: + SQFILE _handle; + bool _owns; +}; + +static SQInteger _file__typeof(HSQUIRRELVM v) +{ + sq_pushstring(v,_SC("file"),-1); + return 1; +} + +static SQInteger _file_releasehook(SQUserPointer p, SQInteger size) +{ + SQFile *self = (SQFile*)p; + delete self; + return 1; +} + +static SQInteger _file_constructor(HSQUIRRELVM v) +{ + const SQChar *filename,*mode; + bool owns = true; + SQFile *f; + SQFILE newf; + if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) { + sq_getstring(v, 2, &filename); + sq_getstring(v, 3, &mode); + newf = sqstd_fopen(filename, mode); + if(!newf) return sq_throwerror(v, _SC("cannot open file")); + } else if(sq_gettype(v,2) == OT_USERPOINTER) { + owns = !(sq_gettype(v,3) == OT_NULL); + sq_getuserpointer(v,2,&newf); + } else { + return sq_throwerror(v,_SC("wrong parameter")); + } + f = new SQFile(newf,owns); + if(SQ_FAILED(sq_setinstanceup(v,1,f))) { + delete f; + return sq_throwerror(v, _SC("cannot create blob with negative size")); + } + sq_setreleasehook(v,1,_file_releasehook); + return 0; +} + +//bindings +#define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck} +static SQRegFunction _file_methods[] = { + _DECL_FILE_FUNC(constructor,3,_SC("x")), + _DECL_FILE_FUNC(_typeof,1,_SC("x")), + {0,0,0,0}, +}; + + + +SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own) +{ + SQInteger top = sq_gettop(v); + sq_pushregistrytable(v); + sq_pushstring(v,_SC("std_file"),-1); + if(SQ_SUCCEEDED(sq_get(v,-2))) { + sq_remove(v,-2); //removes the registry + sq_pushroottable(v); // push the this + sq_pushuserpointer(v,file); //file + if(own){ + sq_pushinteger(v,1); //true + } + else{ + sq_pushnull(v); //false + } + if(SQ_SUCCEEDED( sq_call(v,3,SQTrue,SQFalse) )) { + sq_remove(v,-2); + return SQ_OK; + } + } + sq_settop(v,top); + return SQ_OK; +} + +SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file) +{ + SQFile *fileobj = NULL; + if(SQ_SUCCEEDED(sq_getinstanceup(v,idx,(SQUserPointer*)&fileobj,(SQUserPointer)SQSTD_FILE_TYPE_TAG))) { + *file = fileobj->GetHandle(); + return SQ_OK; + } + return sq_throwerror(v,_SC("not a file")); +} + + + +static SQInteger _io_file_lexfeed_ASCII(SQUserPointer file) +{ + SQInteger ret; + char c; + if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) ) + return c; + return 0; +} + +static SQInteger _io_file_lexfeed_UTF8(SQUserPointer file) +{ +#define READ() \ + if(sqstd_fread(&inchar,sizeof(inchar),1,(FILE *)file) != 1) \ + return 0; + + static const SQInteger utf8_lengths[16] = + { + 1,1,1,1,1,1,1,1, /* 0000 to 0111 : 1 byte (plain ASCII) */ + 0,0,0,0, /* 1000 to 1011 : not valid */ + 2,2, /* 1100, 1101 : 2 bytes */ + 3, /* 1110 : 3 bytes */ + 4 /* 1111 :4 bytes */ + }; + static unsigned char byte_masks[5] = {0,0,0x1f,0x0f,0x07}; + unsigned char inchar; + SQInteger c = 0; + READ(); + c = inchar; + // + if(c >= 0x80) { + SQInteger tmp; + SQInteger codelen = utf8_lengths[c>>4]; + if(codelen == 0) + return 0; + //"invalid UTF-8 stream"; + tmp = c&byte_masks[codelen]; + for(SQInteger n = 0; n < codelen-1; n++) { + tmp<<=6; + READ(); + tmp |= inchar & 0x3F; + } + c = tmp; + } + return c; +} + +static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer file) +{ + SQInteger ret; + wchar_t c; + if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) ) + return (SQChar)c; + return 0; +} + +static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer file) +{ + SQInteger ret; + unsigned short c; + if( ( ret=sqstd_fread(&c,sizeof(c),1,(FILE *)file )>0) ) { + c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00); + return (SQChar)c; + } + return 0; +} + +SQInteger file_read(SQUserPointer file,SQUserPointer buf,SQInteger size) +{ + SQInteger ret; + if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret; + return -1; +} + +SQInteger file_write(SQUserPointer file,SQUserPointer p,SQInteger size) +{ + return sqstd_fwrite(p,1,size,(SQFILE)file); +} + +SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror) +{ + SQFILE file = sqstd_fopen(filename,_SC("rb")); + SQInteger ret; + unsigned short us; + unsigned char uc; + SQLEXREADFUNC func = _io_file_lexfeed_ASCII; + if(file){ + ret = sqstd_fread(&us,1,2,file); + if(ret != 2) { + //probably an empty file + us = 0; + } + if(us == SQ_BYTECODE_STREAM_TAG) { //BYTECODE + sqstd_fseek(file,0,SQ_SEEK_SET); + if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) { + sqstd_fclose(file); + return SQ_OK; + } + } + else { //SCRIPT + switch(us) + { + //gotta swap the next 2 lines on BIG endian machines + case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian; + case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian; + case 0xBBEF: + if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) { + sqstd_fclose(file); + return sq_throwerror(v,_SC("io error")); + } + if(uc != 0xBF) { + sqstd_fclose(file); + return sq_throwerror(v,_SC("Unrecognozed ecoding")); + } + func = _io_file_lexfeed_UTF8; + break;//UTF-8 ; + default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii + } + + if(SQ_SUCCEEDED(sq_compile(v,func,file,filename,printerror))){ + sqstd_fclose(file); + return SQ_OK; + } + } + sqstd_fclose(file); + return SQ_ERROR; + } + return sq_throwerror(v,_SC("cannot open the file")); +} + +SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror) +{ + if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) { + sq_push(v,-2); + if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) { + sq_remove(v,retval?-2:-1); //removes the closure + return 1; + } + sq_pop(v,1); //removes the closure + } + return SQ_ERROR; +} + +SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename) +{ + SQFILE file = sqstd_fopen(filename,_SC("wb+")); + if(!file) return sq_throwerror(v,_SC("cannot open the file")); + if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) { + sqstd_fclose(file); + return SQ_OK; + } + sqstd_fclose(file); + return SQ_ERROR; //forward the error +} + +SQInteger _g_io_loadfile(HSQUIRRELVM v) +{ + const SQChar *filename; + SQBool printerror = SQFalse; + sq_getstring(v,2,&filename); + if(sq_gettop(v) >= 3) { + sq_getbool(v,3,&printerror); + } + if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) + return 1; + return SQ_ERROR; //propagates the error +} + +SQInteger _g_io_writeclosuretofile(HSQUIRRELVM v) +{ + const SQChar *filename; + sq_getstring(v,2,&filename); + if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,filename))) + return 1; + return SQ_ERROR; //propagates the error +} + +SQInteger _g_io_dofile(HSQUIRRELVM v) +{ + const SQChar *filename; + SQBool printerror = SQFalse; + sq_getstring(v,2,&filename); + if(sq_gettop(v) >= 3) { + sq_getbool(v,3,&printerror); + } + sq_push(v,1); //repush the this + if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror))) + return 1; + return SQ_ERROR; //propagates the error +} + +#define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck} +static SQRegFunction iolib_funcs[]={ + _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")), + _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")), + _DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")), + {0,0,0,0} +}; + +SQRESULT sqstd_register_iolib(HSQUIRRELVM v) +{ + SQInteger top = sq_gettop(v); + //create delegate + declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs); + sq_pushstring(v,_SC("stdout"),-1); + sqstd_createfile(v,stdout,SQFalse); + sq_createslot(v,-3); + sq_pushstring(v,_SC("stdin"),-1); + sqstd_createfile(v,stdin,SQFalse); + sq_createslot(v,-3); + sq_pushstring(v,_SC("stderr"),-1); + sqstd_createfile(v,stderr,SQFalse); + sq_createslot(v,-3); + sq_settop(v,top); + return SQ_OK; +} diff --git a/src/3rdparty/squirrel/sqstdlib/sqstdlib.dsp b/src/3rdparty/squirrel/sqstdlib/sqstdlib.dsp new file mode 100644 index 0000000000..ad0bcece30 --- /dev/null +++ b/src/3rdparty/squirrel/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/src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp new file mode 100644 index 0000000000..7d35f40e42 --- /dev/null +++ b/src/3rdparty/squirrel/sqstdlib/sqstdmath.cpp @@ -0,0 +1,106 @@ +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include + +#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,0,0}, +}; + +#ifndef M_PI +#define M_PI (3.14159265358979323846) +#endif + +SQRESULT sqstd_register_mathlib(HSQUIRRELVM v) +{ + SQInteger i=0; + while(mathlib_funcs[i].name!=0) { + sq_pushstring(v,mathlib_funcs[i].name,-1); + sq_newclosure(v,mathlib_funcs[i].f,0); + sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask); + sq_setnativeclosurename(v,-1,mathlib_funcs[i].name); + sq_createslot(v,-3); + i++; + } + sq_pushstring(v,_SC("RAND_MAX"),-1); + sq_pushinteger(v,RAND_MAX); + sq_createslot(v,-3); + sq_pushstring(v,_SC("PI"),-1); + sq_pushfloat(v,(SQFloat)M_PI); + sq_createslot(v,-3); + return SQ_OK; +} diff --git a/src/3rdparty/squirrel/sqstdlib/sqstdrex.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdrex.cpp new file mode 100644 index 0000000000..f07899d1eb --- /dev/null +++ b/src/3rdparty/squirrel/sqstdlib/sqstdrex.cpp @@ -0,0 +1,635 @@ +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include +#include "sqstdstring.h" + +#ifdef _UNICODE +#define scisprint iswprint +#else +#define scisprint isprint +#endif + +#ifdef _DEBUG +#include + +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; + 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; + throw std::exception(); +} + +static void sqstd_rex_expect(SQRex *exp, SQChar 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((SQChar)first>*exp->_p) sqstd_rex_error(exp,_SC("invalid range")); + if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges")); + exp->_nodes[r].left = exp->_nodes[first].type; + SQInteger t = sqstd_rex_escapechar(exp); + exp->_nodes[r].right = t; + exp->_nodes[chain].next = r; + chain = r; + first = -1; + } + else{ + if(first!=-1){ + SQInteger c = first; + exp->_nodes[chain].next = c; + chain = c; + first = sqstd_rex_charnode(exp,SQTrue); + } + else{ + first = sqstd_rex_charnode(exp,SQTrue); + } + } + } + if(first!=-1){ + SQInteger c = first; + exp->_nodes[chain].next = c; + chain = c; + first = -1; + } + /* hack? */ + exp->_nodes[ret].left = exp->_nodes[ret].next; + exp->_nodes[ret].next = -1; + return ret; +} + +static SQInteger sqstd_rex_parsenumber(SQRex *exp) +{ + SQInteger ret = *exp->_p-'0'; + SQInteger positions = 10; + exp->_p++; + while(isdigit(*exp->_p)) { + ret = ret*10+(*exp->_p++-'0'); + if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant")); + positions *= 10; + }; + return ret; +} + +static SQInteger sqstd_rex_element(SQRex *exp) +{ + SQInteger ret = -1; + switch(*exp->_p) + { + case '(': { + SQInteger expr; + exp->_p++; + + + if(*exp->_p =='?') { + exp->_p++; + sqstd_rex_expect(exp,_SC(':')); + 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,_SC(')')); + } + break; + case '[': + exp->_p++; + ret = sqstd_rex_class(exp); + sqstd_rex_expect(exp,_SC(']')); + 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,_SC('}')); + 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,SQInteger c) +{ + do { + switch(node->type) { + case OP_RANGE: + if(c >= node->left && c <= node->right) return SQTrue; + break; + case OP_CCLASS: + if(sqstd_rex_matchcclass(node->left,c)) return SQTrue; + break; + default: + if(c == node->type)return SQTrue; + } + } while((node->next != -1) && (node = &exp->_nodes[node->next])); + return SQFalse; +} + +static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str,SQRexNode *next) +{ + + SQRexNodeType type = node->type; + switch(type) { + case OP_GREEDY: { + //SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; + SQRexNode *greedystop = NULL; + SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; + const SQChar *s=str, *good = str; + + if(node->next != -1) { + greedystop = &exp->_nodes[node->next]; + } + else { + greedystop = next; + } + + while((nmaches == 0xFFFF || nmaches < p1)) { + + const SQChar *stop; + if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) + break; + nmaches++; + good=s; + if(greedystop) { + //checks that 0 matches satisfy the expression(if so skips) + //if not would always stop(for instance if is a '?') + if(greedystop->type != OP_GREEDY || + (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) + { + SQRexNode *gnext = NULL; + if(greedystop->next != -1) { + gnext = &exp->_nodes[greedystop->next]; + }else if(next && next->next != -1){ + gnext = &exp->_nodes[next->next]; + } + stop = sqstd_rex_matchnode(exp,greedystop,s,gnext); + if(stop) { + //if satisfied stop it + if(p0 == p1 && p0 == nmaches) break; + else if(nmaches >= p0 && p1 == 0xFFFF) break; + else if(nmaches >= p0 && nmaches <= p1) break; + } + } + } + + if(s >= exp->_eol) + break; + } + if(p0 == p1 && p0 == nmaches) return good; + else if(nmaches >= p0 && p1 == 0xFFFF) return good; + else if(nmaches >= p0 && nmaches <= p1) return good; + return NULL; + } + case OP_OR: { + const SQChar *asd = str; + SQRexNode *temp=&exp->_nodes[node->left]; + while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + asd = str; + temp = &exp->_nodes[node->right]; + while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + return NULL; + break; + } + case OP_EXPR: + case OP_NOCAPEXPR:{ + SQRexNode *n = &exp->_nodes[node->left]; + const SQChar *cur = str; + SQInteger capture = -1; + if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { + capture = exp->_currsubexp; + exp->_matches[capture].begin = cur; + exp->_currsubexp++; + } + + do { + SQRexNode *subnext = NULL; + if(n->next != -1) { + subnext = &exp->_nodes[n->next]; + }else { + subnext = next; + } + if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) { + if(capture != -1){ + exp->_matches[capture].begin = 0; + exp->_matches[capture].len = 0; + } + return NULL; + } + } while((n->next != -1) && (n = &exp->_nodes[n->next])); + + if(capture != -1) + exp->_matches[capture].len = cur - exp->_matches[capture].begin; + return cur; + } + case OP_WB: + if((str == exp->_bol && !isspace(*str)) + || (str == exp->_eol && !isspace(*(str-1))) + || (!isspace(*str) && isspace(*(str+1))) + || (isspace(*str) && !isspace(*(str+1))) ) { + return (node->left == 'b')?str:NULL; + } + return (node->left == 'b')?NULL:str; + case OP_BOL: + if(str == exp->_bol) return str; + return NULL; + case OP_EOL: + if(str == exp->_eol) return str; + return NULL; + case OP_DOT:{ + *str++; + } + return str; + case OP_NCLASS: + case OP_CLASS: + if(sqstd_rex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?SQTrue:SQFalse):(type == OP_NCLASS?SQTrue:SQFalse)) { + *str++; + return str; + } + return NULL; + case OP_CCLASS: + if(sqstd_rex_matchcclass(node->left,*str)) { + *str++; + return str; + } + return NULL; + default: /* char */ + if(*str != (SQChar)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; + try { + 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")); + /* XXX -- The (int) casts are needed to silent warnings on 64bit systems (SQInteger is 64bit, %d assumes 32bit, (int) is 32bit) */ + for(i = 0;i < nsize; i++) { + if(exp->_nodes[i].type>MAX_CHAR) + scprintf(_SC("[%02d] %10s "),(int)i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); + else + scprintf(_SC("[%02d] %10c "),(int)i,exp->_nodes[i].type); + scprintf(_SC("left %02d right %02d next %02d\n"),(int)exp->_nodes[i].left,(int)exp->_nodes[i].right,(int)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)); + return exp; + } + catch (...) { + sqstd_rex_free(exp); + return NULL; + } +} + +void sqstd_rex_free(SQRex *exp) +{ + if(exp) { + if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode)); + 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/src/3rdparty/squirrel/sqstdlib/sqstdstream.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdstream.cpp new file mode 100644 index 0000000000..147fc66ca7 --- /dev/null +++ b/src/3rdparty/squirrel/sqstdlib/sqstdstream.cpp @@ -0,0 +1,330 @@ +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include +#include +#include +#include +#include "sqstdstream.h" +#include "sqstdblobimpl.h" + +#define SETUP_STREAM(v) \ + SQStream *self = NULL; \ + if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_STREAM_TYPE_TAG))) \ + return sq_throwerror(v,_SC("invalid type tag")); \ + if(!self->IsValid()) \ + return sq_throwerror(v,_SC("the stream is invalid")); + +SQInteger _stream_readblob(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + SQUserPointer data,blobp; + SQInteger size,res; + sq_getinteger(v,2,&size); + if(size > self->Len()) { + size = self->Len(); + } + data = sq_getscratchpad(v,size); + res = self->Read(data,size); + if(res <= 0) + return sq_throwerror(v,_SC("no data left to read")); + blobp = sqstd_createblob(v,res); + memcpy(blobp,data,res); + return 1; +} + +#define SAFE_READN(ptr,len) { \ + if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \ + } +SQInteger _stream_readn(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + SQInteger format; + sq_getinteger(v, 2, &format); + switch(format) { + case 'l': { + SQInteger i; + SAFE_READN(&i, sizeof(i)); + sq_pushinteger(v, i); + } + break; + case 'i': { + SQInt32 i; + SAFE_READN(&i, sizeof(i)); + sq_pushinteger(v, i); + } + break; + case 's': { + short s; + SAFE_READN(&s, sizeof(short)); + sq_pushinteger(v, s); + } + break; + case 'w': { + unsigned short w; + SAFE_READN(&w, sizeof(unsigned short)); + sq_pushinteger(v, w); + } + break; + case 'c': { + char c; + SAFE_READN(&c, sizeof(char)); + sq_pushinteger(v, c); + } + break; + case 'b': { + unsigned char c; + SAFE_READN(&c, sizeof(unsigned char)); + sq_pushinteger(v, c); + } + break; + case 'f': { + float f; + SAFE_READN(&f, sizeof(float)); + sq_pushfloat(v, f); + } + break; + case 'd': { + double d; + SAFE_READN(&d, sizeof(double)); + sq_pushfloat(v, (SQFloat)d); + } + break; + default: + return sq_throwerror(v, _SC("invalid format")); + } + return 1; +} + +SQInteger _stream_writeblob(HSQUIRRELVM v) +{ + SQUserPointer data; + SQInteger size; + SETUP_STREAM(v); + if(SQ_FAILED(sqstd_getblob(v,2,&data))) + return sq_throwerror(v,_SC("invalid parameter")); + size = sqstd_getblobsize(v,2); + if(self->Write(data,size) != size) + return sq_throwerror(v,_SC("io error")); + sq_pushinteger(v,size); + return 1; +} + +SQInteger _stream_writen(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + SQInteger format, ti; + SQFloat tf; + sq_getinteger(v, 3, &format); + switch(format) { + case 'l': { + SQInteger i; + sq_getinteger(v, 2, &ti); + i = ti; + self->Write(&i, sizeof(SQInteger)); + } + break; + case 'i': { + SQInt32 i; + sq_getinteger(v, 2, &ti); + i = (SQInt32)ti; + self->Write(&i, sizeof(SQInt32)); + } + break; + case 's': { + short s; + sq_getinteger(v, 2, &ti); + s = (short)ti; + self->Write(&s, sizeof(short)); + } + break; + case 'w': { + unsigned short w; + sq_getinteger(v, 2, &ti); + w = (unsigned short)ti; + self->Write(&w, sizeof(unsigned short)); + } + break; + case 'c': { + char c; + sq_getinteger(v, 2, &ti); + c = (char)ti; + self->Write(&c, sizeof(char)); + } + break; + case 'b': { + unsigned char b; + sq_getinteger(v, 2, &ti); + b = (unsigned char)ti; + self->Write(&b, sizeof(unsigned char)); + } + break; + case 'f': { + float f; + sq_getfloat(v, 2, &tf); + f = (float)tf; + self->Write(&f, sizeof(float)); + } + break; + case 'd': { + double d; + sq_getfloat(v, 2, &tf); + d = tf; + self->Write(&d, sizeof(double)); + } + break; + default: + return sq_throwerror(v, _SC("invalid format")); + } + return 0; +} + +SQInteger _stream_seek(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + SQInteger offset, origin = SQ_SEEK_SET; + sq_getinteger(v, 2, &offset); + if(sq_gettop(v) > 2) { + SQInteger t; + sq_getinteger(v, 3, &t); + switch(t) { + case 'b': origin = SQ_SEEK_SET; break; + case 'c': origin = SQ_SEEK_CUR; break; + case 'e': origin = SQ_SEEK_END; break; + default: return sq_throwerror(v,_SC("invalid origin")); + } + } + sq_pushinteger(v, self->Seek(offset, origin)); + return 1; +} + +SQInteger _stream_tell(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + sq_pushinteger(v, self->Tell()); + return 1; +} + +SQInteger _stream_len(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + sq_pushinteger(v, self->Len()); + return 1; +} + +SQInteger _stream_flush(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + if(!self->Flush()) + sq_pushinteger(v, 1); + else + sq_pushnull(v); + return 1; +} + +SQInteger _stream_eos(HSQUIRRELVM v) +{ + SETUP_STREAM(v); + if(self->EOS()) + sq_pushinteger(v, 1); + else + sq_pushnull(v); + return 1; +} + +static SQRegFunction _stream_methods[] = { + _DECL_STREAM_FUNC(readblob,2,_SC("xn")), + _DECL_STREAM_FUNC(readn,2,_SC("xn")), + _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")), + _DECL_STREAM_FUNC(writen,3,_SC("xnn")), + _DECL_STREAM_FUNC(seek,-2,_SC("xnn")), + _DECL_STREAM_FUNC(tell,1,_SC("x")), + _DECL_STREAM_FUNC(len,1,_SC("x")), + _DECL_STREAM_FUNC(eos,1,_SC("x")), + _DECL_STREAM_FUNC(flush,1,_SC("x")), + {0,0,0,0} +}; + +void init_streamclass(HSQUIRRELVM v) +{ + sq_pushregistrytable(v); + sq_pushstring(v,_SC("std_stream"),-1); + if(SQ_FAILED(sq_get(v,-2))) { + sq_pushstring(v,_SC("std_stream"),-1); + sq_newclass(v,SQFalse); + sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG); + SQInteger i = 0; + while(_stream_methods[i].name != 0) { + SQRegFunction &f = _stream_methods[i]; + sq_pushstring(v,f.name,-1); + sq_newclosure(v,f.f,0); + sq_setparamscheck(v,f.nparamscheck,f.typemask); + sq_createslot(v,-3); + i++; + } + sq_createslot(v,-3); + sq_pushroottable(v); + sq_pushstring(v,_SC("stream"),-1); + sq_pushstring(v,_SC("std_stream"),-1); + sq_get(v,-4); + sq_createslot(v,-3); + sq_pop(v,1); + } + else { + sq_pop(v,1); //result + } + sq_pop(v,1); +} + +SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals) +{ + if(sq_gettype(v,-1) != OT_TABLE) + return sq_throwerror(v,_SC("table expected")); + SQInteger top = sq_gettop(v); + //create delegate + init_streamclass(v); + sq_pushregistrytable(v); + sq_pushstring(v,reg_name,-1); + sq_pushstring(v,_SC("std_stream"),-1); + if(SQ_SUCCEEDED(sq_get(v,-3))) { + sq_newclass(v,SQTrue); + sq_settypetag(v,-1,typetag); + SQInteger i = 0; + while(methods[i].name != 0) { + SQRegFunction &f = methods[i]; + sq_pushstring(v,f.name,-1); + sq_newclosure(v,f.f,0); + sq_setparamscheck(v,f.nparamscheck,f.typemask); + sq_setnativeclosurename(v,-1,f.name); + sq_createslot(v,-3); + i++; + } + sq_createslot(v,-3); + sq_pop(v,1); + + i = 0; + while(globals[i].name!=0) + { + SQRegFunction &f = globals[i]; + sq_pushstring(v,f.name,-1); + sq_newclosure(v,f.f,0); + sq_setparamscheck(v,f.nparamscheck,f.typemask); + sq_setnativeclosurename(v,-1,f.name); + sq_createslot(v,-3); + i++; + } + //register the class in the target table + sq_pushstring(v,name,-1); + sq_pushregistrytable(v); + sq_pushstring(v,reg_name,-1); + sq_get(v,-2); + sq_remove(v,-2); + sq_createslot(v,-3); + + sq_settop(v,top); + return SQ_OK; + } + sq_settop(v,top); + return SQ_ERROR; +} diff --git a/src/3rdparty/squirrel/sqstdlib/sqstdstream.h b/src/3rdparty/squirrel/sqstdlib/sqstdstream.h new file mode 100644 index 0000000000..4dcc000545 --- /dev/null +++ b/src/3rdparty/squirrel/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/src/3rdparty/squirrel/sqstdlib/sqstdstring.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdstring.cpp new file mode 100644 index 0000000000..00b1667e09 --- /dev/null +++ b/src/3rdparty/squirrel/sqstdlib/sqstdstring.cpp @@ -0,0 +1,364 @@ +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef SQUNICODE +#define scstrchr wcschr +#define scatoi _wtoi +#define scstrtok wcstok +#else +#define scstrchr strchr +#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; +} + +/* + * Little hack to remove the "format not a string literal, argument types not checked" warning. + * This check has been added to OpenTTD to make sure that nobody passes wrong string literals, + * but three lines in Squirrel have a little problem with those. Therefor we use this hack + * which basically uses vsnprintf instead of sprintf as vsnprintf is not testing for the right + * string literal at compile time. + */ +static void _append_string(SQInteger &i, SQChar *dest, SQInteger allocated, const SQChar *fmt, ...) +{ + va_list va; + va_start(va, fmt); + i += scvsnprintf(&dest[i],allocated-i,fmt,va); + va_end(va); +} + +static SQInteger _string_format(HSQUIRRELVM v) +{ + const SQChar *format; + SQChar *dest; + SQChar fmt[MAX_FORMAT_LEN]; + sq_getstring(v,2,&format); + SQInteger allocated = (sq_getsize(v,2)+1)*sizeof(SQChar); + dest = sq_getscratchpad(v,allocated); + SQInteger n = 0,i = 0, nparam = 3, w = 0; + while(format[n] != '\0') { + if(format[n] != '%') { + assert(i < allocated); + dest[i++] = format[n]; + n++; + } + else if(format[n+1] == '%') { //handles %% + dest[i++] = '%'; + n += 2; + } + else { + n++; + if( nparam > sq_gettop(v) ) + return sq_throwerror(v,_SC("not enough paramters for the given format string")); + n = validate_format(v,fmt,format,n,w); + if(n < 0) return -1; + SQInteger addlen = 0; + SQInteger valtype = 0; + const SQChar *ts; + SQInteger ti; + SQFloat tf; + switch(format[n]) { + case 's': + if(SQ_FAILED(sq_getstring(v,nparam,&ts))) + return sq_throwerror(v,_SC("string expected for the specified format")); + addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar)); + valtype = 's'; + break; + case 'i': case 'd': case 'c':case 'o': case 'u': case 'x': case 'X': + if(SQ_FAILED(sq_getinteger(v,nparam,&ti))) + return sq_throwerror(v,_SC("integer expected for the specified format")); + addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); + valtype = 'i'; + break; + case 'f': case 'g': case 'G': case 'e': case 'E': + if(SQ_FAILED(sq_getfloat(v,nparam,&tf))) + return sq_throwerror(v,_SC("float expected for the specified format")); + addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar)); + valtype = 'f'; + break; + default: + return sq_throwerror(v,_SC("invalid format")); + } + n++; + allocated += addlen; + dest = sq_getscratchpad(v,allocated); + switch(valtype) { + case 's': _append_string(i,dest,allocated,fmt,ts); break; + case 'i': _append_string(i,dest,allocated,fmt,ti); break; + case 'f': _append_string(i,dest,allocated,fmt,tf); break; + }; + nparam ++; + } + } + sq_pushstring(v,dest,i); + 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,0,0} +}; + +#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask} +static SQRegFunction stringlib_funcs[]={ + _DECL_FUNC(format,-2,_SC(".s")), + _DECL_FUNC(strip,2,_SC(".s")), + _DECL_FUNC(lstrip,2,_SC(".s")), + _DECL_FUNC(rstrip,2,_SC(".s")), + _DECL_FUNC(split,3,_SC(".ss")), + {0,0,0,0} +}; + + +SQInteger sqstd_register_stringlib(HSQUIRRELVM v) +{ + sq_pushstring(v,_SC("regexp"),-1); + sq_newclass(v,SQFalse); + SQInteger i = 0; + while(rexobj_funcs[i].name != 0) { + SQRegFunction &f = rexobj_funcs[i]; + sq_pushstring(v,f.name,-1); + sq_newclosure(v,f.f,0); + sq_setparamscheck(v,f.nparamscheck,f.typemask); + sq_setnativeclosurename(v,-1,f.name); + sq_createslot(v,-3); + i++; + } + sq_createslot(v,-3); + + i = 0; + while(stringlib_funcs[i].name!=0) + { + sq_pushstring(v,stringlib_funcs[i].name,-1); + sq_newclosure(v,stringlib_funcs[i].f,0); + sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask); + sq_setnativeclosurename(v,-1,stringlib_funcs[i].name); + sq_createslot(v,-3); + i++; + } + return 1; +} diff --git a/src/3rdparty/squirrel/sqstdlib/sqstdsystem.cpp b/src/3rdparty/squirrel/sqstdlib/sqstdsystem.cpp new file mode 100644 index 0000000000..e1fcdfbd99 --- /dev/null +++ b/src/3rdparty/squirrel/sqstdlib/sqstdsystem.cpp @@ -0,0 +1,147 @@ +/* see copyright notice in squirrel.h */ +#include +#include +#include +#include +#include + +#ifdef SQUNICODE +#include +#define scgetenv _wgetenv +#define scsystem _wsystem +#define scasctime _wasctime +#define scremove _wremove +#define screname _wrename +#else +#define scgetenv getenv +#define scsystem system +#define scasctime asctime +#define scremove remove +#define screname rename +#endif + +static SQInteger _system_getenv(HSQUIRRELVM v) +{ + const SQChar *s; + if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ + sq_pushstring(v,scgetenv(s),-1); + return 1; + } + return 0; +} + + +static SQInteger _system_system(HSQUIRRELVM v) +{ + const SQChar *s; + if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){ + sq_pushinteger(v,scsystem(s)); + return 1; + } + return sq_throwerror(v,_SC("wrong param")); +} + + +static SQInteger _system_clock(HSQUIRRELVM v) +{ + sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC); + return 1; +} + +static SQInteger _system_time(HSQUIRRELVM v) +{ + time_t t; + time(&t); + sq_pushinteger(v,*((SQInteger *)&t)); + return 1; +} + +static SQInteger _system_remove(HSQUIRRELVM v) +{ + const SQChar *s; + sq_getstring(v,2,&s); + if(scremove(s)==-1) + return sq_throwerror(v,_SC("remove() failed")); + return 0; +} + +static SQInteger _system_rename(HSQUIRRELVM v) +{ + const SQChar *oldn,*newn; + sq_getstring(v,2,&oldn); + sq_getstring(v,3,&newn); + if(screname(oldn,newn)==-1) + return sq_throwerror(v,_SC("rename() failed")); + return 0; +} + +static void _set_integer_slot(HSQUIRRELVM v,const SQChar *name,SQInteger val) +{ + sq_pushstring(v,name,-1); + sq_pushinteger(v,val); + sq_rawset(v,-3); +} + +static SQInteger _system_date(HSQUIRRELVM v) +{ + time_t t; + SQInteger it; + SQInteger format = 'l'; + if(sq_gettop(v) > 1) { + sq_getinteger(v,2,&it); + t = it; + if(sq_gettop(v) > 2) { + sq_getinteger(v,3,(SQInteger*)&format); + } + } + else { + time(&t); + } + tm *date; + if(format == 'u') + date = gmtime(&t); + else + date = localtime(&t); + if(!date) + return sq_throwerror(v,_SC("crt api failure")); + sq_newtable(v); + _set_integer_slot(v, _SC("sec"), date->tm_sec); + _set_integer_slot(v, _SC("min"), date->tm_min); + _set_integer_slot(v, _SC("hour"), date->tm_hour); + _set_integer_slot(v, _SC("day"), date->tm_mday); + _set_integer_slot(v, _SC("month"), date->tm_mon); + _set_integer_slot(v, _SC("year"), date->tm_year+1900); + _set_integer_slot(v, _SC("wday"), date->tm_wday); + _set_integer_slot(v, _SC("yday"), date->tm_yday); + return 1; +} + + + +#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_system_##name,nparams,pmask} +static SQRegFunction systemlib_funcs[]={ + _DECL_FUNC(getenv,2,_SC(".s")), + _DECL_FUNC(system,2,_SC(".s")), + _DECL_FUNC(clock,1,NULL), + _DECL_FUNC(time,1,NULL), + _DECL_FUNC(date,-1,_SC(".nn")), + _DECL_FUNC(remove,2,_SC(".s")), + _DECL_FUNC(rename,3,_SC(".ss")), + {0,0,0,0} +}; + + +SQInteger sqstd_register_systemlib(HSQUIRRELVM v) +{ + SQInteger i=0; + while(systemlib_funcs[i].name!=0) + { + sq_pushstring(v,systemlib_funcs[i].name,-1); + sq_newclosure(v,systemlib_funcs[i].f,0); + sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask); + sq_setnativeclosurename(v,-1,systemlib_funcs[i].name); + sq_createslot(v,-3); + i++; + } + return 1; +} diff --git a/src/3rdparty/squirrel/squirrel.dsw b/src/3rdparty/squirrel/squirrel.dsw new file mode 100644 index 0000000000..721509106c --- /dev/null +++ b/src/3rdparty/squirrel/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/src/3rdparty/squirrel/squirrel/Makefile b/src/3rdparty/squirrel/squirrel/Makefile new file mode 100644 index 0000000000..e48eaffa0f --- /dev/null +++ b/src/3rdparty/squirrel/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 \ + sqcompiler.o \ + sqdebug.o \ + sqlexer.o \ + sqobject.o \ + sqparser.o \ + sqstate.o \ + sqtable.o \ + sqvm.o \ + sqmem.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-rtti -Wall -c $(SRCS) $(INCZ) $(DEFS) + ar rc $(OUT) *.o + +sqprof: + gcc -O2 -pg -fno-rtti -pie -gstabs -g3 -Wall -c $(SRCS) $(INCZ) $(DEFS) + ar rc $(OUT) *.o + +sq64: + gcc -O2 -D_SQ64 -fno-rtti -Wall -c $(SRCS) $(INCZ) $(DEFS) + ar rc $(OUT) *.o + +clean: + rm -f $(OUT) $(SRCS:%.cpp=%.o) diff --git a/src/3rdparty/squirrel/squirrel/sqapi.cpp b/src/3rdparty/squirrel/squirrel/sqapi.cpp new file mode 100644 index 0000000000..34d32ec854 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqapi.cpp @@ -0,0 +1,1282 @@ +/* + see copyright notice in squirrel.h +*/ +#include +#include "sqpcheader.h" +#include "sqvm.h" +#include "sqstring.h" +#include "sqtable.h" +#include "sqarray.h" +#include "sqfuncproto.h" +#include "sqclosure.h" +#include "squserdata.h" +#include "sqcompiler.h" +#include "sqfuncstate.h" +#include "sqclass.h" + +bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPtr **o) +{ + *o = &stack_get(v,idx); + if(type(**o) != type){ + SQObjectPtr oval = v->PrintObjVal(**o); + v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval)); + return false; + } + return true; +} + +#define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; } + +#define sq_aux_paramscheck(v,count) \ +{ \ + if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\ +} + +SQInteger sq_aux_throwobject(HSQUIRRELVM v,SQObjectPtr &e) +{ + v->_lasterror = e; + return SQ_ERROR; +} + +SQInteger sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type) +{ + scsprintf(_ss(v)->GetScratchPad(100), _SC("unexpected type %s"), IdType2Name(type)); + return sq_throwerror(v, _ss(v)->GetScratchPad(-1)); +} + +HSQUIRRELVM sq_open(SQInteger initialstacksize) +{ + SQSharedState *ss; + SQVM *v; + sq_new(ss, SQSharedState); + ss->Init(); + v = (SQVM *)SQ_MALLOC(sizeof(SQVM)); + new (v) SQVM(ss); + ss->_root_vm = v; + if(v->Init(NULL, initialstacksize)) { + return v; + } else { + sq_delete(v, SQVM); + return NULL; + } + return v; +} + +HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize) +{ + SQSharedState *ss; + SQVM *v; + ss=_ss(friendvm); + + v= (SQVM *)SQ_MALLOC(sizeof(SQVM)); + new (v) SQVM(ss); + + if(v->Init(friendvm, initialstacksize)) { + friendvm->Push(v); + return v; + } else { + sq_delete(v, SQVM); + return NULL; + } +} + +SQInteger sq_getvmstate(HSQUIRRELVM v) +{ + if(v->_suspended) + return SQ_VMSTATE_SUSPENDED; + else { + if(v->_callsstacksize != 0) return SQ_VMSTATE_RUNNING; + else return SQ_VMSTATE_IDLE; + } +} + +void sq_seterrorhandler(HSQUIRRELVM v) +{ + SQObject o = stack_get(v, -1); + if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) { + v->_errorhandler = o; + v->Pop(); + } +} + +void sq_setdebughook(HSQUIRRELVM v) +{ + SQObject o = stack_get(v,-1); + if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) { + v->_debughook = o; + v->Pop(); + } +} + +void sq_close(HSQUIRRELVM v) +{ + SQSharedState *ss = _ss(v); + _thread(ss->_root_vm)->Finalize(); + sq_delete(ss, SQSharedState); +} + +SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror) +{ + SQObjectPtr o; + if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) { + v->Push(SQClosure::Create(_ss(v), _funcproto(o))); + return SQ_OK; + } + return SQ_ERROR; +} + +void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable) +{ + _ss(v)->_debuginfo = enable?true:false; +} + +void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable) +{ + _ss(v)->_notifyallexceptions = enable?true:false; +} + +void sq_addref(HSQUIRRELVM v,HSQOBJECT *po) +{ + if(!ISREFCOUNTED(type(*po))) return; +#ifdef NO_GARBAGE_COLLECTOR + __AddRef(po->_type,po->_unVal); +#else + _ss(v)->_refs_table.AddRef(*po); +#endif +} + +SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po) +{ + if(!ISREFCOUNTED(type(*po))) return SQTrue; +#ifdef NO_GARBAGE_COLLECTOR + __Release(po->_type,po->_unVal); + return SQFalse; //the ret val doesn't work(and cannot be fixed) +#else + return _ss(v)->_refs_table.Release(*po); +#endif +} + +const SQChar *sq_objtostring(HSQOBJECT *o) +{ + if(sq_type(*o) == OT_STRING) { + return _stringval(*o); + } + return NULL; +} + +SQInteger sq_objtointeger(HSQOBJECT *o) +{ + if(sq_isnumeric(*o)) { + return tointeger(*o); + } + return 0; +} + +SQFloat sq_objtofloat(HSQOBJECT *o) +{ + if(sq_isnumeric(*o)) { + return tofloat(*o); + } + return 0; +} + +SQBool sq_objtobool(HSQOBJECT *o) +{ + if(sq_isbool(*o)) { + return _integer(*o); + } + return SQFalse; +} + +void sq_pushnull(HSQUIRRELVM v) +{ + v->Push(_null_); +} + +void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len) +{ + if(s) + v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len))); + else v->Push(_null_); +} + +void sq_pushinteger(HSQUIRRELVM v,SQInteger n) +{ + v->Push(n); +} + +void sq_pushbool(HSQUIRRELVM v,SQBool b) +{ + v->Push(b?true:false); +} + +void sq_pushfloat(HSQUIRRELVM v,SQFloat n) +{ + v->Push(n); +} + +void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p) +{ + v->Push(p); +} + +SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size) +{ + SQUserData *ud = SQUserData::Create(_ss(v), size); + v->Push(ud); + return ud->_val; +} + +void sq_newtable(HSQUIRRELVM v) +{ + v->Push(SQTable::Create(_ss(v), 0)); +} + +void sq_newarray(HSQUIRRELVM v,SQInteger size) +{ + v->Push(SQArray::Create(_ss(v), size)); +} + +SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase) +{ + SQClass *baseclass = NULL; + if(hasbase) { + SQObjectPtr &base = stack_get(v,-1); + if(type(base) != OT_CLASS) + return sq_throwerror(v,_SC("invalid base type")); + baseclass = _class(base); + } + SQClass *newclass = SQClass::Create(_ss(v), baseclass); + if(baseclass) v->Pop(); + v->Push(newclass); + return SQ_OK; +} + +SQBool sq_instanceof(HSQUIRRELVM v) +{ + SQObjectPtr &inst = stack_get(v,-1); + SQObjectPtr &cl = stack_get(v,-2); + if(type(inst) != OT_INSTANCE || type(cl) != OT_CLASS) + return sq_throwerror(v,_SC("invalid param type")); + return _instance(inst)->InstanceOf(_class(cl))?SQTrue:SQFalse; +} + +SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx) +{ + sq_aux_paramscheck(v,2); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + _array(*arr)->Append(v->GetUp(-1)); + v->Pop(1); + return SQ_OK; +} + +SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval) +{ + sq_aux_paramscheck(v, 1); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + if(_array(*arr)->Size() > 0) { + if(pushval != 0){ v->Push(_array(*arr)->Top()); } + _array(*arr)->Pop(); + return SQ_OK; + } + return sq_throwerror(v, _SC("empty array")); +} + +SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize) +{ + sq_aux_paramscheck(v,1); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + if(newsize >= 0) { + _array(*arr)->Resize(newsize); + return SQ_OK; + } + return sq_throwerror(v,_SC("negative size")); +} + + +SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx) +{ + sq_aux_paramscheck(v, 1); + SQObjectPtr *o; + _GETSAFE_OBJ(v, idx, OT_ARRAY,o); + SQArray *arr = _array(*o); + if(arr->Size() > 0) { + SQObjectPtr t; + SQInteger size = arr->Size(); + SQInteger n = size >> 1; size -= 1; + for(SQInteger i = 0; i < n; i++) { + t = arr->_values[i]; + arr->_values[i] = arr->_values[size-i]; + arr->_values[size-i] = t; + } + return SQ_OK; + } + return SQ_OK; +} + +SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx) +{ + sq_aux_paramscheck(v, 1); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range")); +} + +SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos) +{ + sq_aux_paramscheck(v, 1); + SQObjectPtr *arr; + _GETSAFE_OBJ(v, idx, OT_ARRAY,arr); + SQRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? SQ_OK : sq_throwerror(v,_SC("index out of range")); + v->Pop(); + return ret; +} + + +void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars) +{ + SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func); + nc->_nparamscheck = 0; + for(SQUnsignedInteger i = 0; i < nfreevars; i++) { + nc->_outervalues.push_back(v->Top()); + v->Pop(); + } + v->Push(SQObjectPtr(nc)); +} + +SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars) +{ + SQObject o = stack_get(v, idx); + if(sq_isclosure(o)) { + SQClosure *c = _closure(o); + SQFunctionProto *proto = _funcproto(c->_function); + *nparams = (SQUnsignedInteger)proto->_nparameters; + *nfreevars = (SQUnsignedInteger)c->_outervalues.size(); + return SQ_OK; + } + return sq_throwerror(v,_SC("the object is not a closure")); +} + +SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name) +{ + SQObject o = stack_get(v, idx); + if(sq_isnativeclosure(o)) { + SQNativeClosure *nc = _nativeclosure(o); + nc->_name = SQString::Create(_ss(v),name); + return SQ_OK; + } + return sq_throwerror(v,_SC("the object is not a nativeclosure")); +} + +SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask) +{ + SQObject o = stack_get(v, -1); + if(!sq_isnativeclosure(o)) + return sq_throwerror(v, _SC("native closure expected")); + SQNativeClosure *nc = _nativeclosure(o); + nc->_nparamscheck = nparamscheck; + if(typemask) { + SQIntVec res; + if(!CompileTypemask(res, typemask)) + return sq_throwerror(v, _SC("invalid typemask")); + nc->_typecheck.copy(res); + } + else { + nc->_typecheck.resize(0); + } + if(nparamscheck == SQ_MATCHTYPEMASKSTRING) { + nc->_nparamscheck = nc->_typecheck.size(); + } + return SQ_OK; +} + +SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &o = stack_get(v,idx); + if(!sq_isnativeclosure(o) && + !sq_isclosure(o)) + return sq_throwerror(v,_SC("the target is not a closure")); + SQObjectPtr &env = stack_get(v,-1); + if(!sq_istable(env) && + !sq_isclass(env) && + !sq_isinstance(env)) + return sq_throwerror(v,_SC("invalid environment")); + SQObjectPtr w = _refcounted(env)->GetWeakRef(type(env)); + SQObjectPtr ret; + if(sq_isclosure(o)) { + SQClosure *c = _closure(o)->Clone(); + c->_env = w; + ret = c; + } + else { //then must be a native closure + SQNativeClosure *c = _nativeclosure(o)->Clone(); + c->_env = w; + ret = c; + } + v->Pop(); + v->Push(ret); + return SQ_OK; +} + +SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx) +{ + SQObject &o=stack_get(v,idx); + switch(type(o)) { + case OT_TABLE: _table(o)->Clear(); break; + case OT_ARRAY: _array(o)->Resize(0); break; + default: + return sq_throwerror(v, _SC("clear only works on table and array")); + break; + + } + return SQ_OK; +} + +void sq_pushroottable(HSQUIRRELVM v) +{ + v->Push(v->_roottable); +} + +void sq_pushregistrytable(HSQUIRRELVM v) +{ + v->Push(_ss(v)->_registry); +} + +void sq_pushconsttable(HSQUIRRELVM v) +{ + v->Push(_ss(v)->_consts); +} + +SQRESULT sq_setroottable(HSQUIRRELVM v) +{ + SQObject o = stack_get(v, -1); + if(sq_istable(o) || sq_isnull(o)) { + v->_roottable = o; + v->Pop(); + return SQ_OK; + } + return sq_throwerror(v, _SC("ivalid type")); +} + +SQRESULT sq_setconsttable(HSQUIRRELVM v) +{ + SQObject o = stack_get(v, -1); + if(sq_istable(o)) { + _ss(v)->_consts = o; + v->Pop(); + return SQ_OK; + } + return sq_throwerror(v, _SC("ivalid type, expected table")); +} + +void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p) +{ + v->_foreignptr = p; +} + +SQUserPointer sq_getforeignptr(HSQUIRRELVM v) +{ + return v->_foreignptr; +} + +void sq_push(HSQUIRRELVM v,SQInteger idx) +{ + v->Push(stack_get(v, idx)); +} + +SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx) +{ + return type(stack_get(v, idx)); +} + + +void sq_tostring(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &o = stack_get(v, idx); + SQObjectPtr res; + v->ToString(o,res); + v->Push(res); +} + +void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b) +{ + SQObjectPtr &o = stack_get(v, idx); + *b = v->IsFalse(o)?SQFalse:SQTrue; +} + +SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i) +{ + SQObjectPtr &o = stack_get(v, idx); + if(sq_isnumeric(o)) { + *i = tointeger(o); + return SQ_OK; + } + return SQ_ERROR; +} + +SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f) +{ + SQObjectPtr &o = stack_get(v, idx); + if(sq_isnumeric(o)) { + *f = tofloat(o); + return SQ_OK; + } + return SQ_ERROR; +} + +SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b) +{ + SQObjectPtr &o = stack_get(v, idx); + if(sq_isbool(o)) { + *b = _integer(o); + return SQ_OK; + } + return SQ_ERROR; +} + +SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_STRING,o); + *c = _stringval(*o); + return SQ_OK; +} + +SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_THREAD,o); + *thread = _thread(*o); + return SQ_OK; +} + +SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &o = stack_get(v,idx); + v->Push(_null_); + if(!v->Clone(o, stack_get(v, -1))){ + v->Pop(); + return sq_aux_invalidtype(v, type(o)); + } + return SQ_OK; +} + +SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx) +{ + SQObjectPtr &o = stack_get(v, idx); + SQObjectType type = type(o); + switch(type) { + case OT_STRING: return _string(o)->_len; + case OT_TABLE: return _table(o)->CountUsed(); + case OT_ARRAY: return _array(o)->Size(); + case OT_USERDATA: return _userdata(o)->_size; + default: + return sq_aux_invalidtype(v, type); + } +} + +SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_USERDATA,o); + (*p) = _userdataval(*o); + if(typetag) *typetag = _userdata(*o)->_typetag; + return SQ_OK; +} + +SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag) +{ + SQObjectPtr &o = stack_get(v,idx); + switch(type(o)) { + case OT_USERDATA: _userdata(o)->_typetag = typetag; break; + case OT_CLASS: _class(o)->_typetag = typetag; break; + default: return sq_throwerror(v,_SC("invalid object type")); + } + return SQ_OK; +} + +SQRESULT sq_getobjtypetag(HSQOBJECT *o,SQUserPointer * typetag) +{ + switch(type(*o)) { + case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break; + case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break; + case OT_CLASS: *typetag = _class(*o)->_typetag; break; + default: return SQ_ERROR; + } + return SQ_OK; +} + +SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag) +{ + SQObjectPtr &o = stack_get(v,idx); + if(SQ_FAILED(sq_getobjtypetag(&o,typetag))) + return sq_throwerror(v,_SC("invalid object type")); + return SQ_OK; +} + +SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o); + (*p) = _userpointer(*o); + return SQ_OK; +} + +SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p) +{ + SQObjectPtr &o = stack_get(v,idx); + if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance")); + _instance(o)->_userpointer = p; + return SQ_OK; +} + +SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize) +{ + SQObjectPtr &o = stack_get(v,idx); + if(type(o) != OT_CLASS) return sq_throwerror(v,_SC("the object is not a class")); + if(_class(o)->_locked) return sq_throwerror(v,_SC("the class is locked")); + _class(o)->_udsize = udsize; + return SQ_OK; +} + + +SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag) +{ + SQObjectPtr &o = stack_get(v,idx); + if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance")); + (*p) = _instance(o)->_userpointer; + if(typetag != 0) { + SQClass *cl = _instance(o)->_class; + do{ + if(cl->_typetag == typetag) + return SQ_OK; + cl = cl->_base; + }while(cl != NULL); + return sq_throwerror(v,_SC("invalid type tag")); + } + return SQ_OK; +} + +SQInteger sq_gettop(HSQUIRRELVM v) +{ + return (v->_top) - v->_stackbase; +} + +void sq_settop(HSQUIRRELVM v, SQInteger newtop) +{ + SQInteger top = sq_gettop(v); + if(top > newtop) + sq_pop(v, top - newtop); + else + while(top++ < newtop) sq_pushnull(v); +} + +void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop) +{ + assert(v->_top >= nelemstopop); + v->Pop(nelemstopop); +} + +void sq_poptop(HSQUIRRELVM v) +{ + assert(v->_top >= 1); + v->Pop(); +} + + +void sq_remove(HSQUIRRELVM v, SQInteger idx) +{ + v->Remove(idx); +} + +SQInteger sq_cmp(HSQUIRRELVM v) +{ + SQInteger res; + v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res); + return res; +} + +SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic) +{ + sq_aux_paramscheck(v, 3); + SQObjectPtr &self = stack_get(v, idx); + if(type(self) == OT_TABLE || type(self) == OT_CLASS) { + SQObjectPtr &key = v->GetUp(-2); + if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); + v->NewSlot(self, key, v->GetUp(-1),bstatic?true:false); + v->Pop(2); + } + return SQ_OK; +} + +SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval) +{ + sq_aux_paramscheck(v, 2); + SQObjectPtr *self; + _GETSAFE_OBJ(v, idx, OT_TABLE,self); + SQObjectPtr &key = v->GetUp(-1); + if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key")); + SQObjectPtr res; + if(!v->DeleteSlot(*self, key, res)){ + return SQ_ERROR; + } + if(pushval) v->GetUp(-1) = res; + else v->Pop(1); + return SQ_OK; +} + +SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &self = stack_get(v, idx); + if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) { + v->Pop(2); + return SQ_OK; + } + v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR; +} + +SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &self = stack_get(v, idx); + if(type(v->GetUp(-2)) == OT_NULL) return sq_throwerror(v, _SC("null key")); + switch(type(self)) { + case OT_TABLE: + _table(self)->NewSlot(v->GetUp(-2), v->GetUp(-1)); + v->Pop(2); + return SQ_OK; + break; + case OT_CLASS: + _class(self)->NewSlot(_ss(v), v->GetUp(-2), v->GetUp(-1),false); + v->Pop(2); + return SQ_OK; + break; + case OT_INSTANCE: + if(_instance(self)->Set(v->GetUp(-2), v->GetUp(-1))) { + v->Pop(2); + return SQ_OK; + } + break; + case OT_ARRAY: + if(v->Set(self, v->GetUp(-2), v->GetUp(-1),false)) { + v->Pop(2); + return SQ_OK; + } + break; + default: + v->Pop(2); + return sq_throwerror(v, _SC("rawset works only on array/table/class and instance")); + } + v->Raise_IdxError(v->GetUp(-2));return SQ_ERROR; +} + +SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &self = stack_get(v, idx); + SQObjectPtr &mt = v->GetUp(-1); + SQObjectType type = type(self); + switch(type) { + case OT_TABLE: + if(type(mt) == OT_TABLE) { + if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, _SC("delagate cycle")); v->Pop();} + else if(type(mt)==OT_NULL) { + _table(self)->SetDelegate(NULL); v->Pop(); } + else return sq_aux_invalidtype(v,type); + break; + case OT_USERDATA: + if(type(mt)==OT_TABLE) { + _userdata(self)->SetDelegate(_table(mt)); v->Pop(); } + else if(type(mt)==OT_NULL) { + _userdata(self)->SetDelegate(NULL); v->Pop(); } + else return sq_aux_invalidtype(v, type); + break; + default: + return sq_aux_invalidtype(v, type); + break; + } + return SQ_OK; +} + +SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval) +{ + sq_aux_paramscheck(v, 2); + SQObjectPtr *self; + _GETSAFE_OBJ(v, idx, OT_TABLE,self); + SQObjectPtr &key = v->GetUp(-1); + SQObjectPtr t; + if(_table(*self)->Get(key,t)) { + _table(*self)->Remove(key); + } + if(pushval != 0) { + if(pushval) v->GetUp(-1) = t; + } else { + v->Pop(1); + } + return SQ_OK; +} + +SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &self=stack_get(v,idx); + switch(type(self)){ + case OT_TABLE: + case OT_USERDATA: + if(!_delegable(self)->_delegate){ + v->Push(_null_); + break; + } + v->Push(SQObjectPtr(_delegable(self)->_delegate)); + break; + default: return sq_throwerror(v,_SC("wrong type")); break; + } + return SQ_OK; + +} + +SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &self=stack_get(v,idx); + if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false)) + return SQ_OK; + v->Pop(1); + return sq_throwerror(v,_SC("the index doesn't exist")); +} + +SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &self=stack_get(v,idx); + switch(type(self)) { + case OT_TABLE: + if(_table(self)->Get(v->GetUp(-1),v->GetUp(-1))) + return SQ_OK; + break; + case OT_CLASS: + if(_class(self)->Get(v->GetUp(-1),v->GetUp(-1))) + return SQ_OK; + break; + case OT_INSTANCE: + if(_instance(self)->Get(v->GetUp(-1),v->GetUp(-1))) + return SQ_OK; + break; + case OT_ARRAY: + if(v->Get(self,v->GetUp(-1),v->GetUp(-1),false,false)) + return SQ_OK; + break; + default: + v->Pop(1); + return sq_throwerror(v,_SC("rawget works only on array/table/instance and class")); + } + v->Pop(1); + return sq_throwerror(v,_SC("the index doesn't exist")); +} + +SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po) +{ + *po=stack_get(v,idx); + return SQ_OK; +} + +const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx) +{ + SQUnsignedInteger cstksize=v->_callsstacksize; + SQUnsignedInteger lvl=(cstksize-level)-1; + SQInteger stackbase=v->_stackbase; + if(lvl_callsstack[(cstksize-i)-1]; + stackbase-=ci._prevstkbase; + } + SQVM::CallInfo &ci=v->_callsstack[lvl]; + if(type(ci._closure)!=OT_CLOSURE) + return NULL; + SQClosure *c=_closure(ci._closure); + SQFunctionProto *func=_funcproto(c->_function); + if(func->_noutervalues > (SQInteger)idx) { + v->Push(c->_outervalues[idx]); + return _stringval(func->_outervalues[idx]._name); + } + idx -= func->_noutervalues; + return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-1); + } + return NULL; +} + +void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj) +{ + v->Push(SQObjectPtr(obj)); +} + +void sq_resetobject(HSQOBJECT *po) +{ + po->_unVal.pUserPointer=NULL;po->_type=OT_NULL; +} + +SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err) +{ + v->_lasterror=SQString::Create(_ss(v),err); + return -1; +} + +void sq_reseterror(HSQUIRRELVM v) +{ + v->_lasterror = _null_; +} + +void sq_getlasterror(HSQUIRRELVM v) +{ + v->Push(v->_lasterror); +} + +void sq_reservestack(HSQUIRRELVM v,SQInteger nsize) +{ + if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) { + v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size())); + } +} + +SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror) +{ + if(type(v->GetUp(-1))==OT_GENERATOR){ + v->Push(_null_); //retval + v->_can_suspend = false; + if(!v->Execute(v->GetUp(-2),v->_top,0,v->_top,v->GetUp(-1),raiseerror,SQVM::ET_RESUME_GENERATOR)) + {v->Raise_Error(v->_lasterror); return SQ_ERROR;} + if(!retval) + v->Pop(); + return SQ_OK; + } + return sq_throwerror(v,_SC("only generators can be resumed")); +} + +SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror, int suspend) +{ + SQObjectPtr res; + v->_can_suspend = suspend >= 0; + if (v->_can_suspend) v->_ops_till_suspend = suspend; + + if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false,v->_can_suspend)){ + 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) +{ + SQObjectPtr ret; + if(!v->_suspended) + return sq_throwerror(v,_SC("cannot resume a vm that is not running any code")); + if(wakeupret) { + v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval + v->Pop(); + } else v->GetAt(v->_stackbase+v->_suspended_target)=_null_; + v->_can_suspend = false; + if(!v->Execute(_null_,v->_top,-1,-1,ret,raiseerror,SQVM::ET_RESUME_VM)) { + return SQ_ERROR; + } + if(retval) + v->Push(ret); + return SQ_OK; +} + +bool sq_resumecatch(HSQUIRRELVM v, int suspend) +{ + SQObjectPtr ret; + v->_can_suspend = suspend >= 0; + if (v->_can_suspend) v->_ops_till_suspend = suspend; + return v->Execute(_null_, v->_top, -1, -1, ret, SQTrue, SQVM::ET_RESUME_OPENTTD); +} + +void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook) +{ + if(sq_gettop(v) >= 1){ + SQObjectPtr &ud=stack_get(v,idx); + switch( type(ud) ) { + case OT_USERDATA: _userdata(ud)->_hook = hook; break; + case OT_INSTANCE: _instance(ud)->_hook = hook; break; + case OT_CLASS: _class(ud)->_hook = hook; break; + default: break; //shutup compiler + } + } +} + +void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f) +{ + _ss(v)->_compilererrorhandler = f; +} + +SQRESULT sq_writeclosure(HSQUIRRELVM v,SQWRITEFUNC w,SQUserPointer up) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, -1, OT_CLOSURE,o); + unsigned short tag = SQ_BYTECODE_STREAM_TAG; + if(w(up,&tag,2) != 2) + return sq_throwerror(v,_SC("io error")); + if(!_closure(*o)->Save(v,up,w)) + return SQ_ERROR; + return SQ_OK; +} + +SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up) +{ + SQObjectPtr closure; + + unsigned short tag; + if(r(up,&tag,2) != 2) + return sq_throwerror(v,_SC("io error")); + if(tag != SQ_BYTECODE_STREAM_TAG) + return sq_throwerror(v,_SC("invalid stream")); + if(!SQClosure::Load(v,up,r,closure)) + return SQ_ERROR; + v->Push(closure); + return SQ_OK; +} + +SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize) +{ + return _ss(v)->GetScratchPad(minsize); +} + +SQInteger sq_collectgarbage(HSQUIRRELVM v) +{ +#ifndef NO_GARBAGE_COLLECTOR + return _ss(v)->CollectGarbage(v); +#else + return -1; +#endif +} + +const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval) +{ + SQObjectPtr &self = stack_get(v,idx); + const SQChar *name = NULL; + if(type(self) == OT_CLOSURE) { + if(_closure(self)->_outervalues.size()>nval) { + v->Push(_closure(self)->_outervalues[nval]); + SQFunctionProto *fp = _funcproto(_closure(self)->_function); + SQOuterVar &ov = fp->_outervalues[nval]; + name = _stringval(ov._name); + } + } + return name; +} + +SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval) +{ + SQObjectPtr &self=stack_get(v,idx); + switch(type(self)) + { + case OT_CLOSURE: + if(_closure(self)->_outervalues.size()>nval){ + _closure(self)->_outervalues[nval]=stack_get(v,-1); + } + else return sq_throwerror(v,_SC("invalid free var index")); + break; + case OT_NATIVECLOSURE: + if(_nativeclosure(self)->_outervalues.size()>nval){ + _nativeclosure(self)->_outervalues[nval]=stack_get(v,-1); + } + else return sq_throwerror(v,_SC("invalid free var index")); + break; + default: + return sq_aux_invalidtype(v,type(self)); + } + v->Pop(1); + return SQ_OK; +} + +SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + SQObjectPtr &key = stack_get(v,-2); + SQObjectPtr &val = stack_get(v,-1); + SQObjectPtr attrs; + if(type(key) == OT_NULL) { + attrs = _class(*o)->_attributes; + _class(*o)->_attributes = val; + v->Pop(2); + v->Push(attrs); + return SQ_OK; + }else if(_class(*o)->GetAttributes(key,attrs)) { + _class(*o)->SetAttributes(key,val); + v->Pop(2); + v->Push(attrs); + return SQ_OK; + } + return sq_throwerror(v,_SC("wrong index")); +} + +SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + SQObjectPtr &key = stack_get(v,-1); + SQObjectPtr attrs; + if(type(key) == OT_NULL) { + attrs = _class(*o)->_attributes; + v->Pop(); + v->Push(attrs); + return SQ_OK; + } + else if(_class(*o)->GetAttributes(key,attrs)) { + v->Pop(); + v->Push(attrs); + return SQ_OK; + } + return sq_throwerror(v,_SC("wrong index")); +} + +SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + if(_class(*o)->_base) + v->Push(SQObjectPtr(_class(*o)->_base)); + else + v->Push(_null_); + return SQ_OK; +} + +SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_INSTANCE,o); + v->Push(SQObjectPtr(_instance(*o)->_class)); + return SQ_OK; +} + +SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr *o = NULL; + _GETSAFE_OBJ(v, idx, OT_CLASS,o); + v->Push(_class(*o)->CreateInstance()); + return SQ_OK; +} + +void sq_weakref(HSQUIRRELVM v,SQInteger idx) +{ + SQObject &o=stack_get(v,idx); + if(ISREFCOUNTED(type(o))) { + v->Push(_refcounted(o)->GetWeakRef(type(o))); + return; + } + v->Push(o); +} + +SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr &o = stack_get(v,idx); + if(type(o) != OT_WEAKREF) { + return sq_throwerror(v,_SC("the object must be a weakref")); + } + v->Push(_weakref(o)->_obj); + return SQ_OK; +} + +SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t) +{ + SQSharedState *ss = _ss(v); + switch(t) { + case OT_TABLE: v->Push(ss->_table_default_delegate); break; + case OT_ARRAY: v->Push(ss->_array_default_delegate); break; + case OT_STRING: v->Push(ss->_string_default_delegate); break; + case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break; + case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break; + case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break; + case OT_THREAD: v->Push(ss->_thread_default_delegate); break; + case OT_CLASS: v->Push(ss->_class_default_delegate); break; + case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break; + case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break; + default: return sq_throwerror(v,_SC("the type doesn't have a default delegate")); + } + return SQ_OK; +} + +SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx) +{ + SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val; + if(type(o) == OT_GENERATOR) { + return sq_throwerror(v,_SC("cannot iterate a generator")); + } + int faketojump; + if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump)) + return SQ_ERROR; + if(faketojump != 666) { + v->Push(realkey); + v->Push(val); + return SQ_OK; + } + return SQ_ERROR; +} + +struct BufState{ + const SQChar *buf; + SQInteger ptr; + SQInteger size; +}; + +SQInteger buf_lexfeed(SQUserPointer file) +{ + BufState *buf=(BufState*)file; + if(buf->size<(buf->ptr+1)) + return 0; + return buf->buf[buf->ptr++]; +} + +SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror) { + BufState buf; + buf.buf = s; + buf.size = size; + buf.ptr = 0; + return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror); +} + +void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx) +{ + dest->Push(stack_get(src,idx)); +} + +void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc) +{ + _ss(v)->_printfunc = printfunc; +} + +SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v) +{ + return _ss(v)->_printfunc; +} + +void *sq_malloc(SQUnsignedInteger size) +{ + return SQ_MALLOC(size); +} + +void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize) +{ + return SQ_REALLOC(p,oldsize,newsize); +} + +void sq_free(void *p,SQUnsignedInteger size) +{ + SQ_FREE(p,size); +} + diff --git a/src/3rdparty/squirrel/squirrel/sqarray.h b/src/3rdparty/squirrel/squirrel/sqarray.h new file mode 100644 index 0000000000..5c26352079 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqarray.h @@ -0,0 +1,87 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQARRAY_H_ +#define _SQARRAY_H_ + +struct SQArray : public CHAINABLE_OBJ +{ +private: + SQArray(SQSharedState *ss,SQInteger nsize){_values.resize(nsize); INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} + ~SQArray() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + } +public: + static SQArray* Create(SQSharedState *ss,SQInteger nInitialSize){ + SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray)); + new (newarray) SQArray(ss,nInitialSize); + return newarray; + } +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); +#endif + void Finalize(){ + _values.resize(0); + } + bool Get(const SQInteger nidx,SQObjectPtr &val) + { + if(nidx>=0 && nidx<(SQInteger)_values.size()){ + SQObjectPtr &o = _values[nidx]; + val = _realval(o); + return true; + } + else return false; + } + bool Set(const SQInteger nidx,const SQObjectPtr &val) + { + if(nidx>=0 && nidx<(SQInteger)_values.size()){ + _values[nidx]=val; + return true; + } + else return false; + } + SQInteger Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval) + { + SQUnsignedInteger idx=TranslateIndex(refpos); + while(idx<_values.size()){ + //first found + outkey=(SQInteger)idx; + SQObjectPtr &o = _values[idx]; + outval = _realval(o); + //return idx for the next iteration + return ++idx; + } + //nothing to iterate anymore + return -1; + } + SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),Size()); anew->_values.copy(_values); return anew; } + SQInteger Size() const {return _values.size();} + void Resize(SQInteger size,SQObjectPtr &fill = _null_) { _values.resize(size,fill); ShrinkIfNeeded(); } + void Reserve(SQInteger size) { _values.reserve(size); } + void Append(const SQObject &o){_values.push_back(o);} + void Extend(const SQArray *a); + SQObjectPtr &Top(){return _values.top();} + void Pop(){_values.pop_back(); ShrinkIfNeeded(); } + bool Insert(SQInteger idx,const SQObject &val){ + if(idx < 0 || idx > (SQInteger)_values.size()) + return false; + _values.insert(idx,val); + return true; + } + void ShrinkIfNeeded() { + if(_values.size() <= _values.capacity()>>2) //shrink the array + _values.shrinktofit(); + } + bool Remove(SQInteger idx){ + if(idx < 0 || idx >= (SQInteger)_values.size()) + return false; + _values.remove(idx); + ShrinkIfNeeded(); + return true; + } + void Release() + { + sq_delete(this,SQArray); + } + SQObjectPtrVec _values; +}; +#endif //_SQARRAY_H_ diff --git a/src/3rdparty/squirrel/squirrel/sqbaselib.cpp b/src/3rdparty/squirrel/squirrel/sqbaselib.cpp new file mode 100644 index 0000000000..312e2f7ff9 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqbaselib.cpp @@ -0,0 +1,921 @@ +/* + 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 +#include +#include + +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; + } +} + +#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS +static SQInteger base_dummy(HSQUIRRELVM v) +{ + return 0; +} + +#ifndef NO_GARBAGE_COLLECTOR +static SQInteger base_collectgarbage(HSQUIRRELVM v) +{ + sq_pushinteger(v, sq_collectgarbage(v)); + return 1; +} +#endif + +static SQInteger base_getroottable(HSQUIRRELVM v) +{ + v->Push(v->_roottable); + return 1; +} + +static SQInteger base_getconsttable(HSQUIRRELVM v) +{ + v->Push(_ss(v)->_consts); + return 1; +} + + +static SQInteger base_setroottable(HSQUIRRELVM v) +{ + SQObjectPtr &o=stack_get(v,2); + if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR; + v->Push(o); + return 1; +} + +static SQInteger base_setconsttable(HSQUIRRELVM v) +{ + SQObjectPtr &o=stack_get(v,2); + if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR; + v->Push(o); + return 1; +} + +static SQInteger base_seterrorhandler(HSQUIRRELVM v) +{ + sq_seterrorhandler(v); + return 0; +} + +static SQInteger base_setdebughook(HSQUIRRELVM v) +{ + sq_setdebughook(v); + return 0; +} + +static SQInteger base_enabledebuginfo(HSQUIRRELVM v) +{ + SQObjectPtr &o=stack_get(v,2); + sq_enabledebuginfo(v,(type(o) != OT_NULL)?1:0); + return 0; +} + +static SQInteger base_getstackinfos(HSQUIRRELVM v) +{ + SQInteger level; + SQStackInfos si; + SQInteger seq = 0; + const SQChar *name = NULL; + sq_getinteger(v, -1, &level); + if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si))) + { + const SQChar *fn = _SC("unknown"); + const SQChar *src = _SC("unknown"); + if(si.funcname)fn = si.funcname; + if(si.source)src = si.source; + sq_newtable(v); + sq_pushstring(v, _SC("func"), -1); + sq_pushstring(v, fn, -1); + sq_createslot(v, -3); + sq_pushstring(v, _SC("src"), -1); + sq_pushstring(v, src, -1); + sq_createslot(v, -3); + sq_pushstring(v, _SC("line"), -1); + sq_pushinteger(v, si.line); + sq_createslot(v, -3); + sq_pushstring(v, _SC("locals"), -1); + sq_newtable(v); + seq=0; + while ((name = sq_getlocal(v, level, seq))) { + sq_pushstring(v, name, -1); + sq_push(v, -2); + sq_createslot(v, -4); + sq_pop(v, 1); + seq++; + } + sq_createslot(v, -3); + return 1; + } + + return 0; +} +#endif /* EXPORT_DEFAULT_SQUIRREL_FUNCTIONS */ + +static SQInteger base_assert(HSQUIRRELVM v) +{ + if(v->IsFalse(stack_get(v,2))){ + return sq_throwerror(v,_SC("assertion failed")); + } + return 0; +} + +static SQInteger get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,SQObjectPtr &o) +{ + SQInteger top = sq_gettop(v); + sidx=0; + eidx=0; + o=stack_get(v,1); + SQObjectPtr &start=stack_get(v,2); + if(type(start)!=OT_NULL && sq_isnumeric(start)){ + sidx=tointeger(start); + } + if(top>2){ + SQObjectPtr &end=stack_get(v,3); + if(sq_isnumeric(end)){ + eidx=tointeger(end); + } + } + else { + eidx = sq_getsize(v,1); + } + return 1; +} + +static SQInteger base_print(HSQUIRRELVM v) +{ + const SQChar *str; + sq_tostring(v,2); + sq_getstring(v,-1,&str); + if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str); + return 0; +} + +#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS +static SQInteger base_compilestring(HSQUIRRELVM v) +{ + SQInteger nargs=sq_gettop(v); + const SQChar *src=NULL,*name=_SC("unnamedbuffer"); + SQInteger size; + sq_getstring(v,2,&src); + size=sq_getsize(v,2); + if(nargs>2){ + sq_getstring(v,3,&name); + } + if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse))) + return 1; + else + return SQ_ERROR; +} + +static SQInteger base_newthread(HSQUIRRELVM v) +{ + SQObjectPtr &func = stack_get(v,2); + SQInteger stksize = (_funcproto(_closure(func)->_function)->_stacksize << 1) +2; + HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize); + sq_move(newv,v,-2); + return 1; +} + +static SQInteger base_suspend(HSQUIRRELVM v) +{ + return sq_suspendvm(v); +} +#endif /* EXPORT_DEFAULT_SQUIRREL_FUNCTIONS */ + +static SQInteger base_array(HSQUIRRELVM v) +{ + SQArray *a; + SQObject &size = stack_get(v,2); + if(sq_gettop(v) > 2) { + a = SQArray::Create(_ss(v),0); + a->Resize(tointeger(size),stack_get(v,3)); + } + else { + a = SQArray::Create(_ss(v),tointeger(size)); + } + v->Push(a); + return 1; +} + +static SQInteger base_type(HSQUIRRELVM v) +{ + SQObjectPtr &o = stack_get(v,2); + v->Push(SQString::Create(_ss(v),GetTypeName(o),-1)); + return 1; +} + +static SQRegFunction base_funcs[]={ + //generic +#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS + {_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}, +#endif + {_SC("assert"),base_assert,2, NULL}, + {_SC("print"),base_print,2, NULL}, +#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS + {_SC("compilestring"),base_compilestring,-2, _SC(".ss")}, + {_SC("newthread"),base_newthread,2, _SC(".c")}, + {_SC("suspend"),base_suspend,-1, NULL}, +#endif + {_SC("array"),base_array,-2, _SC(".n")}, + {_SC("type"),base_type,2, NULL}, +#ifdef EXPORT_DEFAULT_SQUIRREL_FUNCTIONS + {_SC("dummy"),base_dummy,0,NULL}, +#ifndef NO_GARBAGE_COLLECTOR + {_SC("collectgarbage"),base_collectgarbage,1, _SC("t")}, +#endif +#endif + {0,0,0,0} +}; + +void sq_base_register(HSQUIRRELVM v) +{ + SQInteger i=0; + sq_pushroottable(v); + while(base_funcs[i].name!=0) { + sq_pushstring(v,base_funcs[i].name,-1); + sq_newclosure(v,base_funcs[i].f,0); + sq_setnativeclosurename(v,-1,base_funcs[i].name); + sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask); + sq_createslot(v,-3); + i++; + } + sq_pushstring(v,_SC("_version_"),-1); + sq_pushstring(v,SQUIRREL_VERSION,-1); + sq_createslot(v,-3); + sq_pushstring(v,_SC("_charsize_"),-1); + sq_pushinteger(v,sizeof(SQChar)); + sq_createslot(v,-3); + sq_pushstring(v,_SC("_intsize_"),-1); + sq_pushinteger(v,sizeof(SQInteger)); + sq_createslot(v,-3); + sq_pop(v,1); +} + +static SQInteger default_delegate_len(HSQUIRRELVM v) +{ + v->Push(SQInteger(sq_getsize(v,1))); + return 1; +} + +static SQInteger default_delegate_tofloat(HSQUIRRELVM v) +{ + SQObjectPtr &o=stack_get(v,1); + switch(type(o)){ + case OT_STRING:{ + SQObjectPtr res; + if(str2num(_stringval(o),res)){ + v->Push(SQObjectPtr(tofloat(res))); + break; + }} + return sq_throwerror(v, _SC("cannot convert the string")); + break; + case OT_INTEGER:case OT_FLOAT: + v->Push(SQObjectPtr(tofloat(o))); + break; + case OT_BOOL: + v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0))); + break; + default: + v->Push(_null_); + break; + } + return 1; +} + +static SQInteger default_delegate_tointeger(HSQUIRRELVM v) +{ + SQObjectPtr &o=stack_get(v,1); + switch(type(o)){ + case OT_STRING:{ + SQObjectPtr res; + if(str2num(_stringval(o),res)){ + v->Push(SQObjectPtr(tointeger(res))); + break; + }} + return sq_throwerror(v, _SC("cannot convert the string")); + break; + case OT_INTEGER:case OT_FLOAT: + v->Push(SQObjectPtr(tointeger(o))); + break; + case OT_BOOL: + v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0)); + break; + default: + v->Push(_null_); + break; + } + return 1; +} + +static SQInteger default_delegate_tostring(HSQUIRRELVM v) +{ + sq_tostring(v,1); + return 1; +} + +static SQInteger obj_delegate_weakref(HSQUIRRELVM v) +{ + sq_weakref(v,1); + return 1; +} + +static SQInteger obj_clear(HSQUIRRELVM v) +{ + return sq_clear(v,-1); +} + + +static SQInteger number_delegate_tochar(HSQUIRRELVM v) +{ + SQObject &o=stack_get(v,1); + SQChar c = (SQChar)tointeger(o); + v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1)); + return 1; +} + + +///////////////////////////////////////////////////////////////// +//TABLE DEFAULT DELEGATE + +static SQInteger table_rawdelete(HSQUIRRELVM v) +{ + if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue))) + return SQ_ERROR; + return 1; +} + + +static SQInteger container_rawexists(HSQUIRRELVM v) +{ + if(SQ_SUCCEEDED(sq_rawget(v,-2))) { + sq_pushbool(v,SQTrue); + return 1; + } + sq_pushbool(v,SQFalse); + return 1; +} + +static SQInteger table_rawset(HSQUIRRELVM v) +{ + return sq_rawset(v,-3); +} + + +static SQInteger table_rawget(HSQUIRRELVM v) +{ + return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR; +} + + +SQRegFunction SQSharedState::_table_default_delegate_funcz[]={ + {_SC("len"),default_delegate_len,1, _SC("t")}, + {_SC("rawget"),table_rawget,2, _SC("t")}, + {_SC("rawset"),table_rawset,3, _SC("t")}, + {_SC("rawdelete"),table_rawdelete,2, _SC("t")}, + {_SC("rawin"),container_rawexists,2, _SC("t")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("clear"),obj_clear,1, _SC(".")}, + {0,0,0,0} +}; + +//ARRAY DEFAULT DELEGATE/////////////////////////////////////// + +static SQInteger array_append(HSQUIRRELVM v) +{ + return sq_arrayappend(v,-2); +} + +static SQInteger array_extend(HSQUIRRELVM v) +{ + _array(stack_get(v,1))->Extend(_array(stack_get(v,2))); + return 0; +} + +static SQInteger array_reverse(HSQUIRRELVM v) +{ + return sq_arrayreverse(v,-1); +} + +static SQInteger array_pop(HSQUIRRELVM v) +{ + return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR; +} + +static SQInteger array_top(HSQUIRRELVM v) +{ + SQObject &o=stack_get(v,1); + if(_array(o)->Size()>0){ + v->Push(_array(o)->Top()); + return 1; + } + else return sq_throwerror(v,_SC("top() on a empty array")); +} + +static SQInteger array_insert(HSQUIRRELVM v) +{ + SQObject &o=stack_get(v,1); + SQObject &idx=stack_get(v,2); + SQObject &val=stack_get(v,3); + if(!_array(o)->Insert(tointeger(idx),val)) + return sq_throwerror(v,_SC("index out of range")); + return 0; +} + +static SQInteger array_remove(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v, 1); + SQObject &idx = stack_get(v, 2); + if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type")); + SQObjectPtr val; + if(_array(o)->Get(tointeger(idx), val)) { + _array(o)->Remove(tointeger(idx)); + v->Push(val); + return 1; + } + return sq_throwerror(v, _SC("idx out of range")); +} + +static SQInteger array_resize(HSQUIRRELVM v) +{ + SQObject &o = stack_get(v, 1); + SQObject &nsize = stack_get(v, 2); + SQObjectPtr fill; + if(sq_isnumeric(nsize)) { + if(sq_gettop(v) > 2) + fill = stack_get(v, 3); + _array(o)->Resize(tointeger(nsize),fill); + return 0; + } + return sq_throwerror(v, _SC("size must be a number")); +} + + +//QSORT ala Sedgewick +bool _qsort_compare(HSQUIRRELVM v,SQObjectPtr &arr,SQObjectPtr &a,SQObjectPtr &b,SQInteger func,SQInteger &ret) +{ + if(func < 0) { + if(!v->ObjCmp(a,b,ret)) return false; + } + else { + SQInteger top = sq_gettop(v); + sq_push(v, func); + sq_pushroottable(v); + v->Push(a); + v->Push(b); + if(SQ_FAILED(sq_call(v, 3, SQTrue, SQFalse))) { + if(!sq_isstring( v->_lasterror)) + v->Raise_Error(_SC("compare func failed")); + return false; + } + sq_getinteger(v, -1, &ret); + sq_settop(v, top); + return true; + } + return true; +} +//QSORT ala Sedgewick +bool _qsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger l, SQInteger r,SQInteger func) +{ + SQInteger i, j; + SQArray *a=_array(arr); + SQObjectPtr pivot,t; + if( l < r ){ + pivot = a->_values[l]; + i = l; j = r+1; + while(1){ + SQInteger ret; + do { + ++i; + if(i > r) break; + if(!_qsort_compare(v,arr,a->_values[i],pivot,func,ret)) + return false; + } while( ret <= 0); + do { + --j; + if ( j < 0 ) { + v->Raise_Error( _SC("Invalid qsort, probably compare function defect") ); + return false; + } + if(!_qsort_compare(v,arr,a->_values[j],pivot,func,ret)) + return false; + } + while( ret > 0 ); + if( i >= j ) break; + t = a->_values[i]; a->_values[i] = a->_values[j]; a->_values[j] = t; + } + t = a->_values[l]; a->_values[l] = a->_values[j]; a->_values[j] = t; + if(!_qsort( v, arr, l, j-1,func)) return false; + if(!_qsort( v, arr, j+1, r,func)) return false; + } + return true; +} + +static SQInteger array_sort(HSQUIRRELVM v) +{ + SQInteger func = -1; + SQObjectPtr &o = stack_get(v,1); + SQObject &funcobj = stack_get(v,2); + if(_array(o)->Size() > 1) { + if(type(funcobj) == OT_CLOSURE || type(funcobj) == OT_NATIVECLOSURE) func = 2; + if(!_qsort(v, o, 0, _array(o)->Size()-1, func)) + return SQ_ERROR; + + } + return 0; +} +static SQInteger array_slice(HSQUIRRELVM v) +{ + SQInteger sidx,eidx; + SQObjectPtr o; + if(get_slice_params(v,sidx,eidx,o)==-1)return -1; + SQInteger alen = _array(o)->Size(); + if(sidx < 0)sidx = alen + sidx; + if(eidx < 0)eidx = alen + eidx; + if(eidx < sidx)return sq_throwerror(v,_SC("wrong indexes")); + if(eidx > alen)return sq_throwerror(v,_SC("slice out of range")); + SQArray *arr=SQArray::Create(_ss(v),eidx-sidx); + SQObjectPtr t; + SQInteger count=0; + for(SQInteger i=sidx;iGet(i,t); + arr->Set(count++,t); + } + v->Push(arr); + return 1; + +} + +SQRegFunction SQSharedState::_array_default_delegate_funcz[]={ + {_SC("len"),default_delegate_len,1, _SC("a")}, + {_SC("append"),array_append,2, _SC("a")}, + {_SC("extend"),array_extend,2, _SC("aa")}, + {_SC("push"),array_append,2, _SC("a")}, + {_SC("pop"),array_pop,1, _SC("a")}, + {_SC("top"),array_top,1, _SC("a")}, + {_SC("insert"),array_insert,3, _SC("an")}, + {_SC("remove"),array_remove,2, _SC("an")}, + {_SC("resize"),array_resize,-2, _SC("an")}, + {_SC("reverse"),array_reverse,1, _SC("a")}, + {_SC("sort"),array_sort,-1, _SC("ac")}, + {_SC("slice"),array_slice,-1, _SC("ann")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("clear"),obj_clear,1, _SC(".")}, + {0,0,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;iPush(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,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,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;iPush(aparams->_values[i]); + return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue,raiseerror))?1:SQ_ERROR; +} + +static SQInteger closure_acall(HSQUIRRELVM v) +{ + return _closure_acall(v,SQTrue); +} + +static SQInteger closure_pacall(HSQUIRRELVM v) +{ + return _closure_acall(v,SQFalse); +} + +static SQInteger closure_bindenv(HSQUIRRELVM v) +{ + if(SQ_FAILED(sq_bindenv(v,1))) + return SQ_ERROR; + return 1; +} + +static SQInteger closure_getinfos(HSQUIRRELVM v) { + SQObject o = stack_get(v,1); + SQTable *res = SQTable::Create(_ss(v),4); + if(type(o) == OT_CLOSURE) { + SQFunctionProto *f = _funcproto(_closure(o)->_function); + SQInteger nparams = f->_nparameters + (f->_varparams?1:0); + SQObjectPtr params = SQArray::Create(_ss(v),nparams); + for(SQInteger n = 0; n_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_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,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,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,SQFalse))) { + sq_move(v,thread,-1); + sq_pop(thread,1); //pop retval + if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) { + sq_settop(thread,1); //pop roottable + } + return 1; + } + sq_settop(thread,1); + v->_lasterror = thread->_lasterror; + return SQ_ERROR; + } + return sq_throwerror(v,_SC("wrong parameter")); +} + +static SQInteger thread_getstatus(HSQUIRRELVM v) +{ + SQObjectPtr &o = stack_get(v,1); + switch(sq_getvmstate(_thread(o))) { + case SQ_VMSTATE_IDLE: + sq_pushstring(v,_SC("idle"),-1); + break; + case SQ_VMSTATE_RUNNING: + sq_pushstring(v,_SC("running"),-1); + break; + case SQ_VMSTATE_SUSPENDED: + sq_pushstring(v,_SC("suspended"),-1); + break; + default: + return sq_throwerror(v,_SC("internal VM error")); + } + return 1; +} + +SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = { + {_SC("call"), thread_call, -1, _SC("v")}, + {_SC("wakeup"), thread_wakeup, -1, _SC("v")}, + {_SC("getstatus"), thread_getstatus, 1, _SC("v")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {0,0,0,0}, +}; + +static SQInteger class_getattributes(HSQUIRRELVM v) +{ + if(SQ_SUCCEEDED(sq_getattributes(v,-2))) + return 1; + return SQ_ERROR; +} + +static SQInteger class_setattributes(HSQUIRRELVM v) +{ + if(SQ_SUCCEEDED(sq_setattributes(v,-3))) + return 1; + return SQ_ERROR; +} + +static SQInteger class_instance(HSQUIRRELVM v) +{ + if(SQ_SUCCEEDED(sq_createinstance(v,-1))) + return 1; + return SQ_ERROR; +} + +SQRegFunction SQSharedState::_class_default_delegate_funcz[] = { + {_SC("getattributes"), class_getattributes, 2, _SC("y.")}, + {_SC("setattributes"), class_setattributes, 3, _SC("y..")}, + {_SC("rawin"),container_rawexists,2, _SC("y")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {_SC("instance"),class_instance,1, _SC("y")}, + {0,0,0,0} +}; + +static SQInteger instance_getclass(HSQUIRRELVM v) +{ + if(SQ_SUCCEEDED(sq_getclass(v,1))) + return 1; + return SQ_ERROR; +} + +SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = { + {_SC("getclass"), instance_getclass, 1, _SC("x")}, + {_SC("rawin"),container_rawexists,2, _SC("x")}, + {_SC("weakref"),obj_delegate_weakref,1, NULL }, + {_SC("tostring"),default_delegate_tostring,1, _SC(".")}, + {0,0,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,0,0} +}; + + diff --git a/src/3rdparty/squirrel/squirrel/sqclass.cpp b/src/3rdparty/squirrel/squirrel/sqclass.cpp new file mode 100644 index 0000000000..73c8848b5b --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqclass.cpp @@ -0,0 +1,194 @@ +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqvm.h" +#include "sqtable.h" +#include "sqclass.h" +#include "sqclosure.h" + +SQClass::SQClass(SQSharedState *ss,SQClass *base) +{ + _base = base; + _typetag = 0; + _hook = NULL; + _udsize = 0; + _metamethods.resize(MT_LAST); //size it to max size + if(_base) { + _defaultvalues.copy(base->_defaultvalues); + _methods.copy(base->_methods); + _metamethods.copy(base->_metamethods); + __ObjAddRef(_base); + } + _members = base?base->_members->Clone() : SQTable::Create(ss,0); + __ObjAddRef(_members); + _locked = false; + INIT_CHAIN(); + ADD_TO_CHAIN(&_sharedstate->_gc_chain, this); +} + +void SQClass::Finalize() { + _attributes = _null_; + _defaultvalues.resize(0); + _methods.resize(0); + _metamethods.resize(0); + __ObjRelease(_members); + if(_base) { + __ObjRelease(_base); + } +} + +SQClass::~SQClass() +{ + REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); + Finalize(); +} + +bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) +{ + SQObjectPtr temp; + if(_locked) + return false; //the class already has an instance so cannot be modified + if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value + { + _defaultvalues[_member_idx(temp)].val = val; + return true; + } + if(type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic) { + SQInteger mmidx; + if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) && + (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) { + _metamethods[mmidx] = val; + } + else { + if(type(temp) == OT_NULL) { + SQClassMember m; + m.val = val; + _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size()))); + _methods.push_back(m); + } + else { + _methods[_member_idx(temp)].val = val; + } + } + return true; + } + SQClassMember m; + m.val = val; + _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size()))); + _defaultvalues.push_back(m); + return true; +} + +SQInstance *SQClass::CreateInstance() +{ + if(!_locked) Lock(); + return SQInstance::Create(_opt_ss(this),this); +} + +SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval) +{ + SQObjectPtr oval; + SQInteger idx = _members->Next(false,refpos,outkey,oval); + if(idx != -1) { + if(_ismethod(oval)) { + outval = _methods[_member_idx(oval)].val; + } + else { + SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val; + outval = _realval(o); + } + } + return idx; +} + +bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val) +{ + SQObjectPtr idx; + if(_members->Get(key,idx)) { + if(_isfield(idx)) + _defaultvalues[_member_idx(idx)].attrs = val; + else + _methods[_member_idx(idx)].attrs = val; + return true; + } + return false; +} + +bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval) +{ + SQObjectPtr idx; + if(_members->Get(key,idx)) { + outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs); + return true; + } + return false; +} + +/////////////////////////////////////////////////////////////////////// +void SQInstance::Init(SQSharedState *ss) +{ + _userpointer = NULL; + _hook = NULL; + __ObjAddRef(_class); + _delegate = _class->_members; + INIT_CHAIN(); + ADD_TO_CHAIN(&_sharedstate->_gc_chain, this); +} + +SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize) +{ + _memsize = memsize; + _class = c; + SQUnsignedInteger nvalues = _class->_defaultvalues.size(); + for(SQUnsignedInteger n = 0; n < nvalues; n++) { + new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val); + } + Init(ss); +} + +SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize) +{ + _memsize = memsize; + _class = i->_class; + SQUnsignedInteger nvalues = _class->_defaultvalues.size(); + for(SQUnsignedInteger n = 0; n < nvalues; n++) { + new (&_values[n]) SQObjectPtr(i->_values[n]); + } + Init(ss); +} + +void SQInstance::Finalize() +{ + SQUnsignedInteger nvalues = _class->_defaultvalues.size(); + __ObjRelease(_class); + for(SQUnsignedInteger i = 0; i < nvalues; i++) { + _values[i] = _null_; + } +} + +SQInstance::~SQInstance() +{ + REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); + if(_class){ Finalize(); } //if _class is null it was already finalized by the GC +} + +bool SQInstance::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) +{ + if(type(_class->_metamethods[mm]) != OT_NULL) { + res = _class->_metamethods[mm]; + return true; + } + return false; +} + +bool SQInstance::InstanceOf(SQClass *trg) +{ + SQClass *parent = _class; + while(parent != NULL) { + if(parent == trg) + return true; + parent = parent->_base; + } + return false; +} diff --git a/src/3rdparty/squirrel/squirrel/sqclass.h b/src/3rdparty/squirrel/squirrel/sqclass.h new file mode 100644 index 0000000000..06f2b51e9d --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqclass.h @@ -0,0 +1,152 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQCLASS_H_ +#define _SQCLASS_H_ + +struct SQInstance; + +struct SQClassMember { + SQClassMember(){} + SQClassMember(const SQClassMember &o) { + val = o.val; + attrs = o.attrs; + } + SQObjectPtr val; + SQObjectPtr attrs; +}; + +typedef sqvector SQClassMemberVec; + +#define MEMBER_TYPE_METHOD 0x01000000 +#define MEMBER_TYPE_FIELD 0x02000000 + +#define _ismethod(o) (_integer(o)&MEMBER_TYPE_METHOD) +#define _isfield(o) (_integer(o)&MEMBER_TYPE_FIELD) +#define _make_method_idx(i) ((SQInteger)(MEMBER_TYPE_METHOD|i)) +#define _make_field_idx(i) ((SQInteger)(MEMBER_TYPE_FIELD|i)) +#define _member_type(o) (_integer(o)&0xFF000000) +#define _member_idx(o) (_integer(o)&0x00FFFFFF) + +struct SQClass : public CHAINABLE_OBJ +{ + SQClass(SQSharedState *ss,SQClass *base); +public: + static SQClass* Create(SQSharedState *ss,SQClass *base) { + SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass)); + new (newclass) SQClass(ss, base); + return newclass; + } + ~SQClass(); + bool NewSlot(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic); + bool Get(const SQObjectPtr &key,SQObjectPtr &val) { + if(_members->Get(key,val)) { + if(_isfield(val)) { + SQObjectPtr &o = _defaultvalues[_member_idx(val)].val; + val = _realval(o); + } + else { + val = _methods[_member_idx(val)].val; + } + return true; + } + return false; + } + bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val); + bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval); + void Lock() { _locked = true; if(_base) _base->Lock(); } + void Release() { + if (_hook) { _hook(_typetag,0);} + sq_delete(this, SQClass); + } + void Finalize(); +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable ** ); +#endif + SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); + SQInstance *CreateInstance(); + SQTable *_members; + SQClass *_base; + SQClassMemberVec _defaultvalues; + SQClassMemberVec _methods; + SQObjectPtrVec _metamethods; + SQObjectPtr _attributes; + SQUserPointer _typetag; + SQRELEASEHOOK _hook; + bool _locked; + SQInteger _udsize; +}; + +#define calcinstancesize(_theclass_) \ + (_theclass_->_udsize + sizeof(SQInstance) + (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))) + +struct SQInstance : public SQDelegable +{ + void Init(SQSharedState *ss); + SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize); + SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize); +public: + static SQInstance* Create(SQSharedState *ss,SQClass *theclass) { + + SQInteger size = calcinstancesize(theclass); + SQInstance *newinst = (SQInstance *)SQ_MALLOC(size); + new (newinst) SQInstance(ss, theclass,size); + if(theclass->_udsize) { + newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize); + } + return newinst; + } + SQInstance *Clone(SQSharedState *ss) + { + SQInteger size = calcinstancesize(_class); + SQInstance *newinst = (SQInstance *)SQ_MALLOC(size); + new (newinst) SQInstance(ss, this,size); + if(_class->_udsize) { + newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize); + } + return newinst; + } + ~SQInstance(); + bool Get(const SQObjectPtr &key,SQObjectPtr &val) { + if(_class->_members->Get(key,val)) { + if(_isfield(val)) { + SQObjectPtr &o = _values[_member_idx(val)]; + val = _realval(o); + } + else { + val = _class->_methods[_member_idx(val)].val; + } + return true; + } + return false; + } + bool Set(const SQObjectPtr &key,const SQObjectPtr &val) { + SQObjectPtr idx; + if(_class->_members->Get(key,idx) && _isfield(idx)) { + _values[_member_idx(idx)] = val; + return true; + } + return false; + } + void Release() { + _uiRef++; + if (_hook) { _hook(_userpointer,0);} + _uiRef--; + if(_uiRef > 0) return; + SQInteger size = _memsize; + this->~SQInstance(); + SQ_FREE(this, size); + } + void Finalize(); +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable ** ); +#endif + bool InstanceOf(SQClass *trg); + bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res); + + SQClass *_class; + SQUserPointer _userpointer; + SQRELEASEHOOK _hook; + SQInteger _memsize; + SQObjectPtr _values[1]; +}; + +#endif //_SQCLASS_H_ diff --git a/src/3rdparty/squirrel/squirrel/sqclosure.h b/src/3rdparty/squirrel/squirrel/sqclosure.h new file mode 100644 index 0000000000..f872f2b8d3 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqclosure.h @@ -0,0 +1,122 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQCLOSURE_H_ +#define _SQCLOSURE_H_ + +struct SQFunctionProto; + +struct SQClosure : public CHAINABLE_OBJ +{ +private: + SQClosure(SQSharedState *ss,SQFunctionProto *func){_function=func; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} +public: + static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func){ + SQClosure *nc=(SQClosure*)SQ_MALLOC(sizeof(SQClosure)); + new (nc) SQClosure(ss,func); + return nc; + } + void Release(){ + sq_delete(this,SQClosure); + } + SQClosure *Clone() + { + SQClosure * ret = SQClosure::Create(_opt_ss(this),_funcproto(_function)); + ret->_env = _env; + ret->_outervalues.copy(_outervalues); + ret->_defaultparams.copy(_defaultparams); + return ret; + } + ~SQClosure() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + } + bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); + static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret); +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); + void Finalize(){_outervalues.resize(0); } +#endif + SQObjectPtr _env; + SQObjectPtr _function; + SQObjectPtrVec _outervalues; + SQObjectPtrVec _defaultparams; +}; +////////////////////////////////////////////// +struct SQGenerator : public CHAINABLE_OBJ +{ + enum SQGeneratorState{eRunning,eSuspended,eDead}; +private: + SQGenerator(SQSharedState *ss,SQClosure *closure){_closure=closure;_state=eRunning;_ci._generator=NULL;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);} +public: + static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){ + SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator)); + new (nc) SQGenerator(ss,closure); + return nc; + } + ~SQGenerator() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + } + void Kill(){ + _state=eDead; + _stack.resize(0); + _closure=_null_;} + void Release(){ + sq_delete(this,SQGenerator); + } + bool Yield(SQVM *v); + bool Resume(SQVM *v,SQInteger target); +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); + void Finalize(){_stack.resize(0);_closure=_null_;} +#endif + SQObjectPtr _closure; + SQObjectPtrVec _stack; + SQObjectPtrVec _vargsstack; + SQVM::CallInfo _ci; + ExceptionsTraps _etraps; + SQGeneratorState _state; +}; + +struct SQNativeClosure : public CHAINABLE_OBJ +{ +private: + SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); } +public: + static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func) + { + SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(sizeof(SQNativeClosure)); + new (nc) SQNativeClosure(ss,func); + return nc; + } + SQNativeClosure *Clone() + { + SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function); + ret->_env = _env; + ret->_name = _name; + ret->_outervalues.copy(_outervalues); + ret->_typecheck.copy(_typecheck); + ret->_nparamscheck = _nparamscheck; + return ret; + } + ~SQNativeClosure() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); + } + void Release(){ + sq_delete(this,SQNativeClosure); + } +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); + void Finalize(){_outervalues.resize(0);} +#endif + SQInteger _nparamscheck; + SQIntVec _typecheck; + SQObjectPtrVec _outervalues; + SQObjectPtr _env; + SQFUNCTION _function; + SQObjectPtr _name; +}; + + + +#endif //_SQCLOSURE_H_ diff --git a/src/3rdparty/squirrel/squirrel/sqcompiler.cpp b/src/3rdparty/squirrel/squirrel/sqcompiler.cpp new file mode 100644 index 0000000000..6839e922bc --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqcompiler.cpp @@ -0,0 +1,1347 @@ +/* + see copyright notice in squirrel.h +*/ +#include +#include "sqpcheader.h" +#include +#include "sqopcodes.h" +#include "sqstring.h" +#include "sqfuncproto.h" +#include "sqcompiler.h" +#include "sqfuncstate.h" +#include "sqlexer.h" +#include "sqvm.h" +#include "sqtable.h" + +#define DEREF_NO_DEREF -1 +#define DEREF_FIELD -2 + +SQInteger _last_stacksize; + +struct ExpState +{ + ExpState() + { + _deref = DEREF_NO_DEREF; + _freevar = false; + _class_or_delete = false; + _funcarg = false; + } + bool _class_or_delete; + bool _funcarg; + bool _freevar; + SQInteger _deref; +}; + +typedef sqvector ExpStateVec; + +#define _exst (_expstates.top()) + +#define BEGIN_BREAKBLE_BLOCK() SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \ + SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \ + _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0); + +#define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \ + __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \ + if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \ + if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \ + _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();} + +class SQCompiler +{ +public: + SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo) + { + _vm=v; + _lex.Init(_ss(v), rg, up,ThrowError,this); + _sourcename = SQString::Create(_ss(v), sourcename); + _lineinfo = lineinfo;_raiseerror = raiseerror; + } + 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); + throw temp; + } + void Lex(){ _token = _lex.Lex();} + void PushExpState(){ _expstates.push_back(ExpState()); } + bool IsDerefToken(SQInteger tok) + { + switch(tok){ + case _SC('='): case _SC('('): case TK_NEWSLOT: + case TK_MODEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ: case TK_PLUSPLUS: case TK_MINUSMINUS: return true; + } + return false; + } + ExpState PopExpState() + { + ExpState ret = _expstates.top(); + _expstates.pop_back(); + return ret; + } + SQObject Expect(SQInteger tok) + { + + if(_token != tok) { + if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) { + //ret = SQString::Create(_ss(_vm),_SC("constructor")); + //do nothing + } + else { + const SQChar *etypename; + if(tok > 255) { + switch(tok) + { + case TK_IDENTIFIER: + etypename = _SC("IDENTIFIER"); + break; + case TK_STRING_LITERAL: + etypename = _SC("STRING_LITERAL"); + break; + case TK_INTEGER: + etypename = _SC("INTEGER"); + break; + case TK_FLOAT: + etypename = _SC("FLOAT"); + break; + default: + etypename = _lex.Tok2Str(tok); + } + Error(_SC("expected '%s'"), etypename); + } + Error(_SC("expected '%c'"), tok); + } + } + SQObjectPtr ret; + switch(tok) + { + case TK_IDENTIFIER: + ret = _fs->CreateString(_lex._svalue); + break; + case TK_STRING_LITERAL: + ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1); + break; + case TK_INTEGER: + ret = SQObjectPtr(_lex._nvalue); + break; + case TK_FLOAT: + ret = SQObjectPtr(_lex._fvalue); + break; + } + Lex(); + return ret; + } + bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); } + void OptionalSemicolon() + { + if(_token == _SC(';')) { Lex(); return; } + if(!IsEndOfStatement()) { + Error(_SC("end of statement expected (; or lf)")); + } + } + void MoveIfCurrentTargetIsLocal() { + SQInteger trg = _fs->TopTarget(); + if(_fs->IsLocal(trg)) { + trg = _fs->PopTarget(); //no pops the target and move it + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg); + } + } + bool Compile(SQObjectPtr &o) + { + _debugline = 1; + _debugop = 0; + + SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this); + funcstate._name = SQString::Create(_ss(_vm), _SC("main")); + _fs = &funcstate; + _fs->AddParameter(_fs->CreateString(_SC("this"))); + _fs->_sourcename = _sourcename; + SQInteger stacksize = _fs->GetStackSize(); + try { + Lex(); + while(_token > 0){ + Statement(); + if(_lex._prevtoken != _SC('}')) OptionalSemicolon(); + } + CleanStack(stacksize); + _fs->AddLineInfos(_lex._currentline, _lineinfo, true); + _fs->AddInstruction(_OP_RETURN, 0xFF); + _fs->SetStackSize(0); + o =_fs->BuildProto(); +#ifdef _DEBUG_DUMP + _fs->Dump(_funcproto(o)); +#endif + return true; + } + catch (SQChar *compilererror) { + 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; + } + } + void Statements() + { + while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) { + Statement(); + if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon(); + } + } + void Statement() + { + _fs->AddLineInfos(_lex._currentline, _lineinfo); + switch(_token){ + case _SC(';'): Lex(); break; + case TK_IF: IfStatement(); break; + case TK_WHILE: WhileStatement(); break; + case TK_DO: DoWhileStatement(); break; + case TK_FOR: ForStatement(); break; + case TK_FOREACH: ForEachStatement(); break; + case TK_SWITCH: SwitchStatement(); break; + case TK_LOCAL: LocalDeclStatement(); break; + case TK_RETURN: + case TK_YIELD: { + SQOpcode op; + if(_token == TK_RETURN) { + op = _OP_RETURN; + + } + else { + op = _OP_YIELD; + _fs->_bgenerator = true; + } + Lex(); + if(!IsEndOfStatement()) { + SQInteger retexp = _fs->GetCurrentPos()+1; + CommaExpr(); + if(op == _OP_RETURN && _fs->_traps > 0) + _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0); + _fs->_returnexp = retexp; + _fs->AddInstruction(op, 1, _fs->PopTarget()); + } + else{ + if(op == _OP_RETURN && _fs->_traps > 0) + _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0); + _fs->_returnexp = -1; + _fs->AddInstruction(op, 0xFF); + } + break;} + case TK_BREAK: + if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block")); + if(_fs->_breaktargets.top() > 0){ + _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0); + } + _fs->AddInstruction(_OP_SCOPE_END, _last_stacksize, _fs->GetStackSize()); + _fs->AddInstruction(_OP_JMP, 0, -1234); + _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos()); + Lex(); + break; + case TK_CONTINUE: + if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block")); + if(_fs->_continuetargets.top() > 0) { + _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0); + } + _fs->AddInstruction(_OP_SCOPE_END, _last_stacksize, _fs->GetStackSize()); + _fs->AddInstruction(_OP_JMP, 0, -1234); + _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos()); + Lex(); + break; + case TK_FUNCTION: + FunctionStatement(); + break; + case TK_CLASS: + ClassStatement(); + break; + case TK_ENUM: + EnumStatement(); + break; + case _SC('{'):{ + SQInteger stacksize = _fs->GetStackSize(); + Lex(); + Statements(); + Expect(_SC('}')); + _fs->AddInstruction(_OP_SCOPE_END, stacksize, _fs->GetStackSize()); + _fs->SetStackSize(stacksize); + } + break; + case TK_TRY: + TryCatchStatement(); + break; + case TK_THROW: + Lex(); + CommaExpr(); + _fs->AddInstruction(_OP_THROW, _fs->PopTarget()); + break; + case TK_CONST: + { + Lex(); + SQObject id = Expect(TK_IDENTIFIER); + Expect('='); + SQObject val = ExpectScalar(); + OptionalSemicolon(); + SQTable *enums = _table(_ss(_vm)->_consts); + SQObjectPtr strongid = id; + enums->NewSlot(strongid,SQObjectPtr(val)); + strongid.Null(); + } + break; + default: + CommaExpr(); + _fs->PopTarget(); + break; + } + _fs->SnoozeOpt(); + } + void EmitDerefOp(SQOpcode op) + { + SQInteger val = _fs->PopTarget(); + SQInteger key = _fs->PopTarget(); + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(op,_fs->PushTarget(),src,key,val); + } + void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0) + { + SQInteger p2 = _fs->PopTarget(); //src in OP_GET + SQInteger p1 = _fs->PopTarget(); //key in OP_GET + _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3); + } + void EmitCompoundArith(SQInteger tok,bool deref) + { + SQInteger oper; + switch(tok){ + case TK_MINUSEQ: oper = '-'; break; + case TK_PLUSEQ: oper = '+'; break; + case TK_MULEQ: oper = '*'; break; + case TK_DIVEQ: oper = '/'; break; + case TK_MODEQ: oper = '%'; break; + default: oper = 0; //shut up compiler + assert(0); break; + }; + if(deref) { + SQInteger val = _fs->PopTarget(); + SQInteger key = _fs->PopTarget(); + SQInteger src = _fs->PopTarget(); + //mixes dest obj and source val in the arg1(hack?) + _fs->AddInstruction(_OP_COMPARITH,_fs->PushTarget(),(src<<16)|val,key,oper); + } + else { + Emit2ArgsOP(_OP_COMPARITHL, oper); + } + } + void CommaExpr() + { + for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr()) {} + } + ExpState Expression(bool funcarg = false) + { + PushExpState(); + _exst._class_or_delete = false; + _exst._funcarg = funcarg; + LogicalOrExp(); + switch(_token) { + case _SC('='): + case TK_NEWSLOT: + case TK_MINUSEQ: + case TK_PLUSEQ: + case TK_MULEQ: + case TK_DIVEQ: + case TK_MODEQ: + { + SQInteger op = _token; + SQInteger ds = _exst._deref; + bool freevar = _exst._freevar; + if(ds == DEREF_NO_DEREF) Error(_SC("can't assign expression")); + Lex(); Expression(); + + switch(op){ + case TK_NEWSLOT: + if(freevar) Error(_SC("free variables cannot be modified")); + if(ds == DEREF_FIELD) + EmitDerefOp(_OP_NEWSLOT); + else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local + Error(_SC("can't 'create' a local slot")); + break; + case _SC('='): //ASSIGN + if(freevar) Error(_SC("free variables cannot be modified")); + if(ds == DEREF_FIELD) + EmitDerefOp(_OP_SET); + else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local + SQInteger p2 = _fs->PopTarget(); //src in OP_GET + SQInteger p1 = _fs->TopTarget(); //key in OP_GET + _fs->AddInstruction(_OP_MOVE, p1, p2); + } + break; + case TK_MINUSEQ: + case TK_PLUSEQ: + case TK_MULEQ: + case TK_DIVEQ: + case TK_MODEQ: + EmitCompoundArith(op,ds == DEREF_FIELD); + break; + } + } + break; + case _SC('?'): { + Lex(); + _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); + SQInteger jzpos = _fs->GetCurrentPos(); + SQInteger trg = _fs->PushTarget(); + Expression(); + SQInteger first_exp = _fs->PopTarget(); + if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); + SQInteger endfirstexp = _fs->GetCurrentPos(); + _fs->AddInstruction(_OP_JMP, 0, 0); + Expect(_SC(':')); + SQInteger jmppos = _fs->GetCurrentPos(); + Expression(); + SQInteger second_exp = _fs->PopTarget(); + if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); + _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos); + _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1); + _fs->SnoozeOpt(); + } + break; + } + return PopExpState(); + } + void BIN_EXP(SQOpcode op, void (SQCompiler::*f)(void),SQInteger op3 = 0) + { + Lex(); (this->*f)(); + SQInteger op1 = _fs->PopTarget();SQInteger op2 = _fs->PopTarget(); + _fs->AddInstruction(op, _fs->PushTarget(), op1, op2, op3); + } + void LogicalOrExp() + { + LogicalAndExp(); + for(;;) if(_token == TK_OR) { + SQInteger first_exp = _fs->PopTarget(); + SQInteger trg = _fs->PushTarget(); + _fs->AddInstruction(_OP_OR, trg, 0, first_exp, 0); + SQInteger jpos = _fs->GetCurrentPos(); + if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); + Lex(); LogicalOrExp(); + _fs->SnoozeOpt(); + SQInteger second_exp = _fs->PopTarget(); + if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); + _fs->SnoozeOpt(); + _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos)); + break; + }else return; + } + void LogicalAndExp() + { + BitwiseOrExp(); + for(;;) switch(_token) { + case TK_AND: { + SQInteger first_exp = _fs->PopTarget(); + SQInteger trg = _fs->PushTarget(); + _fs->AddInstruction(_OP_AND, trg, 0, first_exp, 0); + SQInteger jpos = _fs->GetCurrentPos(); + if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp); + Lex(); LogicalAndExp(); + _fs->SnoozeOpt(); + SQInteger second_exp = _fs->PopTarget(); + if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp); + _fs->SnoozeOpt(); + _fs->SetIntructionParam(jpos, 1, (_fs->GetCurrentPos() - jpos)); + break; + } + case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::BitwiseOrExp); break; + case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &SQCompiler::BitwiseOrExp); break; + default: + return; + } + } + void BitwiseOrExp() + { + BitwiseXorExp(); + for(;;) if(_token == _SC('|')) + {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR); + }else return; + } + void BitwiseXorExp() + { + BitwiseAndExp(); + for(;;) if(_token == _SC('^')) + {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR); + }else return; + } + void BitwiseAndExp() + { + CompExp(); + for(;;) if(_token == _SC('&')) + {BIN_EXP(_OP_BITW, &SQCompiler::CompExp,BW_AND); + }else return; + } + void CompExp() + { + ShiftExp(); + for(;;) switch(_token) { + case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::ShiftExp); break; + case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break; + case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break; + case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break; + case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break; + case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::ShiftExp); break; + default: return; + } + } + void ShiftExp() + { + PlusExp(); + for(;;) switch(_token) { + case TK_USHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_USHIFTR); break; + case TK_SHIFTL: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTL); break; + case TK_SHIFTR: BIN_EXP(_OP_BITW, &SQCompiler::PlusExp,BW_SHIFTR); break; + default: return; + } + } + void PlusExp() + { + MultExp(); + for(;;) switch(_token) { + case _SC('+'): case _SC('-'): + BIN_EXP(_OP_ARITH, &SQCompiler::MultExp,_token); break; + default: return; + } + } + + void MultExp() + { + PrefixedExpr(); + for(;;) switch(_token) { + case _SC('*'): case _SC('/'): case _SC('%'): + BIN_EXP(_OP_ARITH, &SQCompiler::PrefixedExpr,_token); break; + default: return; + } + } + //if 'pos' != -1 the previous variable is a local variable + void PrefixedExpr() + { + SQInteger pos = Factor(); + for(;;) { + switch(_token) { + case _SC('.'): { + pos = -1; + Lex(); + if(_token == TK_PARENT) { + Lex(); + if(!NeedGet()) + Error(_SC("parent cannot be set")); + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), src); + } + else { + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); + if(NeedGet()) Emit2ArgsOP(_OP_GET); + } + _exst._deref = DEREF_FIELD; + _exst._freevar = false; + } + break; + case _SC('['): + if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration")); + Lex(); Expression(); Expect(_SC(']')); + pos = -1; + if(NeedGet()) Emit2ArgsOP(_OP_GET); + _exst._deref = DEREF_FIELD; + _exst._freevar = false; + break; + case TK_MINUSMINUS: + case TK_PLUSPLUS: + if(_exst._deref != DEREF_NO_DEREF && !IsEndOfStatement()) { + SQInteger tok = _token; Lex(); + if(pos < 0) + Emit2ArgsOP(_OP_PINC,tok == TK_MINUSMINUS?-1:1); + else {//if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, tok == TK_MINUSMINUS?-1:1); + } + + } + return; + break; + case _SC('('): + { + if(_exst._deref != DEREF_NO_DEREF) { + if(pos<0) { + SQInteger key = _fs->PopTarget(); //key + SQInteger table = _fs->PopTarget(); //table etc... + SQInteger closure = _fs->PushTarget(); + SQInteger ttarget = _fs->PushTarget(); + _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget); + } + else{ + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); + } + } + else + _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0); + _exst._deref = DEREF_NO_DEREF; + Lex(); + FunctionCallArgs(); + } + break; + default: return; + } + } + } + SQInteger Factor() + { + switch(_token) + { + case TK_STRING_LITERAL: { + //SQObjectPtr id(SQString::Create(_ss(_vm), _lex._svalue,_lex._longstr.size()-1)); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1))); + Lex(); + } + break; + case TK_VARGC: Lex(); _fs->AddInstruction(_OP_VARGC, _fs->PushTarget()); break; + case TK_VARGV: { Lex(); + Expect(_SC('[')); + Expression(); + Expect(_SC(']')); + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(_OP_GETVARGV, _fs->PushTarget(), src); + } + break; + case TK_IDENTIFIER: + case TK_CONSTRUCTOR: + case TK_THIS:{ + _exst._freevar = false; + SQObject id; + SQObject constant; + switch(_token) { + case TK_IDENTIFIER: id = _fs->CreateString(_lex._svalue); break; + case TK_THIS: id = _fs->CreateString(_SC("this")); break; + case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor")); break; + } + SQInteger pos = -1; + Lex(); + if((pos = _fs->GetLocalVariable(id)) == -1) { + //checks if is a free variable + if((pos = _fs->GetOuterVariable(id)) != -1) { + _exst._deref = _fs->PushTarget(); + _fs->AddInstruction(_OP_LOADFREEVAR, _exst._deref ,pos); + _exst._freevar = true; + } + else if(_fs->IsConstant(id,constant)) { //line 634 + SQObjectPtr constval; + SQObject constid; + if(type(constant) == OT_TABLE) { + Expect('.'); constid = Expect(TK_IDENTIFIER); + if(!_table(constant)->Get(constid,constval)) { + constval.Null(); + Error(_SC("invalid constant [%s.%s]"), _stringval(id),_stringval(constid)); + } + } + else { + constval = constant; + } + _exst._deref = _fs->PushTarget(); + SQObjectType ctype = type(constval); + if(ctype == OT_INTEGER && (_integer(constval) & (~0x7FFFFFFF)) == 0) { + _fs->AddInstruction(_OP_LOADINT, _exst._deref,_integer(constval)); + } + else if(ctype == OT_FLOAT && sizeof(SQFloat) == sizeof(SQInt32)) { + SQFloat f = _float(constval); + _fs->AddInstruction(_OP_LOADFLOAT, _exst._deref,*((SQInt32 *)&f)); + } + else { + _fs->AddInstruction(_OP_LOAD, _exst._deref, _fs->GetConstant(constval)); + } + + _exst._freevar = true; + } + else { + _fs->PushTarget(0); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + if(NeedGet()) Emit2ArgsOP(_OP_GET); + _exst._deref = DEREF_FIELD; + } + } + + else{ + _fs->PushTarget(pos); + _exst._deref = pos; + } + return _exst._deref; + } + break; + case TK_PARENT: Lex();_fs->AddInstruction(_OP_GETPARENT, _fs->PushTarget(), 0); break; + case TK_DOUBLE_COLON: // "::" + _fs->AddInstruction(_OP_LOADROOTTABLE, _fs->PushTarget()); + _exst._deref = DEREF_FIELD; + _token = _SC('.'); //hack + return -1; + break; + case TK_NULL: + _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1); + Lex(); + break; + case TK_INTEGER: { + if((_lex._nvalue & (~0x7FFFFFFF)) == 0) { //does it fit in 32 bits? + _fs->AddInstruction(_OP_LOADINT, _fs->PushTarget(),_lex._nvalue); + } + else { + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._nvalue)); + } + Lex(); + } + break; + case TK_FLOAT: + if(sizeof(SQFloat) == sizeof(SQInt32)) { + _fs->AddInstruction(_OP_LOADFLOAT, _fs->PushTarget(),*((SQInt32 *)&_lex._fvalue)); + } + else { + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetNumericConstant(_lex._fvalue)); + } + Lex(); + break; + case TK_TRUE: case TK_FALSE: + _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0); + Lex(); + break; + case _SC('['): { + _fs->AddInstruction(_OP_NEWARRAY, _fs->PushTarget()); + SQInteger apos = _fs->GetCurrentPos(),key = 0; + Lex(); + while(_token != _SC(']')) { + Expression(); + if(_token == _SC(',')) Lex(); + SQInteger val = _fs->PopTarget(); + SQInteger array = _fs->TopTarget(); + _fs->AddInstruction(_OP_APPENDARRAY, array, val); + key++; + } + _fs->SetIntructionParam(apos, 1, key); + Lex(); + } + break; + case _SC('{'):{ + _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); + Lex();ParseTableOrClass(_SC(',')); + } + break; + case TK_FUNCTION: FunctionExp(_token);break; + case TK_CLASS: Lex(); ClassExp();break; + case _SC('-'): UnaryOP(_OP_NEG); break; + case _SC('!'): UnaryOP(_OP_NOT); break; + case _SC('~'): UnaryOP(_OP_BWNOT); break; + case TK_TYPEOF : UnaryOP(_OP_TYPEOF); break; + case TK_RESUME : UnaryOP(_OP_RESUME); break; + case TK_CLONE : UnaryOP(_OP_CLONE); break; + case TK_MINUSMINUS : + case TK_PLUSPLUS :PrefixIncDec(_token); break; + case TK_DELETE : DeleteExpr(); break; + case TK_DELEGATE : DelegateExpr(); break; + case _SC('('): Lex(); CommaExpr(); Expect(_SC(')')); + break; + default: Error(_SC("expression expected")); + } + return -1; + } + void UnaryOP(SQOpcode op) + { + Lex(); PrefixedExpr(); + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(op, _fs->PushTarget(), src); + } + bool NeedGet() + { + switch(_token) { + case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_PLUSPLUS: case TK_MINUSMINUS: + case TK_PLUSEQ: case TK_MINUSEQ: case TK_MULEQ: case TK_DIVEQ: case TK_MODEQ: + return false; + } + return (!_exst._class_or_delete) || (_exst._class_or_delete && (_token == _SC('.') || _token == _SC('['))); + } + + void FunctionCallArgs() + { + SQInteger nargs = 1;//this + while(_token != _SC(')')) { + Expression(true); + MoveIfCurrentTargetIsLocal(); + nargs++; + if(_token == _SC(',')){ + Lex(); + if(_token == ')') Error(_SC("expression expected, found ')'")); + } + } + Lex(); + for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget(); + SQInteger stackbase = _fs->PopTarget(); + SQInteger closure = _fs->PopTarget(); + _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs); + } + void ParseTableOrClass(SQInteger separator,SQInteger terminator = '}') + { + SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0; + + while(_token != terminator) { + bool hasattrs = false; + bool isstatic = false; + //check if is an attribute + if(separator == ';') { + if(_token == TK_ATTR_OPEN) { + _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); Lex(); + ParseTableOrClass(',',TK_ATTR_CLOSE); + hasattrs = true; + } + if(_token == TK_STATIC) { + isstatic = true; + Lex(); + } + } + switch(_token) { + case TK_FUNCTION: + case TK_CONSTRUCTOR:{ + SQInteger tk = _token; + Lex(); + SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor")); + Expect(_SC('(')); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + CreateFunction(id); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); + } + break; + case _SC('['): + Lex(); CommaExpr(); Expect(_SC(']')); + Expect(_SC('=')); Expression(); + break; + default : + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER))); + Expect(_SC('=')); Expression(); + } + + if(_token == separator) Lex();//optional comma/semicolon + nkeys++; + SQInteger val = _fs->PopTarget(); + SQInteger key = _fs->PopTarget(); + SQInteger attrs = hasattrs ? _fs->PopTarget():-1; + assert((hasattrs && attrs == key-1) || !hasattrs); + unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0); + SQInteger table = _fs->TopTarget(); //<AddInstruction(_OP_NEWSLOTA, flags, table, key, val); + //_fs->PopTarget(); + } + if(separator == _SC(',')) //hack recognizes a table from the separator + _fs->SetIntructionParam(tpos, 1, nkeys); + Lex(); + } + void LocalDeclStatement() + { + SQObject varname; + do { + Lex(); varname = Expect(TK_IDENTIFIER); + if(_token == _SC('=')) { + Lex(); Expression(); + SQInteger src = _fs->PopTarget(); + SQInteger dest = _fs->PushTarget(); + if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src); + } + else{ + _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1); + } + _fs->PopTarget(); + _fs->PushLocalVariable(varname); + + } while(_token == _SC(',')); + } + void IfStatement() + { + SQInteger jmppos; + bool haselse = false; + Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); + _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); + SQInteger jnepos = _fs->GetCurrentPos(); + SQInteger stacksize = _fs->GetStackSize(); + + Statement(); + // + if(_token != _SC('}') && _token != TK_ELSE) OptionalSemicolon(); + + CleanStack(stacksize); + SQInteger endifblock = _fs->GetCurrentPos(); + if(_token == TK_ELSE){ + haselse = true; + stacksize = _fs->GetStackSize(); + _fs->AddInstruction(_OP_JMP); + jmppos = _fs->GetCurrentPos(); + Lex(); + Statement(); OptionalSemicolon(); + CleanStack(stacksize); + _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos); + } + _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0)); + } + void WhileStatement() + { + SQInteger jzpos, jmppos; + SQInteger stacksize = _fs->GetStackSize(); + jmppos = _fs->GetCurrentPos(); + Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); + + BEGIN_BREAKBLE_BLOCK(); + _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); + jzpos = _fs->GetCurrentPos(); + stacksize = _fs->GetStackSize(); + _last_stacksize = _fs->GetStackSize(); + + Statement(); + + CleanStack(stacksize); + _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); + _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); + + END_BREAKBLE_BLOCK(jmppos); + } + void DoWhileStatement() + { + Lex(); + SQInteger jzpos = _fs->GetCurrentPos(); + SQInteger stacksize = _fs->GetStackSize(); + BEGIN_BREAKBLE_BLOCK() + _last_stacksize = _fs->GetStackSize(); + Statement(); + CleanStack(stacksize); + Expect(TK_WHILE); + SQInteger continuetrg = _fs->GetCurrentPos(); + Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); + _fs->AddInstruction(_OP_JNZ, _fs->PopTarget(), jzpos - _fs->GetCurrentPos() - 1); + END_BREAKBLE_BLOCK(continuetrg); + } + void ForStatement() + { + Lex(); + SQInteger stacksize = _fs->GetStackSize(); + Expect(_SC('(')); + if(_token == TK_LOCAL) LocalDeclStatement(); + else if(_token != _SC(';')){ + CommaExpr(); + _fs->PopTarget(); + } + Expect(_SC(';')); + _fs->SnoozeOpt(); + SQInteger jmppos = _fs->GetCurrentPos(); + SQInteger jzpos = -1; + if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); } + Expect(_SC(';')); + _fs->SnoozeOpt(); + SQInteger expstart = _fs->GetCurrentPos() + 1; + if(_token != _SC(')')) { + CommaExpr(); + _fs->PopTarget(); + } + Expect(_SC(')')); + _fs->SnoozeOpt(); + SQInteger expend = _fs->GetCurrentPos(); + SQInteger expsize = (expend - expstart) + 1; + SQInstructionVec exp; + if(expsize > 0) { + for(SQInteger i = 0; i < expsize; i++) + exp.push_back(_fs->GetInstruction(expstart + i)); + _fs->PopInstructions(expsize); + } + BEGIN_BREAKBLE_BLOCK() + _last_stacksize = _fs->GetStackSize(); + Statement(); + SQInteger continuetrg = _fs->GetCurrentPos(); + if(expsize > 0) { + for(SQInteger i = 0; i < expsize; i++) + _fs->AddInstruction(exp[i]); + } + _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0); + if(jzpos> 0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos); + CleanStack(stacksize); + + END_BREAKBLE_BLOCK(continuetrg); + } + void ForEachStatement() + { + SQObject idxname, valname; + Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER); + if(_token == _SC(',')) { + idxname = valname; + Lex(); valname = Expect(TK_IDENTIFIER); + } + else{ + idxname = _fs->CreateString(_SC("@INDEX@")); + } + Expect(TK_IN); + + //save the stack size + SQInteger stacksize = _fs->GetStackSize(); + //put the table in the stack(evaluate the table expression) + Expression(); Expect(_SC(')')); + SQInteger container = _fs->TopTarget(); + //push the index local var + SQInteger indexpos = _fs->PushLocalVariable(idxname); + _fs->AddInstruction(_OP_LOADNULLS, indexpos,1); + //push the value local var + SQInteger valuepos = _fs->PushLocalVariable(valname); + _fs->AddInstruction(_OP_LOADNULLS, valuepos,1); + //push reference index + SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible + _fs->AddInstruction(_OP_LOADNULLS, itrpos,1); + SQInteger jmppos = _fs->GetCurrentPos(); + _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos); + SQInteger foreachpos = _fs->GetCurrentPos(); + _fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos); + //generate the statement code + BEGIN_BREAKBLE_BLOCK() + _last_stacksize = _fs->GetStackSize(); + Statement(); + _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1); + _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos); + _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos); + //restore the local variable stack(remove index,val and ref idx) + CleanStack(stacksize); + END_BREAKBLE_BLOCK(foreachpos - 1); + } + void SwitchStatement() + { + Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')')); + Expect(_SC('{')); + SQInteger expr = _fs->TopTarget(); + bool bfirst = true; + SQInteger tonextcondjmp = -1; + SQInteger skipcondjmp = -1; + SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size(); + _fs->_breaktargets.push_back(0); + while(_token == TK_CASE) { + //_fs->AddLineInfos(_lex._currentline, _lineinfo); think about this one + if(!bfirst) { + _fs->AddInstruction(_OP_JMP, 0, 0); + skipcondjmp = _fs->GetCurrentPos(); + _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp); + } + //condition + Lex(); Expression(); Expect(_SC(':')); + SQInteger trg = _fs->PopTarget(); + _fs->AddInstruction(_OP_EQ, trg, trg, expr); + _fs->AddInstruction(_OP_JZ, trg, 0); + //end condition + if(skipcondjmp != -1) { + _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp)); + } + tonextcondjmp = _fs->GetCurrentPos(); + SQInteger stacksize = _fs->GetStackSize(); + _last_stacksize = _fs->GetStackSize(); + Statements(); + _fs->SetStackSize(stacksize); + bfirst = false; + } + if(tonextcondjmp != -1) + _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp); + if(_token == TK_DEFAULT) { + // _fs->AddLineInfos(_lex._currentline, _lineinfo); + Lex(); Expect(_SC(':')); + SQInteger stacksize = _fs->GetStackSize(); + _last_stacksize = _fs->GetStackSize(); + Statements(); + _fs->SetStackSize(stacksize); + } + Expect(_SC('}')); + _fs->PopTarget(); + __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__; + if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__); + _fs->_breaktargets.pop_back(); + + } + void FunctionStatement() + { + SQObject id; + Lex(); id = Expect(TK_IDENTIFIER); + _fs->PushTarget(0); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET); + + while(_token == TK_DOUBLE_COLON) { + Lex(); + id = Expect(TK_IDENTIFIER); + _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id)); + if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET); + } + Expect(_SC('(')); + CreateFunction(id); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0); + EmitDerefOp(_OP_NEWSLOT); + _fs->PopTarget(); + } + void ClassStatement() + { + ExpState es; + Lex(); PushExpState(); + _exst._class_or_delete = true; + _exst._funcarg = false; + PrefixedExpr(); + es = PopExpState(); + if(es._deref == DEREF_NO_DEREF) Error(_SC("invalid class name")); + if(es._deref == DEREF_FIELD) { + ClassExp(); + EmitDerefOp(_OP_NEWSLOT); + _fs->PopTarget(); + } + else Error(_SC("cannot create a class in a local with the syntax(class )")); + } + SQObject ExpectScalar() + { + SQObject val; + switch(_token) { + case TK_INTEGER: + val._type = OT_INTEGER; + val._unVal.nInteger = _lex._nvalue; + break; + case TK_FLOAT: + val._type = OT_FLOAT; + val._unVal.fFloat = _lex._fvalue; + break; + case TK_STRING_LITERAL: + val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1); + break; + default: + Error(_SC("scalar expected : integer,float or string")); + val._type = OT_NULL; // Silent compile-warning + } + Lex(); + return val; + } + void EnumStatement() + { + + Lex(); + SQObject id = Expect(TK_IDENTIFIER); + Expect(_SC('{')); + + SQObject table = _fs->CreateTable(); + SQInteger nval = 0; + while(_token != _SC('}')) { + SQObject key = Expect(TK_IDENTIFIER); + SQObject val; + if(_token == _SC('=')) { + Lex(); + val = ExpectScalar(); + } + else { + val._type = OT_INTEGER; + val._unVal.nInteger = nval++; + } + _table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val)); + if(_token == ',') Lex(); + } + SQTable *enums = _table(_ss(_vm)->_consts); + SQObjectPtr strongid = id; + /*SQObjectPtr dummy; + if(enums->Get(strongid,dummy)) { + dummy.Null(); strongid.Null(); + Error(_SC("enumeration already exists")); + }*/ + enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table)); + strongid.Null(); + Lex(); + + } + void TryCatchStatement() + { + SQObject exid; + Lex(); + _fs->AddInstruction(_OP_PUSHTRAP,0,0); + _fs->_traps++; + if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++; + if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++; + SQInteger trappos = _fs->GetCurrentPos(); + Statement(); + _fs->_traps--; + _fs->AddInstruction(_OP_POPTRAP, 1, 0); + if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--; + if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--; + _fs->AddInstruction(_OP_JMP, 0, 0); + SQInteger jmppos = _fs->GetCurrentPos(); + _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos)); + Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')')); + SQInteger stacksize = _fs->GetStackSize(); + SQInteger ex_target = _fs->PushLocalVariable(exid); + _fs->SetIntructionParam(trappos, 0, ex_target); + Statement(); + _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0); + CleanStack(stacksize); + } + void FunctionExp(SQInteger ftype) + { + Lex(); Expect(_SC('(')); + CreateFunction(_null_); + _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1); + } + void ClassExp() + { + SQInteger base = -1; + SQInteger attrs = -1; + if(_token == TK_EXTENDS) { + Lex(); Expression(); + base = _fs->TopTarget(); + } + if(_token == TK_ATTR_OPEN) { + Lex(); + _fs->AddInstruction(_OP_NEWTABLE, _fs->PushTarget()); + ParseTableOrClass(_SC(','),TK_ATTR_CLOSE); + attrs = _fs->TopTarget(); + } + Expect(_SC('{')); + if(attrs != -1) _fs->PopTarget(); + if(base != -1) _fs->PopTarget(); + _fs->AddInstruction(_OP_CLASS, _fs->PushTarget(), base, attrs); + ParseTableOrClass(_SC(';')); + } + void DelegateExpr() + { + Lex(); CommaExpr(); + Expect(_SC(':')); + CommaExpr(); + SQInteger table = _fs->PopTarget(), delegate = _fs->PopTarget(); + _fs->AddInstruction(_OP_DELEGATE, _fs->PushTarget(), table, delegate); + } + void DeleteExpr() + { + ExpState es; + Lex(); PushExpState(); + _exst._class_or_delete = true; + _exst._funcarg = false; + PrefixedExpr(); + es = PopExpState(); + if(es._deref == DEREF_NO_DEREF) Error(_SC("can't delete an expression")); + if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_DELETE); + else Error(_SC("cannot delete a local")); + } + void PrefixIncDec(SQInteger token) + { + ExpState es; + Lex(); PushExpState(); + _exst._class_or_delete = true; + _exst._funcarg = false; + PrefixedExpr(); + es = PopExpState(); + if(es._deref == DEREF_FIELD) Emit2ArgsOP(_OP_INC,token == TK_MINUSMINUS?-1:1); + else { + SQInteger src = _fs->PopTarget(); + _fs->AddInstruction(_OP_INCL, _fs->PushTarget(), src, 0, token == TK_MINUSMINUS?-1:1); + } + } + void CreateFunction(SQObject &name) + { + + SQFuncState *funcstate = _fs->PushChildState(_ss(_vm)); + funcstate->_name = name; + SQObject paramname; + funcstate->AddParameter(_fs->CreateString(_SC("this"))); + funcstate->_sourcename = _sourcename; + SQInteger defparams = 0; + while(_token!=_SC(')')) { + if(_token == TK_VARPARAMS) { + if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters")); + funcstate->_varparams = true; + Lex(); + if(_token != _SC(')')) Error(_SC("expected ')'")); + break; + } + else { + paramname = Expect(TK_IDENTIFIER); + funcstate->AddParameter(paramname); + if(_token == _SC('=')) { + Lex(); + Expression(); + funcstate->AddDefaultParam(_fs->TopTarget()); + defparams++; + } + else { + if(defparams > 0) Error(_SC("expected '='")); + } + if(_token == _SC(',')) Lex(); + else if(_token != _SC(')')) Error(_SC("expected ')' or ','")); + } + } + Expect(_SC(')')); + for(SQInteger n = 0; n < defparams; n++) { + _fs->PopTarget(); + } + //outer values + if(_token == _SC(':')) { + Lex(); Expect(_SC('(')); + while(_token != _SC(')')) { + paramname = Expect(TK_IDENTIFIER); + //outers are treated as implicit local variables + funcstate->AddOuterValue(paramname); + if(_token == _SC(',')) Lex(); + else if(_token != _SC(')')) Error(_SC("expected ')' or ','")); + } + Lex(); + } + + SQFuncState *currchunk = _fs; + _fs = funcstate; + Statement(); + funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true); + funcstate->AddInstruction(_OP_RETURN, -1); + funcstate->SetStackSize(0); + //_fs->->_stacksize = _fs->_stacksize; + SQFunctionProto *func = funcstate->BuildProto(); +#ifdef _DEBUG_DUMP + funcstate->Dump(func); +#endif + _fs = currchunk; + _fs->_functions.push_back(func); + _fs->PopChildState(); + } + void CleanStack(SQInteger stacksize) + { + if(_fs->GetStackSize() != stacksize) + _fs->SetStackSize(stacksize); + } + void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve) + { + while(ntoresolve > 0) { + SQInteger pos = funcstate->_unresolvedbreaks.back(); + funcstate->_unresolvedbreaks.pop_back(); + //set the jmp instruction + funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0); + ntoresolve--; + } + } + void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos) + { + while(ntoresolve > 0) { + SQInteger pos = funcstate->_unresolvedcontinues.back(); + funcstate->_unresolvedcontinues.pop_back(); + //set the jmp instruction + funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0); + ntoresolve--; + } + } +private: + SQInteger _token; + SQFuncState *_fs; + SQObjectPtr _sourcename; + SQLexer _lex; + bool _lineinfo; + bool _raiseerror; + SQInteger _debugline; + SQInteger _debugop; + ExpStateVec _expstates; + 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); +} diff --git a/src/3rdparty/squirrel/squirrel/sqcompiler.h b/src/3rdparty/squirrel/squirrel/sqcompiler.h new file mode 100644 index 0000000000..dd55888b6e --- /dev/null +++ b/src/3rdparty/squirrel/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_DELEGATE 262 +#define TK_DELETE 263 +#define TK_EQ 264 +#define TK_NE 265 +#define TK_LE 266 +#define TK_GE 267 +#define TK_SWITCH 268 +#define TK_ARROW 269 +#define TK_AND 270 +#define TK_OR 271 +#define TK_IF 272 +#define TK_ELSE 273 +#define TK_WHILE 274 +#define TK_BREAK 275 +#define TK_FOR 276 +#define TK_DO 277 +#define TK_NULL 278 +#define TK_FOREACH 279 +#define TK_IN 280 +#define TK_NEWSLOT 281 +#define TK_MODULO 282 +#define TK_LOCAL 283 +#define TK_CLONE 284 +#define TK_FUNCTION 285 +#define TK_RETURN 286 +#define TK_TYPEOF 287 +#define TK_UMINUS 288 +#define TK_PLUSEQ 289 +#define TK_MINUSEQ 290 +#define TK_CONTINUE 291 +#define TK_YIELD 292 +#define TK_TRY 293 +#define TK_CATCH 294 +#define TK_THROW 295 +#define TK_SHIFTL 296 +#define TK_SHIFTR 297 +#define TK_RESUME 298 +#define TK_DOUBLE_COLON 299 +#define TK_CASE 300 +#define TK_DEFAULT 301 +#define TK_THIS 302 +#define TK_PLUSPLUS 303 +#define TK_MINUSMINUS 304 +#define TK_PARENT 305 +#define TK_USHIFTR 306 +#define TK_CLASS 307 +#define TK_EXTENDS 308 +#define TK_CONSTRUCTOR 310 +#define TK_INSTANCEOF 311 +#define TK_VARPARAMS 312 +#define TK_VARGC 313 +#define TK_VARGV 314 +#define TK_TRUE 315 +#define TK_FALSE 316 +#define TK_MULEQ 317 +#define TK_DIVEQ 318 +#define TK_MODEQ 319 +#define TK_ATTR_OPEN 320 +#define TK_ATTR_CLOSE 321 +#define TK_STATIC 322 +#define TK_ENUM 323 +#define TK_CONST 324 + + +typedef void(*CompilerErrorFunc)(void *ud, const SQChar *s); +bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo); +#endif //_SQCOMPILER_H_ diff --git a/src/3rdparty/squirrel/squirrel/sqdebug.cpp b/src/3rdparty/squirrel/squirrel/sqdebug.cpp new file mode 100644 index 0000000000..0b0964ceb3 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqdebug.cpp @@ -0,0 +1,104 @@ +/* + see copyright notice in squirrel.h +*/ +#include +#include "sqpcheader.h" +#include +#include "sqvm.h" +#include "sqfuncproto.h" +#include "sqclosure.h" +#include "sqstring.h" + +SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si) +{ + SQInteger cssize = v->_callsstacksize; + if (cssize > level) { + memset(si, 0, sizeof(SQStackInfos)); + SQVM::CallInfo &ci = v->_callsstack[cssize-level-1]; + switch (type(ci._closure)) { + case OT_CLOSURE:{ + SQFunctionProto *func = _funcproto(_closure(ci._closure)->_function); + if (type(func->_name) == OT_STRING) + si->funcname = _stringval(func->_name); + if (type(func->_sourcename) == OT_STRING) + si->source = _stringval(func->_sourcename); + si->line = func->GetLine(ci._ip); + } + break; + case OT_NATIVECLOSURE: + si->source = _SC("NATIVE"); + si->funcname = _SC("unknown"); + if(type(_nativeclosure(ci._closure)->_name) == OT_STRING) + si->funcname = _stringval(_nativeclosure(ci._closure)->_name); + si->line = -1; + break; + default: break; //shutup compiler + } + return SQ_OK; + } + return SQ_ERROR; +} + +void SQVM::Raise_Error(const SQChar *s, ...) +{ + va_list vl; + va_start(vl, s); + scvsprintf(_sp(rsl((SQInteger)scstrlen(s)+(NUMBER_MAX_CHAR*2))), s, vl); + va_end(vl); + _lasterror = SQString::Create(_ss(this),_spval,-1); +} + +void SQVM::Raise_Error(SQObjectPtr &desc) +{ + _lasterror = desc; +} + +SQString *SQVM::PrintObjVal(const SQObject &o) +{ + switch(type(o)) { + case OT_STRING: return _string(o); + case OT_INTEGER: +#if defined(_SQ64) + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%ld"), _integer(o)); +#else + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%d"), _integer(o)); +#endif + return SQString::Create(_ss(this), _spval); + break; + case OT_FLOAT: + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)), _SC("%.14g"), _float(o)); + return SQString::Create(_ss(this), _spval); + break; + default: + return SQString::Create(_ss(this), GetTypeName(o)); + } +} + +void SQVM::Raise_IdxError(SQObject &o) +{ + SQObjectPtr oval = PrintObjVal(o); + Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval)); +} + +void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2) +{ + SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2); + Raise_Error(_SC("comparsion between '%.50s' and '%.50s'"), _stringval(oval1), _stringval(oval2)); +} + + +void SQVM::Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type) +{ + SQObjectPtr exptypes = SQString::Create(_ss(this), _SC(""), -1); + SQInteger found = 0; + for(SQInteger i=0; i<16; i++) + { + SQInteger mask = 0x00000001 << i; + if(typemask & (mask)) { + if(found>0) StringCat(exptypes,SQString::Create(_ss(this), _SC("|"), -1), exptypes); + found ++; + StringCat(exptypes,SQString::Create(_ss(this), IdType2Name((SQObjectType)mask), -1), exptypes); + } + } + Raise_Error(_SC("parameter %d has an invalid type '%s' ; expected: '%s'"), nparam, IdType2Name((SQObjectType)type), _stringval(exptypes)); +} diff --git a/src/3rdparty/squirrel/squirrel/sqfuncproto.h b/src/3rdparty/squirrel/squirrel/sqfuncproto.h new file mode 100644 index 0000000000..faac9e925a --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqfuncproto.h @@ -0,0 +1,160 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQFUNCTION_H_ +#define _SQFUNCTION_H_ + +#include "sqopcodes.h" + +enum SQOuterType { + otLOCAL = 0, + otSYMBOL = 1, + otOUTER = 2 +}; + +struct SQOuterVar +{ + + SQOuterVar(){} + SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t) + { + _name = name; + _src=src; + _type=t; + } + SQOuterVar(const SQOuterVar &ov) + { + _type=ov._type; + _src=ov._src; + _name=ov._name; + } + SQOuterType _type; + SQObjectPtr _name; + SQObjectPtr _src; +}; + +struct SQLocalVarInfo +{ + SQLocalVarInfo():_start_op(0),_end_op(0){} + SQLocalVarInfo(const SQLocalVarInfo &lvi) + { + _name=lvi._name; + _start_op=lvi._start_op; + _end_op=lvi._end_op; + _pos=lvi._pos; + } + SQObjectPtr _name; + SQUnsignedInteger _start_op; + SQUnsignedInteger _end_op; + SQUnsignedInteger _pos; +}; + +struct SQLineInfo { SQInteger _line;SQInteger _op; }; + +typedef sqvector SQOuterVarVec; +typedef sqvector SQLocalVarInfoVec; +typedef sqvector SQLineInfoVec; + +#define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf,defparams) (sizeof(SQFunctionProto) \ + +((ni-1)*sizeof(SQInstruction))+(nl*sizeof(SQObjectPtr)) \ + +(nparams*sizeof(SQObjectPtr))+(nfuncs*sizeof(SQObjectPtr)) \ + +(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \ + +(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger))) + +#define _CONSTRUCT_VECTOR(type,size,ptr) { \ + for(SQInteger n = 0; n < size; n++) { \ + new (&ptr[n]) type(); \ + } \ +} + +#define _DESTRUCT_VECTOR(type,size,ptr) { \ + for(SQInteger nl = 0; nl < size; nl++) { \ + ptr[nl].~type(); \ + } \ +} +struct SQFunctionProto : public SQRefCounted +{ +private: + SQFunctionProto(){ + _stacksize=0; + _bgenerator=false;} +public: + static SQFunctionProto *Create(SQInteger ninstructions, + SQInteger nliterals,SQInteger nparameters, + SQInteger nfunctions,SQInteger noutervalues, + SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams) + { + SQFunctionProto *f; + //I compact the whole class and members in a single memory allocation + f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams)); + new (f) SQFunctionProto; + f->_ninstructions = ninstructions; + f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions]; + f->_nliterals = nliterals; + f->_parameters = (SQObjectPtr*)&f->_literals[nliterals]; + f->_nparameters = nparameters; + f->_functions = (SQObjectPtr*)&f->_parameters[nparameters]; + f->_nfunctions = nfunctions; + f->_outervalues = (SQOuterVar*)&f->_functions[nfunctions]; + f->_noutervalues = noutervalues; + f->_lineinfos = (SQLineInfo *)&f->_outervalues[noutervalues]; + f->_nlineinfos = nlineinfos; + f->_localvarinfos = (SQLocalVarInfo *)&f->_lineinfos[nlineinfos]; + f->_nlocalvarinfos = nlocalvarinfos; + f->_defaultparams = (SQInteger *)&f->_localvarinfos[nlocalvarinfos]; + f->_ndefaultparams = ndefaultparams; + + _CONSTRUCT_VECTOR(SQObjectPtr,f->_nliterals,f->_literals); + _CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters); + _CONSTRUCT_VECTOR(SQObjectPtr,f->_nfunctions,f->_functions); + _CONSTRUCT_VECTOR(SQOuterVar,f->_noutervalues,f->_outervalues); + //_CONSTRUCT_VECTOR(SQLineInfo,f->_nlineinfos,f->_lineinfos); //not required are 2 integers + _CONSTRUCT_VECTOR(SQLocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos); + return f; + } + void Release(){ + _DESTRUCT_VECTOR(SQObjectPtr,_nliterals,_literals); + _DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters); + _DESTRUCT_VECTOR(SQObjectPtr,_nfunctions,_functions); + _DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues); + //_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers + _DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos); + SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams); + this->~SQFunctionProto(); + sq_vm_free(this,size); + } + const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop); + SQInteger GetLine(SQInstruction *curr); + bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write); + static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret); + + SQObjectPtr _sourcename; + SQObjectPtr _name; + SQInteger _stacksize; + bool _bgenerator; + bool _varparams; + + SQInteger _nlocalvarinfos; + SQLocalVarInfo *_localvarinfos; + + SQInteger _nlineinfos; + SQLineInfo *_lineinfos; + + SQInteger _nliterals; + SQObjectPtr *_literals; + + SQInteger _nparameters; + SQObjectPtr *_parameters; + + SQInteger _nfunctions; + SQObjectPtr *_functions; + + SQInteger _noutervalues; + SQOuterVar *_outervalues; + + SQInteger _ndefaultparams; + SQInteger *_defaultparams; + + SQInteger _ninstructions; + SQInstruction _instructions[1]; +}; + +#endif //_SQFUNCTION_H_ diff --git a/src/3rdparty/squirrel/squirrel/sqfuncstate.cpp b/src/3rdparty/squirrel/squirrel/sqfuncstate.cpp new file mode 100644 index 0000000000..8d536fdbb6 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqfuncstate.cpp @@ -0,0 +1,572 @@ +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqcompiler.h" +#include "sqfuncproto.h" +#include "sqstring.h" +#include "sqtable.h" +#include "sqopcodes.h" +#include "sqfuncstate.h" + +#ifdef _DEBUG_DUMP +SQInstructionDesc g_InstrDesc[]={ + {_SC("_OP_LINE")}, + {_SC("_OP_LOAD")}, + {_SC("_OP_LOADINT")}, + {_SC("_OP_LOADFLOAT")}, + {_SC("_OP_DLOAD")}, + {_SC("_OP_TAILCALL")}, + {_SC("_OP_CALL")}, + {_SC("_OP_PREPCALL")}, + {_SC("_OP_PREPCALLK")}, + {_SC("_OP_GETK")}, + {_SC("_OP_MOVE")}, + {_SC("_OP_NEWSLOT")}, + {_SC("_OP_DELETE")}, + {_SC("_OP_SET")}, + {_SC("_OP_GET")}, + {_SC("_OP_EQ")}, + {_SC("_OP_NE")}, + {_SC("_OP_ARITH")}, + {_SC("_OP_BITW")}, + {_SC("_OP_RETURN")}, + {_SC("_OP_LOADNULLS")}, + {_SC("_OP_LOADROOTTABLE")}, + {_SC("_OP_LOADBOOL")}, + {_SC("_OP_DMOVE")}, + {_SC("_OP_JMP")}, + {_SC("_OP_JNZ")}, + {_SC("_OP_JZ")}, + {_SC("_OP_LOADFREEVAR")}, + {_SC("_OP_VARGC")}, + {_SC("_OP_GETVARGV")}, + {_SC("_OP_NEWTABLE")}, + {_SC("_OP_NEWARRAY")}, + {_SC("_OP_APPENDARRAY")}, + {_SC("_OP_GETPARENT")}, + {_SC("_OP_COMPARITH")}, + {_SC("_OP_COMPARITHL")}, + {_SC("_OP_INC")}, + {_SC("_OP_INCL")}, + {_SC("_OP_PINC")}, + {_SC("_OP_PINCL")}, + {_SC("_OP_CMP")}, + {_SC("_OP_EXISTS")}, + {_SC("_OP_INSTANCEOF")}, + {_SC("_OP_AND")}, + {_SC("_OP_OR")}, + {_SC("_OP_NEG")}, + {_SC("_OP_NOT")}, + {_SC("_OP_BWNOT")}, + {_SC("_OP_CLOSURE")}, + {_SC("_OP_YIELD")}, + {_SC("_OP_RESUME")}, + {_SC("_OP_FOREACH")}, + {_SC("_OP_POSTFOREACH")}, + {_SC("_OP_DELEGATE")}, + {_SC("_OP_CLONE")}, + {_SC("_OP_TYPEOF")}, + {_SC("_OP_PUSHTRAP")}, + {_SC("_OP_POPTRAP")}, + {_SC("_OP_THROW")}, + {_SC("_OP_CLASS")}, + {_SC("_OP_NEWSLOTA")}, + {_SC("_OP_SCOPE_END")} +}; +#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; +#if defined(_SQ64) + case OT_INTEGER: scprintf(_SC("{%ld}"),_integer(o));break; +#else + case OT_INTEGER: scprintf(_SC("{%d}"),_integer(o));break; +#endif + case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break; + default: scprintf(_SC("(%s %p)"),GetTypeName(o),_rawval(o));break; break; //shut up compiler + } +} + +SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed) +{ + _nliterals = 0; + _literals = SQTable::Create(ss,0); + _strings = SQTable::Create(ss,0); + _sharedstate = ss; + _lastline = 0; + _optimization = true; + _parent = parent; + _stacksize = 0; + _traps = 0; + _returnexp = 0; + _varparams = false; + _errfunc = efunc; + _errtarget = ed; + _bgenerator = false; + +} + +void SQFuncState::Error(const SQChar *err) +{ + _errfunc(_errtarget,err); +} + +#ifdef _DEBUG_DUMP +void SQFuncState::Dump(SQFunctionProto *func) +{ + SQUnsignedInteger n=0,i; + SQInteger si; + scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction)); + scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject)); + scprintf(_SC("--------------------------------------------------------------------\n")); + scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown")); + scprintf(_SC("-----LITERALS\n")); + SQObjectPtr refidx,key,val; + SQInteger idx; + SQObjectPtrVec templiterals; + templiterals.resize(_nliterals); + while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) { + refidx=idx; + templiterals[_integer(val)]=key; + } + for(i=0;i>\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_nlocalvarinfos;si++){ + SQLocalVarInfo lvi=func->_localvarinfos[si]; + scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op); + n++; + } + scprintf(_SC("-----LINE INFO\n")); + for(i=0;i<_lineinfos.size();i++){ + SQLineInfo li=_lineinfos[i]; + scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line); + n++; + } + scprintf(_SC("-----dump\n")); + n=0; + for(i=0;i<_instructions.size();i++){ + SQInstruction &inst=_instructions[i]; + if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){ + + SQInteger lidx = inst._arg1; + scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0); + if(lidx >= 0xFFFFFFFF) + scprintf(_SC("null")); + else { + SQInteger refidx; + SQObjectPtr val,key,refo; + while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) { + refo = refidx; + } + DumpLiteral(key); + } + if(inst.op != _OP_DLOAD) { + scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3); + } + else { + scprintf(_SC(" %d "),inst._arg2); + lidx = inst._arg3; + if(lidx >= 0xFFFFFFFF) + scprintf(_SC("null")); + else { + SQInteger refidx; + SQObjectPtr val,key,refo; + while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) { + refo = refidx; + } + DumpLiteral(key); + scprintf(_SC("\n")); + } + } + } + else if(inst.op==_OP_LOADFLOAT) { + scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3); + } + else if(inst.op==_OP_ARITH){ + scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); + } + else + scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3); + n++; + } + scprintf(_SC("-----\n")); + scprintf(_SC("stack size[%d]\n"),func->_stacksize); + scprintf(_SC("--------------------------------------------------------------------\n\n")); +} +#endif + +SQInteger SQFuncState::GetNumericConstant(const SQInteger cons) +{ + return GetConstant(SQObjectPtr(cons)); +} + +SQInteger SQFuncState::GetNumericConstant(const SQFloat cons) +{ + return GetConstant(SQObjectPtr(cons)); +} + +SQInteger SQFuncState::GetConstant(const SQObject &cons) +{ + SQObjectPtr val; + if(!_table(_literals)->Get(cons,val)) + { + val = _nliterals; + _table(_literals)->NewSlot(cons,val); + _nliterals++; + if(_nliterals > MAX_LITERALS) { + val.Null(); + Error(_SC("internal compiler error: too many literals")); + } + } + return _integer(val); +} + +void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3) +{ + _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0); + _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1); + _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2); + _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3); +} + +void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val) +{ + switch(arg){ + case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break; + case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break; + case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break; + case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break; + }; +} + +SQInteger SQFuncState::AllocStackPos() +{ + SQInteger npos=_vlocals.size(); + _vlocals.push_back(SQLocalVarInfo()); + if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) { + if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals")); + _stacksize=_vlocals.size(); + } + return npos; +} + +SQInteger SQFuncState::PushTarget(SQInteger n) +{ + if(n!=-1){ + _targetstack.push_back(n); + return n; + } + n=AllocStackPos(); + _targetstack.push_back(n); + return n; +} + +SQInteger SQFuncState::GetUpTarget(SQInteger n){ + return _targetstack[((_targetstack.size()-1)-n)]; +} + +SQInteger SQFuncState::TopTarget(){ + return _targetstack.back(); +} +SQInteger SQFuncState::PopTarget() +{ + SQInteger npos=_targetstack.back(); + SQLocalVarInfo t=_vlocals[_targetstack.back()]; + if(type(t._name)==OT_NULL){ + _vlocals.pop_back(); + } + _targetstack.pop_back(); + return npos; +} + +SQInteger SQFuncState::GetStackSize() +{ + return _vlocals.size(); +} + +void SQFuncState::SetStackSize(SQInteger n) +{ + SQInteger size=_vlocals.size(); + while(size>n){ + size--; + SQLocalVarInfo lvi=_vlocals.back(); + if(type(lvi._name)!=OT_NULL){ + lvi._end_op=GetCurrentPos(); + _localvarinfos.push_back(lvi); + } + _vlocals.pop_back(); + } +} + +bool SQFuncState::IsConstant(const SQObject &name,SQObject &e) +{ + SQObjectPtr val; + if(_table(_sharedstate->_consts)->Get(name,val)) { + e = val; + return true; + } + return false; +} + +bool SQFuncState::IsLocal(SQUnsignedInteger stkpos) +{ + if(stkpos>=_vlocals.size())return false; + else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true; + return false; +} + +SQInteger SQFuncState::PushLocalVariable(const SQObject &name) +{ + SQInteger pos=_vlocals.size(); + SQLocalVarInfo lvi; + lvi._name=name; + lvi._start_op=GetCurrentPos()+1; + lvi._pos=_vlocals.size(); + _vlocals.push_back(lvi); + if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size(); + + return pos; +} + +SQInteger SQFuncState::GetLocalVariable(const SQObject &name) +{ + SQInteger locals=_vlocals.size(); + while(locals>=1){ + if(type(_vlocals[locals-1]._name)==OT_STRING && _string(_vlocals[locals-1]._name)==_string(name)){ + return locals-1; + } + locals--; + } + return -1; +} + +SQInteger SQFuncState::GetOuterVariable(const SQObject &name) +{ + SQInteger outers = _outervalues.size(); + for(SQInteger i = 0; iGetLocalVariable(name); + if(pos == -1) { + pos = _parent->GetOuterVariable(name); + if(pos != -1) { + _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local + return; + } + } + else { + _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local + return; + } + } + _outervalues.push_back(SQOuterVar(name,name,otSYMBOL)); //global +} + +void SQFuncState::AddParameter(const SQObject &name) +{ + PushLocalVariable(name); + _parameters.push_back(name); +} + +void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force) +{ + if(_lastline!=line || force){ + SQLineInfo li; + li._line=line;li._op=(GetCurrentPos()+1); + if(lineop)AddInstruction(_OP_LINE,0,line); + _lineinfos.push_back(li); + _lastline=line; + } +} + +void SQFuncState::AddInstruction(SQInstruction &i) +{ + SQInteger size = _instructions.size(); + if(size > 0 && _optimization){ //simple optimizer + SQInstruction &pi = _instructions[size-1];//previous instruction + switch(i.op) { + case _OP_RETURN: + if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) { + pi.op = _OP_TAILCALL; + } + break; + case _OP_GET: + if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){ + pi._arg1 = pi._arg1; + pi._arg2 = (unsigned char)i._arg1; + pi.op = _OP_GETK; + pi._arg0 = i._arg0; + + return; + } + break; + case _OP_PREPCALL: + if( pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ + pi.op = _OP_PREPCALLK; + pi._arg0 = i._arg0; + pi._arg1 = pi._arg1; + pi._arg2 = i._arg2; + pi._arg3 = i._arg3; + return; + } + break; + case _OP_APPENDARRAY: + if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){ + pi.op = _OP_APPENDARRAY; + pi._arg0 = i._arg0; + pi._arg1 = pi._arg1; + pi._arg2 = MAX_FUNC_STACKSIZE; + pi._arg3 = MAX_FUNC_STACKSIZE; + return; + } + break; + case _OP_MOVE: + if((pi.op == _OP_GET || pi.op == _OP_ARITH || pi.op == _OP_BITW) && (pi._arg0 == i._arg1)) + { + pi._arg0 = i._arg0; + _optimization = false; + return; + } + + if(pi.op == _OP_MOVE) + { + pi.op = _OP_DMOVE; + pi._arg2 = i._arg0; + pi._arg3 = (unsigned char)i._arg1; + return; + } + break; + case _OP_LOAD: + if(pi.op == _OP_LOAD && i._arg1 < 256) { + pi.op = _OP_DLOAD; + pi._arg2 = i._arg0; + pi._arg3 = (unsigned char)i._arg1; + return; + } + break; + case _OP_EQ:case _OP_NE: + if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) )) + { + pi.op = i.op; + pi._arg0 = i._arg0; + pi._arg1 = pi._arg1; + pi._arg2 = i._arg2; + pi._arg3 = MAX_FUNC_STACKSIZE; + return; + } + break; + case _OP_LOADNULLS: + if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) { + + pi._arg1 = pi._arg1 + 1; + pi.op = _OP_LOADNULLS; + return; + } + break; + case _OP_LINE: + if(pi.op == _OP_LINE) { + _instructions.pop_back(); + _lineinfos.pop_back(); + } + break; + } + } + _optimization = true; + _instructions.push_back(i); +} + +SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len) +{ + SQObjectPtr ns(SQString::Create(_sharedstate,s,len)); + _table(_strings)->NewSlot(ns,(SQInteger)1); + return ns; +} + +SQObject SQFuncState::CreateTable() +{ + SQObjectPtr nt(SQTable::Create(_sharedstate,0)); + _table(_strings)->NewSlot(nt,(SQInteger)1); + return nt; +} + +SQFunctionProto *SQFuncState::BuildProto() +{ + SQFunctionProto *f=SQFunctionProto::Create(_instructions.size(), + _nliterals,_parameters.size(),_functions.size(),_outervalues.size(), + _lineinfos.size(),_localvarinfos.size(),_defaultparams.size()); + + SQObjectPtr refidx,key,val; + SQInteger idx; + + f->_stacksize = _stacksize; + f->_sourcename = _sourcename; + f->_bgenerator = _bgenerator; + f->_name = _name; + + while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) { + f->_literals[_integer(val)]=key; + refidx=idx; + } + + for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf]; + for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np]; + for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no]; + for(SQUnsignedInteger no = 0; no < _localvarinfos.size(); no++) f->_localvarinfos[no] = _localvarinfos[no]; + for(SQUnsignedInteger no = 0; no < _lineinfos.size(); no++) f->_lineinfos[no] = _lineinfos[no]; + for(SQUnsignedInteger no = 0; no < _defaultparams.size(); no++) f->_defaultparams[no] = _defaultparams[no]; + + memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction)); + + f->_varparams = _varparams; + + return f; +} + +SQFuncState *SQFuncState::PushChildState(SQSharedState *ss) +{ + SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState)); + new (child) SQFuncState(ss,this,_errfunc,_errtarget); + _childstates.push_back(child); + return child; +} + +void SQFuncState::PopChildState() +{ + SQFuncState *child = _childstates.back(); + sq_delete(child,SQFuncState); + _childstates.pop_back(); +} + +SQFuncState::~SQFuncState() +{ + while(_childstates.size() > 0) + { + PopChildState(); + } +} diff --git a/src/3rdparty/squirrel/squirrel/sqfuncstate.h b/src/3rdparty/squirrel/squirrel/sqfuncstate.h new file mode 100644 index 0000000000..c0bf1e5e9e --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqfuncstate.h @@ -0,0 +1,85 @@ +/* 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 _childstates; + SQInteger GetConstant(const SQObject &cons); +private: + CompilerErrorFunc _errfunc; + void *_errtarget; +}; + + +#endif //_SQFUNCSTATE_H_ + diff --git a/src/3rdparty/squirrel/squirrel/sqlexer.cpp b/src/3rdparty/squirrel/squirrel/sqlexer.cpp new file mode 100644 index 0000000000..1f5fbff490 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqlexer.cpp @@ -0,0 +1,476 @@ +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include +#include +#include "sqtable.h" +#include "sqstring.h" +#include "sqcompiler.h" +#include "sqlexer.h" + +#define CUR_CHAR (_currdata) +#define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;} +#define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB) +#define NEXT() {Next();_currentcolumn++;} +#define INIT_TEMP_STRING() { _longstr.resize(0);} +#define APPEND_CHAR(c) { _longstr.push_back(c);} +#define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));} +#define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id)) + +SQLexer::SQLexer(){} +SQLexer::~SQLexer() +{ + _keywords->Release(); +} + +void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerErrorFunc efunc,void *ed) +{ + _errfunc = efunc; + _errtarget = ed; + _sharedstate = ss; + _keywords = SQTable::Create(ss, 26); + ADD_KEYWORD(while, TK_WHILE); + ADD_KEYWORD(do, TK_DO); + ADD_KEYWORD(if, TK_IF); + ADD_KEYWORD(else, TK_ELSE); + ADD_KEYWORD(break, TK_BREAK); + ADD_KEYWORD(continue, TK_CONTINUE); + ADD_KEYWORD(return, TK_RETURN); + ADD_KEYWORD(null, TK_NULL); + ADD_KEYWORD(function, TK_FUNCTION); + ADD_KEYWORD(local, TK_LOCAL); + ADD_KEYWORD(for, TK_FOR); + ADD_KEYWORD(foreach, TK_FOREACH); + ADD_KEYWORD(in, TK_IN); + ADD_KEYWORD(typeof, TK_TYPEOF); + ADD_KEYWORD(delegate, TK_DELEGATE); + ADD_KEYWORD(delete, TK_DELETE); + ADD_KEYWORD(try, TK_TRY); + ADD_KEYWORD(catch, TK_CATCH); + ADD_KEYWORD(throw, TK_THROW); + ADD_KEYWORD(clone, TK_CLONE); + ADD_KEYWORD(yield, TK_YIELD); + ADD_KEYWORD(resume, TK_RESUME); + ADD_KEYWORD(switch, TK_SWITCH); + ADD_KEYWORD(case, TK_CASE); + ADD_KEYWORD(default, TK_DEFAULT); + ADD_KEYWORD(this, TK_THIS); + ADD_KEYWORD(parent,TK_PARENT); + ADD_KEYWORD(class,TK_CLASS); + ADD_KEYWORD(extends,TK_EXTENDS); + ADD_KEYWORD(constructor,TK_CONSTRUCTOR); + ADD_KEYWORD(instanceof,TK_INSTANCEOF); + ADD_KEYWORD(vargc,TK_VARGC); + ADD_KEYWORD(vargv,TK_VARGV); + ADD_KEYWORD(true,TK_TRUE); + ADD_KEYWORD(false,TK_FALSE); + ADD_KEYWORD(static,TK_STATIC); + ADD_KEYWORD(enum,TK_ENUM); + ADD_KEYWORD(const,TK_CONST); + + _readf = rg; + _up = up; + _lasttokenline = _currentline = 1; + _currentcolumn = 0; + _prevtoken = -1; + Next(); +} + +void SQLexer::Error(const SQChar *err) +{ + _errfunc(_errtarget,err); +} + +void SQLexer::Next() +{ + SQInteger t = _readf(_up); + if(t > MAX_CHAR) Error(_SC("Invalid character")); + if(t != 0) { + _currdata = (LexChar)t; + return; + } + _currdata = SQUIRREL_EOB; +} + +const SQChar *SQLexer::Tok2Str(SQInteger tok) +{ + SQObjectPtr itr, key, val; + SQInteger nitr; + while((nitr = _keywords->Next(false,itr, key, val)) != -1) { + itr = (SQInteger)nitr; + if(((SQInteger)_integer(val)) == tok) + return _stringval(key); + } + return NULL; +} + +void SQLexer::LexBlockComment() +{ + bool done = false; + while(!done) { + switch(CUR_CHAR) { + case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue; + case _SC('\n'): _currentline++; NEXT(); continue; + case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment")); + default: NEXT(); + } + } +} + +SQInteger SQLexer::Lex() +{ + _lasttokenline = _currentline; + while(CUR_CHAR != SQUIRREL_EOB) { + switch(CUR_CHAR){ + case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue; + case _SC('\n'): + _currentline++; + _prevtoken=_curtoken; + _curtoken=_SC('\n'); + NEXT(); + _currentcolumn=1; + continue; + case _SC('/'): + NEXT(); + switch(CUR_CHAR){ + case _SC('*'): + NEXT(); + LexBlockComment(); + continue; + case _SC('/'): + do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB())); + continue; + case _SC('='): + NEXT(); + RETURN_TOKEN(TK_DIVEQ); + continue; + case _SC('>'): + NEXT(); + RETURN_TOKEN(TK_ATTR_CLOSE); + continue; + default: + RETURN_TOKEN('/'); + } + case _SC('='): + NEXT(); + if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') } + else { NEXT(); RETURN_TOKEN(TK_EQ); } + case _SC('<'): + NEXT(); + if ( CUR_CHAR == _SC('=') ) { NEXT(); RETURN_TOKEN(TK_LE) } + else if ( CUR_CHAR == _SC('-') ) { NEXT(); RETURN_TOKEN(TK_NEWSLOT); } + else if ( CUR_CHAR == _SC('<') ) { NEXT(); RETURN_TOKEN(TK_SHIFTL); } + else if ( CUR_CHAR == _SC('/') ) { NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); } + //else if ( CUR_CHAR == _SC('[') ) { NEXT(); ReadMultilineString(); RETURN_TOKEN(TK_STRING_LITERAL); } + else { RETURN_TOKEN('<') } + case _SC('>'): + NEXT(); + if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);} + else if(CUR_CHAR == _SC('>')){ + NEXT(); + if(CUR_CHAR == _SC('>')){ + NEXT(); + RETURN_TOKEN(TK_USHIFTR); + } + RETURN_TOKEN(TK_SHIFTR); + } + else { RETURN_TOKEN('>') } + case _SC('!'): + NEXT(); + if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')} + else { NEXT(); RETURN_TOKEN(TK_NE); } + case _SC('@'): { + SQInteger stype; + NEXT(); + if(CUR_CHAR != _SC('"')) + Error(_SC("string expected")); + if((stype=ReadString(_SC('"'),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(SQChar 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(SQChar 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/src/3rdparty/squirrel/squirrel/sqlexer.h b/src/3rdparty/squirrel/squirrel/sqlexer.h new file mode 100644 index 0000000000..4b5ac203c0 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqlexer.h @@ -0,0 +1,45 @@ +/* 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(SQChar ndelim,bool verbatim); + SQInteger ReadNumber(); + void LexBlockComment(); + SQInteger ReadID(); + void Next(); + SQInteger _curtoken; + SQTable *_keywords; +public: + SQInteger _prevtoken; + SQInteger _currentline; + SQInteger _lasttokenline; + SQInteger _currentcolumn; + const SQChar *_svalue; + SQInteger _nvalue; + SQFloat _fvalue; + SQLEXREADFUNC _readf; + SQUserPointer _up; + LexChar _currdata; + SQSharedState *_sharedstate; + sqvector _longstr; + CompilerErrorFunc _errfunc; + void *_errtarget; +}; + +#endif diff --git a/src/3rdparty/squirrel/squirrel/sqmem.cpp b/src/3rdparty/squirrel/squirrel/sqmem.cpp new file mode 100644 index 0000000000..6faf8165ae --- /dev/null +++ b/src/3rdparty/squirrel/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/src/3rdparty/squirrel/squirrel/sqobject.cpp b/src/3rdparty/squirrel/squirrel/sqobject.cpp new file mode 100644 index 0000000000..0455eb7e3d --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqobject.cpp @@ -0,0 +1,587 @@ +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqvm.h" +#include "sqstring.h" +#include "sqarray.h" +#include "sqtable.h" +#include "squserdata.h" +#include "sqfuncproto.h" +#include "sqclass.h" +#include "sqclosure.h" + + +const SQChar *IdType2Name(SQObjectType type) +{ + switch(_RAW_TYPE(type)) + { + case _RT_NULL:return _SC("null"); + case _RT_INTEGER:return _SC("integer"); + case _RT_FLOAT:return _SC("float"); + case _RT_BOOL:return _SC("bool"); + case _RT_STRING:return _SC("string"); + case _RT_TABLE:return _SC("table"); + case _RT_ARRAY:return _SC("array"); + case _RT_GENERATOR:return _SC("generator"); + case _RT_CLOSURE: + case _RT_NATIVECLOSURE: + return _SC("function"); + case _RT_USERDATA: + case _RT_USERPOINTER: + return _SC("userdata"); + case _RT_THREAD: return _SC("thread"); + case _RT_FUNCPROTO: return _SC("function"); + case _RT_CLASS: return _SC("class"); + case _RT_INSTANCE: return _SC("instance"); + case _RT_WEAKREF: return _SC("weakref"); + default: + return NULL; + } +} + +const SQChar *GetTypeName(const SQObjectPtr &obj1) +{ + return IdType2Name(type(obj1)); +} + +SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len) +{ + SQString *str=ADD_STRING(ss,s,len); + str->_sharedstate=ss; + return str; +} + +void SQString::Release() +{ + REMOVE_STRING(_sharedstate,this); +} + +SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval) +{ + SQInteger idx = (SQInteger)TranslateIndex(refpos); + while(idx < _len){ + outkey = (SQInteger)idx; + outval = SQInteger(_val[idx]); + //return idx for the next iteration + return ++idx; + } + //nothing to iterate anymore + return -1; +} + +SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx) +{ + switch(type(idx)){ + case OT_NULL: + return 0; + case OT_INTEGER: + return (SQUnsignedInteger)_integer(idx); + default: assert(0); break; + } + return 0; +} + +SQWeakRef *SQRefCounted::GetWeakRef(SQObjectType type) +{ + if(!_weakref) { + sq_new(_weakref,SQWeakRef); + _weakref->_obj._type = type; + _weakref->_obj._unVal.pRefCounted = this; + } + return _weakref; +} + +SQRefCounted::~SQRefCounted() +{ + if(_weakref) { + _weakref->_obj._type = OT_NULL; + _weakref->_obj._unVal.pRefCounted = NULL; + } +} + +void SQWeakRef::Release() { + if(ISREFCOUNTED(_obj._type)) { + _obj._unVal.pRefCounted->_weakref = NULL; + } + sq_delete(this,SQWeakRef); +} + +bool SQDelegable::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) { + if(_delegate) { + return _delegate->Get((*_ss(v)->_metamethods)[mm],res); + } + return false; +} + +bool SQDelegable::SetDelegate(SQTable *mt) +{ + SQTable *temp = mt; + if(temp == this) return false; + while (temp) { + if (temp->_delegate == this) return false; //cycle detected + temp = temp->_delegate; + } + if (mt) __ObjAddRef(mt); + __ObjRelease(_delegate); + _delegate = mt; + return true; +} + +bool SQGenerator::Yield(SQVM *v) +{ + if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator")); return false;} + if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; } + SQInteger size = v->_top-v->_stackbase; + _ci=*v->ci; + _stack.resize(size); + for(SQInteger n =0; n_stack[v->_stackbase+n]; + v->_stack[v->_stackbase+n] = _null_; + } + SQInteger nvargs = v->ci->_vargs.size; + SQInteger vargsbase = v->ci->_vargs.base; + for(SQInteger j = nvargs - 1; j >= 0; j--) { + _vargsstack.push_back(v->_vargsstack[vargsbase+j]); + } + _ci._generator=NULL; + for(SQInteger i=0;i<_ci._etraps;i++) { + _etraps.push_back(v->_etraps.top()); + v->_etraps.pop_back(); + } + _state=eSuspended; + return true; +} + +bool SQGenerator::Resume(SQVM *v,SQInteger target) +{ + SQInteger size=_stack.size(); + if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; } + if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; } + SQInteger prevtop=v->_top-v->_stackbase; + PUSH_CALLINFO(v,_ci); + SQInteger oldstackbase=v->_stackbase; + v->_stackbase = v->_top; + v->ci->_target = (SQInt32)target; + v->ci->_generator = this; + v->ci->_vargs.size = (unsigned short)_vargsstack.size(); + + for(SQInteger i=0;i<_ci._etraps;i++) { + v->_etraps.push_back(_etraps.top()); + _etraps.pop_back(); + } + for(SQInteger n =0; n_stack[v->_stackbase+n] = _stack._vals[n]; + _stack._vals[0] = _null_; + } + while(_vargsstack.size()) { + v->_vargsstack.push_back(_vargsstack.back()); + _vargsstack.pop_back(); + } + v->ci->_vargs.base = (unsigned short)(v->_vargsstack.size() - v->ci->_vargs.size); + v->_top=v->_stackbase+size; + v->ci->_prevtop = (SQInt32)prevtop; + v->ci->_prevstkbase = (SQInt32)(v->_stackbase - oldstackbase); + _state=eRunning; + if (type(v->_debughook) != OT_NULL && _rawval(v->_debughook) != _rawval(v->ci->_closure)) + v->CallDebugHook(_SC('c')); + + return true; +} + +void SQArray::Extend(const SQArray *a){ + SQInteger xlen; + if((xlen=a->Size())) + for(SQInteger i=0;i_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=nop) + { + if(nseq==0){ + vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]); + res=_stringval(_localvarinfos[i]._name); + break; + } + nseq--; + } + } + } + return res; +} + +SQInteger SQFunctionProto::GetLine(SQInstruction *curr) +{ + SQInteger op = (SQInteger)(curr-_instructions); + SQInteger line=_lineinfos[0]._line; + for(SQInteger i=1;i<_nlineinfos;i++){ + if(_lineinfos[i]._op>=op) + return line; + line=_lineinfos[i]._line; + } + return line; +} + +#define _CHECK_IO(exp) { if(!exp)return false; } +bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size) +{ + if(write(up,dest,size) != size) { + v->Raise_Error(_SC("io error (write function failure)")); + return false; + } + return true; +} + +bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,SQInteger size) +{ + if(size && read(up,dest,size) != size) { + v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated")); + return false; + } + return true; +} + +bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQInteger tag) +{ + return SafeWrite(v,write,up,&tag,sizeof(tag)); +} + +bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQInteger tag) +{ + SQInteger t; + _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t))); + if(t != tag){ + v->Raise_Error(_SC("invalid or corrupted closure stream")); + return false; + } + return true; +} + +bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o) +{ + _CHECK_IO(SafeWrite(v,write,up,&type(o),sizeof(SQObjectType))); + switch(type(o)){ + case OT_STRING: + _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger))); + _CHECK_IO(SafeWrite(v,write,up,_stringval(o),rsl(_string(o)->_len))); + break; + case OT_INTEGER: + _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break; + case OT_FLOAT: + _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break; + case OT_NULL: + break; + default: + v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o)); + return false; + } + return true; +} + +bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o) +{ + SQObjectType t; + _CHECK_IO(SafeRead(v,read,up,&t,sizeof(SQObjectType))); + switch(t){ + case OT_STRING:{ + SQInteger len; + _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger))); + _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(rsl(len)),rsl(len))); + o=SQString::Create(_ss(v),_ss(v)->GetScratchPad(-1),len); + } + break; + case OT_INTEGER:{ + SQInteger i; + _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o = i; break; + } + case OT_FLOAT:{ + SQFloat f; + _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break; + } + case OT_NULL: + o=_null_; + break; + default: + v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t)); + return false; + } + return true; +} + +bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write) +{ + _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD)); + _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar))); + _CHECK_IO(_funcproto(_function)->Save(v,up,write)); + _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL)); + return true; +} + +bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret) +{ + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD)); + _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar))); + SQObjectPtr func; + _CHECK_IO(SQFunctionProto::Load(v,up,read,func)); + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL)); + ret = SQClosure::Create(_ss(v),_funcproto(func)); + return true; +} + +bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write) +{ + SQInteger i,nliterals = _nliterals,nparameters = _nparameters; + SQInteger noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos; + SQInteger nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions; + SQInteger ndefaultparams = _ndefaultparams; + _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(WriteObject(v,up,write,_sourcename)); + _CHECK_IO(WriteObject(v,up,write,_name)); + _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeWrite(v,write,up,&nliterals,sizeof(nliterals))); + _CHECK_IO(SafeWrite(v,write,up,&nparameters,sizeof(nparameters))); + _CHECK_IO(SafeWrite(v,write,up,&noutervalues,sizeof(noutervalues))); + _CHECK_IO(SafeWrite(v,write,up,&nlocalvarinfos,sizeof(nlocalvarinfos))); + _CHECK_IO(SafeWrite(v,write,up,&nlineinfos,sizeof(nlineinfos))); + _CHECK_IO(SafeWrite(v,write,up,&ndefaultparams,sizeof(ndefaultparams))); + _CHECK_IO(SafeWrite(v,write,up,&ninstructions,sizeof(ninstructions))); + _CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions))); + _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART)); + for(i=0;iSave(v,up,write)); + } + _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize))); + _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator))); + _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams))); + return true; +} + +bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret) +{ + SQInteger i, nliterals,nparameters; + SQInteger noutervalues ,nlocalvarinfos ; + SQInteger nlineinfos,ninstructions ,nfunctions,ndefaultparams ; + SQObjectPtr sourcename, name; + SQObjectPtr o; + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(ReadObject(v, up, read, sourcename)); + _CHECK_IO(ReadObject(v, up, read, name)); + + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, &nliterals, sizeof(nliterals))); + _CHECK_IO(SafeRead(v,read,up, &nparameters, sizeof(nparameters))); + _CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues))); + _CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos))); + _CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos))); + _CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams))); + _CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions))); + _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions))); + + + SQFunctionProto *f = SQFunctionProto::Create(ninstructions,nliterals,nparameters, + nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams); + SQObjectPtr proto = f; //gets a ref in case of failure + f->_sourcename = sourcename; + f->_name = name; + + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + + for(i = 0;i < nliterals; i++){ + _CHECK_IO(ReadObject(v, up, read, o)); + f->_literals[i] = o; + } + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + + for(i = 0; i < nparameters; i++){ + _CHECK_IO(ReadObject(v, up, read, o)); + f->_parameters[i] = o; + } + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + + for(i = 0; i < noutervalues; i++){ + SQUnsignedInteger type; + SQObjectPtr name; + _CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger))); + _CHECK_IO(ReadObject(v, up, read, o)); + _CHECK_IO(ReadObject(v, up, read, name)); + f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type); + } + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + + for(i = 0; i < nlocalvarinfos; i++){ + SQLocalVarInfo lvi; + _CHECK_IO(ReadObject(v, up, read, lvi._name)); + _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(SQUnsignedInteger))); + _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(SQUnsignedInteger))); + _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(SQUnsignedInteger))); + f->_localvarinfos[i] = lvi; + } + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(SQLineInfo)*nlineinfos)); + + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(SQInteger)*ndefaultparams)); + + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + _CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(SQInstruction)*ninstructions)); + + _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART)); + for(i = 0; i < nfunctions; i++){ + _CHECK_IO(_funcproto(o)->Load(v, up, read, o)); + f->_functions[i] = o; + } + _CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize))); + _CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator))); + _CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams))); + + ret = f; + return true; +} + +#ifndef NO_GARBAGE_COLLECTOR + +#define START_MARK() if(!(_uiRef&MARK_FLAG)){ \ + _uiRef|=MARK_FLAG; + +#define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \ + AddToChain(chain, this); } + +void SQVM::Mark(SQCollectable **chain) +{ + START_MARK() + SQSharedState::MarkObject(_lasterror,chain); + SQSharedState::MarkObject(_errorhandler,chain); + SQSharedState::MarkObject(_debughook,chain); + SQSharedState::MarkObject(_roottable, chain); + SQSharedState::MarkObject(temp_reg, chain); + for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain); + for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain); + for(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain); + END_MARK() +} + +void SQArray::Mark(SQCollectable **chain) +{ + START_MARK() + SQInteger len = _values.size(); + for(SQInteger i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain); + END_MARK() +} +void SQTable::Mark(SQCollectable **chain) +{ + START_MARK() + if(_delegate) _delegate->Mark(chain); + SQInteger len = _numofnodes; + for(SQInteger i = 0; i < len; i++){ + SQSharedState::MarkObject(_nodes[i].key, chain); + SQSharedState::MarkObject(_nodes[i].val, chain); + } + END_MARK() +} + +void SQClass::Mark(SQCollectable **chain) +{ + START_MARK() + _members->Mark(chain); + if(_base) _base->Mark(chain); + SQSharedState::MarkObject(_attributes, chain); + for(SQUnsignedInteger i =0; i< _defaultvalues.size(); i++) { + SQSharedState::MarkObject(_defaultvalues[i].val, chain); + SQSharedState::MarkObject(_defaultvalues[i].attrs, chain); + } + for(SQUnsignedInteger j =0; j< _methods.size(); j++) { + SQSharedState::MarkObject(_methods[j].val, chain); + SQSharedState::MarkObject(_methods[j].attrs, chain); + } + for(SQUnsignedInteger k =0; k< _metamethods.size(); k++) { + SQSharedState::MarkObject(_metamethods[k], chain); + } + END_MARK() +} + +void SQInstance::Mark(SQCollectable **chain) +{ + START_MARK() + _class->Mark(chain); + SQUnsignedInteger nvalues = _class->_defaultvalues.size(); + for(SQUnsignedInteger i =0; i< nvalues; i++) { + SQSharedState::MarkObject(_values[i], chain); + } + END_MARK() +} + +void SQGenerator::Mark(SQCollectable **chain) +{ + START_MARK() + for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain); + for(SQUnsignedInteger j = 0; j < _vargsstack.size(); j++) SQSharedState::MarkObject(_vargsstack[j], chain); + SQSharedState::MarkObject(_closure, chain); + END_MARK() +} + +void SQClosure::Mark(SQCollectable **chain) +{ + START_MARK() + for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain); + for(SQUnsignedInteger i = 0; i < _defaultparams.size(); i++) SQSharedState::MarkObject(_defaultparams[i], chain); + END_MARK() +} + +void SQNativeClosure::Mark(SQCollectable **chain) +{ + START_MARK() + for(SQUnsignedInteger i = 0; i < _outervalues.size(); i++) SQSharedState::MarkObject(_outervalues[i], chain); + END_MARK() +} + +void SQUserData::Mark(SQCollectable **chain){ + START_MARK() + if(_delegate) _delegate->Mark(chain); + END_MARK() +} + +void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; } + +#endif + diff --git a/src/3rdparty/squirrel/squirrel/sqobject.h b/src/3rdparty/squirrel/squirrel/sqobject.h new file mode 100644 index 0000000000..7deeafb87a --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqobject.h @@ -0,0 +1,352 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQOBJECT_H_ +#define _SQOBJECT_H_ + +#include "squtils.h" + +#define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R')) +#define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T')) +#define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L')) + +struct SQSharedState; + +enum SQMetaMethod{ + MT_ADD=0, + MT_SUB=1, + MT_MUL=2, + MT_DIV=3, + MT_UNM=4, + MT_MODULO=5, + MT_SET=6, + MT_GET=7, + MT_TYPEOF=8, + MT_NEXTI=9, + MT_CMP=10, + MT_CALL=11, + MT_CLONED=12, + MT_NEWSLOT=13, + MT_DELSLOT=14, + MT_TOSTRING=15, + MT_NEWMEMBER=16, + MT_INHERITED=17, + MT_LAST = 18 +}; + +#define MM_ADD _SC("_add") +#define MM_SUB _SC("_sub") +#define MM_MUL _SC("_mul") +#define MM_DIV _SC("_div") +#define MM_UNM _SC("_unm") +#define MM_MODULO _SC("_modulo") +#define MM_SET _SC("_set") +#define MM_GET _SC("_get") +#define MM_TYPEOF _SC("_typeof") +#define MM_NEXTI _SC("_nexti") +#define MM_CMP _SC("_cmp") +#define MM_CALL _SC("_call") +#define MM_CLONED _SC("_cloned") +#define MM_NEWSLOT _SC("_newslot") +#define MM_DELSLOT _SC("_delslot") +#define MM_TOSTRING _SC("_tostring") +#define MM_NEWMEMBER _SC("_newmember") +#define MM_INHERITED _SC("_inherited") + +#define MINPOWER2 4 + +struct SQRefCounted +{ + SQRefCounted() { _uiRef = 0; _weakref = NULL; } + virtual ~SQRefCounted(); + SQWeakRef *GetWeakRef(SQObjectType type); + SQUnsignedInteger _uiRef; + struct SQWeakRef *_weakref; + virtual void Release()=0; +}; + +struct SQWeakRef : SQRefCounted +{ + void Release(); + SQObject _obj; +}; + +#define _realval(o) (type((o)) != OT_WEAKREF?(SQObject)o:_weakref(o)->_obj) + +struct SQObjectPtr; + +#define __AddRef(type,unval) if(ISREFCOUNTED(type)) \ + { \ + unval.pRefCounted->_uiRef++; \ + } + +#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)<=0)) \ + { \ + unval.pRefCounted->Release(); \ + } + +#define __ObjRelease(obj) { \ + if((obj)) { \ + (obj)->_uiRef--; \ + if((obj)->_uiRef == 0) \ + (obj)->Release(); \ + (obj) = NULL; \ + } \ +} + +#define __ObjAddRef(obj) { \ + (obj)->_uiRef++; \ +} + +#define type(obj) ((obj)._type) +#define is_delegable(t) (type(t)&SQOBJECT_DELEGABLE) +#define raw_type(obj) _RAW_TYPE((obj)._type) + +#define _integer(obj) ((obj)._unVal.nInteger) +#define _float(obj) ((obj)._unVal.fFloat) +#define _string(obj) ((obj)._unVal.pString) +#define _table(obj) ((obj)._unVal.pTable) +#define _array(obj) ((obj)._unVal.pArray) +#define _closure(obj) ((obj)._unVal.pClosure) +#define _generator(obj) ((obj)._unVal.pGenerator) +#define _nativeclosure(obj) ((obj)._unVal.pNativeClosure) +#define _userdata(obj) ((obj)._unVal.pUserData) +#define _userpointer(obj) ((obj)._unVal.pUserPointer) +#define _thread(obj) ((obj)._unVal.pThread) +#define _funcproto(obj) ((obj)._unVal.pFunctionProto) +#define _class(obj) ((obj)._unVal.pClass) +#define _instance(obj) ((obj)._unVal.pInstance) +#define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable) +#define _weakref(obj) ((obj)._unVal.pWeakRef) +#define _refcounted(obj) ((obj)._unVal.pRefCounted) +#define _rawval(obj) ((obj)._unVal.pRefCounted) + +#define _stringval(obj) (obj)._unVal.pString->_val +#define _userdataval(obj) (obj)._unVal.pUserData->_val + +#define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num)) +#define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num)) +///////////////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////////////// +struct SQObjectPtr : public SQObject +{ + SQObjectPtr() + { + _type=OT_NULL; + _unVal.pUserPointer=NULL; + } + SQObjectPtr(const SQObjectPtr &o) + { + _type=o._type; + _unVal=o._unVal; + __AddRef(_type,_unVal); + } + SQObjectPtr(const SQObject &o) + { + _type=o._type; + _unVal=o._unVal; + __AddRef(_type,_unVal); + } + SQObjectPtr(SQTable *pTable) + { + _type=OT_TABLE; + _unVal.pTable=pTable; + assert(_unVal.pTable); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQClass *pClass) + { + _type=OT_CLASS; + _unVal.pClass=pClass; + assert(_unVal.pClass); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQInstance *pInstance) + { + _type=OT_INSTANCE; + _unVal.pInstance=pInstance; + assert(_unVal.pInstance); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQArray *pArray) + { + _type=OT_ARRAY; + _unVal.pArray=pArray; + assert(_unVal.pArray); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQClosure *pClosure) + { + _type=OT_CLOSURE; + _unVal.pClosure=pClosure; + assert(_unVal.pClosure); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQGenerator *pGenerator) + { + _type=OT_GENERATOR; + _unVal.pGenerator=pGenerator; + assert(_unVal.pGenerator); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQNativeClosure *pNativeClosure) + { + _type=OT_NATIVECLOSURE; + _unVal.pNativeClosure=pNativeClosure; + assert(_unVal.pNativeClosure); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQString *pString) + { + _type=OT_STRING; + _unVal.pString=pString; + assert(_unVal.pString); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQUserData *pUserData) + { + _type=OT_USERDATA; + _unVal.pUserData=pUserData; + assert(_unVal.pUserData); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQVM *pThread) + { + _type=OT_THREAD; + _unVal.pThread=pThread; + assert(_unVal.pThread); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQWeakRef *pWeakRef) + { + _type=OT_WEAKREF; + _unVal.pWeakRef=pWeakRef; + assert(_unVal.pWeakRef); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQFunctionProto *pFunctionProto) + { + _type=OT_FUNCPROTO; + _unVal.pFunctionProto=pFunctionProto; + assert(_unVal.pFunctionProto); + __AddRef(_type,_unVal); + } + SQObjectPtr(SQInteger nInteger) + { + _unVal.pUserPointer=NULL; + _type=OT_INTEGER; + _unVal.nInteger=nInteger; + } + SQObjectPtr(SQFloat fFloat) + { + _unVal.pUserPointer=NULL; + _type=OT_FLOAT; + _unVal.fFloat=fFloat; + } + SQObjectPtr(bool bBool) + { + _unVal.pUserPointer=NULL; + _type = OT_BOOL; + _unVal.nInteger = bBool?1:0; + } + SQObjectPtr(SQUserPointer pUserPointer) + { + _type=OT_USERPOINTER; + _unVal.pUserPointer=pUserPointer; + } + ~SQObjectPtr() + { + __Release(_type,_unVal); + } + inline void Null() + { + SQObjectType tOldType; + SQObjectValue unOldVal; + tOldType = _type; + unOldVal = _unVal; + _type = OT_NULL; + _unVal.pUserPointer = NULL; + __Release(tOldType,unOldVal); + } + inline SQObjectPtr& operator=(SQInteger i) + { + __Release(_type,_unVal); + _unVal.nInteger = i; + _type = OT_INTEGER; + return *this; + } + inline SQObjectPtr& operator=(SQFloat f) + { + __Release(_type,_unVal); + _unVal.fFloat = f; + _type = OT_FLOAT; + return *this; + } + inline SQObjectPtr& operator=(const SQObjectPtr& obj) + { + SQObjectType tOldType; + SQObjectValue unOldVal; + tOldType=_type; + unOldVal=_unVal; + _unVal = obj._unVal; + _type = obj._type; + __AddRef(_type,_unVal); + __Release(tOldType,unOldVal); + return *this; + } + inline SQObjectPtr& operator=(const SQObject& obj) + { + SQObjectType tOldType; + SQObjectValue unOldVal; + tOldType=_type; + unOldVal=_unVal; + _unVal = obj._unVal; + _type = obj._type; + __AddRef(_type,_unVal); + __Release(tOldType,unOldVal); + return *this; + } + private: + SQObjectPtr(const SQChar *){} //safety +}; +///////////////////////////////////////////////////////////////////////////////////// +#ifndef NO_GARBAGE_COLLECTOR +#define MARK_FLAG 0x80000000 +struct SQCollectable : public SQRefCounted { + SQCollectable *_next; + SQCollectable *_prev; + SQSharedState *_sharedstate; + virtual void Release()=0; + virtual void Mark(SQCollectable **chain)=0; + void UnMark(); + virtual void Finalize()=0; + static void AddToChain(SQCollectable **chain,SQCollectable *c); + static void RemoveFromChain(SQCollectable **chain,SQCollectable *c); +}; + + +#define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj) +#define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);} +#define CHAINABLE_OBJ SQCollectable +#define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;} +#else + +#define ADD_TO_CHAIN(chain,obj) ((void)0) +#define REMOVE_FROM_CHAIN(chain,obj) ((void)0) +#define CHAINABLE_OBJ SQRefCounted +#define INIT_CHAIN() ((void)0) +#endif + +struct SQDelegable : public CHAINABLE_OBJ { + bool SetDelegate(SQTable *m); + virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res); + SQTable *_delegate; +}; + +SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx); +typedef sqvector SQObjectPtrVec; +typedef sqvector SQIntVec; +const SQChar *GetTypeName(const SQObjectPtr &obj1); +const SQChar *IdType2Name(SQObjectType type); + + + +#endif //_SQOBJECT_H_ diff --git a/src/3rdparty/squirrel/squirrel/sqopcodes.h b/src/3rdparty/squirrel/squirrel/sqopcodes.h new file mode 100644 index 0000000000..d20ef4f3f5 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqopcodes.h @@ -0,0 +1,116 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQOPCODES_H_ +#define _SQOPCODES_H_ + +#define MAX_FUNC_STACKSIZE 0xFF +#define MAX_LITERALS ((SQInteger)0x7FFFFFFF) + +enum BitWiseOP { + BW_AND = 0, + BW_OR = 2, + BW_XOR = 3, + BW_SHIFTL = 4, + BW_SHIFTR = 5, + BW_USHIFTR = 6 +}; + +enum CmpOP { + CMP_G = 0, + CMP_GE = 2, + CMP_L = 3, + CMP_LE = 4 +}; +enum SQOpcode +{ + _OP_LINE= 0x00, + _OP_LOAD= 0x01, + _OP_LOADINT= 0x02, + _OP_LOADFLOAT= 0x03, + _OP_DLOAD= 0x04, + _OP_TAILCALL= 0x05, + _OP_CALL= 0x06, + _OP_PREPCALL= 0x07, + _OP_PREPCALLK= 0x08, + _OP_GETK= 0x09, + _OP_MOVE= 0x0A, + _OP_NEWSLOT= 0x0B, + _OP_DELETE= 0x0C, + _OP_SET= 0x0D, + _OP_GET= 0x0E, + _OP_EQ= 0x0F, + _OP_NE= 0x10, + _OP_ARITH= 0x11, + _OP_BITW= 0x12, + _OP_RETURN= 0x13, + _OP_LOADNULLS= 0x14, + _OP_LOADROOTTABLE= 0x15, + _OP_LOADBOOL= 0x16, + _OP_DMOVE= 0x17, + _OP_JMP= 0x18, + _OP_JNZ= 0x19, + _OP_JZ= 0x1A, + _OP_LOADFREEVAR= 0x1B, + _OP_VARGC= 0x1C, + _OP_GETVARGV= 0x1D, + _OP_NEWTABLE= 0x1E, + _OP_NEWARRAY= 0x1F, + _OP_APPENDARRAY= 0x20, + _OP_GETPARENT= 0x21, + _OP_COMPARITH= 0x22, + _OP_COMPARITHL= 0x23, + _OP_INC= 0x24, + _OP_INCL= 0x25, + _OP_PINC= 0x26, + _OP_PINCL= 0x27, + _OP_CMP= 0x28, + _OP_EXISTS= 0x29, + _OP_INSTANCEOF= 0x2A, + _OP_AND= 0x2B, + _OP_OR= 0x2C, + _OP_NEG= 0x2D, + _OP_NOT= 0x2E, + _OP_BWNOT= 0x2F, + _OP_CLOSURE= 0x30, + _OP_YIELD= 0x31, + _OP_RESUME= 0x32, + _OP_FOREACH= 0x33, + _OP_POSTFOREACH= 0x34, + _OP_DELEGATE= 0x35, + _OP_CLONE= 0x36, + _OP_TYPEOF= 0x37, + _OP_PUSHTRAP= 0x38, + _OP_POPTRAP= 0x39, + _OP_THROW= 0x3A, + _OP_CLASS= 0x3B, + _OP_NEWSLOTA= 0x3C, + _OP_SCOPE_END= 0x3D, +}; + +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 SQInstructionVec; + +#define NEW_SLOT_ATTRIBUTES_FLAG 0x01 +#define NEW_SLOT_STATIC_FLAG 0x02 + +#endif // _SQOPCODES_H_ diff --git a/src/3rdparty/squirrel/squirrel/sqpcheader.h b/src/3rdparty/squirrel/squirrel/sqpcheader.h new file mode 100644 index 0000000000..db49f5e0d1 --- /dev/null +++ b/src/3rdparty/squirrel/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 +#endif + +#include +#include +#include +#include +#include +//squirrel stuff +#include +#include "sqobject.h" +#include "sqstate.h" + +#endif //_SQPCHEADER_H_ diff --git a/src/3rdparty/squirrel/squirrel/sqstate.cpp b/src/3rdparty/squirrel/squirrel/sqstate.cpp new file mode 100644 index 0000000000..5532625432 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqstate.cpp @@ -0,0 +1,572 @@ +/* + see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqopcodes.h" +#include "sqvm.h" +#include "sqfuncproto.h" +#include "sqclosure.h" +#include "sqstring.h" +#include "sqtable.h" +#include "sqarray.h" +#include "squserdata.h" +#include "sqclass.h" + +SQObjectPtr _null_; +SQObjectPtr _true_(true); +SQObjectPtr _false_(false); +SQObjectPtr _one_((SQInteger)1); +SQObjectPtr _minusone_((SQInteger)-1); + +SQSharedState::SQSharedState() +{ + _compilererrorhandler = NULL; + _printfunc = NULL; + _debuginfo = false; + _notifyallexceptions = false; +} + +#define newsysstring(s) { \ + _systemstrings->push_back(SQString::Create(this,s)); \ + } + +#define newmetamethod(s) { \ + _metamethods->push_back(SQString::Create(this,s)); \ + _table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \ + } + +bool CompileTypemask(SQIntVec &res,const SQChar *typemask) +{ + SQInteger i = 0; + + SQInteger mask = 0; + while(typemask[i] != 0) { + + switch(typemask[i]){ + case 'o': mask |= _RT_NULL; break; + case 'i': mask |= _RT_INTEGER; break; + case 'f': mask |= _RT_FLOAT; break; + case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break; + case 's': mask |= _RT_STRING; break; + case 't': mask |= _RT_TABLE; break; + case 'a': mask |= _RT_ARRAY; break; + case 'u': mask |= _RT_USERDATA; break; + case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break; + case 'b': mask |= _RT_BOOL; break; + case 'g': mask |= _RT_GENERATOR; break; + case 'p': mask |= _RT_USERPOINTER; break; + case 'v': mask |= _RT_THREAD; break; + case 'x': mask |= _RT_INSTANCE; break; + case 'y': mask |= _RT_CLASS; break; + case 'r': mask |= _RT_WEAKREF; break; + case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue; + case ' ': i++; continue; //ignores spaces + default: + return false; + } + i++; + if(typemask[i] == '|') { + i++; + if(typemask[i] == 0) + return false; + continue; + } + res.push_back(mask); + mask = 0; + + } + return true; +} + +SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz) +{ + SQInteger i=0; + SQTable *t=SQTable::Create(ss,0); + while(funcz[i].name!=0){ + SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f); + nc->_nparamscheck = funcz[i].nparamscheck; + nc->_name = SQString::Create(ss,funcz[i].name); + if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask)) + return NULL; + t->NewSlot(SQString::Create(ss,funcz[i].name),nc); + i++; + } + return t; +} + +void SQSharedState::Init() +{ + _scratchpad=NULL; + _scratchpadsize=0; +#ifndef NO_GARBAGE_COLLECTOR + _gc_chain=NULL; +#endif + sq_new(_stringtable,StringTable); + sq_new(_metamethods,SQObjectPtrVec); + sq_new(_systemstrings,SQObjectPtrVec); + sq_new(_types,SQObjectPtrVec); + _metamethodsmap = SQTable::Create(this,MT_LAST-1); + //adding type strings to avoid memory trashing + //types names + newsysstring(_SC("null")); + newsysstring(_SC("table")); + newsysstring(_SC("array")); + newsysstring(_SC("closure")); + newsysstring(_SC("string")); + newsysstring(_SC("userdata")); + newsysstring(_SC("integer")); + newsysstring(_SC("float")); + newsysstring(_SC("userpointer")); + newsysstring(_SC("function")); + newsysstring(_SC("generator")); + newsysstring(_SC("thread")); + newsysstring(_SC("class")); + newsysstring(_SC("instance")); + newsysstring(_SC("bool")); + //meta methods + newmetamethod(MM_ADD); + newmetamethod(MM_SUB); + newmetamethod(MM_MUL); + newmetamethod(MM_DIV); + newmetamethod(MM_UNM); + newmetamethod(MM_MODULO); + newmetamethod(MM_SET); + newmetamethod(MM_GET); + newmetamethod(MM_TYPEOF); + newmetamethod(MM_NEXTI); + newmetamethod(MM_CMP); + newmetamethod(MM_CALL); + newmetamethod(MM_CLONED); + newmetamethod(MM_NEWSLOT); + newmetamethod(MM_DELSLOT); + newmetamethod(MM_TOSTRING); + newmetamethod(MM_NEWMEMBER); + newmetamethod(MM_INHERITED); + + _constructoridx = SQString::Create(this,_SC("constructor")); + _registry = SQTable::Create(this,0); + _consts = SQTable::Create(this,0); + _table_default_delegate = CreateDefaultDelegate(this,_table_default_delegate_funcz); + _array_default_delegate = CreateDefaultDelegate(this,_array_default_delegate_funcz); + _string_default_delegate = CreateDefaultDelegate(this,_string_default_delegate_funcz); + _number_default_delegate = CreateDefaultDelegate(this,_number_default_delegate_funcz); + _closure_default_delegate = CreateDefaultDelegate(this,_closure_default_delegate_funcz); + _generator_default_delegate = CreateDefaultDelegate(this,_generator_default_delegate_funcz); + _thread_default_delegate = CreateDefaultDelegate(this,_thread_default_delegate_funcz); + _class_default_delegate = CreateDefaultDelegate(this,_class_default_delegate_funcz); + _instance_default_delegate = CreateDefaultDelegate(this,_instance_default_delegate_funcz); + _weakref_default_delegate = CreateDefaultDelegate(this,_weakref_default_delegate_funcz); + +} + +SQSharedState::~SQSharedState() +{ + _constructoridx = _null_; + _table(_registry)->Finalize(); + _table(_consts)->Finalize(); + _table(_metamethodsmap)->Finalize(); + _registry = _null_; + _consts = _null_; + _metamethodsmap = _null_; + while(!_systemstrings->empty()) { + _systemstrings->back()=_null_; + _systemstrings->pop_back(); + } + _thread(_root_vm)->Finalize(); + _root_vm = _null_; + _table_default_delegate = _null_; + _array_default_delegate = _null_; + _string_default_delegate = _null_; + _number_default_delegate = _null_; + _closure_default_delegate = _null_; + _generator_default_delegate = _null_; + _thread_default_delegate = _null_; + _class_default_delegate = _null_; + _instance_default_delegate = _null_; + _weakref_default_delegate = _null_; + _refs_table.Finalize(); +#ifndef NO_GARBAGE_COLLECTOR + SQCollectable *t = _gc_chain; + SQCollectable *nx = NULL; + while(t) { + t->_uiRef++; + t->Finalize(); + nx = t->_next; + if(--t->_uiRef == 0) + t->Release(); + t=nx; + } +// assert(_gc_chain==NULL); //just to proove a theory + while(_gc_chain){ + _gc_chain->_uiRef++; + _gc_chain->Release(); + } +#endif + + sq_delete(_types,SQObjectPtrVec); + sq_delete(_systemstrings,SQObjectPtrVec); + sq_delete(_metamethods,SQObjectPtrVec); + sq_delete(_stringtable,StringTable); + if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize); +} + + +SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name) +{ + if(type(name) != OT_STRING) + return -1; + SQObjectPtr ret; + if(_table(_metamethodsmap)->Get(name,ret)) { + return _integer(ret); + } + return -1; +} + +#ifndef NO_GARBAGE_COLLECTOR + +void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain) +{ + switch(type(o)){ + case OT_TABLE:_table(o)->Mark(chain);break; + case OT_ARRAY:_array(o)->Mark(chain);break; + case OT_USERDATA:_userdata(o)->Mark(chain);break; + case OT_CLOSURE:_closure(o)->Mark(chain);break; + case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break; + case OT_GENERATOR:_generator(o)->Mark(chain);break; + case OT_THREAD:_thread(o)->Mark(chain);break; + case OT_CLASS:_class(o)->Mark(chain);break; + case OT_INSTANCE:_instance(o)->Mark(chain);break; + default: break; //shutup compiler + } +} + + +SQInteger SQSharedState::CollectGarbage(SQVM *vm) +{ + SQInteger n=0; + SQCollectable *tchain=NULL; + SQVM *vms = _thread(_root_vm); + + vms->Mark(&tchain); + SQInteger x = _table(_thread(_root_vm)->_roottable)->CountUsed(); + _refs_table.Mark(&tchain); + MarkObject(_registry,&tchain); + MarkObject(_consts,&tchain); + MarkObject(_metamethodsmap,&tchain); + MarkObject(_table_default_delegate,&tchain); + MarkObject(_array_default_delegate,&tchain); + MarkObject(_string_default_delegate,&tchain); + MarkObject(_number_default_delegate,&tchain); + MarkObject(_generator_default_delegate,&tchain); + MarkObject(_thread_default_delegate,&tchain); + MarkObject(_closure_default_delegate,&tchain); + MarkObject(_class_default_delegate,&tchain); + MarkObject(_instance_default_delegate,&tchain); + MarkObject(_weakref_default_delegate,&tchain); + + SQCollectable *t = _gc_chain; + SQCollectable *nx = NULL; + while(t) { + t->_uiRef++; + t->Finalize(); + nx = t->_next; + if(--t->_uiRef == 0) + t->Release(); + t = nx; + n++; + } + + t = tchain; + while(t) { + t->UnMark(); + t = t->_next; + } + _gc_chain = tchain; + SQInteger z = _table(_thread(_root_vm)->_roottable)->CountUsed(); + assert(z == x); + return n; +} +#endif + +#ifndef NO_GARBAGE_COLLECTOR +void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c) +{ + c->_prev = NULL; + c->_next = *chain; + if(*chain) (*chain)->_prev = c; + *chain = c; +} + +void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c) +{ + if(c->_prev) c->_prev->_next = c->_next; + else *chain = c->_next; + if(c->_next) + c->_next->_prev = c->_prev; + c->_next = NULL; + c->_prev = NULL; +} +#endif + +SQChar* SQSharedState::GetScratchPad(SQInteger size) +{ + SQInteger newsize; + if(size>0) { + if(_scratchpadsize < size) { + newsize = size + (size>>1); + _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize); + _scratchpadsize = newsize; + + }else if(_scratchpadsize >= (size<<5)) { + newsize = _scratchpadsize >> 1; + _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize); + _scratchpadsize = newsize; + } + } + return _scratchpad; +} + +RefTable::RefTable() +{ + AllocNodes(4); +} + +void RefTable::Finalize() +{ + RefNode *nodes = _nodes; + for(SQUnsignedInteger n = 0; n < _numofslots; n++) { + nodes->obj = _null_; + nodes++; + } +} + +RefTable::~RefTable() +{ + SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode))); +} + +#ifndef NO_GARBAGE_COLLECTOR +void RefTable::Mark(SQCollectable **chain) +{ + RefNode *nodes = (RefNode *)_nodes; + for(SQUnsignedInteger n = 0; n < _numofslots; n++) { + if(type(nodes->obj) != OT_NULL) { + SQSharedState::MarkObject(nodes->obj,chain); + } + nodes++; + } +} +#endif + +void RefTable::AddRef(SQObject &obj) +{ + SQHash mainpos; + RefNode *prev; + RefNode *ref = Get(obj,mainpos,&prev,true); + ref->refs++; +} + +SQBool RefTable::Release(SQObject &obj) +{ + SQHash mainpos; + RefNode *prev; + RefNode *ref = Get(obj,mainpos,&prev,false); + if(ref) { + if(--ref->refs == 0) { + SQObjectPtr o = ref->obj; + if(prev) { + prev->next = ref->next; + } + else { + _buckets[mainpos] = ref->next; + } + ref->next = _freelist; + _freelist = ref; + _slotused--; + ref->obj = _null_; + //<>test for shrink? + return SQTrue; + } + } + else { + assert(0); + } + return SQFalse; +} + +void RefTable::Resize(SQUnsignedInteger size) +{ + RefNode **oldbucks = _buckets; + RefNode *t = _nodes; + SQUnsignedInteger oldnumofslots = _numofslots; + AllocNodes(size); + //rehash + SQUnsignedInteger nfound = 0; + for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) { + if(type(t->obj) != OT_NULL) { + //add back; + assert(t->refs != 0); + RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj); + nn->refs = t->refs; + t->obj = _null_; + nfound++; + } + t++; + } + assert(nfound == oldnumofslots); + SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode))); +} + +RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj) +{ + RefNode *t = _buckets[mainpos]; + RefNode *newnode = _freelist; + newnode->obj = obj; + _buckets[mainpos] = newnode; + _freelist = _freelist->next; + newnode->next = t; + assert(newnode->refs == 0); + _slotused++; + return newnode; +} + +RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add) +{ + RefNode *ref; + mainpos = ::HashObj(obj)&(_numofslots-1); + *prev = NULL; + for (ref = _buckets[mainpos]; ref; ) { + if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj)) + break; + *prev = ref; + ref = ref->next; + } + if(ref == NULL && add) { + if(_numofslots == _slotused) { + assert(_freelist == 0); + Resize(_numofslots*2); + mainpos = ::HashObj(obj)&(_numofslots-1); + } + ref = Add(mainpos,obj); + } + return ref; +} + +void RefTable::AllocNodes(SQUnsignedInteger size) +{ + RefNode **bucks; + RefNode *nodes; + bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode))); + nodes = (RefNode *)&bucks[size]; + RefNode *temp = nodes; + SQUnsignedInteger n; + for(n = 0; n < size - 1; n++) { + bucks[n] = NULL; + temp->refs = 0; + new (&temp->obj) SQObjectPtr; + temp->next = temp+1; + temp++; + } + bucks[n] = NULL; + temp->refs = 0; + new (&temp->obj) SQObjectPtr; + temp->next = NULL; + _freelist = nodes; + _nodes = nodes; + _buckets = bucks; + _slotused = 0; + _numofslots = size; +} +////////////////////////////////////////////////////////////////////////// +//StringTable +/* +* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.) +* http://www.lua.org/copyright.html#4 +* http://www.lua.org/source/4.0.1/src_lstring.c.html +*/ + +StringTable::StringTable() +{ + AllocNodes(4); + _slotused = 0; +} + +StringTable::~StringTable() +{ + SQ_FREE(_strings,sizeof(SQString*)*_numofslots); + _strings = NULL; +} + +void StringTable::AllocNodes(SQInteger size) +{ + _numofslots = size; + _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots); + memset(_strings,0,sizeof(SQString*)*_numofslots); +} + +SQString *StringTable::Add(const SQChar *news,SQInteger len) +{ + if(len<0) + len = (SQInteger)scstrlen(news); + SQHash h = ::_hashstr(news,len)&(_numofslots-1); + SQString *s; + for (s = _strings[h]; s; s = s->_next){ + if(s->_len == len && (!memcmp(news,s->_val,rsl(len)))) + return s; //found + } + + SQString *t=(SQString *)SQ_MALLOC(rsl(len)+sizeof(SQString)); + new (t) SQString; + memcpy(t->_val,news,rsl(len)); + t->_val[len] = _SC('\0'); + t->_len = len; + t->_hash = ::_hashstr(news,len); + t->_next = _strings[h]; + _strings[h] = t; + _slotused++; + if (_slotused > _numofslots) /* too crowded? */ + Resize(_numofslots*2); + return t; +} + +void StringTable::Resize(SQInteger size) +{ + SQInteger oldsize=_numofslots; + SQString **oldtable=_strings; + AllocNodes(size); + for (SQInteger i=0; i_next; + SQHash h = p->_hash&(_numofslots-1); + p->_next = _strings[h]; + _strings[h] = p; + p = next; + } + } + SQ_FREE(oldtable,oldsize*sizeof(SQString*)); +} + +void StringTable::Remove(SQString *bs) +{ + SQString *s; + SQString *prev=NULL; + SQHash h = bs->_hash&(_numofslots - 1); + + for (s = _strings[h]; s; ){ + if(s == bs){ + if(prev) + prev->_next = s->_next; + else + _strings[h] = s->_next; + _slotused--; + SQInteger slen = s->_len; + s->~SQString(); + SQ_FREE(s,sizeof(SQString) + rsl(slen)); + return; + } + prev = s; + s = s->_next; + } + assert(0);//if this fail something is wrong +} diff --git a/src/3rdparty/squirrel/squirrel/sqstate.h b/src/3rdparty/squirrel/squirrel/sqstate.h new file mode 100644 index 0000000000..8ddd2254e2 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqstate.h @@ -0,0 +1,143 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQSTATE_H_ +#define _SQSTATE_H_ + +#include "squtils.h" +#include "sqobject.h" +struct SQString; +struct SQTable; +//max number of character for a printed number +#define NUMBER_MAX_CHAR 50 + +struct StringTable +{ + StringTable(); + ~StringTable(); + SQString *Add(const SQChar *,SQInteger len); + void Remove(SQString *); +private: + void Resize(SQInteger size); + void AllocNodes(SQInteger size); + SQString **_strings; + SQUnsignedInteger _numofslots; + SQUnsignedInteger _slotused; +}; + +struct RefTable { + struct RefNode { + SQObjectPtr obj; + SQUnsignedInteger refs; + struct RefNode *next; + }; + RefTable(); + ~RefTable(); + void AddRef(SQObject &obj); + SQBool Release(SQObject &obj); +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); +#endif + void Finalize(); +private: + RefNode *Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add); + RefNode *Add(SQHash mainpos,SQObject &obj); + void Resize(SQUnsignedInteger size); + void AllocNodes(SQUnsignedInteger size); + SQUnsignedInteger _numofslots; + SQUnsignedInteger _slotused; + RefNode *_nodes; + RefNode *_freelist; + RefNode **_buckets; +}; + +#define ADD_STRING(ss,str,len) ss->_stringtable->Add(str,len) +#define REMOVE_STRING(ss,bstr) ss->_stringtable->Remove(bstr) + +struct SQObjectPtr; + +struct SQSharedState +{ + SQSharedState(); + ~SQSharedState(); + void Init(); +public: + SQChar* GetScratchPad(SQInteger size); + SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name); +#ifndef NO_GARBAGE_COLLECTOR + SQInteger CollectGarbage(SQVM *vm); + static void MarkObject(SQObjectPtr &o,SQCollectable **chain); +#endif + SQObjectPtrVec *_metamethods; + SQObjectPtr _metamethodsmap; + SQObjectPtrVec *_systemstrings; + SQObjectPtrVec *_types; + StringTable *_stringtable; + RefTable _refs_table; + SQObjectPtr _registry; + SQObjectPtr _consts; + SQObjectPtr _constructoridx; +#ifndef NO_GARBAGE_COLLECTOR + SQCollectable *_gc_chain; +#endif + SQObjectPtr _root_vm; + SQObjectPtr _table_default_delegate; + static SQRegFunction _table_default_delegate_funcz[]; + SQObjectPtr _array_default_delegate; + static SQRegFunction _array_default_delegate_funcz[]; + SQObjectPtr _string_default_delegate; + static SQRegFunction _string_default_delegate_funcz[]; + SQObjectPtr _number_default_delegate; + static SQRegFunction _number_default_delegate_funcz[]; + SQObjectPtr _generator_default_delegate; + static SQRegFunction _generator_default_delegate_funcz[]; + SQObjectPtr _closure_default_delegate; + static SQRegFunction _closure_default_delegate_funcz[]; + SQObjectPtr _thread_default_delegate; + static SQRegFunction _thread_default_delegate_funcz[]; + SQObjectPtr _class_default_delegate; + static SQRegFunction _class_default_delegate_funcz[]; + SQObjectPtr _instance_default_delegate; + static SQRegFunction _instance_default_delegate_funcz[]; + SQObjectPtr _weakref_default_delegate; + static SQRegFunction _weakref_default_delegate_funcz[]; + + SQCOMPILERERROR _compilererrorhandler; + SQPRINTFUNCTION _printfunc; + bool _debuginfo; + bool _notifyallexceptions; +private: + SQChar *_scratchpad; + SQInteger _scratchpadsize; +}; + +#define _sp(s) (_sharedstate->GetScratchPad(s)) +#define _spval (_sharedstate->GetScratchPad(-1)) + +#define _table_ddel _table(_sharedstate->_table_default_delegate) +#define _array_ddel _table(_sharedstate->_array_default_delegate) +#define _string_ddel _table(_sharedstate->_string_default_delegate) +#define _number_ddel _table(_sharedstate->_number_default_delegate) +#define _generator_ddel _table(_sharedstate->_generator_default_delegate) +#define _closure_ddel _table(_sharedstate->_closure_default_delegate) +#define _thread_ddel _table(_sharedstate->_thread_default_delegate) +#define _class_ddel _table(_sharedstate->_class_default_delegate) +#define _instance_ddel _table(_sharedstate->_instance_default_delegate) +#define _weakref_ddel _table(_sharedstate->_weakref_default_delegate) + +#ifdef SQUNICODE //rsl REAL STRING LEN +#define rsl(l) ((l)<<1) +#else +#define rsl(l) (l) +#endif + +extern SQObjectPtr _null_; +extern SQObjectPtr _true_; +extern SQObjectPtr _false_; +extern SQObjectPtr _one_; +extern SQObjectPtr _minusone_; + +bool CompileTypemask(SQIntVec &res,const SQChar *typemask); + +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/src/3rdparty/squirrel/squirrel/sqstring.h b/src/3rdparty/squirrel/squirrel/sqstring.h new file mode 100644 index 0000000000..14f09e1b0f --- /dev/null +++ b/src/3rdparty/squirrel/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/src/3rdparty/squirrel/squirrel/sqtable.cpp b/src/3rdparty/squirrel/squirrel/sqtable.cpp new file mode 100644 index 0000000000..bb5feba3e7 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqtable.cpp @@ -0,0 +1,196 @@ +/* +see copyright notice in squirrel.h +*/ +#include "sqpcheader.h" +#include "sqvm.h" +#include "sqtable.h" +#include "sqfuncproto.h" +#include "sqclosure.h" + +SQTable::SQTable(SQSharedState *ss,SQInteger nInitialSize) +{ + SQInteger pow2size=MINPOWER2; + while(nInitialSize>pow2size)pow2size=pow2size<<1; + AllocNodes(pow2size); + _usednodes = 0; + _delegate = NULL; + INIT_CHAIN(); + ADD_TO_CHAIN(&_sharedstate->_gc_chain,this); +} + +void SQTable::Remove(const SQObjectPtr &key) +{ + + _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); + if (n) { + n->val = n->key = _null_; + _usednodes--; + Rehash(false); + } +} + +void SQTable::AllocNodes(SQInteger nSize) +{ + _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize); + for(SQInteger i=0;i= 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; ikey) != OT_NULL) + NewSlot(old->key,old->val); + } + for(SQInteger k=0;kNewSlot(key,val); + } + nt->SetDelegate(_delegate); + return nt; +} + +bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val) +{ + if(type(key) == OT_NULL) + return false; + _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); + if (n) { + val = _realval(n->val); + return true; + } + return false; +} +bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val) +{ + assert(type(key) != OT_NULL); + SQHash h = HashObj(key) & (_numofnodes - 1); + _HashNode *n = _Get(key, h); + if (n) { + n->val = val; + return false; + } + _HashNode *mp = &_nodes[h]; + n = mp; + + + //key not found I'll insert it + //main pos is not free + + if(type(mp->key) != OT_NULL) { + n = _firstfree; /* get a free place */ + SQHash mph = HashObj(mp->key) & (_numofnodes - 1); + _HashNode *othern; /* main position of colliding node */ + + if (mp > n && (othern = &_nodes[mph]) != mp){ + /* yes; move colliding node into free position */ + while (othern->next != mp){ + assert(othern->next != NULL); + othern = othern->next; /* find previous */ + } + othern->next = n; /* redo the chain with `n' in place of `mp' */ + n->key = mp->key; + n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */ + n->next = mp->next; + mp->key = _null_; + mp->val = _null_; + mp->next = NULL; /* now `mp' is free */ + } + else{ + /* new node will go into free position */ + n->next = mp->next; /* chain new position */ + mp->next = n; + mp = n; + } + } + mp->key = key; + + for (;;) { /* correct `firstfree' */ + if (type(_firstfree->key) == OT_NULL && _firstfree->next == NULL) { + mp->val = val; + _usednodes++; + return true; /* OK; table still has a free place */ + } + else if (_firstfree == _nodes) break; /* cannot decrement from here */ + else (_firstfree)--; + } + Rehash(true); + return NewSlot(key, val); +} + +SQInteger SQTable::Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval) +{ + SQInteger idx = (SQInteger)TranslateIndex(refpos); + while (idx < _numofnodes) { + if(type(_nodes[idx].key) != OT_NULL) { + //first found + _HashNode &n = _nodes[idx]; + outkey = n.key; + outval = getweakrefs?(SQObject)n.val:_realval(n.val); + //return idx for the next iteration + return ++idx; + } + ++idx; + } + //nothing to iterate anymore + return -1; +} + + +bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val) +{ + _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1)); + if (n) { + n->val = val; + return true; + } + return false; +} + +void SQTable::_ClearNodes() +{ + for(SQInteger i = 0;i < _numofnodes; i++) { _nodes[i].key = _null_; _nodes[i].val = _null_; } +} + +void SQTable::Finalize() +{ + _ClearNodes(); + SetDelegate(NULL); +} + +void SQTable::Clear() +{ + _ClearNodes(); + _usednodes = 0; + Rehash(true); +} diff --git a/src/3rdparty/squirrel/squirrel/sqtable.h b/src/3rdparty/squirrel/squirrel/sqtable.h new file mode 100644 index 0000000000..2b4a3d4de4 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqtable.h @@ -0,0 +1,91 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQTABLE_H_ +#define _SQTABLE_H_ +/* +* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.) +* http://www.lua.org/copyright.html#4 +* http://www.lua.org/source/4.0.1/src_ltable.c.html +*/ + +#include "sqstring.h" + + +#define hashptr(p) ((SQHash)(((SQInteger)p) >> 3)) + +inline SQHash HashObj(const SQObjectPtr &key) +{ + switch(type(key)) { + case OT_STRING: return _string(key)->_hash; + case OT_FLOAT: return (SQHash)((SQInteger)_float(key)); + case OT_BOOL: case OT_INTEGER: return (SQHash)((SQInteger)_integer(key)); + default: return hashptr(key._unVal.pRefCounted); + } +} + +struct SQTable : public SQDelegable +{ +private: + struct _HashNode + { + _HashNode() { next = NULL; } + SQObjectPtr val; + SQObjectPtr key; + _HashNode *next; + }; + _HashNode *_firstfree; + _HashNode *_nodes; + SQInteger _numofnodes; + SQInteger _usednodes; + +/////////////////////////// + void AllocNodes(SQInteger nSize); + void Rehash(bool force); + SQTable(SQSharedState *ss, SQInteger nInitialSize); + void _ClearNodes(); +public: + static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize) + { + SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable)); + new (newtable) SQTable(ss, nInitialSize); + newtable->_delegate = NULL; + return newtable; + } + void Finalize(); + SQTable *Clone(); + ~SQTable() + { + SetDelegate(NULL); + REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this); + for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode(); + SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode)); + } +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); +#endif + inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash) + { + _HashNode *n = &_nodes[hash]; + do{ + if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){ + return n; + } + }while((n = n->next)); + return NULL; + } + bool Get(const SQObjectPtr &key,SQObjectPtr &val); + void Remove(const SQObjectPtr &key); + bool Set(const SQObjectPtr &key, const SQObjectPtr &val); + //returns true if a new slot has been created false if it was already present + bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val); + SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval); + + SQInteger CountUsed(){ return _usednodes;} + void Clear(); + void Release() + { + sq_delete(this, SQTable); + } + +}; + +#endif //_SQTABLE_H_ diff --git a/src/3rdparty/squirrel/squirrel/squirrel.dsp b/src/3rdparty/squirrel/squirrel/squirrel.dsp new file mode 100644 index 0000000000..eb8a0c1774 --- /dev/null +++ b/src/3rdparty/squirrel/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" /D "GARBAGE_COLLECTOR" /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/src/3rdparty/squirrel/squirrel/squserdata.h b/src/3rdparty/squirrel/squirrel/squserdata.h new file mode 100644 index 0000000000..8b6b431481 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/squserdata.h @@ -0,0 +1,38 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQUSERDATA_H_ +#define _SQUSERDATA_H_ + +struct SQUserData : SQDelegable +{ + SQUserData(SQSharedState *ss){ _delegate = 0; _hook = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); } + ~SQUserData() + { + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain, this); + SetDelegate(NULL); + } + static SQUserData* Create(SQSharedState *ss, SQInteger size) + { + SQUserData* ud = (SQUserData*)SQ_MALLOC(sizeof(SQUserData)+(size-1)); + new (ud) SQUserData(ss); + ud->_size = size; + ud->_typetag = 0; + return ud; + } +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); + void Finalize(){SetDelegate(NULL);} +#endif + void Release() { + if (_hook) _hook(_val,_size); + SQInteger tsize = _size - 1; + this->~SQUserData(); + SQ_FREE(this, sizeof(SQUserData) + tsize); + } + + SQInteger _size; + SQRELEASEHOOK _hook; + SQUserPointer _typetag; + SQChar _val[1]; +}; + +#endif //_SQUSERDATA_H_ diff --git a/src/3rdparty/squirrel/squirrel/squtils.h b/src/3rdparty/squirrel/squirrel/squtils.h new file mode 100644 index 0000000000..b6a436e4a8 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/squtils.h @@ -0,0 +1,104 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQUTILS_H_ +#define _SQUTILS_H_ + +#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;} +#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));} +#define SQ_MALLOC(__size) sq_vm_malloc((__size)); +#define SQ_FREE(__ptr,__size) sq_vm_free((__ptr),(__size)); +#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc((__ptr),(__oldsize),(__size)); + +//sqvector mini vector class, supports objects by value +template class sqvector +{ +public: + sqvector() + { + _vals = NULL; + _size = 0; + _allocated = 0; + } + sqvector(const sqvector& v) + { + copy(v); + } + void copy(const sqvector& v) + { + resize(v._size); + for(SQUnsignedInteger i = 0; i < v._size; i++) { + new ((void *)&_vals[i]) T(v._vals[i]); + } + _size = v._size; + } + ~sqvector() + { + if(_allocated) { + for(SQUnsignedInteger i = 0; i < _size; i++) + _vals[i].~T(); + SQ_FREE(_vals, (_allocated * sizeof(T))); + } + } + void reserve(SQUnsignedInteger newsize) { _realloc(newsize); } + void resize(SQUnsignedInteger newsize, const T& fill = T()) + { + if(newsize > _allocated) + _realloc(newsize); + if(newsize > _size) { + while(_size < newsize) { + new ((void *)&_vals[_size]) T(fill); + _size++; + } + } + else{ + for(SQUnsignedInteger i = newsize; i < _size; i++) { + _vals[i].~T(); + } + _size = newsize; + } + } + void shrinktofit() { if(_size > 4) { _realloc(_size); } } + T& top() const { return _vals[_size - 1]; } + inline SQUnsignedInteger size() const { return _size; } + bool empty() const { return (_size <= 0); } + inline T &push_back(const T& val = T()) + { + if(_allocated <= _size) + _realloc(_size * 2); + return *(new ((void *)&_vals[_size++]) T(val)); + } + inline void pop_back() + { + _size--; _vals[_size].~T(); + } + void insert(SQUnsignedInteger idx, const T& val) + { + resize(_size + 1); + for(SQUnsignedInteger i = _size - 1; i > idx; i--) { + _vals[i] = _vals[i - 1]; + } + _vals[idx] = val; + } + void remove(SQUnsignedInteger idx) + { + _vals[idx].~T(); + if(idx < (_size - 1)) { + memmove(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1)); + } + _size--; + } + SQUnsignedInteger capacity() { return _allocated; } + inline T &back() const { return _vals[_size - 1]; } + inline T& operator[](SQUnsignedInteger pos) const{ return _vals[pos]; } + T* _vals; +private: + void _realloc(SQUnsignedInteger newsize) + { + newsize = (newsize > 0)?newsize:4; + _vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T)); + _allocated = newsize; + } + SQUnsignedInteger _size; + SQUnsignedInteger _allocated; +}; + +#endif //_SQUTILS_H_ diff --git a/src/3rdparty/squirrel/squirrel/sqvm.cpp b/src/3rdparty/squirrel/squirrel/sqvm.cpp new file mode 100644 index 0000000000..dbd9e9dd89 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqvm.cpp @@ -0,0 +1,1537 @@ +/* + see copyright notice in squirrel.h +*/ +#include +#include "sqpcheader.h" +#include +#include +#include "sqopcodes.h" +#include "sqfuncproto.h" +#include "sqvm.h" +#include "sqclosure.h" +#include "sqstring.h" +#include "sqtable.h" +#include "squserdata.h" +#include "sqarray.h" +#include "sqclass.h" + +#define TOP() (_stack._vals[_top-1]) + +bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) +{ + SQInteger res; + SQInteger i1 = _integer(o1), i2 = _integer(o2); + if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) + { + switch(op) { + case BW_AND: res = i1 & i2; break; + case BW_OR: res = i1 | i2; break; + case BW_XOR: res = i1 ^ i2; break; + case BW_SHIFTL: res = i1 << i2; break; + case BW_SHIFTR: res = i1 >> i2; break; + case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); break; + default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; } + } + } + else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;} + trg = res; + return true; +} + +bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2) +{ + if(sq_isnumeric(o1) && sq_isnumeric(o2)) { + if((type(o1)==OT_INTEGER) && (type(o2)==OT_INTEGER)) { + SQInteger res, i1 = _integer(o1), i2 = _integer(o2); + switch(op) { + case '+': res = i1 + i2; break; + case '-': res = i1 - i2; break; + case '/': if(i2 == 0) { Raise_Error(_SC("division by zero")); return false; } + res = i1 / i2; + break; + case '*': res = i1 * i2; break; + case '%': res = i1 % i2; break; + default: res = 0xDEADBEEF; + } + trg = res; + }else{ + SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2); + switch(op) { + case '+': res = f1 + f2; break; + case '-': res = f1 - f2; break; + case '/': res = f1 / f2; break; + case '*': res = f1 * f2; break; + case '%': res = SQFloat(fmod((double)f1,(double)f2)); break; + default: res = 0x0f; + } + trg = res; + } + } else { + if(op == '+' && (type(o1) == OT_STRING || type(o2) == OT_STRING)){ + if(!StringCat(o1, o2, trg)) return false; + } + else if(!ArithMetaMethod(op,o1,o2,trg)) { + Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); return false; + } + } + return true; +} + +SQVM::SQVM(SQSharedState *ss) +{ + _sharedstate=ss; + _suspended = SQFalse; + _suspended_target=-1; + _suspended_root = SQFalse; + _suspended_traps=-1; + _foreignptr=NULL; + _nnativecalls=0; + _lasterror = _null_; + _errorhandler = _null_; + _debughook = _null_; + _can_suspend = false; + _ops_till_suspend = 0; + ci = NULL; + INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); +} + +void SQVM::Finalize() +{ + _roottable = _null_; + _lasterror = _null_; + _errorhandler = _null_; + _debughook = _null_; + temp_reg = _null_; + _callstackdata.resize(0); + SQInteger size=_stack.size(); + for(SQInteger i=size - 1;i>=0;i--) + _stack[i]=_null_; +} + +SQVM::~SQVM() +{ + Finalize(); + //sq_free(_callsstack,_alloccallsstacksize*sizeof(CallInfo)); + REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); +} + +bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &dest) +{ + SQMetaMethod mm; + switch(op){ + case _SC('+'): mm=MT_ADD; break; + case _SC('-'): mm=MT_SUB; break; + case _SC('/'): mm=MT_DIV; break; + case _SC('*'): mm=MT_MUL; break; + case _SC('%'): mm=MT_MODULO; break; + default: mm = MT_ADD; assert(0); break; //shutup compiler + } + if(is_delegable(o1) && _delegable(o1)->_delegate) { + Push(o1);Push(o2); + return CallMetaMethod(_delegable(o1),mm,2,dest); + } + return false; +} + +bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o) +{ + + switch(type(o)) { + case OT_INTEGER: + trg = -_integer(o); + return true; + case OT_FLOAT: + trg = -_float(o); + return true; + case OT_TABLE: + case OT_USERDATA: + case OT_INSTANCE: + if(_delegable(o)->_delegate) { + Push(o); + if(CallMetaMethod(_delegable(o), MT_UNM, 1, temp_reg)) { + trg = temp_reg; + return true; + } + } + default:break; //shutup compiler + } + Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o)); + return false; +} + +#define _RET_SUCCEED(exp) { result = (exp); return true; } +bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result) +{ + if(type(o1)==type(o2)){ + if(_userpointer(o1)==_userpointer(o2))_RET_SUCCEED(0); + SQObjectPtr res; + switch(type(o1)){ + case OT_STRING: + _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2))); + case OT_INTEGER: + _RET_SUCCEED(_integer(o1)-_integer(o2)); + case OT_FLOAT: + _RET_SUCCEED((_float(o1)<_float(o2))?-1:1); + case OT_TABLE: + case OT_USERDATA: + case OT_INSTANCE: + if(_delegable(o1)->_delegate) { + Push(o1);Push(o2); + if(CallMetaMethod(_delegable(o1),MT_CMP,2,res)) break; + } + //continues through (no break needed) + default: + _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 ); + } + if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; } + _RET_SUCCEED(_integer(res)); + + } + else{ + if(sq_isnumeric(o1) && sq_isnumeric(o2)){ + if((type(o1)==OT_INTEGER) && (type(o2)==OT_FLOAT)) { + if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); } + else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); } + _RET_SUCCEED(1); + } + else{ + if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); } + else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); } + _RET_SUCCEED(1); + } + } + else if(type(o1)==OT_NULL) {_RET_SUCCEED(-1);} + else if(type(o2)==OT_NULL) {_RET_SUCCEED(1);} + else { Raise_CompareError(o1,o2); return false; } + + } + assert(0); + _RET_SUCCEED(0); //cannot happen +} + +bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res) +{ + SQInteger r; + if(ObjCmp(o1,o2,r)) { + switch(op) { + case CMP_G: res = (r > 0)?_true_:_false_; return true; + case CMP_GE: res = (r >= 0)?_true_:_false_; return true; + case CMP_L: res = (r < 0)?_true_:_false_; return true; + case CMP_LE: res = (r <= 0)?_true_:_false_; return true; + + } + assert(0); + } + return false; +} + +void SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res) +{ + switch(type(o)) { + case OT_STRING: + res = o; + return; + case OT_FLOAT: + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%g"),_float(o)); + break; + case OT_INTEGER: +#if defined(_SQ64) + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%ld"),_integer(o)); +#else + scsprintf(_sp(rsl(NUMBER_MAX_CHAR+1)),_SC("%d"),_integer(o)); +#endif + break; + case OT_BOOL: + scsprintf(_sp(rsl(6)),_integer(o)?_SC("true"):_SC("false")); + break; + case OT_TABLE: + case OT_USERDATA: + case OT_INSTANCE: + if(_delegable(o)->_delegate) { + Push(o); + if(CallMetaMethod(_delegable(o),MT_TOSTRING,1,res)) { + if(type(res) == OT_STRING) + return; + //else keeps going to the default + } + } + default: + scsprintf(_sp(rsl(sizeof(void*)+20)),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o)); + } + res = SQString::Create(_ss(this),_spval); +} + + +bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest) +{ + SQObjectPtr a, b; + ToString(str, a); + ToString(obj, b); + SQInteger l = _string(a)->_len , ol = _string(b)->_len; + SQChar *s = _sp(rsl(l + ol + 1)); + memcpy(s, _stringval(a), rsl(l)); + memcpy(s + l, _stringval(b), rsl(ol)); + dest = SQString::Create(_ss(this), _spval, l + ol); + return true; +} + +void SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest) +{ + if(is_delegable(obj1) && _delegable(obj1)->_delegate) { + Push(obj1); + if(CallMetaMethod(_delegable(obj1),MT_TYPEOF,1,dest)) + return; + } + dest = SQString::Create(_ss(this),GetTypeName(obj1)); +} + +bool SQVM::Init(SQVM *friendvm, SQInteger stacksize) +{ + _stack.resize(stacksize); + //_callsstack.reserve(4); + _alloccallsstacksize = 4; + _callstackdata.resize(_alloccallsstacksize); + _callsstacksize = 0; + _callsstack = &_callstackdata[0]; + //_callsstack = (CallInfo*)sq_malloc(_alloccallsstacksize*sizeof(CallInfo)); + _stackbase = 0; + _top = 0; + if(!friendvm) + _roottable = SQTable::Create(_ss(this), 0); + else { + _roottable = friendvm->_roottable; + _errorhandler = friendvm->_errorhandler; + _debughook = friendvm->_debughook; + } + + sq_base_register(this); + return true; +} + +extern SQInstructionDesc g_InstrDesc[]; + +bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall) +{ + SQFunctionProto *func = _funcproto(closure->_function); + + const SQInteger paramssize = func->_nparameters; + const SQInteger newtop = stackbase + func->_stacksize; + SQInteger nargs = args; + if (paramssize != nargs) { + SQInteger ndef = func->_ndefaultparams; + if(ndef && nargs < paramssize) { + SQInteger diff = paramssize - nargs; + for(SQInteger n = ndef - diff; n < ndef; n++) { + _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n]; + } + } + else if(func->_varparams) + { + if (nargs < paramssize) { + Raise_Error(_SC("wrong number of parameters")); + return false; + } + for(SQInteger n = 0; n < nargs - paramssize; n++) { + _vargsstack.push_back(_stack._vals[stackbase+paramssize+n]); + _stack._vals[stackbase+paramssize+n] = _null_; + } + } + else { + Raise_Error(_SC("wrong number of parameters")); + return false; + } + } + + if(type(closure->_env) == OT_WEAKREF) { + _stack._vals[stackbase] = _weakref(closure->_env)->_obj; + } + + if (!tailcall) { + CallInfo lc; + memset(&lc, 0, sizeof(lc)); + lc._generator = NULL; + lc._etraps = 0; + lc._prevstkbase = (SQInt32) ( stackbase - _stackbase ); + lc._target = (SQInt32) target; + lc._prevtop = (SQInt32) (_top - _stackbase); + lc._ncalls = 1; + lc._root = SQFalse; + PUSH_CALLINFO(this, lc); + } + else { + ci->_ncalls++; + } + ci->_vargs.size = (SQInt32)(nargs - paramssize); + ci->_vargs.base = (SQInt32)(_vargsstack.size()-(ci->_vargs.size)); + ci->_closure = closure; + ci->_literals = func->_literals; + ci->_ip = func->_instructions; + //grows the stack if needed + if (((SQUnsignedInteger)newtop + (func->_stacksize<<1)) > _stack.size()) { + _stack.resize(_stack.size() + (func->_stacksize<<1)); + } + + _top = newtop; + _stackbase = stackbase; + if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) + CallDebugHook(_SC('c')); + return true; +} + +bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval) +{ + if (type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) + for(SQInteger i=0;i_ncalls;i++) + CallDebugHook(_SC('r')); + + SQBool broot = ci->_root; + SQInteger last_top = _top; + SQInteger target = ci->_target; + SQInteger oldstackbase = _stackbase; + _stackbase -= ci->_prevstkbase; + _top = _stackbase + ci->_prevtop; + if(ci->_vargs.size) PopVarArgs(ci->_vargs); + POP_CALLINFO(this); + if (broot) { + if (_arg0 != MAX_FUNC_STACKSIZE) retval = _stack._vals[oldstackbase+_arg1]; + else retval = _null_; + } + else { + if(target != -1) { //-1 is when a class contructor ret value has to be ignored + if (_arg0 != MAX_FUNC_STACKSIZE) + STK(target) = _stack._vals[oldstackbase+_arg1]; + else + STK(target) = _null_; + } + } + + while (last_top > oldstackbase) _stack._vals[last_top--].Null(); + assert(oldstackbase >= _stackbase); + return broot?true:false; +} + +#define _RET_ON_FAIL(exp) { if(!exp) return false; } + +bool SQVM::LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) +{ + _RET_ON_FAIL(ARITH_OP( op , target, a, incr)); + a = target; + return true; +} + +bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr) +{ + SQObjectPtr trg; + _RET_ON_FAIL(ARITH_OP( op , trg, a, incr)); + target = a; + a = trg; + return true; +} + +bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix) +{ + SQObjectPtr tmp, tself = self, tkey = key; + if (!Get(tself, tkey, tmp, false, true)) { Raise_IdxError(tkey); return false; } + _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr)) + Set(tself, tkey, target,true); + if (postfix) target = tmp; + return true; +} + +#define arg0 (_i_._arg0) +#define arg1 (_i_._arg1) +#define sarg1 (*((SQInt32 *)&_i_._arg1)) +#define arg2 (_i_._arg2) +#define arg3 (_i_._arg3) +#define sarg3 ((SQInteger)*((signed char *)&_i_._arg3)) + +SQRESULT SQVM::Suspend() +{ + if (_suspended) + return sq_throwerror(this, _SC("cannot suspend an already suspended vm")); + if (_nnativecalls!=2) + return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods")); + return SQ_SUSPEND_FLAG; +} + +void SQVM::PopVarArgs(VarArgs &vargs) +{ + for(SQInteger n = 0; n< vargs.size; n++) + _vargsstack.pop_back(); +} + +#define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; } +bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr +&o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump) +{ + SQInteger nrefidx; + switch(type(o1)) { + case OT_TABLE: + if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(exitpos); + o4 = (SQInteger)nrefidx; _FINISH(1); + case OT_ARRAY: + if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(exitpos); + o4 = (SQInteger) nrefidx; _FINISH(1); + case OT_STRING: + if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos); + o4 = (SQInteger)nrefidx; _FINISH(1); + case OT_CLASS: + if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos); + o4 = (SQInteger)nrefidx; _FINISH(1); + case OT_USERDATA: + case OT_INSTANCE: + if(_delegable(o1)->_delegate) { + SQObjectPtr itr; + Push(o1); + Push(o4); + if(CallMetaMethod(_delegable(o1), MT_NEXTI, 2, itr)){ + o4 = o2 = itr; + if(type(itr) == OT_NULL) _FINISH(exitpos); + if(!Get(o1, itr, o3, false,false)) { + Raise_Error(_SC("_nexti returned an invalid idx")); + return false; + } + _FINISH(1); + } + Raise_Error(_SC("_nexti failed")); + return false; + } + break; + case OT_GENERATOR: + if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(exitpos); + if(_generator(o1)->_state == SQGenerator::eSuspended) { + SQInteger idx = 0; + if(type(o4) == OT_INTEGER) { + idx = _integer(o4) + 1; + } + o2 = idx; + o4 = idx; + _generator(o1)->Resume(this, arg_2+1); + _FINISH(0); + } + default: + Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1)); + } + return false; //cannot be hit(just to avoid warnings) +} + +bool SQVM::DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2) +{ + if(type(o1) != OT_TABLE) { Raise_Error(_SC("delegating a '%s'"), GetTypeName(o1)); return false; } + switch(type(o2)) { + case OT_TABLE: + if(!_table(o1)->SetDelegate(_table(o2))){ + Raise_Error(_SC("delegate cycle detected")); + return false; + } + break; + case OT_NULL: + _table(o1)->SetDelegate(NULL); + break; + default: + Raise_Error(_SC("using '%s' as delegate"), GetTypeName(o2)); + return false; + break; + } + trg = o1; + return true; +} +#define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1)) + +#define _GUARD(exp) { if(!exp) { Raise_Error(_lasterror); SQ_THROW();} } + +#define SQ_THROW() { goto exception_trap; } + +bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func) +{ + SQInteger nouters; + SQClosure *closure = SQClosure::Create(_ss(this), func); + if((nouters = func->_noutervalues)) { + closure->_outervalues.reserve(nouters); + for(SQInteger i = 0; i_outervalues[i]; + switch(v._type){ + case otSYMBOL: + closure->_outervalues.push_back(_null_); + if(!Get(_stack._vals[_stackbase]/*STK(0)*/, v._src, closure->_outervalues.top(), false,true)) + {Raise_IdxError(v._src); return false; } + break; + case otLOCAL: + closure->_outervalues.push_back(_stack._vals[_stackbase+_integer(v._src)]); + break; + case otOUTER: + closure->_outervalues.push_back(_closure(ci->_closure)->_outervalues[_integer(v._src)]); + break; + } + } + } + SQInteger ndefparams; + if((ndefparams = func->_ndefaultparams)) { + closure->_defaultparams.reserve(ndefparams); + for(SQInteger i = 0; i < ndefparams; i++) { + SQInteger spos = func->_defaultparams[i]; + closure->_defaultparams.push_back(_stack._vals[_stackbase + spos]); + } + } + target = closure; + return true; + +} + +bool SQVM::GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &index,CallInfo *ci) +{ + if(ci->_vargs.size == 0) { + Raise_Error(_SC("the function doesn't have var args")); + return false; + } + if(!sq_isnumeric(index)){ + Raise_Error(_SC("indexing 'vargv' with %s"),GetTypeName(index)); + return false; + } + SQInteger idx = tointeger(index); + if(idx < 0 || idx >= ci->_vargs.size){ Raise_Error(_SC("vargv index out of range")); return false; } + target = _vargsstack[ci->_vargs.base+idx]; + return true; +} + +bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes) +{ + SQClass *base = NULL; + SQObjectPtr attrs; + if(baseclass != -1) { + if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; } + base = _class(_stack._vals[_stackbase + baseclass]); + } + if(attributes != MAX_FUNC_STACKSIZE) { + attrs = _stack._vals[_stackbase+attributes]; + } + target = SQClass::Create(_ss(this),base); + if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) { + int nparams = 2; + SQObjectPtr ret; + Push(target); Push(attrs); + Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false, false); + Pop(nparams); + } + _class(target)->_attributes = attrs; + return true; +} + + + +bool SQVM::IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res) +{ + if(type(o1) == type(o2)) { + res = ((_userpointer(o1) == _userpointer(o2)?true:false)); + } + else { + if(sq_isnumeric(o1) && sq_isnumeric(o2)) { + SQInteger cmpres; + if(!ObjCmp(o1, o2,cmpres)) return false; + res = (cmpres == 0); + } + else { + res = false; + } + } + return true; +} + +bool SQVM::IsFalse(SQObjectPtr &o) +{ + if(((type(o) & SQOBJECT_CANBEFALSE) && ( (type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0)) )) + || (_integer(o) == 0) ) { //OT_NULL|OT_INTEGER|OT_BOOL + return true; + } + return false; +} + +bool SQVM::GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target) +{ + switch(type(o)) { + case OT_TABLE: target = _table(o)->_delegate?SQObjectPtr(_table(o)->_delegate):_null_; + break; + case OT_CLASS: target = _class(o)->_base?_class(o)->_base:_null_; + break; + default: + Raise_Error(_SC("the %s type doesn't have a parent slot"), GetTypeName(o)); + return false; + } + return true; +} + +bool SQVM::Execute(SQObjectPtr &closure, SQInteger target, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et) +{ + if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } + _nnativecalls++; + AutoDec ad(&_nnativecalls); + SQInteger traps = 0; + //temp_reg vars for OP_CALL + SQInteger ct_target; + SQInteger ct_stackbase; + bool ct_tailcall; + + switch(et) { + case ET_CALL: + if(!StartCall(_closure(closure), _top - nargs, nargs, stackbase, false)) { + //call the handler if there are no calls in the stack, if not relies on the previous node + if(ci == NULL) CallErrorHandler(_lasterror); + return false; + } + ci->_root = SQTrue; + break; + case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, target); ci->_root = SQTrue; traps += ci->_etraps; break; + case ET_RESUME_VM: + traps = _suspended_traps; + ci->_root = _suspended_root; + ci->_vargs = _suspend_varargs; + _suspended = SQFalse; + break; + case ET_RESUME_OPENTTD: + _suspended = SQFalse; + break; + } + +exception_restore: + // + { + for(;;) + { + DecreaseOps(1); + if (ShouldSuspend()) { _suspended = SQTrue; return true; } + + const SQInstruction &_i_ = *ci->_ip++; + //dumpstack(_stackbase); + //scprintf("%s %d %d %d %d\n",g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3); + switch(_i_.op) + { + case _OP_LINE: + if(type(_debughook) != OT_NULL && _rawval(_debughook) != _rawval(ci->_closure)) + CallDebugHook(_SC('l'),arg1); + continue; + case _OP_LOAD: TARGET = ci->_literals[arg1]; continue; + case _OP_LOADINT: TARGET = (SQInteger)arg1; continue; + case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue; + case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue; + case _OP_TAILCALL: + temp_reg = STK(arg1); + if (type(temp_reg) == OT_CLOSURE){ + ct_tailcall = true; + if(ci->_vargs.size) PopVarArgs(ci->_vargs); + for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i); + ct_target = ci->_target; + ct_stackbase = _stackbase; + goto common_call; + } + case _OP_CALL: { + ct_tailcall = false; + ct_target = arg0; + temp_reg = STK(arg1); + ct_stackbase = _stackbase+arg2; + +common_call: + SQObjectPtr clo = temp_reg; + SQInteger last_top = _top; + switch (type(clo)) { + case OT_CLOSURE:{ + _GUARD(StartCall(_closure(clo), ct_target, arg3, ct_stackbase, ct_tailcall)); + if (_funcproto(_closure(clo)->_function)->_bgenerator) { + SQGenerator *gen = SQGenerator::Create(_ss(this), _closure(clo)); + _GUARD(gen->Yield(this)); + Return(1, ct_target, clo); + STK(ct_target) = gen; + while (last_top >= _top) _stack._vals[last_top--].Null(); + continue; + } + } + continue; + case OT_NATIVECLOSURE: { + bool suspend; + _suspended_target = ct_target; + _GUARD(CallNative(_nativeclosure(clo), arg3, ct_stackbase, clo,suspend)); + if(suspend){ + _suspended = SQTrue; + _suspended_target = ct_target; + _suspended_root = ci->_root; + _suspended_traps = traps; + _suspend_varargs = ci->_vargs; + outres = clo; + return true; + } + if(ct_target != -1) { //skip return value for constructors + STK(ct_target) = clo; + } + } + continue; + case OT_CLASS:{ + SQObjectPtr inst; + _GUARD(CreateClassInstance(_class(clo),inst,temp_reg)); + STK(ct_target) = inst; + ct_target = -1; //fakes return value target so that is not overwritten by the constructor + if(type(temp_reg) != OT_NULL) { + _stack._vals[ct_stackbase] = inst; + goto common_call; //hard core spaghetti code(reissues the OP_CALL to invoke the constructor) + } + } + break; + case OT_TABLE: + case OT_USERDATA: + case OT_INSTANCE: + { + Push(clo); + for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i)); + if (_delegable(clo) && CallMetaMethod(_delegable(clo), MT_CALL, arg3+1, clo)){ + STK(ct_target) = clo; + break; + } + Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); + SQ_THROW(); + } + default: + Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo)); + SQ_THROW(); + } + } + continue; + case _OP_PREPCALL: + case _OP_PREPCALLK: + { + SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1); + SQObjectPtr &o = STK(arg2); + if (!Get(o, key, temp_reg,false,true)) { + if(type(o) == OT_CLASS) { //hack? + if(_class_ddel->Get(key,temp_reg)) { + STK(arg3) = o; + TARGET = temp_reg; + continue; + } + } + { Raise_IdxError(key); SQ_THROW();} + } + + STK(arg3) = type(o) == OT_CLASS?STK(0):o; + TARGET = temp_reg; + } + continue; + case _OP_SCOPE_END: + { + SQInteger from = arg0; + SQInteger count = arg1 - arg0 + 2; + /* When 'return' is executed, it happens that the stack is already cleaned + * (by Return()), but this OP-code is still executed. So check for this + * situation, and ignore the cleanup */ + if (_stackbase + count + from <= _top) { + while (--count >= 0) _stack._vals[_stackbase + count + from].Null(); + } + } continue; + case _OP_GETK: + if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, false,true)) { Raise_IdxError(ci->_literals[arg1]); SQ_THROW();} + TARGET = temp_reg; + continue; + case _OP_MOVE: TARGET = STK(arg1); continue; + case _OP_NEWSLOT: + _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false)); + if(arg0 != arg3) TARGET = STK(arg3); + continue; + case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue; + case _OP_SET: + if (!Set(STK(arg1), STK(arg2), STK(arg3),true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); } + if (arg0 != arg3) TARGET = STK(arg3); + continue; + case _OP_GET: + if (!Get(STK(arg1), STK(arg2), temp_reg, false,true)) { Raise_IdxError(STK(arg2)); SQ_THROW(); } + TARGET = temp_reg; + continue; + case _OP_EQ:{ + bool res; + if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } + TARGET = res?_true_:_false_; + }continue; + case _OP_NE:{ + bool res; + if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); } + TARGET = (!res)?_true_:_false_; + } continue; + case _OP_ARITH: _GUARD(ARITH_OP( arg3 , temp_reg, STK(arg2), STK(arg1))); TARGET = temp_reg; continue; + case _OP_BITW: _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue; + case _OP_RETURN: + if(ci->_generator) { + ci->_generator->Kill(); + } + if(Return(arg0, arg1, temp_reg)){ + assert(traps==0); + outres = temp_reg; + return true; + } + continue; + case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n) = _null_; }continue; + case _OP_LOADROOTTABLE: TARGET = _roottable; continue; + case _OP_LOADBOOL: TARGET = arg1?_true_:_false_; continue; + case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue; + case _OP_JMP: ci->_ip += (sarg1); continue; + case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; + case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue; + case _OP_LOADFREEVAR: TARGET = _closure(ci->_closure)->_outervalues[arg1]; continue; + case _OP_VARGC: TARGET = SQInteger(ci->_vargs.size); continue; + case _OP_GETVARGV: + if(!GETVARGV_OP(TARGET,STK(arg1),ci)) { SQ_THROW(); } + continue; + case _OP_NEWTABLE: TARGET = SQTable::Create(_ss(this), arg1); continue; + case _OP_NEWARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue; + case _OP_APPENDARRAY: _array(STK(arg0))->Append(COND_LITERAL); continue; + case _OP_GETPARENT: _GUARD(GETPARENT_OP(STK(arg1),TARGET)); continue; + case _OP_COMPARITH: _GUARD(DerefInc(arg3, TARGET, STK((((SQUnsignedInteger)arg1&0xFFFF0000)>>16)), STK(arg2), STK(arg1&0x0000FFFF), false)); continue; + case _OP_COMPARITHL: _GUARD(LOCAL_INC(arg3, TARGET, STK(arg1), STK(arg2))); continue; + case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false));} continue; + case _OP_INCL: {SQObjectPtr o(sarg3); _GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));} continue; + case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true));} continue; + case _OP_PINCL: {SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));} continue; + case _OP_CMP: _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET)) continue; + case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, true,false)?_true_:_false_;continue; + case _OP_INSTANCEOF: + if(type(STK(arg1)) != OT_CLASS || type(STK(arg2)) != OT_INSTANCE) + {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();} + TARGET = _instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?_true_:_false_; + continue; + case _OP_AND: + if(IsFalse(STK(arg2))) { + TARGET = STK(arg2); + ci->_ip += (sarg1); + } + continue; + case _OP_OR: + if(!IsFalse(STK(arg2))) { + TARGET = STK(arg2); + ci->_ip += (sarg1); + } + continue; + case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue; + case _OP_NOT: TARGET = (IsFalse(STK(arg1))?_true_:_false_); continue; + case _OP_BWNOT: + if(type(STK(arg1)) == OT_INTEGER) { + SQInteger t = _integer(STK(arg1)); + TARGET = SQInteger(~t); + continue; + } + Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1))); + SQ_THROW(); + case _OP_CLOSURE: { + SQClosure *c = ci->_closure._unVal.pClosure; + SQFunctionProto *fp = c->_function._unVal.pFunctionProto; + if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); } + continue; + } + case _OP_YIELD:{ + if(ci->_generator) { + if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1); + _GUARD(ci->_generator->Yield(this)); + traps -= ci->_etraps; + if(sarg1 != MAX_FUNC_STACKSIZE) STK(arg1) = temp_reg; + } + else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();} + if(Return(arg0, arg1, temp_reg)){ + assert(traps == 0); + outres = temp_reg; + return true; + } + + } + continue; + case _OP_RESUME: + if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();} + _GUARD(_generator(STK(arg1))->Resume(this, arg0)); + traps += ci->_etraps; + continue; + case _OP_FOREACH:{ int tojump; + _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump)); + ci->_ip += tojump; } + continue; + case _OP_POSTFOREACH: + assert(type(STK(arg0)) == OT_GENERATOR); + if(_generator(STK(arg0))->_state == SQGenerator::eDead) + ci->_ip += (sarg1 - 1); + continue; + case _OP_DELEGATE: _GUARD(DELEGATE_OP(TARGET,STK(arg1),STK(arg2))); continue; + case _OP_CLONE: + if(!Clone(STK(arg1), TARGET)) + { Raise_Error(_SC("cloning a %s"), GetTypeName(STK(arg1))); SQ_THROW();} + continue; + case _OP_TYPEOF: TypeOf(STK(arg1), TARGET); continue; + case _OP_PUSHTRAP:{ + SQInstruction *_iv = _funcproto(_closure(ci->_closure)->_function)->_instructions; + _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++; + ci->_etraps++; + } + continue; + case _OP_POPTRAP: { + for(SQInteger i = 0; i < arg0; i++) { + _etraps.pop_back(); traps--; + ci->_etraps--; + } + } + continue; + case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue; + case _OP_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue; + case _OP_NEWSLOTA: + bool bstatic = (arg0&NEW_SLOT_STATIC_FLAG)?true:false; + if(type(STK(arg1)) == OT_CLASS) { + if(type(_class(STK(arg1))->_metamethods[MT_NEWMEMBER]) != OT_NULL ) { + Push(STK(arg1)); Push(STK(arg2)); Push(STK(arg3)); + Push((arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : _null_); + int nparams = 4; + if(Call(_class(STK(arg1))->_metamethods[MT_NEWMEMBER], nparams, _top - nparams, temp_reg,SQFalse,SQFalse)) { + Pop(nparams); + continue; + } + } + } + _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),bstatic)); + if((arg0&NEW_SLOT_ATTRIBUTES_FLAG)) { + _class(STK(arg1))->SetAttributes(STK(arg2),STK(arg2-1)); + } + continue; + } + + } + } +exception_trap: + { + SQObjectPtr currerror = _lasterror; +// dumpstack(_stackbase); + SQInteger n = 0; + SQInteger last_top = _top; + if(ci) { + if(_ss(this)->_notifyallexceptions) CallErrorHandler(currerror); + + if(traps) { + do { + if(ci->_etraps > 0) { + SQExceptionTrap &et = _etraps.top(); + ci->_ip = et._ip; + _top = et._stacksize; + _stackbase = et._stackbase; + _stack._vals[_stackbase+et._extarget] = currerror; + _etraps.pop_back(); traps--; ci->_etraps--; + while(last_top >= _top) _stack._vals[last_top--].Null(); + goto exception_restore; + } + //if is a native closure + if(type(ci->_closure) != OT_CLOSURE && n) + break; + if(ci->_generator) ci->_generator->Kill(); + PopVarArgs(ci->_vargs); + POP_CALLINFO(this); + n++; + } while(_callsstacksize); + } + else { + //call the hook + if(raiseerror && !_ss(this)->_notifyallexceptions) + CallErrorHandler(currerror); + } + //remove call stack until a C function is found or the cstack is empty + if(ci) do { + SQBool exitafterthisone = ci->_root; + if(ci->_generator) ci->_generator->Kill(); + _stackbase -= ci->_prevstkbase; + _top = _stackbase + ci->_prevtop; + PopVarArgs(ci->_vargs); + POP_CALLINFO(this); + if( (ci && type(ci->_closure) != OT_CLOSURE) || exitafterthisone) break; + } while(_callsstacksize); + + while(last_top >= _top) _stack._vals[last_top--].Null(); + } + _lasterror = currerror; + return false; + } + assert(0); +} + +bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor) +{ + inst = theclass->CreateInstance(); + if(!theclass->Get(_ss(this)->_constructoridx,constructor)) { + //if(!Call(constr,nargs,stackbase,constr,false)) + // return false; + 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,SQFalse); + Pop(2); + } +} + +void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline) +{ + SQObjectPtr temp_reg; + SQInteger nparams=5; + SQFunctionProto *func=_funcproto(_closure(ci->_closure)->_function); + Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name); + Call(_debughook,nparams,_top-nparams,temp_reg,SQFalse,SQFalse); + Pop(nparams); +} + +bool SQVM::CallNative(SQNativeClosure *nclosure,SQInteger nargs,SQInteger stackbase,SQObjectPtr &retval,bool &suspend) +{ + if (_nnativecalls + 1 > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; } + SQInteger nparamscheck = nclosure->_nparamscheck; + if(((nparamscheck > 0) && (nparamscheck != nargs)) + || ((nparamscheck < 0) && (nargs < (-nparamscheck)))) { + Raise_Error(_SC("wrong number of parameters")); + return false; + } + + SQInteger tcs; + if((tcs = nclosure->_typecheck.size())) { + for(SQInteger i = 0; i < nargs && i < tcs; i++) + if((nclosure->_typecheck._vals[i] != -1) && !(type(_stack._vals[stackbase+i]) & nclosure->_typecheck[i])) { + Raise_ParamTypeError(i,nclosure->_typecheck._vals[i],type(_stack._vals[stackbase+i])); + return false; + } + } + _nnativecalls++; + if ((_top + MIN_STACK_OVERHEAD) > (SQInteger)_stack.size()) { + _stack.resize(_stack.size() + (MIN_STACK_OVERHEAD<<1)); + } + SQInteger oldtop = _top; + SQInteger oldstackbase = _stackbase; + _top = stackbase + nargs; + CallInfo lci; + memset(&lci, 0, sizeof(lci)); + lci._closure = nclosure; + lci._generator = NULL; + lci._etraps = 0; + lci._prevstkbase = (SQInt32) (stackbase - _stackbase); + lci._ncalls = 1; + lci._prevtop = (SQInt32) (oldtop - oldstackbase); + PUSH_CALLINFO(this, lci); + _stackbase = stackbase; + //push free variables + SQInteger outers = nclosure->_outervalues.size(); + for (SQInteger i = 0; i < outers; i++) { + Push(nclosure->_outervalues[i]); + } + + if(type(nclosure->_env) == OT_WEAKREF) { + _stack[stackbase] = _weakref(nclosure->_env)->_obj; + } + + + SQInteger ret; + try { + SQBool can_suspend = this->_can_suspend; + this->_can_suspend = false; + ret = (nclosure->_function)(this); + this->_can_suspend = can_suspend; + } catch (...) { + _nnativecalls--; + suspend = false; + + _stackbase = oldstackbase; + _top = oldtop; + + POP_CALLINFO(this); + + while(oldtop > _stackbase + stackbase) _stack._vals[oldtop--].Null(); + throw; + } + + _nnativecalls--; + suspend = false; + if( ret == SQ_SUSPEND_FLAG) suspend = true; + else if (ret < 0) { + _stackbase = oldstackbase; + _top = oldtop; + POP_CALLINFO(this); + while(oldtop > _stackbase + stackbase) _stack._vals[oldtop--].Null(); + Raise_Error(_lasterror); + return false; + } + + if (ret != 0){ retval = TOP(); TOP().Null(); } + else { retval = _null_; } + _stackbase = oldstackbase; + _top = oldtop; + POP_CALLINFO(this); + while(oldtop > _stackbase + stackbase) _stack._vals[oldtop--].Null(); + return true; +} + +bool SQVM::Get(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw, bool fetchroot) +{ + switch(type(self)){ + case OT_TABLE: + if(_table(self)->Get(key,dest))return true; + break; + case OT_ARRAY: + if(sq_isnumeric(key)){ + return _array(self)->Get(tointeger(key),dest); + } + break; + case OT_INSTANCE: + if(_instance(self)->Get(key,dest)) return true; + break; + default:break; //shut up compiler + } + if(FallBackGet(self,key,dest,raw)) return true; + + if(fetchroot) { + if(_rawval(STK(0)) == _rawval(self) && + type(STK(0)) == type(self)) { + return _table(_roottable)->Get(key,dest); + } + } + return false; +} + +bool SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw) +{ + switch(type(self)){ + case OT_CLASS: + return _class(self)->Get(key,dest); + break; + case OT_TABLE: + case OT_USERDATA: + //delegation + if(_delegable(self)->_delegate) { + if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,raw,false)) + return true; + if(raw)return false; + Push(self);Push(key); + if(CallMetaMethod(_delegable(self),MT_GET,2,dest)) + return true; + } + if(type(self) == OT_TABLE) { + if(raw) return false; + return _table_ddel->Get(key,dest); + } + return false; + break; + case OT_ARRAY: + if(raw)return false; + return _array_ddel->Get(key,dest); + case OT_STRING: + if(sq_isnumeric(key)){ + SQInteger n=tointeger(key); + if(abs((int)n)<_string(self)->_len){ + if(n<0)n=_string(self)->_len-n; + dest=SQInteger(_stringval(self)[n]); + return true; + } + return false; + } + else { + if(raw)return false; + return _string_ddel->Get(key,dest); + } + break; + case OT_INSTANCE: + if(raw)return false; + Push(self);Push(key); + if(!CallMetaMethod(_delegable(self),MT_GET,2,dest)) { + return _instance_ddel->Get(key,dest); + } + return true; + case OT_INTEGER:case OT_FLOAT:case OT_BOOL: + if(raw)return false; + return _number_ddel->Get(key,dest); + case OT_GENERATOR: + if(raw)return false; + return _generator_ddel->Get(key,dest); + case OT_CLOSURE: case OT_NATIVECLOSURE: + if(raw)return false; + return _closure_ddel->Get(key,dest); + case OT_THREAD: + if(raw)return false; + return _thread_ddel->Get(key,dest); + case OT_WEAKREF: + if(raw)return false; + return _weakref_ddel->Get(key,dest); + default:return false; + } + return false; +} + +bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool fetchroot) +{ + switch(type(self)){ + case OT_TABLE: + if(_table(self)->Set(key,val)) + return true; + if(_table(self)->_delegate) { + if(Set(_table(self)->_delegate,key,val,false)) { + return true; + } + } + //keeps going + case OT_USERDATA: + if(_delegable(self)->_delegate) { + SQObjectPtr t; + Push(self);Push(key);Push(val); + if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true; + } + break; + case OT_INSTANCE:{ + if(_instance(self)->Set(key,val)) + return true; + SQObjectPtr t; + Push(self);Push(key);Push(val); + if(CallMetaMethod(_delegable(self),MT_SET,3,t)) return true; + } + break; + case OT_ARRAY: + if(!sq_isnumeric(key)) {Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; } + return _array(self)->Set(tointeger(key),val); + default: + Raise_Error(_SC("trying to set '%s'"),GetTypeName(self)); + return false; + } + if(fetchroot) { + if(_rawval(STK(0)) == _rawval(self) && + type(STK(0)) == type(self)) { + return _table(_roottable)->Set(key,val); + } + } + return false; +} + +bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target) +{ + SQObjectPtr temp_reg; + SQObjectPtr newobj; + switch(type(self)){ + case OT_TABLE: + newobj = _table(self)->Clone(); + goto cloned_mt; + case OT_INSTANCE: + newobj = _instance(self)->Clone(_ss(this)); +cloned_mt: + if(_delegable(newobj)->_delegate){ + Push(newobj); + Push(self); + CallMetaMethod(_delegable(newobj),MT_CLONED,2,temp_reg); + } + target = newobj; + return true; + case OT_ARRAY: + target = _array(self)->Clone(); + return true; + default: return false; + } +} + +bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic) +{ + if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; } + switch(type(self)) { + case OT_TABLE: { + bool rawcall = true; + if(_table(self)->_delegate) { + SQObjectPtr res; + if(!_table(self)->Get(key,res)) { + Push(self);Push(key);Push(val); + rawcall = !CallMetaMethod(_table(self),MT_NEWSLOT,3,res); + } + } + if(rawcall) _table(self)->NewSlot(key,val); //cannot fail + + break;} + case OT_INSTANCE: { + SQObjectPtr res; + Push(self);Push(key);Push(val); + if(!CallMetaMethod(_instance(self),MT_NEWSLOT,3,res)) { + Raise_Error(_SC("class instances do not support the new slot operator")); + return false; + } + break;} + case OT_CLASS: + if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) { + if(_class(self)->_locked) { + Raise_Error(_SC("trying to modify a class that has already been instantiated")); + return false; + } + else { + SQObjectPtr oval = PrintObjVal(key); + Raise_Error(_SC("the property '%s' already exists"),_stringval(oval)); + return false; + } + } + break; + default: + Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); + return false; + break; + } + return true; +} + +bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res) +{ + switch(type(self)) { + case OT_TABLE: + case OT_INSTANCE: + case OT_USERDATA: { + SQObjectPtr t; + bool handled = false; + if(_delegable(self)->_delegate) { + Push(self);Push(key); + handled = CallMetaMethod(_delegable(self),MT_DELSLOT,2,t); + } + + if(!handled) { + if(type(self) == OT_TABLE) { + if(_table(self)->Get(key,t)) { + _table(self)->Remove(key); + } + else { + Raise_IdxError((SQObject &)key); + return false; + } + } + else { + Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self)); + return false; + } + } + res = t; + } + break; + default: + Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self)); + return false; + } + return true; +} + +bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror,SQBool can_suspend) +{ +#ifdef _DEBUG +SQInteger prevstackbase = _stackbase; +#endif + switch(type(closure)) { + case OT_CLOSURE: { + assert(!can_suspend || this->_can_suspend); + SQBool backup_suspend = this->_can_suspend; + this->_can_suspend = can_suspend; + bool ret = Execute(closure, _top - nparams, nparams, stackbase,outres,raiseerror); + this->_can_suspend = backup_suspend; + return ret; + } + 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,false); + } + return true; + } + break; + default: + return false; + } +#ifdef _DEBUG + if(!_suspended) { + assert(_stackbase == prevstackbase); + } +#endif + return true; +} + +bool SQVM::CallMetaMethod(SQDelegable *del,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres) +{ + SQObjectPtr closure; + if(del->GetMetaMethod(this, mm, closure)) { + if(Call(closure, nparams, _top - nparams, outres, SQFalse, SQFalse)) { + Pop(nparams); + return true; + } + } + Pop(nparams); + return false; +} + +void SQVM::Remove(SQInteger n) { + n = (n >= 0)?n + _stackbase - 1:_top + n; + for(SQInteger i = n; i < _top; i++){ + _stack[i] = _stack[i+1]; + } + _stack[_top] = _null_; + _top--; +} + +void SQVM::Pop() { + _stack[--_top] = _null_; +} + +void SQVM::Pop(SQInteger n) { + for(SQInteger i = 0; i < n; i++){ + _stack[--_top] = _null_; + } +} + +void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; } +SQObjectPtr &SQVM::Top() { return _stack[_top-1]; } +SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; } +SQObjectPtr &SQVM::GetUp(SQInteger n) { return _stack[_top+n]; } +SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; } + +#ifdef _DEBUG_DUMP +void SQVM::dumpstack(SQInteger stackbase,bool dumpall) +{ + SQInteger size=dumpall?_stack.size():_top; + SQInteger n=0; + scprintf(_SC("\n>>>>stack dump<<<<\n")); + CallInfo &ci=_callsstack[_callsstacksize-1]; + scprintf(_SC("IP: %p\n"),ci._ip); + scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase); + scprintf(_SC("prev top: %d\n"),ci._prevtop); + for(SQInteger i=0;i"));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/src/3rdparty/squirrel/squirrel/sqvm.h b/src/3rdparty/squirrel/squirrel/sqvm.h new file mode 100644 index 0000000000..18c8681e75 --- /dev/null +++ b/src/3rdparty/squirrel/squirrel/sqvm.h @@ -0,0 +1,217 @@ +/* see copyright notice in squirrel.h */ +#ifndef _SQVM_H_ +#define _SQVM_H_ + +#include "sqopcodes.h" +#include "sqobject.h" +#define MAX_NATIVE_CALLS 100 +#define MIN_STACK_OVERHEAD 10 + +#define SQ_SUSPEND_FLAG -666 +//base lib +void sq_base_register(HSQUIRRELVM v); + +struct SQExceptionTrap{ + SQExceptionTrap() {} + SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;} + SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et; } + SQInteger _stackbase; + SQInteger _stacksize; + SQInstruction *_ip; + SQInteger _extarget; +}; + +#define _INLINE + +#define STK(a) _stack._vals[_stackbase+(a)] +#define TARGET _stack._vals[_stackbase+arg0] + +typedef sqvector ExceptionsTraps; + +struct SQVM : public CHAINABLE_OBJ +{ + struct VarArgs { + VarArgs() { size = 0; base = 0; } + unsigned short size; + unsigned short base; + }; + + struct CallInfo{ + //CallInfo() { _generator._type = OT_NULL;} + SQInstruction *_ip; + SQObjectPtr *_literals; + SQObjectPtr _closure; + SQGenerator *_generator; + SQInt32 _etraps; + SQInt32 _prevstkbase; + SQInt32 _prevtop; + SQInt32 _target; + SQInt32 _ncalls; + SQBool _root; + VarArgs _vargs; + }; + +typedef sqvector CallInfoVec; +public: + enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM, ET_RESUME_OPENTTD }; + SQVM(SQSharedState *ss); + ~SQVM(); + bool Init(SQVM *friendvm, SQInteger stacksize); + bool Execute(SQObjectPtr &func, SQInteger target, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL); + //starts a native call return when the NATIVE closure returns + bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger stackbase, SQObjectPtr &retval,bool &suspend); + //starts a SQUIRREL call in the same "Execution loop" + bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall); + bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor); + //call a generic closure pure SQUIRREL or NATIVE + bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror,SQBool can_suspend); + SQRESULT Suspend(); + + void CallDebugHook(SQInteger type,SQInteger forcedline=0); + void CallErrorHandler(SQObjectPtr &e); + bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, bool raw, bool fetchroot); + bool FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest,bool raw); + bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, bool fetchroot); + bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic); + bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res); + bool Clone(const SQObjectPtr &self, SQObjectPtr &target); + bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res); + bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest); + bool IsEqual(SQObjectPtr &o1,SQObjectPtr &o2,bool &res); + void ToString(const SQObjectPtr &o,SQObjectPtr &res); + SQString *PrintObjVal(const SQObject &o); + + + void Raise_Error(const SQChar *s, ...); + void Raise_Error(SQObjectPtr &desc); + void Raise_IdxError(SQObject &o); + void Raise_CompareError(const SQObject &o1, const SQObject &o2); + void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type); + + void TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest); + bool CallMetaMethod(SQDelegable *del, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres); + bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest); + bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval); + //new stuff + _INLINE bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2); + _INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2); + _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1); + _INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res); + bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func); + bool GETVARGV_OP(SQObjectPtr &target,SQObjectPtr &idx,CallInfo *ci); + bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs); + bool GETPARENT_OP(SQObjectPtr &o,SQObjectPtr &target); + //return true if the loop is finished + bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump); + bool DELEGATE_OP(SQObjectPtr &trg,SQObjectPtr &o1,SQObjectPtr &o2); + _INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); + _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr); + _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix); + void PopVarArgs(VarArgs &vargs); +#ifdef _DEBUG_DUMP + void dumpstack(SQInteger stackbase=-1, bool dumpall = false); +#endif + +#ifndef NO_GARBAGE_COLLECTOR + void Mark(SQCollectable **chain); +#endif + void Finalize(); + void GrowCallStack() { + SQInteger newsize = _alloccallsstacksize*2; + _callstackdata.resize(newsize); + _callsstack = &_callstackdata[0]; + _alloccallsstacksize = newsize; + } + void Release(){ sq_delete(this,SQVM); } //does nothing +//////////////////////////////////////////////////////////////////////////// + //stack functions for the api + void Remove(SQInteger n); + + bool IsFalse(SQObjectPtr &o); + + void Pop(); + void Pop(SQInteger n); + void Push(const SQObjectPtr &o); + SQObjectPtr &Top(); + SQObjectPtr &PopGet(); + SQObjectPtr &GetUp(SQInteger n); + SQObjectPtr &GetAt(SQInteger n); + + SQObjectPtrVec _stack; + SQObjectPtrVec _vargsstack; + SQInteger _top; + SQInteger _stackbase; + SQObjectPtr _roottable; + SQObjectPtr _lasterror; + SQObjectPtr _errorhandler; + SQObjectPtr _debughook; + + SQObjectPtr temp_reg; + + + CallInfo* _callsstack; + SQInteger _callsstacksize; + SQInteger _alloccallsstacksize; + sqvector _callstackdata; + + ExceptionsTraps _etraps; + CallInfo *ci; + void *_foreignptr; + //VMs sharing the same state + SQSharedState *_sharedstate; + SQInteger _nnativecalls; + //suspend infos + SQBool _suspended; + SQBool _suspended_root; + SQInteger _suspended_target; + SQInteger _suspended_traps; + VarArgs _suspend_varargs; + + SQBool _can_suspend; + SQInteger _ops_till_suspend; + + bool ShouldSuspend() + { + return _can_suspend && _ops_till_suspend <= 0; + } + + void DecreaseOps(SQInteger amount) + { + if (_ops_till_suspend - amount < _ops_till_suspend) _ops_till_suspend -= amount; + } +}; + +struct AutoDec{ + AutoDec(SQInteger *n) { _n = n; } + ~AutoDec() { (*_n)--; } + SQInteger *_n; +}; + +inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));} + +#define _ss(_vm_) (_vm_)->_sharedstate + +#ifndef NO_GARBAGE_COLLECTOR +#define _opt_ss(_vm_) (_vm_)->_sharedstate +#else +#define _opt_ss(_vm_) NULL +#endif + +#define PUSH_CALLINFO(v,nci){ \ + if(v->_callsstacksize == v->_alloccallsstacksize) { \ + v->GrowCallStack(); \ + } \ + v->ci = &v->_callsstack[v->_callsstacksize]; \ + *(v->ci) = nci; \ + v->_callsstacksize++; \ +} + +#define POP_CALLINFO(v){ \ + v->_callsstacksize--; \ + v->ci->_closure.Null(); \ + if(v->_callsstacksize) \ + v->ci = &v->_callsstack[v->_callsstacksize-1] ; \ + else \ + v->ci = NULL; \ +} +#endif //_SQVM_H_ diff --git a/src/misc_gui.cpp b/src/misc_gui.cpp index ba1d3a1e9c..6b6abb4c1e 100644 --- a/src/misc_gui.cpp +++ b/src/misc_gui.cpp @@ -343,6 +343,7 @@ struct AboutWindow : public Window { " Christian Rosentreter (tokai) - MorphOS / AmigaOS port", " Richard Kempton (richK) - additional airports, initial TGP implementation", "", + " Alberto Demichelis - Squirrel scripting language © 2003-2008", " Michael Blunck - Pre-Signals and Semaphores © 2003", " George - Canal/Lock graphics © 2003-2004", " David Dallaston - Tram tracks",