From a9dd6dc2f595bf8ed3ddfb2949b3e93e0cdfa66d 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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 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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 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",