Kaynağa Gözat

Merge pull request #18 from mfxmfx/master

Normalize whitespace and improve const-correctness.
albertodemichelis 9 yıl önce
ebeveyn
işleme
26d018d8b5
73 değiştirilmiş dosya ile 16437 ekleme ve 16437 silme
  1. 41 41
      COMPILE
  2. 21 21
      COPYRIGHT
  3. 509 509
      HISTORY
  4. 23 23
      README
  5. 78 78
      etc/minimal.c
  6. 4 4
      etc/test.nut
  7. 146 146
      include/sqconfig.h
  8. 16 16
      include/sqstdaux.h
  9. 20 20
      include/sqstdblob.h
  10. 53 53
      include/sqstdio.h
  11. 15 15
      include/sqstdmath.h
  12. 33 33
      include/sqstdstring.h
  13. 15 15
      include/sqstdsystem.h
  14. 399 399
      include/squirrel.h
  15. 23 23
      samples/ackermann.nut
  16. 29 29
      samples/array.nut
  17. 49 49
      samples/class.nut
  18. 35 35
      samples/classattributes.nut
  19. 25 25
      samples/coroutines.nut
  20. 54 54
      samples/delegation.nut
  21. 15 15
      samples/fibonacci.nut
  22. 33 33
      samples/flow.nut
  23. 42 42
      samples/generators.nut
  24. 1 1
      samples/hello.nut
  25. 40 40
      samples/list.nut
  26. 32 32
      samples/loops.nut
  27. 44 44
      samples/matrix.nut
  28. 115 115
      samples/metamethods.nut
  29. 68 68
      samples/methcall.nut
  30. 24 24
      samples/tailstate.nut
  31. 21 21
      sq/Makefile
  32. 350 350
      sq/sq.c
  33. 1 1
      sqstdlib/CMakeLists.txt
  34. 41 41
      sqstdlib/Makefile
  35. 130 130
      sqstdlib/sqstdaux.cpp
  36. 277 277
      sqstdlib/sqstdblob.cpp
  37. 108 108
      sqstdlib/sqstdblobimpl.h
  38. 485 485
      sqstdlib/sqstdio.cpp
  39. 107 107
      sqstdlib/sqstdmath.cpp
  40. 663 663
      sqstdlib/sqstdrex.cpp
  41. 336 336
      sqstdlib/sqstdstream.cpp
  42. 18 18
      sqstdlib/sqstdstream.h
  43. 488 488
      sqstdlib/sqstdstring.cpp
  44. 146 146
      sqstdlib/sqstdsystem.cpp
  45. 52 52
      squirrel/Makefile
  46. 1602 1602
      squirrel/sqapi.cpp
  47. 94 94
      squirrel/sqarray.h
  48. 1266 1266
      squirrel/sqbaselib.cpp
  49. 210 210
      squirrel/sqclass.cpp
  50. 162 162
      squirrel/sqclass.h
  51. 201 201
      squirrel/sqclosure.h
  52. 1577 1577
      squirrel/sqcompiler.cpp
  53. 78 78
      squirrel/sqcompiler.h
  54. 118 118
      squirrel/sqdebug.cpp
  55. 154 154
      squirrel/sqfuncproto.h
  56. 653 653
      squirrel/sqfuncstate.cpp
  57. 91 91
      squirrel/sqfuncstate.h
  58. 491 491
      squirrel/sqlexer.cpp
  59. 47 47
      squirrel/sqlexer.h
  60. 11 11
      squirrel/sqmem.cpp
  61. 677 677
      squirrel/sqobject.cpp
  62. 354 354
      squirrel/sqobject.h
  63. 132 132
      squirrel/sqopcodes.h
  64. 20 20
      squirrel/sqpcheader.h
  65. 658 658
      squirrel/sqstate.cpp
  66. 136 136
      squirrel/sqstate.h
  67. 31 31
      squirrel/sqstring.h
  68. 221 221
      squirrel/sqtable.cpp
  69. 110 110
      squirrel/sqtable.h
  70. 40 40
      squirrel/squserdata.h
  71. 116 116
      squirrel/squtils.h
  72. 1748 1748
      squirrel/sqvm.cpp
  73. 214 214
      squirrel/sqvm.h

+ 41 - 41
COMPILE

@@ -1,41 +1,41 @@
-Squirrel 3.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!)
+Squirrel 3.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!)

+ 21 - 21
COPYRIGHT

@@ -1,21 +1,21 @@
-Copyright (c) 2003-2015 Alberto Demichelis
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
------------------------------------------------------
-END OF COPYRIGHT
+Copyright (c) 2003-2015 Alberto Demichelis
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+-----------------------------------------------------
+END OF COPYRIGHT

+ 509 - 509
HISTORY

@@ -1,509 +1,509 @@
-***version 3.1 stable***
--added slice range for tolower and toupper
--added startswith() and endswith() in string lib
--added SQ_EXCLUDE_DEFAULT_MEMFUNCTIONS to exclude default mem fuction from compilation
--added sq_getreleasehook
--added thread.wakeupthrow()
--added sq_pushthread
--fixed optimizer bug in compound arith oprators(+=,-= etc...)
--fixed sq_getrefvmcount() (thx Gerrit)
--fixed sq_getrefcount() when no references were added with sq_addref() (thx Gerrit)
--fixed weakref comparison in 32bit builds using doubles(thx Domingo)
--fixed compiler bug(thx Peter)
--fixed some error in the documentation(thx Alexander)
--fixed some error reporting in compiler(thx Alexander)
--fixed incorrect optional semicolon after "if block"(thx Alexander)
--fixed crash bug in compiler related to compound arith operators(+=,-= etc...) (thx Jeff1)
-
-***2015-01-10	   ***
-***version 3.1 RC 1***
--added new header sqconfig.h for all optional type declarations(unicode, 64bits etc..)
--added sq_setsharedforeignptr sq_getsharedforeignptr
--added sq_setsharedreleasehook sq_getsharedreleasehook
--added escape() in sqstd string library
--added __LINE__ and __FILE__ (thx mingodad)
--widechar support on gcc builds
--now boolean can be used in constants
--reduced dependencies on C runtime library
--newthread and sq_newthread() no longer reinitialize the root table on friend VMs(thx Lucas Cardellini)
--exceptions in the _inherited metamethod are propagated(thx Lucas Cardellini)
--'in' operator performance improvement(thx unagipai and mingodad)
--fixes crash in compiler when trying to write 'base'
--fixed bug in switch statement when using locals as case values (thx mingodad)
--fixed bug in print()(thx Lucas Cardellini)
-
-***2013-08-30		   ***
-***version 3.1 beta 1***
--added new scoping rule(root attached to closures)
--added closure.setroot() closure.getroot()
--added sq_setclosureroot() and sq_getclosureroot()
--added sq_setvmreleasehook() and sq_getvmreleasehook()
--added documentaion for sq_getbase()
--now string.tointeger() accepts an optional parameter 'base'
--now format accepts zeroes in the format string (thx mingodad)
--fixed bug in sqstd_createfile() (thx mingodad)
--minor buxfixes
-
-***2012-11-10		   ***
-***version 3.0.4 stable***
--sq_deleteslot slot now pops the key in case of failure
--fixed bug when _get metamethod throws null
--fixed a bug in rstrip
--added some error handling
--minor bugfixes
-
-***2012-06-19		   ***
-***version 3.1.0 alpha 1***
--changed in and instanceof operator precendence
--root object in closures
--added closure.setroot closure.getroot
--added sq_setclosureroot and sq_getclosureroot
-
-***version 3.0.3 stable***
--improved error messages for _cmp(when a non integer value is returned) (thx Yexo)
--added class.newmember() built in method (thx Nam)
--added class.rawnewmember()  built in method (thx Nam)
--added sq_rawnewmember() (thx Nam)
--added sq_getversion()
--added sq_typeof()
--added sq_getclosurename()
--added file.close() in stdlib
--documented closure.getinfos() built-in method
--fixed string iteration doesn't return negative numbers for characters > 127
--fixed bug in tofloat() when converting a string with scientific notation without a decimal point (thx wr2)
--fixed potential infinite loop in array.sort() when the _cmp function is inconsistent (thx Yexo)
--fixed obscure bug in the compiler(thx yishin)
--fixed some minor bug
-
-***2011-11-28		   ***
-***version 3.0.2 stable***
--added sq_gethash API
--now array.sort() is implemented with heapsort
--now floats in scientific notation also accept numbers with no '.' (eg. 1e+6 or 1e6)
--fixed some warning
--fixed some documentation
--fixed bug in GC
-
-***2011-09-08		   ***
-***version 3.0.1 stable***
--added # as alternative symbol for "line comment"(mostly useful for shell scripts)
--added sq_throwobject() to throw an arbitrary object from the C API
--added alignement flag for userdata types, SQ_ALIGNMENT (thx Shigemasa)
--added rawset() and rawget() to class and instance default delegate
--changed bytecode format now ensures matching integer size and float size
--now inherited classes also inherit userdatasize
--added SQUIRREL_VERSION_NUMBER in squirrel.h and _versionnumber_ global symbol
--fixed sq_getmemberhandle
--fixed sq_getrefcount
--refactored some sqstdio code
--refactored some clone code
--refactored some stuff in the string lib
--added -s and -fno-exceptions in GCC makefile(better performance when using GCC)
-
-***2011-03-13        ***
-***version 3.0 stable***
--added sq_getcallee()
--sq_getfreevariable() also works for native closures
--minior optimizations
--removed several warning when compiling with GCC 4.x
--fixed some errors in the documentation
--fixed bug when using SQUSEDOUBLE and 32bits intengers
--fixed bug when invoking generators with closure.call() (thx huntercool)
-
-***2010-12-19					        ***
-***version 3.0 release candidate 1(RC 1)***
--improved metamethods error handling
--added parameter 'isstatic' to _newmember metamethod(thx G.Meyer)
--added sq_getrefcount() to return number of refences from C++(thx G.Meyer)
-
-***2010-11-07        ***
-***version 3.0 beta 3***
--license changed to "MIT license"
--added sq_resurrectunreachable() and resurrectunreachable()
--added callee() built in function, returns the current running closure
--added thread.getstackinfos()
--added sq_objtouserpointer()
--added sq_newtableex()
--various refactoring and optimizations
--fixed several 64bits issues regarding integer to string conversions
--fixed some bugs when SQUSEDOUBLE is used in 32bits systems
-
-***2010-08-18          ***
-***version 3.0 beta 2.1***
--fixed bug in class constructor
--fixed bug in compound arith
-
-***2010-08-12        ***
-***version 3.0 beta 2***
--class methods can be added or replaced after the class as been instantiated
--JSON compliant table syntax, this is currently an experimental feature (thx atai)
--sq_getsize() now returns userdatasize for classes and instances
--now setroottable() and setconsttable() return the previous value of the respective table
--fixed bug in compound arith operators when used on a free variable (thx ellon)
--fixed some x64 minor bugs
--fixed minor bug in the compiler
--refactored some VM internals
--documented sq_getmemberhandle, sq_getbyhandle, sq_setbyhandle to set and get value from classes
-
-***2009-11-15        ***
-***version 3.0 beta 1***
--various refactoring and optimizations
--fixed bug in free variables (thx mokehehe)
--fixed bug in functions with default parameters (thx ara & Yexo)
--fixed bug in exception handling
--improved error propagation in _set and _get metamethods ( and 'throw null' for clean failure)
--added sq_getmemberhandle, sq_getbyhandle, sq_setbyhandle to set and get value from classes
-
-***2009-06-30         ***
-***version 3.0 alpha 2***
--added real free variables(thx Paul Ruizendaal)
--added refactored function call implementation and compiler(thx Paul Ruizendaal)
--added sq_getfunctioninfo
--added compile time flag SQUSEDOUBLE to use double precision floats
--added global slot _floatsize_ int the base lib to recognize single precision and double precision builds
--sq_wakeupvm can now resume the vm with an exception
--added sqstd_format
--now blobs can be cloned
--generators can now be instantiated by calling sq_call() or closure.call()
--fixed debughook bug
--fixed cooroutine error propagation
-
-***2008-07-23         ***
-***version 3.0 alpha 1***
--first branch from 2.x source tree
--added 'base' keyword
--removed 'delegate' keyword
--now compiled scripts are vararg functions
--added setdelegate() and getdelegate() table builtin methods
--added <=> 3 ways compare operator
--added lambda expression @(a,b) a + b
--added local function statement
--added array built-in map(),reduce(),apply(),filter() and find()
--generators hold only a weak reference of the enviroment object
--removed 'vargv' and 'vargc' keywords
--now var args are passed as an array called vargv(as a paramter)
--removed 'parent' keyword
--added class getbase() built in method
--instanceof doesn't throw an exception if the left expression is not a class
--lexical scoping for free variables(free variables are no longer in the second parameter list)
--sq_setprintfunc accept error func
--sq_geterrorfunc()
--added sq_arrayremove() and sq_arrayinsert()
--error() built in function(works like print but prints using the errorfunc)
--added native debug hook
-
-***2008-02-17        ***
-***version 2.2 stable***
--added _newslot metamethod in classes
--added enums added constants
--added sq_pushconsttable, sq_setconsttable
--added default param
--added octal literals(thx Dinosaur)
--fixed debug hook, 'calls' and 'returns' are properly notified in the same number.
--fixed a coroutine bug
-
-***2007-07-29          ***
-***version 2.1.2 stable***
--new behaviour for generators iteration using foreach
-now when a generator is iterated by foreach the value returned by a 'return val' statement
-will terminate the iteration but will not be returned as foreach iteration
--added sq_setclassudsize()
--added sq_clear()
--added table.clear(), array.clear()
--fixed sq_cmp() (thx jyuill)
--fixed minor bugs
-
-***2006-08-21		   ***
-***version 2.1.1 stable***
--vm refactoring
--optimized internal function memory layout
--new global symbol _version_ (is the version string)
--code size optimization for float literals(on 32bits float builts)
--now the raw ref API(sq_addref etc...) is fully reentrant.
--fixed a bug in sq_getdelegate() now pushes null if the object doesn't have a delegate(thx MatzeB)
--improved C reference performances in NO_GARBAGE_COLLECTOR builds
--sq_getlocal() now enumerates also outer values.
--fixed regexp library for GCC users.
-
-***2006-03-19	     ***
-***version 2.1 stable***
--added static class fields, new keyword static
--added 64bits architecture support
--added global slot _intsize_ int the base lib to recognize 32bits and 64bits builds
--added functions with fixed environment, closure.bindenv() built-in function
--all types except userdata and null implement the tostring() method
--string concatenation now invokes metamethod _tostring
--new metamethods for class objects _newmember and _inherited
--sq_call() sq_resume() sq_wakeupvm() have a new signature
--new C referencing implementation(scales more with the amount of references)
--refactored hash table
--new api functions sq_newslot(),sq_tobool(),sq_getbase(), sq_instanceof(), sq_bindenv()
--the api func sq_createslot was deprecated but still supported in form of C macro on top of sq_newslot
--sq_setreleasehook() now also works for classes
--stream.readstr() and stream.writestr() have been deprecated(this affects file and blob)
--fixed squirrel.h undeclared api calls
--fixed few minor bugs
--SQChar is now defined as wchar_t
--removed warning when building with -Wall -pedantic for GCC users
--added new std io function writeclosuretofile()
--added new std string functions strip(),rstrip(),lstrip() and split()
--regular expressions operators (+,*) now have more POSIX greedyness behaviour
--class constructors are now invoked as normal functions
-
-***2005-10-02	       ***
-***version 2.0.5 stable***
--fixed some 64bits incompatibilities (thx sarge)
--fixed minor bug in the stdlib format() function (thx Rick)
--fixed a bug in dofile() that was preventing to compile empty files
--added new API sq_poptop() & sq_getfreevariable()
--some performance improvements
-
-***2005-08-14	       ***
-***version 2.0.4 stable***
--weak references and related API calls
--added sq_objtobool()
--class instances memory policies improved(1 mem allocation for the whole instance)
--typetags are now declared as SQUserPointer instead of unsigned int
--first pass for 64bits compatibility
--fixed minor bug in the stdio stream
--fixed a bug in format()
--fixed bug in string.tointeger() and string.tofloat()
-
-***2005-06-24	       ***
-***version 2.0.3 stable***
--dofile() and loadfile() in the iolib now can decode ASCII, UTF8 files UCS2 big-endian and little-endian
--sq_setparamscheck() : now typemesk can check for null
--added string escape sequence \xhhhh
--fixed some C++ standard incompatibilities
-
-***2005-05-15	       ***
-***version 2.0.2 stable***
--performances improvements (expecially for GCC users)
--removed all dependencies from C++ exception handling
--various bugfixes
-
-***2005-04-12		 ***
-***version 2.0.1 stable***
--various bugfixes
--sq_setparamscheck() now allows spaces in the typemask
-
-***2005-04-03		 ***
-***version 2.0 stable***
--added API sq_gettypetag()
--added built-in function to the bool type(tointeger, tostring etc...)
-
-***2005-02-27							***
-***version 2.0 release candidate 1(RC 1)***
--added API sq_reseterror()
--modified sq_release()
--now class instances can be cloned
--various bufixes
-
-***2005-01-26        ***
-***version 2.0 beta 1***
--added bool type
--class properties can be redefined in a derived class
--added ops *= /= and %=
--new syntax for class attributes declaration </ and /> instead of ( and )
--increased the max number of literals per function from 65535 to 16777215
--now free variables have proper lexical scoping
--added API sq_createinstance(), sq_pushbool(), sq_getbool()
--added built-in function type()
--added built-in function obj.rawin(key) in table,class and instance
--sq_rawget() and sq_rawset() now work also on classes and instances
--the VM no longer uses C++ exception handling (more suitable for embedded devices)
--various bufixes
-
-***2004-12-21         ***
-***version 2.0 alpha 2***
--globals scoping changed, now if :: is omitted the VM automatically falls back on the root table
--various bufixes
--added class level attributes
-
-***2004-12-12         ***
-***version 2.0 alpha 1***
--codebase branch from version 1.x
--added classes
--added functions with variable number of parameters(vargc & vargv and the ...)
--0 and 0.0 are now considered 'false' by all conditional statements(if,while,for,?,do-while)
--added new api functions sq_newclass() sq_setinstanceup() sq_getinstanceup() sq_getattributes() sq_setattributes()
--modified api sq_settypetag()
-
-***2004-11-01        ***
-***version 1.0 stable***
--fixed some minor bug
--improved operator 'delete' performances
--added scientific notation for float numbers( eg. 2.e16 or 2.e-2)
-
-***2004-08-30        ***
-***version 1.0 release candidate 2(RC 2)***
--fixed bug in the vm(thx Pierre Renaux)
--fixed bug in the optimizer(thx Pierre Renaux)
--fixed some bug in the documentation(thx JD)
--added new api functions for raw object handling
--removed nested multiline comments
--reduced memory footprint in C references
-
-***2004-08-23        ***
-***version 1.0 release candidate 1(RC 1)***
--fixed division by zero
--the 'in' operator and obj.rawget() do not query the default delegate anymore
--added function sq_getprintfunc()
--added new standard library 'auxlib'(implements default error handlers)
-
-***2004-07-12        ***
-***version 1.0 beta 4***
--fixed a bug in the integer.tochar() built-in method
--fixed unary minus operator
--fixed bug in dofile()
--fixed inconsistency between != and == operators(on float/integer comparison)
--added javascript style unsigned right shift operator '>>>'
--added array(size) constructor built-in function
--array.resize(size,[fill]) built-in function accepts an optional 'fill' value
--improved debug API, added sq_getclosureinfo() and sq_setnativeclosurename()
-
-***2004-05-23        ***
-***version 1.0 beta 3***
--minor vm bug fixes
--string allocation is now faster
--tables and array memory usage is now less conservative(they shrink)
--added regular expression routines in the standard library
--The 'c' expression now accepts only 1 character(thx irbrian)
--multiline strings <[ ]> have been substituted with C# style verbatim strings (eg. @"string")
--added new keyword 'parent' for accessing the delegate of tables and unserdata
--The metamethod '_clone' has been renamed '_cloned'
--the _delslot metamethod's behaviour and prototype have been changed
--new default function in the integer and float object 'tochar()'
--the built-in function chcode2string has been removed
--the default method [table].getdelegate() has been removed
--new api sq_rawdeleteslot()
--new table built-in method rawdelete(key)
--the dynamic mudule loading has been removed from the standard distribution
--some optimizations in the VM
-
-***2004-04-21        ***
-***version 1.0 beta 2***
--minor compiler/parser bug fixes
--sq_newclosure has a different prototype, the "paramscheck" of paramter has been moved to the new function sq_setparamscheck()
--sq_setparamscheck allows to add automatic parameters type checking in native closures
--sq_compile() lost the lineinfo parameter
--new api sq_enabledebuginfo() globally sets compiler's debug info generation
--added consistency check on bytecode serialization
--fixed += operator, now works on strings like +
--added global slot in the base lib _charsize_ to recognize unicode builds from ascii builds runtime
--added registry table
--new api call sq_pushregistrytable()
--added type tag to the userdata type sq_settypetag()
--sq_getuserdata now queries the userdata typetag
--the built in function collect_garbage() as been renamed collectgarbage() for consistency reasons
--new standard libraries(sqlibs are now obsolete)
-
-***2004-02-20	     ***
-***version 1.0 beta 1***
--fixed a bug in the compiler (thanks Martin Kofler)
--fixed bug in the switch case statement
--fixed the _unm metamethod
--fixed minor bugs in the API
--fixed automatic stack resizing
--first beta version 
-	first pass code clean up in the VM and base lib
-	first pass code coverege test has been done on VM and built-in lib
--new VM creation API sq_open() sq_close() (sq_newvm and sq_releasevm are now obsolete)
--new api allows to specifiy a "print" function to output text(sq_printfunc)
--added some small optimizations
--new cooperative multi-threading capabilities in the base library(coroutines), VMs are now a built in type("thread")
--new built in functions have been added for manipulating the new "thread" type
--friend virtual machines share the same root table, error handler and debug hook by default
--new compile time options
-
-***2004-01-19       ***
-***version 0.9 alpha***
--fixed a garbage collection bug
--fixed some API bugs(thanks to Joshua Jensen)
--fixed tail calls (in the version 0.8 the tail call optimization was erroneously disabled)
--new function parameters semantic, now passing a wrong number of parameters generates an exception
--native closures have now a built in parameter number checking
--sq_rawget and sq_rawset now work also on arrays
--sq_getsize now woks also on userdata
--the userdata release hook prototype is changed(now passes the size of the userdata)
--the lexer reader function now returns an integer instead of a char that allows better error checking on the input(thx Joshua Jensen)
--faster compiler
--try/catch blocks do not cause any runtime memory allocation anymore
-
-***2003-12-06       ***
-***version 0.8 alpha***
--fixed a bug that was preventing to have callable userdata throught the metamethod _call
--fixed a garbage collection bug
--fixed == operator now can compare correctly different types
--new built in method getstackinfos(level)
--improved line informations precision for the debug hook
--new api call sq_compilebuffer()
--new built-in api function compilestring()
--new syntactic sugar for function declarations inside tables
--the debug API has been finalized
-
-***2003-11-17       ***
-***version 0.7 alpha***
--fixed critical bug SQInteger the tail call system
--fixed bug in the continue statement code generation
--fixed func call param issue(thanks to Rewoonenco Andrew)
--added _delslot metamethod(thanks to Rewoonenco Andrew)
--new multiline string expression ( delimited by <[ and ]> )
--normal strings ("") do not allow embedded new line anymore
--reduced vm memory footprint(C refs are shared between friend VMs)
--new api method sq_deleteslot()
--new debug hook event 'r' is triggered when a function returns
-
-***2003-11-04       ***
-***version 0.6 alpha***
--fixed switch statement(was executing the default case after a break)
--sq_call() doesn't pop the closure (just the params)
--the vm execution can be suspended from the C API anytime (micro-threads)
--new api calls sq_suspendvm() sq_wakeupvm() sq_getvmstate() and sq_reservestack()
-
-***2003-10-13       ***
-***version 0.5 alpha***
--fixed some minor bug
--tested with non ASCII identifiers in unicode mode(I've tried chinese chars)
--added built-in function string.find()
--the built-in function array.sort() optionally accepts a cmp(a,b) function
--the debug hook function now has a new prototype debug_hook(event_type,sourcefile,line,functionname)
--fixed some debug info imprecision
-
-***2003-10-01       ***
-***version 0.4 alpha***
--faster VM
--sq_call will pop arguments and closure also in case of failure
--fixed a bug in sq_remove
--now the VM detects delegation cycles(and throws an exception)
--new operators ++ and --
--new operator ',' comma operator
--fixed some expression precedence issue
--fixed bug in sq_arraypop
-
-***2003-09-15       ***
-***version 0.3 alpha***
--fixed a bug in array::insert()
--optional Unicode core(define SQUNICODE or _UNICODE on Win32)
--sq_compiler uses a new reader function SQLEXREADFUNC
--the debug hook passes 'l' instead of 'line' for line callbacks
-	and 'c' instead of 'call' for call callbacks
--new array.extend() bulit-in function
--new API sq_clone()
-
-***2003-09-10           ***
-***version 0.2 pre-alpha***
--new completely reentrant VM (sq_open and sq_close are now obsolete)
--sq_newvm() has a new prototype
--allocators are now global and linked in the VM
--_newslot meta method added
--rawset creates a slot if doesn't exists
--the compiler error callback pass the vm handle(thanks Pierre Renaux)
--sq_setforeignptr() sq_getforeingptr() are now public
--sq_resume() now is possible to resume generators from C
--sq_getlasterror() retrieve the last thrown error
--improved docs
-
-***2003-09-06           ***
-***version 0.1 pre-alpha***
-first release
+***version 3.1 stable***
+-added slice range for tolower and toupper
+-added startswith() and endswith() in string lib
+-added SQ_EXCLUDE_DEFAULT_MEMFUNCTIONS to exclude default mem fuction from compilation
+-added sq_getreleasehook
+-added thread.wakeupthrow()
+-added sq_pushthread
+-fixed optimizer bug in compound arith oprators(+=,-= etc...)
+-fixed sq_getrefvmcount() (thx Gerrit)
+-fixed sq_getrefcount() when no references were added with sq_addref() (thx Gerrit)
+-fixed weakref comparison in 32bit builds using doubles(thx Domingo)
+-fixed compiler bug(thx Peter)
+-fixed some error in the documentation(thx Alexander)
+-fixed some error reporting in compiler(thx Alexander)
+-fixed incorrect optional semicolon after "if block"(thx Alexander)
+-fixed crash bug in compiler related to compound arith operators(+=,-= etc...) (thx Jeff1)
+
+***2015-01-10      ***
+***version 3.1 RC 1***
+-added new header sqconfig.h for all optional type declarations(unicode, 64bits etc..)
+-added sq_setsharedforeignptr sq_getsharedforeignptr
+-added sq_setsharedreleasehook sq_getsharedreleasehook
+-added escape() in sqstd string library
+-added __LINE__ and __FILE__ (thx mingodad)
+-widechar support on gcc builds
+-now boolean can be used in constants
+-reduced dependencies on C runtime library
+-newthread and sq_newthread() no longer reinitialize the root table on friend VMs(thx Lucas Cardellini)
+-exceptions in the _inherited metamethod are propagated(thx Lucas Cardellini)
+-'in' operator performance improvement(thx unagipai and mingodad)
+-fixes crash in compiler when trying to write 'base'
+-fixed bug in switch statement when using locals as case values (thx mingodad)
+-fixed bug in print()(thx Lucas Cardellini)
+
+***2013-08-30          ***
+***version 3.1 beta 1***
+-added new scoping rule(root attached to closures)
+-added closure.setroot() closure.getroot()
+-added sq_setclosureroot() and sq_getclosureroot()
+-added sq_setvmreleasehook() and sq_getvmreleasehook()
+-added documentaion for sq_getbase()
+-now string.tointeger() accepts an optional parameter 'base'
+-now format accepts zeroes in the format string (thx mingodad)
+-fixed bug in sqstd_createfile() (thx mingodad)
+-minor buxfixes
+
+***2012-11-10          ***
+***version 3.0.4 stable***
+-sq_deleteslot slot now pops the key in case of failure
+-fixed bug when _get metamethod throws null
+-fixed a bug in rstrip
+-added some error handling
+-minor bugfixes
+
+***2012-06-19          ***
+***version 3.1.0 alpha 1***
+-changed in and instanceof operator precendence
+-root object in closures
+-added closure.setroot closure.getroot
+-added sq_setclosureroot and sq_getclosureroot
+
+***version 3.0.3 stable***
+-improved error messages for _cmp(when a non integer value is returned) (thx Yexo)
+-added class.newmember() built in method (thx Nam)
+-added class.rawnewmember()  built in method (thx Nam)
+-added sq_rawnewmember() (thx Nam)
+-added sq_getversion()
+-added sq_typeof()
+-added sq_getclosurename()
+-added file.close() in stdlib
+-documented closure.getinfos() built-in method
+-fixed string iteration doesn't return negative numbers for characters > 127
+-fixed bug in tofloat() when converting a string with scientific notation without a decimal point (thx wr2)
+-fixed potential infinite loop in array.sort() when the _cmp function is inconsistent (thx Yexo)
+-fixed obscure bug in the compiler(thx yishin)
+-fixed some minor bug
+
+***2011-11-28          ***
+***version 3.0.2 stable***
+-added sq_gethash API
+-now array.sort() is implemented with heapsort
+-now floats in scientific notation also accept numbers with no '.' (eg. 1e+6 or 1e6)
+-fixed some warning
+-fixed some documentation
+-fixed bug in GC
+
+***2011-09-08          ***
+***version 3.0.1 stable***
+-added # as alternative symbol for "line comment"(mostly useful for shell scripts)
+-added sq_throwobject() to throw an arbitrary object from the C API
+-added alignement flag for userdata types, SQ_ALIGNMENT (thx Shigemasa)
+-added rawset() and rawget() to class and instance default delegate
+-changed bytecode format now ensures matching integer size and float size
+-now inherited classes also inherit userdatasize
+-added SQUIRREL_VERSION_NUMBER in squirrel.h and _versionnumber_ global symbol
+-fixed sq_getmemberhandle
+-fixed sq_getrefcount
+-refactored some sqstdio code
+-refactored some clone code
+-refactored some stuff in the string lib
+-added -s and -fno-exceptions in GCC makefile(better performance when using GCC)
+
+***2011-03-13        ***
+***version 3.0 stable***
+-added sq_getcallee()
+-sq_getfreevariable() also works for native closures
+-minior optimizations
+-removed several warning when compiling with GCC 4.x
+-fixed some errors in the documentation
+-fixed bug when using SQUSEDOUBLE and 32bits intengers
+-fixed bug when invoking generators with closure.call() (thx huntercool)
+
+***2010-12-19                           ***
+***version 3.0 release candidate 1(RC 1)***
+-improved metamethods error handling
+-added parameter 'isstatic' to _newmember metamethod(thx G.Meyer)
+-added sq_getrefcount() to return number of refences from C++(thx G.Meyer)
+
+***2010-11-07        ***
+***version 3.0 beta 3***
+-license changed to "MIT license"
+-added sq_resurrectunreachable() and resurrectunreachable()
+-added callee() built in function, returns the current running closure
+-added thread.getstackinfos()
+-added sq_objtouserpointer()
+-added sq_newtableex()
+-various refactoring and optimizations
+-fixed several 64bits issues regarding integer to string conversions
+-fixed some bugs when SQUSEDOUBLE is used in 32bits systems
+
+***2010-08-18          ***
+***version 3.0 beta 2.1***
+-fixed bug in class constructor
+-fixed bug in compound arith
+
+***2010-08-12        ***
+***version 3.0 beta 2***
+-class methods can be added or replaced after the class as been instantiated
+-JSON compliant table syntax, this is currently an experimental feature (thx atai)
+-sq_getsize() now returns userdatasize for classes and instances
+-now setroottable() and setconsttable() return the previous value of the respective table
+-fixed bug in compound arith operators when used on a free variable (thx ellon)
+-fixed some x64 minor bugs
+-fixed minor bug in the compiler
+-refactored some VM internals
+-documented sq_getmemberhandle, sq_getbyhandle, sq_setbyhandle to set and get value from classes
+
+***2009-11-15        ***
+***version 3.0 beta 1***
+-various refactoring and optimizations
+-fixed bug in free variables (thx mokehehe)
+-fixed bug in functions with default parameters (thx ara & Yexo)
+-fixed bug in exception handling
+-improved error propagation in _set and _get metamethods ( and 'throw null' for clean failure)
+-added sq_getmemberhandle, sq_getbyhandle, sq_setbyhandle to set and get value from classes
+
+***2009-06-30         ***
+***version 3.0 alpha 2***
+-added real free variables(thx Paul Ruizendaal)
+-added refactored function call implementation and compiler(thx Paul Ruizendaal)
+-added sq_getfunctioninfo
+-added compile time flag SQUSEDOUBLE to use double precision floats
+-added global slot _floatsize_ int the base lib to recognize single precision and double precision builds
+-sq_wakeupvm can now resume the vm with an exception
+-added sqstd_format
+-now blobs can be cloned
+-generators can now be instantiated by calling sq_call() or closure.call()
+-fixed debughook bug
+-fixed cooroutine error propagation
+
+***2008-07-23         ***
+***version 3.0 alpha 1***
+-first branch from 2.x source tree
+-added 'base' keyword
+-removed 'delegate' keyword
+-now compiled scripts are vararg functions
+-added setdelegate() and getdelegate() table builtin methods
+-added <=> 3 ways compare operator
+-added lambda expression @(a,b) a + b
+-added local function statement
+-added array built-in map(),reduce(),apply(),filter() and find()
+-generators hold only a weak reference of the enviroment object
+-removed 'vargv' and 'vargc' keywords
+-now var args are passed as an array called vargv(as a paramter)
+-removed 'parent' keyword
+-added class getbase() built in method
+-instanceof doesn't throw an exception if the left expression is not a class
+-lexical scoping for free variables(free variables are no longer in the second parameter list)
+-sq_setprintfunc accept error func
+-sq_geterrorfunc()
+-added sq_arrayremove() and sq_arrayinsert()
+-error() built in function(works like print but prints using the errorfunc)
+-added native debug hook
+
+***2008-02-17        ***
+***version 2.2 stable***
+-added _newslot metamethod in classes
+-added enums added constants
+-added sq_pushconsttable, sq_setconsttable
+-added default param
+-added octal literals(thx Dinosaur)
+-fixed debug hook, 'calls' and 'returns' are properly notified in the same number.
+-fixed a coroutine bug
+
+***2007-07-29          ***
+***version 2.1.2 stable***
+-new behaviour for generators iteration using foreach
+now when a generator is iterated by foreach the value returned by a 'return val' statement
+will terminate the iteration but will not be returned as foreach iteration
+-added sq_setclassudsize()
+-added sq_clear()
+-added table.clear(), array.clear()
+-fixed sq_cmp() (thx jyuill)
+-fixed minor bugs
+
+***2006-08-21          ***
+***version 2.1.1 stable***
+-vm refactoring
+-optimized internal function memory layout
+-new global symbol _version_ (is the version string)
+-code size optimization for float literals(on 32bits float builts)
+-now the raw ref API(sq_addref etc...) is fully reentrant.
+-fixed a bug in sq_getdelegate() now pushes null if the object doesn't have a delegate(thx MatzeB)
+-improved C reference performances in NO_GARBAGE_COLLECTOR builds
+-sq_getlocal() now enumerates also outer values.
+-fixed regexp library for GCC users.
+
+***2006-03-19        ***
+***version 2.1 stable***
+-added static class fields, new keyword static
+-added 64bits architecture support
+-added global slot _intsize_ int the base lib to recognize 32bits and 64bits builds
+-added functions with fixed environment, closure.bindenv() built-in function
+-all types except userdata and null implement the tostring() method
+-string concatenation now invokes metamethod _tostring
+-new metamethods for class objects _newmember and _inherited
+-sq_call() sq_resume() sq_wakeupvm() have a new signature
+-new C referencing implementation(scales more with the amount of references)
+-refactored hash table
+-new api functions sq_newslot(),sq_tobool(),sq_getbase(), sq_instanceof(), sq_bindenv()
+-the api func sq_createslot was deprecated but still supported in form of C macro on top of sq_newslot
+-sq_setreleasehook() now also works for classes
+-stream.readstr() and stream.writestr() have been deprecated(this affects file and blob)
+-fixed squirrel.h undeclared api calls
+-fixed few minor bugs
+-SQChar is now defined as wchar_t
+-removed warning when building with -Wall -pedantic for GCC users
+-added new std io function writeclosuretofile()
+-added new std string functions strip(),rstrip(),lstrip() and split()
+-regular expressions operators (+,*) now have more POSIX greedyness behaviour
+-class constructors are now invoked as normal functions
+
+***2005-10-02          ***
+***version 2.0.5 stable***
+-fixed some 64bits incompatibilities (thx sarge)
+-fixed minor bug in the stdlib format() function (thx Rick)
+-fixed a bug in dofile() that was preventing to compile empty files
+-added new API sq_poptop() & sq_getfreevariable()
+-some performance improvements
+
+***2005-08-14          ***
+***version 2.0.4 stable***
+-weak references and related API calls
+-added sq_objtobool()
+-class instances memory policies improved(1 mem allocation for the whole instance)
+-typetags are now declared as SQUserPointer instead of unsigned int
+-first pass for 64bits compatibility
+-fixed minor bug in the stdio stream
+-fixed a bug in format()
+-fixed bug in string.tointeger() and string.tofloat()
+
+***2005-06-24          ***
+***version 2.0.3 stable***
+-dofile() and loadfile() in the iolib now can decode ASCII, UTF8 files UCS2 big-endian and little-endian
+-sq_setparamscheck() : now typemesk can check for null
+-added string escape sequence \xhhhh
+-fixed some C++ standard incompatibilities
+
+***2005-05-15          ***
+***version 2.0.2 stable***
+-performances improvements (expecially for GCC users)
+-removed all dependencies from C++ exception handling
+-various bugfixes
+
+***2005-04-12        ***
+***version 2.0.1 stable***
+-various bugfixes
+-sq_setparamscheck() now allows spaces in the typemask
+
+***2005-04-03        ***
+***version 2.0 stable***
+-added API sq_gettypetag()
+-added built-in function to the bool type(tointeger, tostring etc...)
+
+***2005-02-27                           ***
+***version 2.0 release candidate 1(RC 1)***
+-added API sq_reseterror()
+-modified sq_release()
+-now class instances can be cloned
+-various bufixes
+
+***2005-01-26        ***
+***version 2.0 beta 1***
+-added bool type
+-class properties can be redefined in a derived class
+-added ops *= /= and %=
+-new syntax for class attributes declaration </ and /> instead of ( and )
+-increased the max number of literals per function from 65535 to 16777215
+-now free variables have proper lexical scoping
+-added API sq_createinstance(), sq_pushbool(), sq_getbool()
+-added built-in function type()
+-added built-in function obj.rawin(key) in table,class and instance
+-sq_rawget() and sq_rawset() now work also on classes and instances
+-the VM no longer uses C++ exception handling (more suitable for embedded devices)
+-various bufixes
+
+***2004-12-21         ***
+***version 2.0 alpha 2***
+-globals scoping changed, now if :: is omitted the VM automatically falls back on the root table
+-various bufixes
+-added class level attributes
+
+***2004-12-12         ***
+***version 2.0 alpha 1***
+-codebase branch from version 1.x
+-added classes
+-added functions with variable number of parameters(vargc & vargv and the ...)
+-0 and 0.0 are now considered 'false' by all conditional statements(if,while,for,?,do-while)
+-added new api functions sq_newclass() sq_setinstanceup() sq_getinstanceup() sq_getattributes() sq_setattributes()
+-modified api sq_settypetag()
+
+***2004-11-01        ***
+***version 1.0 stable***
+-fixed some minor bug
+-improved operator 'delete' performances
+-added scientific notation for float numbers( eg. 2.e16 or 2.e-2)
+
+***2004-08-30        ***
+***version 1.0 release candidate 2(RC 2)***
+-fixed bug in the vm(thx Pierre Renaux)
+-fixed bug in the optimizer(thx Pierre Renaux)
+-fixed some bug in the documentation(thx JD)
+-added new api functions for raw object handling
+-removed nested multiline comments
+-reduced memory footprint in C references
+
+***2004-08-23        ***
+***version 1.0 release candidate 1(RC 1)***
+-fixed division by zero
+-the 'in' operator and obj.rawget() do not query the default delegate anymore
+-added function sq_getprintfunc()
+-added new standard library 'auxlib'(implements default error handlers)
+
+***2004-07-12        ***
+***version 1.0 beta 4***
+-fixed a bug in the integer.tochar() built-in method
+-fixed unary minus operator
+-fixed bug in dofile()
+-fixed inconsistency between != and == operators(on float/integer comparison)
+-added javascript style unsigned right shift operator '>>>'
+-added array(size) constructor built-in function
+-array.resize(size,[fill]) built-in function accepts an optional 'fill' value
+-improved debug API, added sq_getclosureinfo() and sq_setnativeclosurename()
+
+***2004-05-23        ***
+***version 1.0 beta 3***
+-minor vm bug fixes
+-string allocation is now faster
+-tables and array memory usage is now less conservative(they shrink)
+-added regular expression routines in the standard library
+-The 'c' expression now accepts only 1 character(thx irbrian)
+-multiline strings <[ ]> have been substituted with C# style verbatim strings (eg. @"string")
+-added new keyword 'parent' for accessing the delegate of tables and unserdata
+-The metamethod '_clone' has been renamed '_cloned'
+-the _delslot metamethod's behaviour and prototype have been changed
+-new default function in the integer and float object 'tochar()'
+-the built-in function chcode2string has been removed
+-the default method [table].getdelegate() has been removed
+-new api sq_rawdeleteslot()
+-new table built-in method rawdelete(key)
+-the dynamic mudule loading has been removed from the standard distribution
+-some optimizations in the VM
+
+***2004-04-21        ***
+***version 1.0 beta 2***
+-minor compiler/parser bug fixes
+-sq_newclosure has a different prototype, the "paramscheck" of paramter has been moved to the new function sq_setparamscheck()
+-sq_setparamscheck allows to add automatic parameters type checking in native closures
+-sq_compile() lost the lineinfo parameter
+-new api sq_enabledebuginfo() globally sets compiler's debug info generation
+-added consistency check on bytecode serialization
+-fixed += operator, now works on strings like +
+-added global slot in the base lib _charsize_ to recognize unicode builds from ascii builds runtime
+-added registry table
+-new api call sq_pushregistrytable()
+-added type tag to the userdata type sq_settypetag()
+-sq_getuserdata now queries the userdata typetag
+-the built in function collect_garbage() as been renamed collectgarbage() for consistency reasons
+-new standard libraries(sqlibs are now obsolete)
+
+***2004-02-20        ***
+***version 1.0 beta 1***
+-fixed a bug in the compiler (thanks Martin Kofler)
+-fixed bug in the switch case statement
+-fixed the _unm metamethod
+-fixed minor bugs in the API
+-fixed automatic stack resizing
+-first beta version
+    first pass code clean up in the VM and base lib
+    first pass code coverege test has been done on VM and built-in lib
+-new VM creation API sq_open() sq_close() (sq_newvm and sq_releasevm are now obsolete)
+-new api allows to specifiy a "print" function to output text(sq_printfunc)
+-added some small optimizations
+-new cooperative multi-threading capabilities in the base library(coroutines), VMs are now a built in type("thread")
+-new built in functions have been added for manipulating the new "thread" type
+-friend virtual machines share the same root table, error handler and debug hook by default
+-new compile time options
+
+***2004-01-19       ***
+***version 0.9 alpha***
+-fixed a garbage collection bug
+-fixed some API bugs(thanks to Joshua Jensen)
+-fixed tail calls (in the version 0.8 the tail call optimization was erroneously disabled)
+-new function parameters semantic, now passing a wrong number of parameters generates an exception
+-native closures have now a built in parameter number checking
+-sq_rawget and sq_rawset now work also on arrays
+-sq_getsize now woks also on userdata
+-the userdata release hook prototype is changed(now passes the size of the userdata)
+-the lexer reader function now returns an integer instead of a char that allows better error checking on the input(thx Joshua Jensen)
+-faster compiler
+-try/catch blocks do not cause any runtime memory allocation anymore
+
+***2003-12-06       ***
+***version 0.8 alpha***
+-fixed a bug that was preventing to have callable userdata throught the metamethod _call
+-fixed a garbage collection bug
+-fixed == operator now can compare correctly different types
+-new built in method getstackinfos(level)
+-improved line informations precision for the debug hook
+-new api call sq_compilebuffer()
+-new built-in api function compilestring()
+-new syntactic sugar for function declarations inside tables
+-the debug API has been finalized
+
+***2003-11-17       ***
+***version 0.7 alpha***
+-fixed critical bug SQInteger the tail call system
+-fixed bug in the continue statement code generation
+-fixed func call param issue(thanks to Rewoonenco Andrew)
+-added _delslot metamethod(thanks to Rewoonenco Andrew)
+-new multiline string expression ( delimited by <[ and ]> )
+-normal strings ("") do not allow embedded new line anymore
+-reduced vm memory footprint(C refs are shared between friend VMs)
+-new api method sq_deleteslot()
+-new debug hook event 'r' is triggered when a function returns
+
+***2003-11-04       ***
+***version 0.6 alpha***
+-fixed switch statement(was executing the default case after a break)
+-sq_call() doesn't pop the closure (just the params)
+-the vm execution can be suspended from the C API anytime (micro-threads)
+-new api calls sq_suspendvm() sq_wakeupvm() sq_getvmstate() and sq_reservestack()
+
+***2003-10-13       ***
+***version 0.5 alpha***
+-fixed some minor bug
+-tested with non ASCII identifiers in unicode mode(I've tried chinese chars)
+-added built-in function string.find()
+-the built-in function array.sort() optionally accepts a cmp(a,b) function
+-the debug hook function now has a new prototype debug_hook(event_type,sourcefile,line,functionname)
+-fixed some debug info imprecision
+
+***2003-10-01       ***
+***version 0.4 alpha***
+-faster VM
+-sq_call will pop arguments and closure also in case of failure
+-fixed a bug in sq_remove
+-now the VM detects delegation cycles(and throws an exception)
+-new operators ++ and --
+-new operator ',' comma operator
+-fixed some expression precedence issue
+-fixed bug in sq_arraypop
+
+***2003-09-15       ***
+***version 0.3 alpha***
+-fixed a bug in array::insert()
+-optional Unicode core(define SQUNICODE or _UNICODE on Win32)
+-sq_compiler uses a new reader function SQLEXREADFUNC
+-the debug hook passes 'l' instead of 'line' for line callbacks
+    and 'c' instead of 'call' for call callbacks
+-new array.extend() bulit-in function
+-new API sq_clone()
+
+***2003-09-10           ***
+***version 0.2 pre-alpha***
+-new completely reentrant VM (sq_open and sq_close are now obsolete)
+-sq_newvm() has a new prototype
+-allocators are now global and linked in the VM
+-_newslot meta method added
+-rawset creates a slot if doesn't exists
+-the compiler error callback pass the vm handle(thanks Pierre Renaux)
+-sq_setforeignptr() sq_getforeingptr() are now public
+-sq_resume() now is possible to resume generators from C
+-sq_getlasterror() retrieve the last thrown error
+-improved docs
+
+***2003-09-06           ***
+***version 0.1 pre-alpha***
+first release

+ 23 - 23
README

@@ -1,23 +1,23 @@
-The programming language SQUIRREL 3.1 stable
-
---------------------------------------------------
-The project has been compiled and run on Windows(x86 and x64) and
-Linux(x86 and x64) and Solaris(x86 and x64).
-
-Has been tested with the following compilers:
-	MS Visual C++ 6.0,7.0,7.1,8.0,9.0,10.0 (32 and 64bits)
-	MinGW gcc 3.2 (mingw special 20020817-1)
-	Cygnus gcc 3.2
-	Linux gcc 3.2.3
-	Linux gcc 4.0.0 (x86 & 64bits)
-	Solaris gcc 4.0.0 (x86 & 64bits)
-	
-
-Feedback and suggestions are appreciated 
-project page - http://www.squirrel-lang.org
-community forums - http://forum.squirrel-lang.org
-wiki - http://wiki.squirrel-lang.org
-author - alberto@demichelis.net
-
-END OF README
-
+The programming language SQUIRREL 3.1 stable
+
+--------------------------------------------------
+The project has been compiled and run on Windows(x86 and x64) and
+Linux(x86 and x64) and Solaris(x86 and x64).
+
+Has been tested with the following compilers:
+    MS Visual C++ 6.0,7.0,7.1,8.0,9.0,10.0 (32 and 64bits)
+    MinGW gcc 3.2 (mingw special 20020817-1)
+    Cygnus gcc 3.2
+    Linux gcc 3.2.3
+    Linux gcc 4.0.0 (x86 & 64bits)
+    Solaris gcc 4.0.0 (x86 & 64bits)
+
+
+Feedback and suggestions are appreciated
+project page - http://www.squirrel-lang.org
+community forums - http://forum.squirrel-lang.org
+wiki - http://wiki.squirrel-lang.org
+author - alberto@demichelis.net
+
+END OF README
+

+ 78 - 78
etc/minimal.c

@@ -1,78 +1,78 @@
-#include <stdarg.h> 
-#include <stdio.h> 
-
-#include <squirrel.h> 
-#include <sqstdio.h> 
-#include <sqstdaux.h> 
-
-#ifdef _MSC_VER
-#pragma comment (lib ,"squirrel.lib")
-#pragma comment (lib ,"sqstdlib.lib")
-#endif
-
-#ifdef SQUNICODE 
-
-#define scvprintf vfwprintf
-#else 
-
-#define scvprintf vfprintf
-#endif 
-
-void printfunc(HSQUIRRELVM v,const SQChar *s,...)
-{
-	va_list vl;
-	va_start(vl, s);
-	scvprintf(stdout, s, vl);
-	va_end(vl);
-}
-
-void errorfunc(HSQUIRRELVM v,const SQChar *s,...)
-{
-	va_list vl;
-	va_start(vl, s);
-	scvprintf(stderr, s, vl);
-	va_end(vl);
-}
-
-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 
-
-	//REGISTRATION OF STDLIB
-	//sq_pushroottable(v); //push the root table where the std function will be registered
-	//sqstd_register_iolib(v);  //registers a library
-	// ... call here other stdlibs string,math etc...
-	//sq_pop(v,1); //pops the root table
-	//END REGISTRATION OF STDLIB
-	
-	sqstd_seterrorhandlers(v); //registers the default error handlers
-
-	sq_setprintfunc(v, printfunc,errorfunc); //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; 
-} 
+#include <stdarg.h>
+#include <stdio.h>
+
+#include <squirrel.h>
+#include <sqstdio.h>
+#include <sqstdaux.h>
+
+#ifdef _MSC_VER
+#pragma comment (lib ,"squirrel.lib")
+#pragma comment (lib ,"sqstdlib.lib")
+#endif
+
+#ifdef SQUNICODE
+
+#define scvprintf vfwprintf
+#else
+
+#define scvprintf vfprintf
+#endif
+
+void printfunc(HSQUIRRELVM v,const SQChar *s,...)
+{
+    va_list vl;
+    va_start(vl, s);
+    scvprintf(stdout, s, vl);
+    va_end(vl);
+}
+
+void errorfunc(HSQUIRRELVM v,const SQChar *s,...)
+{
+    va_list vl;
+    va_start(vl, s);
+    scvprintf(stderr, s, vl);
+    va_end(vl);
+}
+
+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
+
+    //REGISTRATION OF STDLIB
+    //sq_pushroottable(v); //push the root table where the std function will be registered
+    //sqstd_register_iolib(v);  //registers a library
+    // ... call here other stdlibs string,math etc...
+    //sq_pop(v,1); //pops the root table
+    //END REGISTRATION OF STDLIB
+
+    sqstd_seterrorhandlers(v); //registers the default error handlers
+
+    sq_setprintfunc(v, printfunc,errorfunc); //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;
+}

+ 4 - 4
etc/test.nut

@@ -1,4 +1,4 @@
-function foo(i, f, s) 
-{ 
-    print("Called foo(), i="+i+", f="+f+", s='"+s+"'\n"); 
-} 
+function foo(i, f, s)
+{
+    print("Called foo(), i="+i+", f="+f+", s='"+s+"'\n");
+}

+ 146 - 146
include/sqconfig.h

@@ -1,146 +1,146 @@
-
-#ifdef _SQ64
-
-#ifdef _MSC_VER
-typedef __int64 SQInteger;
-typedef unsigned __int64 SQUnsignedInteger;
-typedef unsigned __int64 SQHash; /*should be the same size of a pointer*/
-#else
-typedef long long SQInteger;
-typedef unsigned long long SQUnsignedInteger;
-typedef unsigned long long SQHash; /*should be the same size of a pointer*/
-#endif
-typedef int SQInt32; 
-typedef unsigned int SQUnsignedInteger32;
-#else 
-typedef int SQInteger;
-typedef int SQInt32; /*must be 32 bits(also on 64bits processors)*/
-typedef unsigned int SQUnsignedInteger32; /*must be 32 bits(also on 64bits processors)*/
-typedef unsigned int SQUnsignedInteger;
-typedef unsigned int SQHash; /*should be the same size of a pointer*/
-#endif
-
-
-#ifdef SQUSEDOUBLE
-typedef double SQFloat;
-#else
-typedef float SQFloat;
-#endif
-
-#if defined(SQUSEDOUBLE) && !defined(_SQ64) || !defined(SQUSEDOUBLE) && defined(_SQ64)
-#ifdef _MSC_VER
-typedef __int64 SQRawObjectVal; //must be 64bits
-#else
-typedef long long SQRawObjectVal; //must be 64bits
-#endif
-#define SQ_OBJECT_RAWINIT() { _unVal.raw = 0; }
-#else
-typedef SQUnsignedInteger SQRawObjectVal; //is 32 bits on 32 bits builds and 64 bits otherwise
-#define SQ_OBJECT_RAWINIT()
-#endif
-
-#ifndef SQ_ALIGNMENT // SQ_ALIGNMENT shall be less than or equal to SQ_MALLOC alignments, and its value shall be power of 2.
-#if defined(SQUSEDOUBLE) || defined(_SQ64)
-#define SQ_ALIGNMENT 8
-#else
-#define SQ_ALIGNMENT 4
-#endif
-#endif
-
-typedef void* SQUserPointer;
-typedef SQUnsignedInteger SQBool;
-typedef SQInteger SQRESULT;
-
-#ifdef SQUNICODE
-#include <wchar.h>
-#include <wctype.h>
-
-
-typedef wchar_t SQChar;
-
-
-#define	scstrcmp	wcscmp
-#ifdef _MSC_VER
-#define scsprintf	_snwprintf
-#else
-#define scsprintf	snwprintf
-#endif
-#define scstrlen	wcslen
-#define scstrtod	wcstod
-#ifdef _SQ64
-#define scstrtol	wcstoll
-#else
-#define scstrtol	wcstol
-#endif
-#define scstrtoul	wcstoul
-#define scvsprintf	vswprintf
-#define scstrstr	wcsstr
-#define scprintf	wprintf
-
-#ifdef _WIN32
-#define WCHAR_SIZE 2
-#define WCHAR_SHIFT_MUL 1
-#define MAX_CHAR 0xFFFF
-#else
-#define WCHAR_SIZE 4
-#define WCHAR_SHIFT_MUL 2
-#define MAX_CHAR 0xFFFFFFFF
-#endif
-
-#define _SC(a) L##a
-
-
-#define scisspace	iswspace
-#define scisdigit	iswdigit
-#define scisprint	iswprint
-#define scisxdigit	iswxdigit
-#define scisalpha	iswalpha
-#define sciscntrl	iswcntrl
-#define scisalnum	iswalnum
-
-
-#define sq_rsl(l) ((l)<<WCHAR_SHIFT_MUL)
-
-#else
-typedef char SQChar;
-#define _SC(a) a
-#define	scstrcmp	strcmp
-#ifdef _MSC_VER
-#define scsprintf	_snprintf
-#else
-#define scsprintf	snprintf
-#endif
-#define scstrlen	strlen
-#define scstrtod	strtod
-#ifdef _SQ64
-#ifdef _MSC_VER
-#define scstrtol	_strtoi64
-#else
-#define scstrtol	strtoll
-#endif
-#else
-#define scstrtol	strtol
-#endif
-#define scstrtoul	strtoul
-#define scvsprintf	vsnprintf
-#define scstrstr	strstr
-#define scisspace	isspace
-#define scisdigit	isdigit
-#define scisprint	isprint
-#define scisxdigit	isxdigit
-#define sciscntrl	iscntrl
-#define scisalpha	isalpha
-#define scisalnum	isalnum
-#define scprintf	printf
-#define MAX_CHAR 0xFF
-
-#define sq_rsl(l) (l)
-
-#endif
-
-#ifdef _SQ64
-#define _PRINT_INT_PREC _SC("ll")
-#define _PRINT_INT_FMT _SC("%lld")
-#else
-#define _PRINT_INT_FMT _SC("%d")
-#endif
+
+#ifdef _SQ64
+
+#ifdef _MSC_VER
+typedef __int64 SQInteger;
+typedef unsigned __int64 SQUnsignedInteger;
+typedef unsigned __int64 SQHash; /*should be the same size of a pointer*/
+#else
+typedef long long SQInteger;
+typedef unsigned long long SQUnsignedInteger;
+typedef unsigned long long SQHash; /*should be the same size of a pointer*/
+#endif
+typedef int SQInt32;
+typedef unsigned int SQUnsignedInteger32;
+#else
+typedef int SQInteger;
+typedef int SQInt32; /*must be 32 bits(also on 64bits processors)*/
+typedef unsigned int SQUnsignedInteger32; /*must be 32 bits(also on 64bits processors)*/
+typedef unsigned int SQUnsignedInteger;
+typedef unsigned int SQHash; /*should be the same size of a pointer*/
+#endif
+
+
+#ifdef SQUSEDOUBLE
+typedef double SQFloat;
+#else
+typedef float SQFloat;
+#endif
+
+#if defined(SQUSEDOUBLE) && !defined(_SQ64) || !defined(SQUSEDOUBLE) && defined(_SQ64)
+#ifdef _MSC_VER
+typedef __int64 SQRawObjectVal; //must be 64bits
+#else
+typedef long long SQRawObjectVal; //must be 64bits
+#endif
+#define SQ_OBJECT_RAWINIT() { _unVal.raw = 0; }
+#else
+typedef SQUnsignedInteger SQRawObjectVal; //is 32 bits on 32 bits builds and 64 bits otherwise
+#define SQ_OBJECT_RAWINIT()
+#endif
+
+#ifndef SQ_ALIGNMENT // SQ_ALIGNMENT shall be less than or equal to SQ_MALLOC alignments, and its value shall be power of 2.
+#if defined(SQUSEDOUBLE) || defined(_SQ64)
+#define SQ_ALIGNMENT 8
+#else
+#define SQ_ALIGNMENT 4
+#endif
+#endif
+
+typedef void* SQUserPointer;
+typedef SQUnsignedInteger SQBool;
+typedef SQInteger SQRESULT;
+
+#ifdef SQUNICODE
+#include <wchar.h>
+#include <wctype.h>
+
+
+typedef wchar_t SQChar;
+
+
+#define scstrcmp    wcscmp
+#ifdef _MSC_VER
+#define scsprintf   _snwprintf
+#else
+#define scsprintf   snwprintf
+#endif
+#define scstrlen    wcslen
+#define scstrtod    wcstod
+#ifdef _SQ64
+#define scstrtol    wcstoll
+#else
+#define scstrtol    wcstol
+#endif
+#define scstrtoul   wcstoul
+#define scvsprintf  vswprintf
+#define scstrstr    wcsstr
+#define scprintf    wprintf
+
+#ifdef _WIN32
+#define WCHAR_SIZE 2
+#define WCHAR_SHIFT_MUL 1
+#define MAX_CHAR 0xFFFF
+#else
+#define WCHAR_SIZE 4
+#define WCHAR_SHIFT_MUL 2
+#define MAX_CHAR 0xFFFFFFFF
+#endif
+
+#define _SC(a) L##a
+
+
+#define scisspace   iswspace
+#define scisdigit   iswdigit
+#define scisprint   iswprint
+#define scisxdigit  iswxdigit
+#define scisalpha   iswalpha
+#define sciscntrl   iswcntrl
+#define scisalnum   iswalnum
+
+
+#define sq_rsl(l) ((l)<<WCHAR_SHIFT_MUL)
+
+#else
+typedef char SQChar;
+#define _SC(a) a
+#define scstrcmp    strcmp
+#ifdef _MSC_VER
+#define scsprintf   _snprintf
+#else
+#define scsprintf   snprintf
+#endif
+#define scstrlen    strlen
+#define scstrtod    strtod
+#ifdef _SQ64
+#ifdef _MSC_VER
+#define scstrtol    _strtoi64
+#else
+#define scstrtol    strtoll
+#endif
+#else
+#define scstrtol    strtol
+#endif
+#define scstrtoul   strtoul
+#define scvsprintf  vsnprintf
+#define scstrstr    strstr
+#define scisspace   isspace
+#define scisdigit   isdigit
+#define scisprint   isprint
+#define scisxdigit  isxdigit
+#define sciscntrl   iscntrl
+#define scisalpha   isalpha
+#define scisalnum   isalnum
+#define scprintf    printf
+#define MAX_CHAR 0xFF
+
+#define sq_rsl(l) (l)
+
+#endif
+
+#ifdef _SQ64
+#define _PRINT_INT_PREC _SC("ll")
+#define _PRINT_INT_FMT _SC("%lld")
+#else
+#define _PRINT_INT_FMT _SC("%d")
+#endif

+ 16 - 16
include/sqstdaux.h

@@ -1,16 +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_ */
+/*  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_ */

+ 20 - 20
include/sqstdblob.h

@@ -1,20 +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_*/
-
+/*  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_*/
+

+ 53 - 53
include/sqstdio.h

@@ -1,53 +1,53 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQSTDIO_H_
-#define _SQSTDIO_H_
-
-#ifdef __cplusplus
-
-#define SQSTD_STREAM_TYPE_TAG 0x80000000
-
-struct SQStream {
-	virtual SQInteger Read(void *buffer, SQInteger size) = 0;
-	virtual SQInteger Write(void *buffer, SQInteger size) = 0;
-	virtual SQInteger Flush() = 0;
-	virtual SQInteger Tell() = 0;
-	virtual SQInteger Len() = 0;
-	virtual SQInteger Seek(SQInteger offset, SQInteger origin) = 0;
-	virtual bool IsValid() = 0;
-	virtual bool EOS() = 0;
-};
-
-extern "C" {
-#endif
-
-#define SQ_SEEK_CUR 0
-#define SQ_SEEK_END 1
-#define SQ_SEEK_SET 2
-
-typedef void* SQFILE;
-
-SQUIRREL_API SQFILE sqstd_fopen(const SQChar *,const SQChar *);
-SQUIRREL_API SQInteger sqstd_fread(SQUserPointer, SQInteger, SQInteger, SQFILE);
-SQUIRREL_API SQInteger sqstd_fwrite(const SQUserPointer, SQInteger, SQInteger, SQFILE);
-SQUIRREL_API SQInteger sqstd_fseek(SQFILE , SQInteger , SQInteger);
-SQUIRREL_API SQInteger sqstd_ftell(SQFILE);
-SQUIRREL_API SQInteger sqstd_fflush(SQFILE);
-SQUIRREL_API SQInteger sqstd_fclose(SQFILE);
-SQUIRREL_API SQInteger sqstd_feof(SQFILE);
-
-SQUIRREL_API SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own);
-SQUIRREL_API SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file);
-
-//compiler helpers
-SQUIRREL_API SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror);
-SQUIRREL_API SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror);
-SQUIRREL_API SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename);
-
-SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v);
-
-#ifdef __cplusplus
-} /*extern "C"*/
-#endif
-
-#endif /*_SQSTDIO_H_*/
-
+/*  see copyright notice in squirrel.h */
+#ifndef _SQSTDIO_H_
+#define _SQSTDIO_H_
+
+#ifdef __cplusplus
+
+#define SQSTD_STREAM_TYPE_TAG 0x80000000
+
+struct SQStream {
+    virtual SQInteger Read(void *buffer, SQInteger size) = 0;
+    virtual SQInteger Write(void *buffer, SQInteger size) = 0;
+    virtual SQInteger Flush() = 0;
+    virtual SQInteger Tell() = 0;
+    virtual SQInteger Len() = 0;
+    virtual SQInteger Seek(SQInteger offset, SQInteger origin) = 0;
+    virtual bool IsValid() = 0;
+    virtual bool EOS() = 0;
+};
+
+extern "C" {
+#endif
+
+#define SQ_SEEK_CUR 0
+#define SQ_SEEK_END 1
+#define SQ_SEEK_SET 2
+
+typedef void* SQFILE;
+
+SQUIRREL_API SQFILE sqstd_fopen(const SQChar *,const SQChar *);
+SQUIRREL_API SQInteger sqstd_fread(SQUserPointer, SQInteger, SQInteger, SQFILE);
+SQUIRREL_API SQInteger sqstd_fwrite(const SQUserPointer, SQInteger, SQInteger, SQFILE);
+SQUIRREL_API SQInteger sqstd_fseek(SQFILE , SQInteger , SQInteger);
+SQUIRREL_API SQInteger sqstd_ftell(SQFILE);
+SQUIRREL_API SQInteger sqstd_fflush(SQFILE);
+SQUIRREL_API SQInteger sqstd_fclose(SQFILE);
+SQUIRREL_API SQInteger sqstd_feof(SQFILE);
+
+SQUIRREL_API SQRESULT sqstd_createfile(HSQUIRRELVM v, SQFILE file,SQBool own);
+SQUIRREL_API SQRESULT sqstd_getfile(HSQUIRRELVM v, SQInteger idx, SQFILE *file);
+
+//compiler helpers
+SQUIRREL_API SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror);
+SQUIRREL_API SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror);
+SQUIRREL_API SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename);
+
+SQUIRREL_API SQRESULT sqstd_register_iolib(HSQUIRRELVM v);
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*_SQSTDIO_H_*/
+

+ 15 - 15
include/sqstdmath.h

@@ -1,15 +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_*/
+/*  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_*/

+ 33 - 33
include/sqstdstring.h

@@ -1,33 +1,33 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQSTD_STRING_H_
-#define _SQSTD_STRING_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef unsigned int SQRexBool;
-typedef struct SQRex SQRex;
-
-typedef struct {
-	const SQChar *begin;
-	SQInteger len;
-} SQRexMatch;
-
-SQUIRREL_API SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error);
-SQUIRREL_API void sqstd_rex_free(SQRex *exp);
-SQUIRREL_API SQBool sqstd_rex_match(SQRex* exp,const SQChar* text);
-SQUIRREL_API SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end);
-SQUIRREL_API SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end);
-SQUIRREL_API SQInteger sqstd_rex_getsubexpcount(SQRex* exp);
-SQUIRREL_API SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp);
-
-SQUIRREL_API SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output);
-
-SQUIRREL_API SQRESULT sqstd_register_stringlib(HSQUIRRELVM v);
-
-#ifdef __cplusplus
-} /*extern "C"*/
-#endif
-
-#endif /*_SQSTD_STRING_H_*/
+/*  see copyright notice in squirrel.h */
+#ifndef _SQSTD_STRING_H_
+#define _SQSTD_STRING_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef unsigned int SQRexBool;
+typedef struct SQRex SQRex;
+
+typedef struct {
+    const SQChar *begin;
+    SQInteger len;
+} SQRexMatch;
+
+SQUIRREL_API SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error);
+SQUIRREL_API void sqstd_rex_free(SQRex *exp);
+SQUIRREL_API SQBool sqstd_rex_match(SQRex* exp,const SQChar* text);
+SQUIRREL_API SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end);
+SQUIRREL_API SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end);
+SQUIRREL_API SQInteger sqstd_rex_getsubexpcount(SQRex* exp);
+SQUIRREL_API SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp);
+
+SQUIRREL_API SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output);
+
+SQUIRREL_API SQRESULT sqstd_register_stringlib(HSQUIRRELVM v);
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*_SQSTD_STRING_H_*/

+ 15 - 15
include/sqstdsystem.h

@@ -1,15 +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_ */
+/*  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_ */

+ 399 - 399
include/squirrel.h

@@ -1,399 +1,399 @@
-/*
-Copyright (c) 2003-2014 Alberto Demichelis
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-THE SOFTWARE.
-*/
-#ifndef _SQUIRREL_H_
-#define _SQUIRREL_H_
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef SQUIRREL_API
-#define SQUIRREL_API extern
-#endif
-
-#if (defined(_WIN64) || defined(_LP64))
-#ifndef _SQ64
-#define _SQ64
-#endif
-#endif
-
-
-#define SQTrue	(1)
-#define SQFalse	(0)
-
-struct SQVM;
-struct SQTable;
-struct SQArray;
-struct SQString;
-struct SQClosure;
-struct SQGenerator;
-struct SQNativeClosure;
-struct SQUserData;
-struct SQFunctionProto;
-struct SQRefCounted;
-struct SQClass;
-struct SQInstance;
-struct SQDelegable;
-struct SQOuter;
-
-#ifdef _UNICODE
-#define SQUNICODE
-#endif
-
-#include "sqconfig.h"
-
-#define SQUIRREL_VERSION	_SC("Squirrel 3.1 stable")
-#define SQUIRREL_COPYRIGHT	_SC("Copyright (C) 2003-2015 Alberto Demichelis")
-#define SQUIRREL_AUTHOR		_SC("Alberto Demichelis")
-#define SQUIRREL_VERSION_NUMBER	310
-
-#define SQ_VMSTATE_IDLE			0
-#define SQ_VMSTATE_RUNNING		1
-#define SQ_VMSTATE_SUSPENDED	2
-
-#define SQUIRREL_EOB 0
-#define SQ_BYTECODE_STREAM_TAG	0xFAFA
-
-#define SQOBJECT_REF_COUNTED	0x08000000
-#define SQOBJECT_NUMERIC		0x04000000
-#define SQOBJECT_DELEGABLE		0x02000000
-#define SQOBJECT_CANBEFALSE		0x01000000
-
-#define SQ_MATCHTYPEMASKSTRING (-99999)
-
-#define _RT_MASK 0x00FFFFFF
-#define _RAW_TYPE(type) (type&_RT_MASK)
-
-#define _RT_NULL			0x00000001
-#define _RT_INTEGER			0x00000002
-#define _RT_FLOAT			0x00000004
-#define _RT_BOOL			0x00000008
-#define _RT_STRING			0x00000010
-#define _RT_TABLE			0x00000020
-#define _RT_ARRAY			0x00000040
-#define _RT_USERDATA		0x00000080
-#define _RT_CLOSURE			0x00000100
-#define _RT_NATIVECLOSURE	0x00000200
-#define _RT_GENERATOR		0x00000400
-#define _RT_USERPOINTER		0x00000800
-#define _RT_THREAD			0x00001000
-#define _RT_FUNCPROTO		0x00002000
-#define _RT_CLASS			0x00004000
-#define _RT_INSTANCE		0x00008000
-#define _RT_WEAKREF			0x00010000
-#define _RT_OUTER			0x00020000
-
-typedef enum tagSQObjectType{
-	OT_NULL =			(_RT_NULL|SQOBJECT_CANBEFALSE),
-	OT_INTEGER =		(_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE),
-	OT_FLOAT =			(_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE),
-	OT_BOOL =			(_RT_BOOL|SQOBJECT_CANBEFALSE),
-	OT_STRING =			(_RT_STRING|SQOBJECT_REF_COUNTED),
-	OT_TABLE =			(_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),
-	OT_ARRAY =			(_RT_ARRAY|SQOBJECT_REF_COUNTED),
-	OT_USERDATA =		(_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),
-	OT_CLOSURE =		(_RT_CLOSURE|SQOBJECT_REF_COUNTED),
-	OT_NATIVECLOSURE =	(_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED),
-	OT_GENERATOR =		(_RT_GENERATOR|SQOBJECT_REF_COUNTED),
-	OT_USERPOINTER =	_RT_USERPOINTER,
-	OT_THREAD =			(_RT_THREAD|SQOBJECT_REF_COUNTED) ,
-	OT_FUNCPROTO =		(_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only
-	OT_CLASS =			(_RT_CLASS|SQOBJECT_REF_COUNTED),
-	OT_INSTANCE =		(_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),
-	OT_WEAKREF =		(_RT_WEAKREF|SQOBJECT_REF_COUNTED),
-	OT_OUTER =			(_RT_OUTER|SQOBJECT_REF_COUNTED) //internal usage only
-}SQObjectType;
-
-#define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED)
-
-
-typedef union tagSQObjectValue
-{
-	struct SQTable *pTable;
-	struct SQArray *pArray;
-	struct SQClosure *pClosure;
-	struct SQOuter *pOuter;
-	struct SQGenerator *pGenerator;
-	struct SQNativeClosure *pNativeClosure;
-	struct SQString *pString;
-	struct SQUserData *pUserData;
-	SQInteger nInteger;
-	SQFloat fFloat;
-	SQUserPointer pUserPointer;
-	struct SQFunctionProto *pFunctionProto;
-	struct SQRefCounted *pRefCounted;
-	struct SQDelegable *pDelegable;
-	struct SQVM *pThread;
-	struct SQClass *pClass;
-	struct SQInstance *pInstance;
-	struct SQWeakRef *pWeakRef;
-	SQRawObjectVal raw;
-}SQObjectValue;
-
-
-typedef struct tagSQObject
-{
-	SQObjectType _type;
-	SQObjectValue _unVal;
-}SQObject;
-
-typedef struct  tagSQMemberHandle{
-	SQBool _static;
-	SQInteger _index;
-}SQMemberHandle;
-
-typedef struct tagSQStackInfos{
-	const SQChar* funcname;
-	const SQChar* source;
-	SQInteger line;
-}SQStackInfos;
-
-typedef struct SQVM* HSQUIRRELVM;
-typedef SQObject HSQOBJECT;
-typedef SQMemberHandle HSQMEMBERHANDLE;
-typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM);
-typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size);
-typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/);
-typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...);
-typedef void (*SQDEBUGHOOK)(HSQUIRRELVM /*v*/, SQInteger /*type*/, const SQChar * /*sourcename*/, SQInteger /*line*/, const SQChar * /*funcname*/);
-typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger);
-typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger);
-
-typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer);
-
-typedef struct tagSQRegFunction{
-	const SQChar *name;
-	SQFUNCTION f;
-	SQInteger nparamscheck;
-	const SQChar *typemask;
-}SQRegFunction;
-
-typedef struct tagSQFunctionInfo {
-	SQUserPointer funcid;
-	const SQChar *name;
-	const SQChar *source;
-	SQInteger line;
-}SQFunctionInfo;
-
-/*vm*/
-SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize);
-SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize);
-SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v);
-SQUIRREL_API void sq_close(HSQUIRRELVM v);
-SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p);
-SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v);
-SQUIRREL_API void sq_setsharedforeignptr(HSQUIRRELVM v,SQUserPointer p);
-SQUIRREL_API SQUserPointer sq_getsharedforeignptr(HSQUIRRELVM v);
-SQUIRREL_API void sq_setvmreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook);
-SQUIRREL_API SQRELEASEHOOK sq_getvmreleasehook(HSQUIRRELVM v);
-SQUIRREL_API void sq_setsharedreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook);
-SQUIRREL_API SQRELEASEHOOK sq_getsharedreleasehook(HSQUIRRELVM v);
-SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc);
-SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v);
-SQUIRREL_API SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v);
-SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v);
-SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval,SQBool raiseerror,SQBool throwerror);
-SQUIRREL_API SQInteger sq_getvmstate(HSQUIRRELVM v);
-SQUIRREL_API SQInteger sq_getversion();
-
-/*compiler*/
-SQUIRREL_API SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror);
-SQUIRREL_API SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror);
-SQUIRREL_API void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable);
-SQUIRREL_API void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable);
-SQUIRREL_API void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f);
-
-/*stack operations*/
-SQUIRREL_API void sq_push(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API void sq_pop(HSQUIRRELVM v,SQInteger nelemstopop);
-SQUIRREL_API void sq_poptop(HSQUIRRELVM v);
-SQUIRREL_API void sq_remove(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQInteger sq_gettop(HSQUIRRELVM v);
-SQUIRREL_API void sq_settop(HSQUIRRELVM v,SQInteger newtop);
-SQUIRREL_API SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize);
-SQUIRREL_API SQInteger sq_cmp(HSQUIRRELVM v);
-SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx);
-
-/*object creation handling*/
-SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size);
-SQUIRREL_API void sq_newtable(HSQUIRRELVM v);
-SQUIRREL_API void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity);
-SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size);
-SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars);
-SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask);
-SQUIRREL_API SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_setclosureroot(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_getclosureroot(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 void sq_pushthread(HSQUIRRELVM v, HSQUIRRELVM thread);
-SQUIRREL_API SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx);
-SQUIRREL_API SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQBool sq_instanceof(HSQUIRRELVM v);
-SQUIRREL_API SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b);
-SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c);
-SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i);
-SQUIRREL_API SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f);
-SQUIRREL_API SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b);
-SQUIRREL_API SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread);
-SQUIRREL_API SQRESULT sq_getuserpointer(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p);
-SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag);
-SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag);
-SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag);
-SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook);
-SQUIRREL_API SQRELEASEHOOK sq_getreleasehook(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize);
-SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi);
-SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars);
-SQUIRREL_API SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name);
-SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p);
-SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag);
-SQUIRREL_API SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize);
-SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase);
-SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API void sq_weakref(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t);
-SQUIRREL_API SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle);
-SQUIRREL_API SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle);
-SQUIRREL_API SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle);
-
-/*object manipulation*/
-SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v);
-SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v);
-SQUIRREL_API void sq_pushconsttable(HSQUIRRELVM v);
-SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v);
-SQUIRREL_API SQRESULT sq_setconsttable(HSQUIRRELVM v);
-SQUIRREL_API SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);
-SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
-SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
-SQUIRREL_API SQRESULT sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic);
-SQUIRREL_API SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic);
-SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval); 
-SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize); 
-SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx); 
-SQUIRREL_API SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx);
-SQUIRREL_API SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos);
-SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
-SQUIRREL_API SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx);
-SQUIRREL_API SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx);
-
-/*calls*/
-SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror);
-SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror);
-SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx);
-SQUIRREL_API SQRESULT sq_getcallee(HSQUIRRELVM v);
-SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
-SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err);
-SQUIRREL_API SQRESULT sq_throwobject(HSQUIRRELVM v);
-SQUIRREL_API void sq_reseterror(HSQUIRRELVM v);
-SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v);
-
-/*raw object handling*/
-SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po);
-SQUIRREL_API void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj);
-SQUIRREL_API void sq_addref(HSQUIRRELVM v,HSQOBJECT *po);
-SQUIRREL_API SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po);
-SQUIRREL_API SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po);
-SQUIRREL_API void sq_resetobject(HSQOBJECT *po);
-SQUIRREL_API const SQChar *sq_objtostring(const HSQOBJECT *o);
-SQUIRREL_API SQBool sq_objtobool(const HSQOBJECT *o);
-SQUIRREL_API SQInteger sq_objtointeger(const HSQOBJECT *o);
-SQUIRREL_API SQFloat sq_objtofloat(const HSQOBJECT *o);
-SQUIRREL_API SQUserPointer sq_objtouserpointer(const HSQOBJECT *o);
-SQUIRREL_API SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag);
-SQUIRREL_API SQUnsignedInteger sq_getvmrefcount(HSQUIRRELVM v, const HSQOBJECT *po);
-
-
-/*GC*/
-SQUIRREL_API SQInteger sq_collectgarbage(HSQUIRRELVM v);
-SQUIRREL_API SQRESULT sq_resurrectunreachable(HSQUIRRELVM v);
-
-/*serialization*/
-SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up);
-SQUIRREL_API SQRESULT sq_readclosure(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up);
-
-/*mem allocation*/
-SQUIRREL_API void *sq_malloc(SQUnsignedInteger size);
-SQUIRREL_API void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize);
-SQUIRREL_API void sq_free(void *p,SQUnsignedInteger size);
-
-/*debug*/
-SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,SQInteger level,SQStackInfos *si);
-SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v);
-SQUIRREL_API void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook);
-
-/*UTILITY MACRO*/
-#define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC)
-#define sq_istable(o) ((o)._type==OT_TABLE)
-#define sq_isarray(o) ((o)._type==OT_ARRAY)
-#define sq_isfunction(o) ((o)._type==OT_FUNCPROTO)
-#define sq_isclosure(o) ((o)._type==OT_CLOSURE)
-#define sq_isgenerator(o) ((o)._type==OT_GENERATOR)
-#define sq_isnativeclosure(o) ((o)._type==OT_NATIVECLOSURE)
-#define sq_isstring(o) ((o)._type==OT_STRING)
-#define sq_isinteger(o) ((o)._type==OT_INTEGER)
-#define sq_isfloat(o) ((o)._type==OT_FLOAT)
-#define sq_isuserpointer(o) ((o)._type==OT_USERPOINTER)
-#define sq_isuserdata(o) ((o)._type==OT_USERDATA)
-#define sq_isthread(o) ((o)._type==OT_THREAD)
-#define sq_isnull(o) ((o)._type==OT_NULL)
-#define sq_isclass(o) ((o)._type==OT_CLASS)
-#define sq_isinstance(o) ((o)._type==OT_INSTANCE)
-#define sq_isbool(o) ((o)._type==OT_BOOL)
-#define sq_isweakref(o) ((o)._type==OT_WEAKREF)
-#define sq_type(o) ((o)._type)
-
-/* deprecated */
-#define sq_createslot(v,n) sq_newslot(v,n,SQFalse)
-
-#define SQ_OK (0)
-#define SQ_ERROR (-1)
-
-#define SQ_FAILED(res) (res<0)
-#define SQ_SUCCEEDED(res) (res>=0)
-
-#ifdef __cplusplus
-} /*extern "C"*/
-#endif
-
-#endif /*_SQUIRREL_H_*/
+/*
+Copyright (c) 2003-2014 Alberto Demichelis
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+*/
+#ifndef _SQUIRREL_H_
+#define _SQUIRREL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SQUIRREL_API
+#define SQUIRREL_API extern
+#endif
+
+#if (defined(_WIN64) || defined(_LP64))
+#ifndef _SQ64
+#define _SQ64
+#endif
+#endif
+
+
+#define SQTrue  (1)
+#define SQFalse (0)
+
+struct SQVM;
+struct SQTable;
+struct SQArray;
+struct SQString;
+struct SQClosure;
+struct SQGenerator;
+struct SQNativeClosure;
+struct SQUserData;
+struct SQFunctionProto;
+struct SQRefCounted;
+struct SQClass;
+struct SQInstance;
+struct SQDelegable;
+struct SQOuter;
+
+#ifdef _UNICODE
+#define SQUNICODE
+#endif
+
+#include "sqconfig.h"
+
+#define SQUIRREL_VERSION    _SC("Squirrel 3.1 stable")
+#define SQUIRREL_COPYRIGHT  _SC("Copyright (C) 2003-2015 Alberto Demichelis")
+#define SQUIRREL_AUTHOR     _SC("Alberto Demichelis")
+#define SQUIRREL_VERSION_NUMBER 310
+
+#define SQ_VMSTATE_IDLE         0
+#define SQ_VMSTATE_RUNNING      1
+#define SQ_VMSTATE_SUSPENDED    2
+
+#define SQUIRREL_EOB 0
+#define SQ_BYTECODE_STREAM_TAG  0xFAFA
+
+#define SQOBJECT_REF_COUNTED    0x08000000
+#define SQOBJECT_NUMERIC        0x04000000
+#define SQOBJECT_DELEGABLE      0x02000000
+#define SQOBJECT_CANBEFALSE     0x01000000
+
+#define SQ_MATCHTYPEMASKSTRING (-99999)
+
+#define _RT_MASK 0x00FFFFFF
+#define _RAW_TYPE(type) (type&_RT_MASK)
+
+#define _RT_NULL            0x00000001
+#define _RT_INTEGER         0x00000002
+#define _RT_FLOAT           0x00000004
+#define _RT_BOOL            0x00000008
+#define _RT_STRING          0x00000010
+#define _RT_TABLE           0x00000020
+#define _RT_ARRAY           0x00000040
+#define _RT_USERDATA        0x00000080
+#define _RT_CLOSURE         0x00000100
+#define _RT_NATIVECLOSURE   0x00000200
+#define _RT_GENERATOR       0x00000400
+#define _RT_USERPOINTER     0x00000800
+#define _RT_THREAD          0x00001000
+#define _RT_FUNCPROTO       0x00002000
+#define _RT_CLASS           0x00004000
+#define _RT_INSTANCE        0x00008000
+#define _RT_WEAKREF         0x00010000
+#define _RT_OUTER           0x00020000
+
+typedef enum tagSQObjectType{
+    OT_NULL =           (_RT_NULL|SQOBJECT_CANBEFALSE),
+    OT_INTEGER =        (_RT_INTEGER|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE),
+    OT_FLOAT =          (_RT_FLOAT|SQOBJECT_NUMERIC|SQOBJECT_CANBEFALSE),
+    OT_BOOL =           (_RT_BOOL|SQOBJECT_CANBEFALSE),
+    OT_STRING =         (_RT_STRING|SQOBJECT_REF_COUNTED),
+    OT_TABLE =          (_RT_TABLE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),
+    OT_ARRAY =          (_RT_ARRAY|SQOBJECT_REF_COUNTED),
+    OT_USERDATA =       (_RT_USERDATA|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),
+    OT_CLOSURE =        (_RT_CLOSURE|SQOBJECT_REF_COUNTED),
+    OT_NATIVECLOSURE =  (_RT_NATIVECLOSURE|SQOBJECT_REF_COUNTED),
+    OT_GENERATOR =      (_RT_GENERATOR|SQOBJECT_REF_COUNTED),
+    OT_USERPOINTER =    _RT_USERPOINTER,
+    OT_THREAD =         (_RT_THREAD|SQOBJECT_REF_COUNTED) ,
+    OT_FUNCPROTO =      (_RT_FUNCPROTO|SQOBJECT_REF_COUNTED), //internal usage only
+    OT_CLASS =          (_RT_CLASS|SQOBJECT_REF_COUNTED),
+    OT_INSTANCE =       (_RT_INSTANCE|SQOBJECT_REF_COUNTED|SQOBJECT_DELEGABLE),
+    OT_WEAKREF =        (_RT_WEAKREF|SQOBJECT_REF_COUNTED),
+    OT_OUTER =          (_RT_OUTER|SQOBJECT_REF_COUNTED) //internal usage only
+}SQObjectType;
+
+#define ISREFCOUNTED(t) (t&SQOBJECT_REF_COUNTED)
+
+
+typedef union tagSQObjectValue
+{
+    struct SQTable *pTable;
+    struct SQArray *pArray;
+    struct SQClosure *pClosure;
+    struct SQOuter *pOuter;
+    struct SQGenerator *pGenerator;
+    struct SQNativeClosure *pNativeClosure;
+    struct SQString *pString;
+    struct SQUserData *pUserData;
+    SQInteger nInteger;
+    SQFloat fFloat;
+    SQUserPointer pUserPointer;
+    struct SQFunctionProto *pFunctionProto;
+    struct SQRefCounted *pRefCounted;
+    struct SQDelegable *pDelegable;
+    struct SQVM *pThread;
+    struct SQClass *pClass;
+    struct SQInstance *pInstance;
+    struct SQWeakRef *pWeakRef;
+    SQRawObjectVal raw;
+}SQObjectValue;
+
+
+typedef struct tagSQObject
+{
+    SQObjectType _type;
+    SQObjectValue _unVal;
+}SQObject;
+
+typedef struct  tagSQMemberHandle{
+    SQBool _static;
+    SQInteger _index;
+}SQMemberHandle;
+
+typedef struct tagSQStackInfos{
+    const SQChar* funcname;
+    const SQChar* source;
+    SQInteger line;
+}SQStackInfos;
+
+typedef struct SQVM* HSQUIRRELVM;
+typedef SQObject HSQOBJECT;
+typedef SQMemberHandle HSQMEMBERHANDLE;
+typedef SQInteger (*SQFUNCTION)(HSQUIRRELVM);
+typedef SQInteger (*SQRELEASEHOOK)(SQUserPointer,SQInteger size);
+typedef void (*SQCOMPILERERROR)(HSQUIRRELVM,const SQChar * /*desc*/,const SQChar * /*source*/,SQInteger /*line*/,SQInteger /*column*/);
+typedef void (*SQPRINTFUNCTION)(HSQUIRRELVM,const SQChar * ,...);
+typedef void (*SQDEBUGHOOK)(HSQUIRRELVM /*v*/, SQInteger /*type*/, const SQChar * /*sourcename*/, SQInteger /*line*/, const SQChar * /*funcname*/);
+typedef SQInteger (*SQWRITEFUNC)(SQUserPointer,SQUserPointer,SQInteger);
+typedef SQInteger (*SQREADFUNC)(SQUserPointer,SQUserPointer,SQInteger);
+
+typedef SQInteger (*SQLEXREADFUNC)(SQUserPointer);
+
+typedef struct tagSQRegFunction{
+    const SQChar *name;
+    SQFUNCTION f;
+    SQInteger nparamscheck;
+    const SQChar *typemask;
+}SQRegFunction;
+
+typedef struct tagSQFunctionInfo {
+    SQUserPointer funcid;
+    const SQChar *name;
+    const SQChar *source;
+    SQInteger line;
+}SQFunctionInfo;
+
+/*vm*/
+SQUIRREL_API HSQUIRRELVM sq_open(SQInteger initialstacksize);
+SQUIRREL_API HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize);
+SQUIRREL_API void sq_seterrorhandler(HSQUIRRELVM v);
+SQUIRREL_API void sq_close(HSQUIRRELVM v);
+SQUIRREL_API void sq_setforeignptr(HSQUIRRELVM v,SQUserPointer p);
+SQUIRREL_API SQUserPointer sq_getforeignptr(HSQUIRRELVM v);
+SQUIRREL_API void sq_setsharedforeignptr(HSQUIRRELVM v,SQUserPointer p);
+SQUIRREL_API SQUserPointer sq_getsharedforeignptr(HSQUIRRELVM v);
+SQUIRREL_API void sq_setvmreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook);
+SQUIRREL_API SQRELEASEHOOK sq_getvmreleasehook(HSQUIRRELVM v);
+SQUIRREL_API void sq_setsharedreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook);
+SQUIRREL_API SQRELEASEHOOK sq_getsharedreleasehook(HSQUIRRELVM v);
+SQUIRREL_API void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc);
+SQUIRREL_API SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v);
+SQUIRREL_API SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_suspendvm(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool resumedret,SQBool retval,SQBool raiseerror,SQBool throwerror);
+SQUIRREL_API SQInteger sq_getvmstate(HSQUIRRELVM v);
+SQUIRREL_API SQInteger sq_getversion();
+
+/*compiler*/
+SQUIRREL_API SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror);
+SQUIRREL_API SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror);
+SQUIRREL_API void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable);
+SQUIRREL_API void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable);
+SQUIRREL_API void sq_setcompilererrorhandler(HSQUIRRELVM v,SQCOMPILERERROR f);
+
+/*stack operations*/
+SQUIRREL_API void sq_push(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API void sq_pop(HSQUIRRELVM v,SQInteger nelemstopop);
+SQUIRREL_API void sq_poptop(HSQUIRRELVM v);
+SQUIRREL_API void sq_remove(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQInteger sq_gettop(HSQUIRRELVM v);
+SQUIRREL_API void sq_settop(HSQUIRRELVM v,SQInteger newtop);
+SQUIRREL_API SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize);
+SQUIRREL_API SQInteger sq_cmp(HSQUIRRELVM v);
+SQUIRREL_API void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx);
+
+/*object creation handling*/
+SQUIRREL_API SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size);
+SQUIRREL_API void sq_newtable(HSQUIRRELVM v);
+SQUIRREL_API void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity);
+SQUIRREL_API void sq_newarray(HSQUIRRELVM v,SQInteger size);
+SQUIRREL_API void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars);
+SQUIRREL_API SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask);
+SQUIRREL_API SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_setclosureroot(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_getclosureroot(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 void sq_pushthread(HSQUIRRELVM v, HSQUIRRELVM thread);
+SQUIRREL_API SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQInteger sq_getsize(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx);
+SQUIRREL_API SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQBool sq_instanceof(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b);
+SQUIRREL_API SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c);
+SQUIRREL_API SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i);
+SQUIRREL_API SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f);
+SQUIRREL_API SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b);
+SQUIRREL_API SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread);
+SQUIRREL_API SQRESULT sq_getuserpointer(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p);
+SQUIRREL_API SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag);
+SQUIRREL_API SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag);
+SQUIRREL_API SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag);
+SQUIRREL_API void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook);
+SQUIRREL_API SQRELEASEHOOK sq_getreleasehook(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize);
+SQUIRREL_API SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi);
+SQUIRREL_API SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars);
+SQUIRREL_API SQRESULT sq_getclosurename(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name);
+SQUIRREL_API SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p);
+SQUIRREL_API SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag);
+SQUIRREL_API SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize);
+SQUIRREL_API SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase);
+SQUIRREL_API SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API void sq_weakref(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t);
+SQUIRREL_API SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle);
+SQUIRREL_API SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle);
+SQUIRREL_API SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle);
+
+/*object manipulation*/
+SQUIRREL_API void sq_pushroottable(HSQUIRRELVM v);
+SQUIRREL_API void sq_pushregistrytable(HSQUIRRELVM v);
+SQUIRREL_API void sq_pushconsttable(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_setroottable(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_setconsttable(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic);
+SQUIRREL_API SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
+SQUIRREL_API SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
+SQUIRREL_API SQRESULT sq_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic);
+SQUIRREL_API SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic);
+SQUIRREL_API SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval);
+SQUIRREL_API SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize);
+SQUIRREL_API SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx);
+SQUIRREL_API SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos);
+SQUIRREL_API SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
+SQUIRREL_API SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx);
+SQUIRREL_API SQRESULT sq_clear(HSQUIRRELVM v,SQInteger idx);
+
+/*calls*/
+SQUIRREL_API SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror);
+SQUIRREL_API SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror);
+SQUIRREL_API const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx);
+SQUIRREL_API SQRESULT sq_getcallee(HSQUIRRELVM v);
+SQUIRREL_API const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval);
+SQUIRREL_API SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err);
+SQUIRREL_API SQRESULT sq_throwobject(HSQUIRRELVM v);
+SQUIRREL_API void sq_reseterror(HSQUIRRELVM v);
+SQUIRREL_API void sq_getlasterror(HSQUIRRELVM v);
+
+/*raw object handling*/
+SQUIRREL_API SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po);
+SQUIRREL_API void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj);
+SQUIRREL_API void sq_addref(HSQUIRRELVM v,HSQOBJECT *po);
+SQUIRREL_API SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po);
+SQUIRREL_API SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po);
+SQUIRREL_API void sq_resetobject(HSQOBJECT *po);
+SQUIRREL_API const SQChar *sq_objtostring(const HSQOBJECT *o);
+SQUIRREL_API SQBool sq_objtobool(const HSQOBJECT *o);
+SQUIRREL_API SQInteger sq_objtointeger(const HSQOBJECT *o);
+SQUIRREL_API SQFloat sq_objtofloat(const HSQOBJECT *o);
+SQUIRREL_API SQUserPointer sq_objtouserpointer(const HSQOBJECT *o);
+SQUIRREL_API SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag);
+SQUIRREL_API SQUnsignedInteger sq_getvmrefcount(HSQUIRRELVM v, const HSQOBJECT *po);
+
+
+/*GC*/
+SQUIRREL_API SQInteger sq_collectgarbage(HSQUIRRELVM v);
+SQUIRREL_API SQRESULT sq_resurrectunreachable(HSQUIRRELVM v);
+
+/*serialization*/
+SQUIRREL_API SQRESULT sq_writeclosure(HSQUIRRELVM vm,SQWRITEFUNC writef,SQUserPointer up);
+SQUIRREL_API SQRESULT sq_readclosure(HSQUIRRELVM vm,SQREADFUNC readf,SQUserPointer up);
+
+/*mem allocation*/
+SQUIRREL_API void *sq_malloc(SQUnsignedInteger size);
+SQUIRREL_API void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize);
+SQUIRREL_API void sq_free(void *p,SQUnsignedInteger size);
+
+/*debug*/
+SQUIRREL_API SQRESULT sq_stackinfos(HSQUIRRELVM v,SQInteger level,SQStackInfos *si);
+SQUIRREL_API void sq_setdebughook(HSQUIRRELVM v);
+SQUIRREL_API void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook);
+
+/*UTILITY MACRO*/
+#define sq_isnumeric(o) ((o)._type&SQOBJECT_NUMERIC)
+#define sq_istable(o) ((o)._type==OT_TABLE)
+#define sq_isarray(o) ((o)._type==OT_ARRAY)
+#define sq_isfunction(o) ((o)._type==OT_FUNCPROTO)
+#define sq_isclosure(o) ((o)._type==OT_CLOSURE)
+#define sq_isgenerator(o) ((o)._type==OT_GENERATOR)
+#define sq_isnativeclosure(o) ((o)._type==OT_NATIVECLOSURE)
+#define sq_isstring(o) ((o)._type==OT_STRING)
+#define sq_isinteger(o) ((o)._type==OT_INTEGER)
+#define sq_isfloat(o) ((o)._type==OT_FLOAT)
+#define sq_isuserpointer(o) ((o)._type==OT_USERPOINTER)
+#define sq_isuserdata(o) ((o)._type==OT_USERDATA)
+#define sq_isthread(o) ((o)._type==OT_THREAD)
+#define sq_isnull(o) ((o)._type==OT_NULL)
+#define sq_isclass(o) ((o)._type==OT_CLASS)
+#define sq_isinstance(o) ((o)._type==OT_INSTANCE)
+#define sq_isbool(o) ((o)._type==OT_BOOL)
+#define sq_isweakref(o) ((o)._type==OT_WEAKREF)
+#define sq_type(o) ((o)._type)
+
+/* deprecated */
+#define sq_createslot(v,n) sq_newslot(v,n,SQFalse)
+
+#define SQ_OK (0)
+#define SQ_ERROR (-1)
+
+#define SQ_FAILED(res) (res<0)
+#define SQ_SUCCEEDED(res) (res>=0)
+
+#ifdef __cplusplus
+} /*extern "C"*/
+#endif
+
+#endif /*_SQUIRREL_H_*/

+ 23 - 23
samples/ackermann.nut

@@ -1,23 +1,23 @@
-/*
-*
-* 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(vargv.len()!=0) {
-   n = vargv[0].tointeger();
-  if(n < 1) n = 1;
-} else {   
-  n = 1;
-}
-print("n="+n+"\n");
-print("Ack(3,"+ n+ "):"+ Ack(3, n));
-
+/*
+*
+* 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(vargv.len()!=0) {
+   n = vargv[0].tointeger();
+  if(n < 1) n = 1;
+} else {
+  n = 1;
+}
+print("n="+n+"\n");
+print("Ack(3,"+ n+ "):"+ Ack(3, n));
+

+ 29 - 29
samples/array.nut

@@ -1,29 +1,29 @@
-/*
-*
-* Original Javascript version by David Hedbor(http://www.bagley.org/~doug/shootout/)
-*
-*/
-local n, i, k;
-
-if(vargv.len()!=0) {
-   n = vargv[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]);
-
+/*
+*
+* Original Javascript version by David Hedbor(http://www.bagley.org/~doug/shootout/)
+*
+*/
+local n, i, k;
+
+if(vargv.len()!=0) {
+   n = vargv[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]);
+

+ 49 - 49
samples/class.nut

@@ -1,49 +1,49 @@
-//////////////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////////////
-class BaseVector {
-	constructor(...)
-	{
-		if(vargv.len() >= 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();
+//////////////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////////////
+class BaseVector {
+    constructor(...)
+    {
+        if(vargv.len() >= 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();

+ 35 - 35
samples/classattributes.nut

@@ -1,35 +1,35 @@
-class Foo {
-	//constructor
-	constructor(a)
-	{
-		testy = ["stuff",1,2,3];
-	}
-	//attributes of PrintTesty
-	</ test = "freakin attribute"/>
-	function PrintTesty()
-	{
-		foreach(i,val in testy)
-		{
-			::print("idx = "+i+" = "+val+" \n");
-		}
-	}
-	//attributes of testy
-	</ flippy = 10 , second = [1,2,3] />
-	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<no attributes>\n")
-	}
-}
+class Foo {
+    //constructor
+    constructor(a)
+    {
+        testy = ["stuff",1,2,3];
+    }
+    //attributes of PrintTesty
+    </ test = "freakin attribute"/>
+    function PrintTesty()
+    {
+        foreach(i,val in testy)
+        {
+            ::print("idx = "+i+" = "+val+" \n");
+        }
+    }
+    //attributes of testy
+    </ flippy = 10 , second = [1,2,3] />
+    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<no attributes>\n")
+    }
+}

+ 25 - 25
samples/coroutines.nut

@@ -1,25 +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")
+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")

+ 54 - 54
samples/delegation.nut

@@ -1,54 +1,54 @@
-
-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 p = clone ::PPlayer;
-	local newplayer = ::PEntity.new(name,pos);
-	newplayer.setdelegate(p);
-	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();
+
+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 p = clone ::PPlayer;
+    local newplayer = ::PEntity.new(name,pos);
+    newplayer.setdelegate(p);
+    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();

+ 15 - 15
samples/fibonacci.nut

@@ -1,15 +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 = vargv.len()!=0?vargv[0].tointeger():1
-
-print(fib(n)+"\n")
+/*
+*
+* 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 = vargv.len()!=0?vargv[0].tointeger():1
+
+print(fib(n)+"\n")

+ 33 - 33
samples/flow.nut

@@ -1,33 +1,33 @@
-function min(x,y)
-	return x<y?x:y;
-	
-function max(x,y)
-	return x>y?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");
+function min(x,y)
+    return x<y?x:y;
+
+function max(x,y)
+    return x>y?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");

+ 42 - 42
samples/generators.nut

@@ -1,42 +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<n-1;i+=1)
-	{
-		local res=prev+curr;
-		prev=curr;
-		yield curr=res;
-	}
-	return prev+curr;
-}
-
-foreach(val in fiboz(10))
-{
-	::print(">"+val+"\n");
-}
+/*
+*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<n-1;i+=1)
+    {
+        local res=prev+curr;
+        prev=curr;
+        yield curr=res;
+    }
+    return prev+curr;
+}
+
+foreach(val in fiboz(10))
+{
+    ::print(">"+val+"\n");
+}

+ 1 - 1
samples/hello.nut

@@ -1 +1 @@
-print("Hello World!")
+print("Hello World!")

+ 40 - 40
samples/list.nut

@@ -1,40 +1,40 @@
-/*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;i<size;i+=1) l1[i]=i;
-	local l2=clone l1;
-	local l3=[]
-	
-	l2.reverse();
-	while(l2.len()>0)
-		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 = vargv.len()!=0?vargv[0].tointeger():1
-for(local i=0;i<n;i+=1)
-	if(!test())
-	{
-		print("failed");
-		return;
-	}
-	
-print("oki doki");
-	
+/*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;i<size;i+=1) l1[i]=i;
+    local l2=clone l1;
+    local l3=[]
+
+    l2.reverse();
+    while(l2.len()>0)
+        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 = vargv.len()!=0?vargv[0].tointeger():1
+for(local i=0;i<n;i+=1)
+    if(!test())
+    {
+        print("failed");
+        return;
+    }
+
+print("oki doki");
+

+ 32 - 32
samples/loops.nut

@@ -1,32 +1,32 @@
-local arr=["one","two","three"]
-
-::print("FOREACH\n");
-
-foreach(i,val in arr)
-{
-	::print("index ["+i+"]="+val+"\n");
-}
-
-::print("FOR\n");
-
-for(local i=0;i<arr.len();i+=1)
-{
-	::print("index ["+i+"]="+arr[i]+"\n");
-}
-
-::print("WHILE\n");
-
-local i=0;
-while(i<arr.len())
-{
-	::print("index ["+i+"]="+arr[i]+"\n");
-	i+=1;
-}
-::print("DO WHILE\n");
-
-local i=0;
-do
-{
-	::print("index ["+i+"]="+arr[i]+"\n");
-	i+=1;
-}while(i<arr.len());
+local arr=["one","two","three"]
+
+::print("FOREACH\n");
+
+foreach(i,val in arr)
+{
+    ::print("index ["+i+"]="+val+"\n");
+}
+
+::print("FOR\n");
+
+for(local i=0;i<arr.len();i+=1)
+{
+    ::print("index ["+i+"]="+arr[i]+"\n");
+}
+
+::print("WHILE\n");
+
+local i=0;
+while(i<arr.len())
+{
+    ::print("index ["+i+"]="+arr[i]+"\n");
+    i+=1;
+}
+::print("DO WHILE\n");
+
+local i=0;
+do
+{
+    ::print("index ["+i+"]="+arr[i]+"\n");
+    i+=1;
+}while(i<arr.len());

+ 44 - 44
samples/matrix.nut

@@ -1,44 +1,44 @@
-/*
-*
-* Original Javascript version by David Hedbor(http://www.bagley.org/~doug/shootout/)
-*
-*/
-local SIZE=30;
-
-function mkmatrix(rows, cols) {
-  local i, j, count = 1;
-  local m = []; m.resize(rows);
-  for (i = 0; i < rows; i+=1) {
-    m[i] = [];m[i].resize(cols)
-    for (j = 0; j < cols; j+=1) {
-      m[i][j] = count+=1;
-    }
-  }
-  return m;
-}
-
-function mmult(rows, cols,  m1, m2, m3) {
-  local i, j, k, val;
-  for (i = 0; i < rows; i+=1) {
-    for (j = 0; j < cols; j+=1) {
-      val = 0;
-      for (k = 0; k < cols; k+=1) {
-	val += m1[i][k] * m2[k][j];
-      }
-      m3[i][j] = val;
-    }
-  }
-  return m3;
-}
-
-local n = vargv.len()!=0?vargv[0].tointeger():1
-
-local m1 = mkmatrix(SIZE, SIZE);
-local m2 = mkmatrix(SIZE, SIZE);
-local mm = mkmatrix(SIZE, SIZE);
-
-for (local i = 0; i < n; i+=1) {
-  mmult(SIZE, SIZE, m1, m2, mm);
-}
-
-print(mm[0][0]+" "+mm[2][3]+" "+mm[3][2]+" "+mm[4][4]);
+/*
+*
+* Original Javascript version by David Hedbor(http://www.bagley.org/~doug/shootout/)
+*
+*/
+local SIZE=30;
+
+function mkmatrix(rows, cols) {
+  local i, j, count = 1;
+  local m = []; m.resize(rows);
+  for (i = 0; i < rows; i+=1) {
+    m[i] = [];m[i].resize(cols)
+    for (j = 0; j < cols; j+=1) {
+      m[i][j] = count+=1;
+    }
+  }
+  return m;
+}
+
+function mmult(rows, cols,  m1, m2, m3) {
+  local i, j, k, val;
+  for (i = 0; i < rows; i+=1) {
+    for (j = 0; j < cols; j+=1) {
+      val = 0;
+      for (k = 0; k < cols; k+=1) {
+    val += m1[i][k] * m2[k][j];
+      }
+      m3[i][j] = val;
+    }
+  }
+  return m3;
+}
+
+local n = vargv.len()!=0?vargv[0].tointeger():1
+
+local m1 = mkmatrix(SIZE, SIZE);
+local m2 = mkmatrix(SIZE, SIZE);
+local mm = mkmatrix(SIZE, SIZE);
+
+for (local i = 0; i < n; i+=1) {
+  mmult(SIZE, SIZE, m1, m2, mm);
+}
+
+print(mm[0][0]+" "+mm[2][3]+" "+mm[3][2]+" "+mm[4][4]);

+ 115 - 115
samples/metamethods.nut

@@ -1,115 +1,115 @@
-
-local base_vec={
-	function _add(n)
-	{
-		return {
-			x=x+n.x,
-			y=y+n.y,
-			z=z+n.z,
-		}
-	}
-	function _sub(n)
-	{
-		return {
-			x=x-n.x,
-			y=y-n.y,
-			z=z-n.z,
-		}
-	}
-	function _div(n)
-	{
-		return {
-			x=x/n.x,
-			y=y/n.y,
-			z=z/n.z,
-		}
-	}
-	function _mul(n)
-	{
-		return {
-			x=x*n.x,
-			y=y*n.y,
-			z=z*n.z,
-		}
-	}
-	function _modulo(n)
-	{
-		return {
-			x=x%n,
-			y=y%n,
-			z=z%n,
-		}
-	}
-	function _typeof() {return "vector";}
-	function _get(key)
-	{
-		if(key==100)
-		{
-			return test_field;
-		}
-	},
-	function _set(key,val)
-	{
-		::print("key = "+key+"\n");
-		::print("val = "+val+"\n")
-		if(key==100)
-		{
-			return test_field=val;
-		}
-	}
-	test_field="nothing"
-}
-
-function vector(_x,_y,_z)
-{
-	return {x=_x,y=_y,z=_z }.setdelegate(base_vec); 
-}
-////////////////////////////////////////////////////////////
-
-local v1=vector(1.5,2.5,3.5);
-local v2=vector(1.5,2.5,3.5);
-
-local r=v1+v2;
-
-
-foreach(i,val in r)
-{
-	print(i+" = "+val+"\n");
-}
-
-r=v1*v2;
-
-foreach(i,val in r)
-{
-	print(i+" = "+val+"\n");
-}
-
-r=v1/v2;
-
-foreach(i,val in r)
-{
-	print(i+" = "+val+"\n");
-}
-
-r=v1-v2;
-
-foreach(i,val in r)
-{
-	print(i+" = "+val+"\n");
-}
-
-r=v1%2;
-
-foreach(i,val in r)
-{
-	print(i+" = "+val+"\n");
-}
-
-print(v1[100]+"\n");
-v1[100]="set SUCCEEDED";
-print(v1[100]+"\n");
-
-if(typeof v1=="vector")
-	print("<SUCCEEDED>\n");
-else
-	print("<FAILED>\n");
+
+local base_vec={
+    function _add(n)
+    {
+        return {
+            x=x+n.x,
+            y=y+n.y,
+            z=z+n.z,
+        }
+    }
+    function _sub(n)
+    {
+        return {
+            x=x-n.x,
+            y=y-n.y,
+            z=z-n.z,
+        }
+    }
+    function _div(n)
+    {
+        return {
+            x=x/n.x,
+            y=y/n.y,
+            z=z/n.z,
+        }
+    }
+    function _mul(n)
+    {
+        return {
+            x=x*n.x,
+            y=y*n.y,
+            z=z*n.z,
+        }
+    }
+    function _modulo(n)
+    {
+        return {
+            x=x%n,
+            y=y%n,
+            z=z%n,
+        }
+    }
+    function _typeof() {return "vector";}
+    function _get(key)
+    {
+        if(key==100)
+        {
+            return test_field;
+        }
+    },
+    function _set(key,val)
+    {
+        ::print("key = "+key+"\n");
+        ::print("val = "+val+"\n")
+        if(key==100)
+        {
+            return test_field=val;
+        }
+    }
+    test_field="nothing"
+}
+
+function vector(_x,_y,_z)
+{
+    return {x=_x,y=_y,z=_z }.setdelegate(base_vec);
+}
+////////////////////////////////////////////////////////////
+
+local v1=vector(1.5,2.5,3.5);
+local v2=vector(1.5,2.5,3.5);
+
+local r=v1+v2;
+
+
+foreach(i,val in r)
+{
+    print(i+" = "+val+"\n");
+}
+
+r=v1*v2;
+
+foreach(i,val in r)
+{
+    print(i+" = "+val+"\n");
+}
+
+r=v1/v2;
+
+foreach(i,val in r)
+{
+    print(i+" = "+val+"\n");
+}
+
+r=v1-v2;
+
+foreach(i,val in r)
+{
+    print(i+" = "+val+"\n");
+}
+
+r=v1%2;
+
+foreach(i,val in r)
+{
+    print(i+" = "+val+"\n");
+}
+
+print(v1[100]+"\n");
+v1[100]="set SUCCEEDED";
+print(v1[100]+"\n");
+
+if(typeof v1=="vector")
+    print("<SUCCEEDED>\n");
+else
+    print("<FAILED>\n");

+ 68 - 68
samples/methcall.nut

@@ -1,68 +1,68 @@
-/*translation of the methcall test from The Great Computer Language Shootout 
-*/
-
-class Toggle {
-	bool=null
-}
-
-function Toggle::constructor(startstate) {
-	bool = startstate
-}
-
-function Toggle::value() {
-	return bool;
-}
-
-function Toggle::activate() {
-	bool = !bool;
-	return this;
-}
-
-class NthToggle extends Toggle {
-	count_max=null
-	count=0
-}
-
-function NthToggle::constructor(start_state,max_counter)
-{
-	base.constructor(start_state);
-	count_max = max_counter
-}
-
-function NthToggle::activate () 
-{
-	++count;
-    if (count >= count_max ) {
-      base.activate();
-      count = 0;
-    }
-    return this;
-}
-
-
-function main() {
-	local n = vargv.len()!=0?vargv[0].tointeger():1
-	
-	
-	
-	local val = 1;
-	local toggle = Toggle(val);
-	local i = n;
-	while(i--) {
-	  val = toggle.activate().value();
-	  
-	}
-	print(toggle.value() ? "true\n" : "false\n");
-	
-	val = 1;
-	local ntoggle = NthToggle(val, 3);
-	i = n;
-	while(i--) {
-	  val = ntoggle.activate().value();
-	}
-	print(ntoggle.value() ? "true\n" : "false\n");
-	
-}
-local start=clock();
-main();
-print("TIME="+(clock()-start)+"\n");
+/*translation of the methcall test from The Great Computer Language Shootout
+*/
+
+class Toggle {
+    bool=null
+}
+
+function Toggle::constructor(startstate) {
+    bool = startstate
+}
+
+function Toggle::value() {
+    return bool;
+}
+
+function Toggle::activate() {
+    bool = !bool;
+    return this;
+}
+
+class NthToggle extends Toggle {
+    count_max=null
+    count=0
+}
+
+function NthToggle::constructor(start_state,max_counter)
+{
+    base.constructor(start_state);
+    count_max = max_counter
+}
+
+function NthToggle::activate ()
+{
+    ++count;
+    if (count >= count_max ) {
+      base.activate();
+      count = 0;
+    }
+    return this;
+}
+
+
+function main() {
+    local n = vargv.len()!=0?vargv[0].tointeger():1
+
+
+
+    local val = 1;
+    local toggle = Toggle(val);
+    local i = n;
+    while(i--) {
+      val = toggle.activate().value();
+
+    }
+    print(toggle.value() ? "true\n" : "false\n");
+
+    val = 1;
+    local ntoggle = NthToggle(val, 3);
+    i = n;
+    while(i--) {
+      val = ntoggle.activate().value();
+    }
+    print(ntoggle.value() ? "true\n" : "false\n");
+
+}
+local start=clock();
+main();
+print("TIME="+(clock()-start)+"\n");

+ 24 - 24
samples/tailstate.nut

@@ -1,24 +1,24 @@
-function state1()
-{
-	::suspend("state1");
-	return state2();
-}
-
-function state2()
-{
-	::suspend("state2");
-	return state3();
-}
-
-function state3()
-{
-	::suspend("state3");
-	return state1();
-}
-
-local statethread = ::newthread(state1)
-
-::print(statethread.call()+"\n");
-
-for(local i = 0; i < 10000; i++)
-	::print(statethread.wakeup()+"\n");
+function state1()
+{
+    ::suspend("state1");
+    return state2();
+}
+
+function state2()
+{
+    ::suspend("state2");
+    return state3();
+}
+
+function state3()
+{
+    ::suspend("state3");
+    return state1();
+}
+
+local statethread = ::newthread(state1)
+
+::print(statethread.call()+"\n");
+
+for(local i = 0; i < 10000; i++)
+    ::print(statethread.wakeup()+"\n");

+ 21 - 21
sq/Makefile

@@ -1,21 +1,21 @@
-SQUIRREL= ..
-
-
-OUT= $(SQUIRREL)/bin/sq
-INCZ= -I$(SQUIRREL)/include -I. -I$(SQUIRREL)/sqlibs
-LIBZ= -L$(SQUIRREL)/lib 
-LIB= -lsquirrel -lsqstdlib
-
-OBJS= sq.o
-	
-SRCS= sq.c
-	
-	
-sq32:
-	g++ -O2 -fno-exceptions -fno-rtti -o $(OUT) $(SRCS) $(INCZ) $(LIBZ) $(LIB)
-
-sqprof:
-	g++ -O2 -pg -fno-exceptions -fno-rtti -pie -gstabs -g3 -o $(OUT) $(SRCS) $(INCZ) $(LIBZ) $(LIB)
-	
-sq64:
-	g++ -O2 -m64 -fno-exceptions -fno-rtti -D_SQ64 -o $(OUT) $(SRCS) $(INCZ) $(LIBZ) $(LIB)
+SQUIRREL= ..
+
+
+OUT= $(SQUIRREL)/bin/sq
+INCZ= -I$(SQUIRREL)/include -I. -I$(SQUIRREL)/sqlibs
+LIBZ= -L$(SQUIRREL)/lib
+LIB= -lsquirrel -lsqstdlib
+
+OBJS= sq.o
+
+SRCS= sq.c
+
+
+sq32:
+	g++ -O2 -fno-exceptions -fno-rtti -o $(OUT) $(SRCS) $(INCZ) $(LIBZ) $(LIB)
+
+sqprof:
+	g++ -O2 -pg -fno-exceptions -fno-rtti -pie -gstabs -g3 -o $(OUT) $(SRCS) $(INCZ) $(LIBZ) $(LIB)
+
+sq64:
+	g++ -O2 -m64 -fno-exceptions -fno-rtti -D_SQ64 -o $(OUT) $(SRCS) $(INCZ) $(LIBZ) $(LIB)

+ 350 - 350
sq/sq.c

@@ -1,350 +1,350 @@
-/*	see copyright notice in squirrel.h */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <stdarg.h>
-
-#if defined(_MSC_VER) && defined(_DEBUG)
-#include <crtdbg.h>
-#include <conio.h>
-#endif
-#include <squirrel.h>
-#include <sqstdblob.h>
-#include <sqstdsystem.h>
-#include <sqstdio.h>
-#include <sqstdmath.h>	
-#include <sqstdstring.h>
-#include <sqstdaux.h>
-
-#ifdef SQUNICODE
-#define scfprintf fwprintf
-#define scvprintf vfwprintf
-#else
-#define scfprintf fprintf
-#define scvprintf vfprintf
-#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==769)_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(stdout, s, vl);
-	va_end(vl);
-}
-
-void errorfunc(HSQUIRRELVM v,const SQChar *s,...)
-{
-	va_list vl;
-	va_start(vl, s);
-	scvprintf(stderr, s, vl);
-	va_end(vl);
-}
-
-void PrintVersionInfos()
-{
-	scfprintf(stdout,_SC("%s %s (%d bits)\n"),SQUIRREL_VERSION,SQUIRREL_COPYRIGHT,((int)(sizeof(SQInteger)*8)));
-}
-
-void PrintUsage()
-{
-	scfprintf(stderr,_SC("usage: sq <options> <scriptpath [args]>.\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
-#define _ERROR 3
-//<<FIXME>> this func is a mess
-int getargs(HSQUIRRELVM v,int argc, char* argv[],SQInteger *retval)
-{
-	int i;
-	int compiles_only = 0;
-	static SQChar temp[500];
-	const SQChar *ret=NULL;
-	char * output = NULL;
-	int lineinfo=0;
-	*retval = 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();
-					*retval = -1;
-					return _ERROR;
-				}
-			}else break;
-			arg++;
-		}
-
-		// src file
-		
-		if(arg<argc) {
-			const SQChar *filename=NULL;
-#ifdef SQUNICODE
-			mbstowcs(temp,argv[arg],strlen(argv[arg]));
-			filename=temp;
-#else
-			filename=argv[arg];
-#endif
-
-			arg++;
-			
-			//sq_pushstring(v,_SC("ARGS"),-1);
-			//sq_newarray(v,0);
-			
-			//sq_createslot(v,-3);
-			//sq_pop(v,1);
-			if(compiles_only) {
-				if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,SQTrue))){
-					const SQChar *outfile = _SC("out.cnut");
-					if(output) {
-#ifdef SQUNICODE
-						int len = (int)(strlen(output)+1);
-						mbstowcs(sq_getscratchpad(v,len*sizeof(SQChar)),output,len);
-						outfile = sq_getscratchpad(v,-1);
-#else
-						outfile = output;
-#endif
-					}
-					if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,outfile)))
-						return _DONE;
-				}
-			}
-			else {
-				//if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQFalse,SQTrue))) {
-					//return _DONE;
-				//}
-				if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,SQTrue))) {
-					int callargs = 1;
-					sq_pushroottable(v);
-					for(i=arg;i<argc;i++)
-					{
-						const SQChar *a;
-#ifdef SQUNICODE
-						int alen=(int)strlen(argv[i]);
-						a=sq_getscratchpad(v,(int)(alen*sizeof(SQChar)));
-						mbstowcs(sq_getscratchpad(v,-1),argv[i],alen);
-						sq_getscratchpad(v,-1)[alen] = _SC('\0');
-#else
-						a=argv[i];
-#endif
-						sq_pushstring(v,a,-1);
-						callargs++;
-						//sq_arrayappend(v,-2);
-					}
-					if(SQ_SUCCEEDED(sq_call(v,callargs,SQTrue,SQTrue))) {
-						SQObjectType type = sq_gettype(v,-1);
-						if(type == OT_INTEGER) {
-							*retval = type;
-							sq_getinteger(v,-1,retval);
-						}
-						return _DONE;
-					}
-					else{
-						return _ERROR;
-					}
-					
-				}
-			}
-			//if this point is reached an error occured
-			{
-				const SQChar *err;
-				sq_getlasterror(v);
-				if(SQ_SUCCEEDED(sq_getstring(v,-1,&err))) {
-					scprintf(_SC("Error [%s]\n"),err);
-					*retval = -2;
-					return _ERROR;
-				}
-			}
-			
-		}
-	}
-
-	return _INTERACTIVE;
-}
-
-void Interactive(HSQUIRRELVM v)
-{
-	
-#define MAXINPUT 1024
-	SQChar buffer[MAXINPUT];
-	SQInteger blocks =0;
-	SQInteger string=0;
-	SQInteger retval=0;
-	SQInteger done=0;
-	PrintVersionInfos();
-		
-	sq_pushroottable(v);
-	sq_pushstring(v,_SC("quit"),-1);
-	sq_pushuserpointer(v,&done);
-	sq_newclosure(v,quit,1);
-	sq_setparamscheck(v,1,NULL);
-	sq_newslot(v,-3,SQFalse);
-	sq_pop(v,1);
-
-    while (!done) 
-	{
-		SQInteger i = 0;
-		scprintf(_SC("\nsq>"));
-		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),(size_t)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;
-	SQInteger retval = 0;
-	const SQChar *filename=NULL;
-#if defined(_MSC_VER) && defined(_DEBUG)
-	_CrtSetAllocHook(MemAllocHook);
-#endif
-	
-	v=sq_open(1024);
-	sq_setprintfunc(v,printfunc,errorfunc);
-
-	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,&retval))
-	{
-	case _INTERACTIVE:
-		Interactive(v);
-		break;
-	case _DONE:
-	case _ERROR:
-	default: 
-		break;
-	}
-
-	sq_close(v);
-	
-#if defined(_MSC_VER) && defined(_DEBUG)
-	_getch();
-	_CrtMemDumpAllObjectsSince( NULL );
-#endif
-	return retval;
-}
-
+/*  see copyright notice in squirrel.h */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+
+#if defined(_MSC_VER) && defined(_DEBUG)
+#include <crtdbg.h>
+#include <conio.h>
+#endif
+#include <squirrel.h>
+#include <sqstdblob.h>
+#include <sqstdsystem.h>
+#include <sqstdio.h>
+#include <sqstdmath.h>
+#include <sqstdstring.h>
+#include <sqstdaux.h>
+
+#ifdef SQUNICODE
+#define scfprintf fwprintf
+#define scvprintf vfwprintf
+#else
+#define scfprintf fprintf
+#define scvprintf vfprintf
+#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==769)_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(stdout, s, vl);
+    va_end(vl);
+}
+
+void errorfunc(HSQUIRRELVM v,const SQChar *s,...)
+{
+    va_list vl;
+    va_start(vl, s);
+    scvprintf(stderr, s, vl);
+    va_end(vl);
+}
+
+void PrintVersionInfos()
+{
+    scfprintf(stdout,_SC("%s %s (%d bits)\n"),SQUIRREL_VERSION,SQUIRREL_COPYRIGHT,((int)(sizeof(SQInteger)*8)));
+}
+
+void PrintUsage()
+{
+    scfprintf(stderr,_SC("usage: sq <options> <scriptpath [args]>.\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
+#define _ERROR 3
+//<<FIXME>> this func is a mess
+int getargs(HSQUIRRELVM v,int argc, char* argv[],SQInteger *retval)
+{
+    int i;
+    int compiles_only = 0;
+    static SQChar temp[500];
+    const SQChar *ret=NULL;
+    char * output = NULL;
+    int lineinfo=0;
+    *retval = 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();
+                    *retval = -1;
+                    return _ERROR;
+                }
+            }else break;
+            arg++;
+        }
+
+        // src file
+
+        if(arg<argc) {
+            const SQChar *filename=NULL;
+#ifdef SQUNICODE
+            mbstowcs(temp,argv[arg],strlen(argv[arg]));
+            filename=temp;
+#else
+            filename=argv[arg];
+#endif
+
+            arg++;
+
+            //sq_pushstring(v,_SC("ARGS"),-1);
+            //sq_newarray(v,0);
+
+            //sq_createslot(v,-3);
+            //sq_pop(v,1);
+            if(compiles_only) {
+                if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,SQTrue))){
+                    const SQChar *outfile = _SC("out.cnut");
+                    if(output) {
+#ifdef SQUNICODE
+                        int len = (int)(strlen(output)+1);
+                        mbstowcs(sq_getscratchpad(v,len*sizeof(SQChar)),output,len);
+                        outfile = sq_getscratchpad(v,-1);
+#else
+                        outfile = output;
+#endif
+                    }
+                    if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,outfile)))
+                        return _DONE;
+                }
+            }
+            else {
+                //if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQFalse,SQTrue))) {
+                    //return _DONE;
+                //}
+                if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,SQTrue))) {
+                    int callargs = 1;
+                    sq_pushroottable(v);
+                    for(i=arg;i<argc;i++)
+                    {
+                        const SQChar *a;
+#ifdef SQUNICODE
+                        int alen=(int)strlen(argv[i]);
+                        a=sq_getscratchpad(v,(int)(alen*sizeof(SQChar)));
+                        mbstowcs(sq_getscratchpad(v,-1),argv[i],alen);
+                        sq_getscratchpad(v,-1)[alen] = _SC('\0');
+#else
+                        a=argv[i];
+#endif
+                        sq_pushstring(v,a,-1);
+                        callargs++;
+                        //sq_arrayappend(v,-2);
+                    }
+                    if(SQ_SUCCEEDED(sq_call(v,callargs,SQTrue,SQTrue))) {
+                        SQObjectType type = sq_gettype(v,-1);
+                        if(type == OT_INTEGER) {
+                            *retval = type;
+                            sq_getinteger(v,-1,retval);
+                        }
+                        return _DONE;
+                    }
+                    else{
+                        return _ERROR;
+                    }
+
+                }
+            }
+            //if this point is reached an error occured
+            {
+                const SQChar *err;
+                sq_getlasterror(v);
+                if(SQ_SUCCEEDED(sq_getstring(v,-1,&err))) {
+                    scprintf(_SC("Error [%s]\n"),err);
+                    *retval = -2;
+                    return _ERROR;
+                }
+            }
+
+        }
+    }
+
+    return _INTERACTIVE;
+}
+
+void Interactive(HSQUIRRELVM v)
+{
+
+#define MAXINPUT 1024
+    SQChar buffer[MAXINPUT];
+    SQInteger blocks =0;
+    SQInteger string=0;
+    SQInteger retval=0;
+    SQInteger done=0;
+    PrintVersionInfos();
+
+    sq_pushroottable(v);
+    sq_pushstring(v,_SC("quit"),-1);
+    sq_pushuserpointer(v,&done);
+    sq_newclosure(v,quit,1);
+    sq_setparamscheck(v,1,NULL);
+    sq_newslot(v,-3,SQFalse);
+    sq_pop(v,1);
+
+    while (!done)
+    {
+        SQInteger i = 0;
+        scprintf(_SC("\nsq>"));
+        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),(size_t)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;
+    SQInteger retval = 0;
+    const SQChar *filename=NULL;
+#if defined(_MSC_VER) && defined(_DEBUG)
+    _CrtSetAllocHook(MemAllocHook);
+#endif
+
+    v=sq_open(1024);
+    sq_setprintfunc(v,printfunc,errorfunc);
+
+    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,&retval))
+    {
+    case _INTERACTIVE:
+        Interactive(v);
+        break;
+    case _DONE:
+    case _ERROR:
+    default:
+        break;
+    }
+
+    sq_close(v);
+
+#if defined(_MSC_VER) && defined(_DEBUG)
+    _getch();
+    _CrtMemDumpAllObjectsSince( NULL );
+#endif
+    return retval;
+}
+

+ 1 - 1
sqstdlib/CMakeLists.txt

@@ -8,7 +8,7 @@ set(SQSTD_SRCS
     sqstdstream.cpp
     sqstdmath.cpp
     sqstdsystem.cpp
-    sqstdstring.cpp 
+    sqstdstring.cpp
     sqstdaux.cpp
     sqstdrex.cpp
 )

+ 41 - 41
sqstdlib/Makefile

@@ -1,41 +1,41 @@
-SQUIRREL= ..
-
-
-OUT= $(SQUIRREL)/lib/libsqstdlib.a
-INCZ= -I$(SQUIRREL)/include -I. -Iinclude
-
-OBJS= \
-	sqstdblob.o \
-	sqstdio.o \
-	sqstdstream.o \
-	sqstdmath.o \
-	sqstdsystem.o \
-	sqstdstring.o \
-	sqstdaux.o \
-	sqstdrex.o
-	
-SRCS= \
-	sqstdblob.cpp \
-	sqstdio.cpp \
-	sqstdstream.cpp \
-	sqstdmath.cpp \
-	sqstdsystem.cpp \
-	sqstdstring.cpp \
-	sqstdaux.cpp \
-	sqstdrex.cpp
-	
-	
-sq32:
-	gcc -O2 -fno-exceptions -fno-rtti -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ)
-	ar rc $(OUT) *.o
-	rm *.o
-
-sqprof:
-	gcc -O2 -pg -fno-exceptions -fno-rtti -pie -gstabs -g3 -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ)
-	ar rc $(OUT) *.o
-	rm *.o
-	
-sq64:
-	gcc -O2 -m64 -fno-exceptions -D_SQ64 -fno-rtti -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ)
-	ar rc $(OUT) *.o
-	rm *.o
+SQUIRREL= ..
+
+
+OUT= $(SQUIRREL)/lib/libsqstdlib.a
+INCZ= -I$(SQUIRREL)/include -I. -Iinclude
+
+OBJS= \
+	sqstdblob.o \
+	sqstdio.o \
+	sqstdstream.o \
+	sqstdmath.o \
+	sqstdsystem.o \
+	sqstdstring.o \
+	sqstdaux.o \
+	sqstdrex.o
+
+SRCS= \
+	sqstdblob.cpp \
+	sqstdio.cpp \
+	sqstdstream.cpp \
+	sqstdmath.cpp \
+	sqstdsystem.cpp \
+	sqstdstring.cpp \
+	sqstdaux.cpp \
+	sqstdrex.cpp
+
+
+sq32:
+	gcc -O2 -fno-exceptions -fno-rtti -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ)
+	ar rc $(OUT) *.o
+	rm *.o
+
+sqprof:
+	gcc -O2 -pg -fno-exceptions -fno-rtti -pie -gstabs -g3 -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ)
+	ar rc $(OUT) *.o
+	rm *.o
+
+sq64:
+	gcc -O2 -m64 -fno-exceptions -D_SQ64 -fno-rtti -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ)
+	ar rc $(OUT) *.o
+	rm *.o

+ 130 - 130
sqstdlib/sqstdaux.cpp

@@ -1,130 +1,130 @@
-/* see copyright notice in squirrel.h */
-#include <squirrel.h>
-#include <sqstdaux.h>
-#include <assert.h>
-
-void sqstd_printcallstack(HSQUIRRELVM v)
-{
-	SQPRINTFUNCTION pf = sq_geterrorfunc(v);
-	if(pf) {
-		SQStackInfos si;
-		SQInteger i;
-		SQFloat f;
-		const SQChar *s;
-		SQInteger level=1; //1 is to skip this function that is level 0
-		const SQChar *name=0; 
-		SQInteger seq=0;
-		pf(v,_SC("\nCALLSTACK\n"));
-		while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si)))
-		{
-			const SQChar *fn=_SC("unknown");
-			const SQChar *src=_SC("unknown");
-			if(si.funcname)fn=si.funcname;
-			if(si.source)src=si.source;
-			pf(v,_SC("*FUNCTION [%s()] %s line [%d]\n"),fn,src,si.line);
-			level++;
-		}
-		level=0;
-		pf(v,_SC("\nLOCALS\n"));
-
-		for(level=0;level<10;level++){
-			seq=0;
-			while((name = sq_getlocal(v,level,seq)))
-			{
-				seq++;
-				switch(sq_gettype(v,-1))
-				{
-				case OT_NULL:
-					pf(v,_SC("[%s] NULL\n"),name);
-					break;
-				case OT_INTEGER:
-					sq_getinteger(v,-1,&i);
-					pf(v,_SC("[%s] %d\n"),name,i);
-					break;
-				case OT_FLOAT:
-					sq_getfloat(v,-1,&f);
-					pf(v,_SC("[%s] %.14g\n"),name,f);
-					break;
-				case OT_USERPOINTER:
-					pf(v,_SC("[%s] USERPOINTER\n"),name);
-					break;
-				case OT_STRING:
-					sq_getstring(v,-1,&s);
-					pf(v,_SC("[%s] \"%s\"\n"),name,s);
-					break;
-				case OT_TABLE:
-					pf(v,_SC("[%s] TABLE\n"),name);
-					break;
-				case OT_ARRAY:
-					pf(v,_SC("[%s] ARRAY\n"),name);
-					break;
-				case OT_CLOSURE:
-					pf(v,_SC("[%s] CLOSURE\n"),name);
-					break;
-				case OT_NATIVECLOSURE:
-					pf(v,_SC("[%s] NATIVECLOSURE\n"),name);
-					break;
-				case OT_GENERATOR:
-					pf(v,_SC("[%s] GENERATOR\n"),name);
-					break;
-				case OT_USERDATA:
-					pf(v,_SC("[%s] USERDATA\n"),name);
-					break;
-				case OT_THREAD:
-					pf(v,_SC("[%s] THREAD\n"),name);
-					break;
-				case OT_CLASS:
-					pf(v,_SC("[%s] CLASS\n"),name);
-					break;
-				case OT_INSTANCE:
-					pf(v,_SC("[%s] INSTANCE\n"),name);
-					break;
-				case OT_WEAKREF:
-					pf(v,_SC("[%s] WEAKREF\n"),name);
-					break;
-				case OT_BOOL:{
-					SQBool bval;
-					sq_getbool(v,-1,&bval);
-					pf(v,_SC("[%s] %s\n"),name,bval == SQTrue ? _SC("true"):_SC("false"));
-							 }
-					break;
-				default: assert(0); break;
-				}
-				sq_pop(v,1);
-			}
-		}
-	}
-}
-
-static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v)
-{
-	SQPRINTFUNCTION pf = sq_geterrorfunc(v);
-	if(pf) {
-		const SQChar *sErr = 0;
-		if(sq_gettop(v)>=1) {
-			if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr)))	{
-				pf(v,_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr);
-			}
-			else{
-				pf(v,_SC("\nAN ERROR HAS OCCURED [unknown]\n"));
-			}
-			sqstd_printcallstack(v);
-		}
-	}
-	return 0;
-}
-
-void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSource,SQInteger line,SQInteger column)
-{
-	SQPRINTFUNCTION pf = sq_geterrorfunc(v);
-	if(pf) {
-		pf(v,_SC("%s line = (%d) column = (%d) : error %s\n"),sSource,line,column,sErr);
-	}
-}
-
-void sqstd_seterrorhandlers(HSQUIRRELVM v)
-{
-	sq_setcompilererrorhandler(v,_sqstd_compiler_error);
-	sq_newclosure(v,_sqstd_aux_printerror,0);
-	sq_seterrorhandler(v);
-}
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <sqstdaux.h>
+#include <assert.h>
+
+void sqstd_printcallstack(HSQUIRRELVM v)
+{
+    SQPRINTFUNCTION pf = sq_geterrorfunc(v);
+    if(pf) {
+        SQStackInfos si;
+        SQInteger i;
+        SQFloat f;
+        const SQChar *s;
+        SQInteger level=1; //1 is to skip this function that is level 0
+        const SQChar *name=0;
+        SQInteger seq=0;
+        pf(v,_SC("\nCALLSTACK\n"));
+        while(SQ_SUCCEEDED(sq_stackinfos(v,level,&si)))
+        {
+            const SQChar *fn=_SC("unknown");
+            const SQChar *src=_SC("unknown");
+            if(si.funcname)fn=si.funcname;
+            if(si.source)src=si.source;
+            pf(v,_SC("*FUNCTION [%s()] %s line [%d]\n"),fn,src,si.line);
+            level++;
+        }
+        level=0;
+        pf(v,_SC("\nLOCALS\n"));
+
+        for(level=0;level<10;level++){
+            seq=0;
+            while((name = sq_getlocal(v,level,seq)))
+            {
+                seq++;
+                switch(sq_gettype(v,-1))
+                {
+                case OT_NULL:
+                    pf(v,_SC("[%s] NULL\n"),name);
+                    break;
+                case OT_INTEGER:
+                    sq_getinteger(v,-1,&i);
+                    pf(v,_SC("[%s] %d\n"),name,i);
+                    break;
+                case OT_FLOAT:
+                    sq_getfloat(v,-1,&f);
+                    pf(v,_SC("[%s] %.14g\n"),name,f);
+                    break;
+                case OT_USERPOINTER:
+                    pf(v,_SC("[%s] USERPOINTER\n"),name);
+                    break;
+                case OT_STRING:
+                    sq_getstring(v,-1,&s);
+                    pf(v,_SC("[%s] \"%s\"\n"),name,s);
+                    break;
+                case OT_TABLE:
+                    pf(v,_SC("[%s] TABLE\n"),name);
+                    break;
+                case OT_ARRAY:
+                    pf(v,_SC("[%s] ARRAY\n"),name);
+                    break;
+                case OT_CLOSURE:
+                    pf(v,_SC("[%s] CLOSURE\n"),name);
+                    break;
+                case OT_NATIVECLOSURE:
+                    pf(v,_SC("[%s] NATIVECLOSURE\n"),name);
+                    break;
+                case OT_GENERATOR:
+                    pf(v,_SC("[%s] GENERATOR\n"),name);
+                    break;
+                case OT_USERDATA:
+                    pf(v,_SC("[%s] USERDATA\n"),name);
+                    break;
+                case OT_THREAD:
+                    pf(v,_SC("[%s] THREAD\n"),name);
+                    break;
+                case OT_CLASS:
+                    pf(v,_SC("[%s] CLASS\n"),name);
+                    break;
+                case OT_INSTANCE:
+                    pf(v,_SC("[%s] INSTANCE\n"),name);
+                    break;
+                case OT_WEAKREF:
+                    pf(v,_SC("[%s] WEAKREF\n"),name);
+                    break;
+                case OT_BOOL:{
+                    SQBool bval;
+                    sq_getbool(v,-1,&bval);
+                    pf(v,_SC("[%s] %s\n"),name,bval == SQTrue ? _SC("true"):_SC("false"));
+                             }
+                    break;
+                default: assert(0); break;
+                }
+                sq_pop(v,1);
+            }
+        }
+    }
+}
+
+static SQInteger _sqstd_aux_printerror(HSQUIRRELVM v)
+{
+    SQPRINTFUNCTION pf = sq_geterrorfunc(v);
+    if(pf) {
+        const SQChar *sErr = 0;
+        if(sq_gettop(v)>=1) {
+            if(SQ_SUCCEEDED(sq_getstring(v,2,&sErr)))   {
+                pf(v,_SC("\nAN ERROR HAS OCCURED [%s]\n"),sErr);
+            }
+            else{
+                pf(v,_SC("\nAN ERROR HAS OCCURED [unknown]\n"));
+            }
+            sqstd_printcallstack(v);
+        }
+    }
+    return 0;
+}
+
+void _sqstd_compiler_error(HSQUIRRELVM v,const SQChar *sErr,const SQChar *sSource,SQInteger line,SQInteger column)
+{
+    SQPRINTFUNCTION pf = sq_geterrorfunc(v);
+    if(pf) {
+        pf(v,_SC("%s line = (%d) column = (%d) : error %s\n"),sSource,line,column,sErr);
+    }
+}
+
+void sqstd_seterrorhandlers(HSQUIRRELVM v)
+{
+    sq_setcompilererrorhandler(v,_sqstd_compiler_error);
+    sq_newclosure(v,_sqstd_aux_printerror,0);
+    sq_seterrorhandler(v);
+}

+ 277 - 277
sqstdlib/sqstdblob.cpp

@@ -1,277 +1,277 @@
-/* see copyright notice in squirrel.h */
-#include <new>
-#include <squirrel.h>
-#include <sqstdio.h>
-#include <string.h>
-#include <sqstdblob.h>
-#include "sqstdstream.h"
-#include "sqstdblobimpl.h"
-
-#define SQSTD_BLOB_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000002)
-
-//Blob
-
-
-#define SETUP_BLOB(v) \
-	SQBlob *self = NULL; \
-	{ if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \
-		return sq_throwerror(v,_SC("invalid type tag"));  } \
-	if(!self || !self->IsValid())  \
-		return sq_throwerror(v,_SC("the blob is invalid"));
-
-
-static SQInteger _blob_resize(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
-	SQInteger size;
-	sq_getinteger(v,2,&size);
-	if(!self->Resize(size))
-		return sq_throwerror(v,_SC("resize failed"));
-	return 0;
-}
-
-static void __swap_dword(unsigned int *n)
-{
-	*n=(unsigned int)(((*n&0xFF000000)>>24)  |
-			((*n&0x00FF0000)>>8)  |
-			((*n&0x0000FF00)<<8)  |
-			((*n&0x000000FF)<<24));
-}
-
-static void __swap_word(unsigned short *n)
-{
-	*n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00);
-}
-
-static SQInteger _blob_swap4(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
-	SQInteger num=(self->Len()-(self->Len()%4))>>2;
-	unsigned int *t=(unsigned int *)self->GetBuf();
-	for(SQInteger i = 0; i < num; i++) {
-		__swap_dword(&t[i]);
-	}
-	return 0;
-}
-
-static SQInteger _blob_swap2(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
-	SQInteger num=(self->Len()-(self->Len()%2))>>1;
-	unsigned short *t = (unsigned short *)self->GetBuf();
-	for(SQInteger i = 0; i < num; i++) {
-		__swap_word(&t[i]);
-	}
-	return 0;
-}
-
-static SQInteger _blob__set(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
-	SQInteger idx,val;
-	sq_getinteger(v,2,&idx);
-	sq_getinteger(v,3,&val);
-	if(idx < 0 || idx >= self->Len())
-		return sq_throwerror(v,_SC("index out of range"));
-	((unsigned char *)self->GetBuf())[idx] = (unsigned char) val;
-	sq_push(v,3);
-	return 1;
-}
-
-static SQInteger _blob__get(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
-	SQInteger idx;
-	sq_getinteger(v,2,&idx);
-	if(idx < 0 || idx >= self->Len())
-		return sq_throwerror(v,_SC("index out of range"));
-	sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]);
-	return 1;
-}
-
-static SQInteger _blob__nexti(HSQUIRRELVM v)
-{
-	SETUP_BLOB(v);
-	if(sq_gettype(v,2) == OT_NULL) {
-		sq_pushinteger(v, 0);
-		return 1;
-	}
-	SQInteger idx;
-	if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) {
-		if(idx+1 < self->Len()) {
-			sq_pushinteger(v, idx+1);
-			return 1;
-		}
-		sq_pushnull(v);
-		return 1;
-	}
-	return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type"));
-}
-
-static SQInteger _blob__typeof(HSQUIRRELVM v)
-{
-	sq_pushstring(v,_SC("blob"),-1);
-	return 1;
-}
-
-static SQInteger _blob_releasehook(SQUserPointer p, SQInteger size)
-{
-	SQBlob *self = (SQBlob*)p;
-	self->~SQBlob();
-	sq_free(self,sizeof(SQBlob));
-	return 1;
-}
-
-static SQInteger _blob_constructor(HSQUIRRELVM v)
-{
-	SQInteger nparam = sq_gettop(v);
-	SQInteger size = 0;
-	if(nparam == 2) {
-		sq_getinteger(v, 2, &size);
-	}
-	if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size"));
-	//SQBlob *b = new SQBlob(size);
-
-	SQBlob *b = new (sq_malloc(sizeof(SQBlob)))SQBlob(size);
-	if(SQ_FAILED(sq_setinstanceup(v,1,b))) {
-		b->~SQBlob();
-		sq_free(b,sizeof(SQBlob));
-		return sq_throwerror(v, _SC("cannot create blob"));
-	}
-	sq_setreleasehook(v,1,_blob_releasehook);
-	return 0;
-}
-
-static SQInteger _blob__cloned(HSQUIRRELVM v)
-{
-	SQBlob *other = NULL;
-	{ 
-		if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
-			return SQ_ERROR; 
-	}
-	//SQBlob *thisone = new SQBlob(other->Len());
-	SQBlob *thisone = new (sq_malloc(sizeof(SQBlob)))SQBlob(other->Len());
-	memcpy(thisone->GetBuf(),other->GetBuf(),thisone->Len());
-	if(SQ_FAILED(sq_setinstanceup(v,1,thisone))) {
-		thisone->~SQBlob();
-		sq_free(thisone,sizeof(SQBlob));
-		return sq_throwerror(v, _SC("cannot clone blob"));
-	}
-	sq_setreleasehook(v,1,_blob_releasehook);
-	return 0;
-}
-
-#define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck}
-static SQRegFunction _blob_methods[] = {
-	_DECL_BLOB_FUNC(constructor,-1,_SC("xn")),
-	_DECL_BLOB_FUNC(resize,2,_SC("xn")),
-	_DECL_BLOB_FUNC(swap2,1,_SC("x")),
-	_DECL_BLOB_FUNC(swap4,1,_SC("x")),
-	_DECL_BLOB_FUNC(_set,3,_SC("xnn")),
-	_DECL_BLOB_FUNC(_get,2,_SC("xn")),
-	_DECL_BLOB_FUNC(_typeof,1,_SC("x")),
-	_DECL_BLOB_FUNC(_nexti,2,_SC("x")),
-	_DECL_BLOB_FUNC(_cloned,2,_SC("xx")),
-	{0,0,0,0}
-};
-
-
-
-//GLOBAL FUNCTIONS
-
-static SQInteger _g_blob_casti2f(HSQUIRRELVM v)
-{
-	SQInteger i;
-	sq_getinteger(v,2,&i);
-	sq_pushfloat(v,*((SQFloat *)&i));
-	return 1;
-}
-
-static SQInteger _g_blob_castf2i(HSQUIRRELVM v)
-{
-	SQFloat f;
-	sq_getfloat(v,2,&f);
-	sq_pushinteger(v,*((SQInteger *)&f));
-	return 1;
-}
-
-static SQInteger _g_blob_swap2(HSQUIRRELVM v)
-{
-	SQInteger i;
-	sq_getinteger(v,2,&i);
-	short s=(short)i;
-	sq_pushinteger(v,(s<<8)|((s>>8)&0x00FF));
-	return 1;
-}
-
-static SQInteger _g_blob_swap4(HSQUIRRELVM v)
-{
-	SQInteger i;
-	sq_getinteger(v,2,&i);
-	unsigned int t4 = (unsigned int)i;
-	__swap_dword(&t4);
-	sq_pushinteger(v,(SQInteger)t4);
-	return 1;
-}
-
-static SQInteger _g_blob_swapfloat(HSQUIRRELVM v)
-{
-	SQFloat f;
-	sq_getfloat(v,2,&f);
-	__swap_dword((unsigned int *)&f);
-	sq_pushfloat(v,f);
-	return 1;
-}
-
-#define _DECL_GLOBALBLOB_FUNC(name,nparams,typecheck) {_SC(#name),_g_blob_##name,nparams,typecheck}
-static SQRegFunction bloblib_funcs[]={
-	_DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")),
-	_DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")),
-	_DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")),
-	_DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")),
-	_DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")),
-	{0,0}
-};
-
-SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr)
-{
-	SQBlob *blob;
-	if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
-		return -1;
-	*ptr = blob->GetBuf();
-	return SQ_OK;
-}
-
-SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx)
-{
-	SQBlob *blob;
-	if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
-		return -1;
-	return blob->Len();
-}
-
-SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size)
-{
-	SQInteger top = sq_gettop(v);
-	sq_pushregistrytable(v);
-	sq_pushstring(v,_SC("std_blob"),-1);
-	if(SQ_SUCCEEDED(sq_get(v,-2))) {
-		sq_remove(v,-2); //removes the registry
-		sq_push(v,1); // push the this
-		sq_pushinteger(v,size); //size
-		SQBlob *blob = NULL;
-		if(SQ_SUCCEEDED(sq_call(v,2,SQTrue,SQFalse))
-			&& SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) {
-			sq_remove(v,-2);
-			return blob->GetBuf();
-		}
-	}
-	sq_settop(v,top);
-	return NULL;
-}
-
-SQRESULT sqstd_register_bloblib(HSQUIRRELVM v)
-{
-	return declare_stream(v,_SC("blob"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);
-}
-
+/* see copyright notice in squirrel.h */
+#include <new>
+#include <squirrel.h>
+#include <sqstdio.h>
+#include <string.h>
+#include <sqstdblob.h>
+#include "sqstdstream.h"
+#include "sqstdblobimpl.h"
+
+#define SQSTD_BLOB_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000002)
+
+//Blob
+
+
+#define SETUP_BLOB(v) \
+    SQBlob *self = NULL; \
+    { if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) \
+        return sq_throwerror(v,_SC("invalid type tag"));  } \
+    if(!self || !self->IsValid())  \
+        return sq_throwerror(v,_SC("the blob is invalid"));
+
+
+static SQInteger _blob_resize(HSQUIRRELVM v)
+{
+    SETUP_BLOB(v);
+    SQInteger size;
+    sq_getinteger(v,2,&size);
+    if(!self->Resize(size))
+        return sq_throwerror(v,_SC("resize failed"));
+    return 0;
+}
+
+static void __swap_dword(unsigned int *n)
+{
+    *n=(unsigned int)(((*n&0xFF000000)>>24)  |
+            ((*n&0x00FF0000)>>8)  |
+            ((*n&0x0000FF00)<<8)  |
+            ((*n&0x000000FF)<<24));
+}
+
+static void __swap_word(unsigned short *n)
+{
+    *n=(unsigned short)((*n>>8)&0x00FF)| ((*n<<8)&0xFF00);
+}
+
+static SQInteger _blob_swap4(HSQUIRRELVM v)
+{
+    SETUP_BLOB(v);
+    SQInteger num=(self->Len()-(self->Len()%4))>>2;
+    unsigned int *t=(unsigned int *)self->GetBuf();
+    for(SQInteger i = 0; i < num; i++) {
+        __swap_dword(&t[i]);
+    }
+    return 0;
+}
+
+static SQInteger _blob_swap2(HSQUIRRELVM v)
+{
+    SETUP_BLOB(v);
+    SQInteger num=(self->Len()-(self->Len()%2))>>1;
+    unsigned short *t = (unsigned short *)self->GetBuf();
+    for(SQInteger i = 0; i < num; i++) {
+        __swap_word(&t[i]);
+    }
+    return 0;
+}
+
+static SQInteger _blob__set(HSQUIRRELVM v)
+{
+    SETUP_BLOB(v);
+    SQInteger idx,val;
+    sq_getinteger(v,2,&idx);
+    sq_getinteger(v,3,&val);
+    if(idx < 0 || idx >= self->Len())
+        return sq_throwerror(v,_SC("index out of range"));
+    ((unsigned char *)self->GetBuf())[idx] = (unsigned char) val;
+    sq_push(v,3);
+    return 1;
+}
+
+static SQInteger _blob__get(HSQUIRRELVM v)
+{
+    SETUP_BLOB(v);
+    SQInteger idx;
+    sq_getinteger(v,2,&idx);
+    if(idx < 0 || idx >= self->Len())
+        return sq_throwerror(v,_SC("index out of range"));
+    sq_pushinteger(v,((unsigned char *)self->GetBuf())[idx]);
+    return 1;
+}
+
+static SQInteger _blob__nexti(HSQUIRRELVM v)
+{
+    SETUP_BLOB(v);
+    if(sq_gettype(v,2) == OT_NULL) {
+        sq_pushinteger(v, 0);
+        return 1;
+    }
+    SQInteger idx;
+    if(SQ_SUCCEEDED(sq_getinteger(v, 2, &idx))) {
+        if(idx+1 < self->Len()) {
+            sq_pushinteger(v, idx+1);
+            return 1;
+        }
+        sq_pushnull(v);
+        return 1;
+    }
+    return sq_throwerror(v,_SC("internal error (_nexti) wrong argument type"));
+}
+
+static SQInteger _blob__typeof(HSQUIRRELVM v)
+{
+    sq_pushstring(v,_SC("blob"),-1);
+    return 1;
+}
+
+static SQInteger _blob_releasehook(SQUserPointer p, SQInteger size)
+{
+    SQBlob *self = (SQBlob*)p;
+    self->~SQBlob();
+    sq_free(self,sizeof(SQBlob));
+    return 1;
+}
+
+static SQInteger _blob_constructor(HSQUIRRELVM v)
+{
+    SQInteger nparam = sq_gettop(v);
+    SQInteger size = 0;
+    if(nparam == 2) {
+        sq_getinteger(v, 2, &size);
+    }
+    if(size < 0) return sq_throwerror(v, _SC("cannot create blob with negative size"));
+    //SQBlob *b = new SQBlob(size);
+
+    SQBlob *b = new (sq_malloc(sizeof(SQBlob)))SQBlob(size);
+    if(SQ_FAILED(sq_setinstanceup(v,1,b))) {
+        b->~SQBlob();
+        sq_free(b,sizeof(SQBlob));
+        return sq_throwerror(v, _SC("cannot create blob"));
+    }
+    sq_setreleasehook(v,1,_blob_releasehook);
+    return 0;
+}
+
+static SQInteger _blob__cloned(HSQUIRRELVM v)
+{
+    SQBlob *other = NULL;
+    {
+        if(SQ_FAILED(sq_getinstanceup(v,2,(SQUserPointer*)&other,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
+            return SQ_ERROR;
+    }
+    //SQBlob *thisone = new SQBlob(other->Len());
+    SQBlob *thisone = new (sq_malloc(sizeof(SQBlob)))SQBlob(other->Len());
+    memcpy(thisone->GetBuf(),other->GetBuf(),thisone->Len());
+    if(SQ_FAILED(sq_setinstanceup(v,1,thisone))) {
+        thisone->~SQBlob();
+        sq_free(thisone,sizeof(SQBlob));
+        return sq_throwerror(v, _SC("cannot clone blob"));
+    }
+    sq_setreleasehook(v,1,_blob_releasehook);
+    return 0;
+}
+
+#define _DECL_BLOB_FUNC(name,nparams,typecheck) {_SC(#name),_blob_##name,nparams,typecheck}
+static const SQRegFunction _blob_methods[] = {
+    _DECL_BLOB_FUNC(constructor,-1,_SC("xn")),
+    _DECL_BLOB_FUNC(resize,2,_SC("xn")),
+    _DECL_BLOB_FUNC(swap2,1,_SC("x")),
+    _DECL_BLOB_FUNC(swap4,1,_SC("x")),
+    _DECL_BLOB_FUNC(_set,3,_SC("xnn")),
+    _DECL_BLOB_FUNC(_get,2,_SC("xn")),
+    _DECL_BLOB_FUNC(_typeof,1,_SC("x")),
+    _DECL_BLOB_FUNC(_nexti,2,_SC("x")),
+    _DECL_BLOB_FUNC(_cloned,2,_SC("xx")),
+    {0,0,0,0}
+};
+
+
+
+//GLOBAL FUNCTIONS
+
+static SQInteger _g_blob_casti2f(HSQUIRRELVM v)
+{
+    SQInteger i;
+    sq_getinteger(v,2,&i);
+    sq_pushfloat(v,*((const SQFloat *)&i));
+    return 1;
+}
+
+static SQInteger _g_blob_castf2i(HSQUIRRELVM v)
+{
+    SQFloat f;
+    sq_getfloat(v,2,&f);
+    sq_pushinteger(v,*((const 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 const SQRegFunction bloblib_funcs[]={
+    _DECL_GLOBALBLOB_FUNC(casti2f,2,_SC(".n")),
+    _DECL_GLOBALBLOB_FUNC(castf2i,2,_SC(".n")),
+    _DECL_GLOBALBLOB_FUNC(swap2,2,_SC(".n")),
+    _DECL_GLOBALBLOB_FUNC(swap4,2,_SC(".n")),
+    _DECL_GLOBALBLOB_FUNC(swapfloat,2,_SC(".n")),
+    {0,0}
+};
+
+SQRESULT sqstd_getblob(HSQUIRRELVM v,SQInteger idx,SQUserPointer *ptr)
+{
+    SQBlob *blob;
+    if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
+        return -1;
+    *ptr = blob->GetBuf();
+    return SQ_OK;
+}
+
+SQInteger sqstd_getblobsize(HSQUIRRELVM v,SQInteger idx)
+{
+    SQBlob *blob;
+    if(SQ_FAILED(sq_getinstanceup(v,idx,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG)))
+        return -1;
+    return blob->Len();
+}
+
+SQUserPointer sqstd_createblob(HSQUIRRELVM v, SQInteger size)
+{
+    SQInteger top = sq_gettop(v);
+    sq_pushregistrytable(v);
+    sq_pushstring(v,_SC("std_blob"),-1);
+    if(SQ_SUCCEEDED(sq_get(v,-2))) {
+        sq_remove(v,-2); //removes the registry
+        sq_push(v,1); // push the this
+        sq_pushinteger(v,size); //size
+        SQBlob *blob = NULL;
+        if(SQ_SUCCEEDED(sq_call(v,2,SQTrue,SQFalse))
+            && SQ_SUCCEEDED(sq_getinstanceup(v,-1,(SQUserPointer *)&blob,(SQUserPointer)SQSTD_BLOB_TYPE_TAG))) {
+            sq_remove(v,-2);
+            return blob->GetBuf();
+        }
+    }
+    sq_settop(v,top);
+    return NULL;
+}
+
+SQRESULT sqstd_register_bloblib(HSQUIRRELVM v)
+{
+    return declare_stream(v,_SC("blob"),(SQUserPointer)SQSTD_BLOB_TYPE_TAG,_SC("std_blob"),_blob_methods,bloblib_funcs);
+}
+

+ 108 - 108
sqstdlib/sqstdblobimpl.h

@@ -1,108 +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_
+/*  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_

+ 485 - 485
sqstdlib/sqstdio.cpp

@@ -1,485 +1,485 @@
-/* see copyright notice in squirrel.h */
-#include <new>
-#include <stdio.h>
-#include <squirrel.h>
-#include <sqstdio.h>
-#include "sqstdstream.h"
-
-#define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001)
-//basic API
-SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode)
-{
-#ifndef SQUNICODE
-	return (SQFILE)fopen(filename,mode);
-#else
-	return (SQFILE)_wfopen(filename,mode);
-#endif
-}
-
-SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file)
-{
-	SQInteger ret = (SQInteger)fread(buffer,size,count,(FILE *)file);
-	return ret;
-}
-
-SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file)
-{
-	return (SQInteger)fwrite(buffer,size,count,(FILE *)file);
-}
-
-SQInteger sqstd_fseek(SQFILE file, SQInteger offset, SQInteger origin)
-{
-	SQInteger realorigin;
-	switch(origin) {
-		case SQ_SEEK_CUR: realorigin = SEEK_CUR; break;
-		case SQ_SEEK_END: realorigin = SEEK_END; break;
-		case SQ_SEEK_SET: realorigin = SEEK_SET; break;
-		default: return -1; //failed
-	}
-	return fseek((FILE *)file,(long)offset,(int)realorigin);
-}
-
-SQInteger sqstd_ftell(SQFILE file)
-{
-	return ftell((FILE *)file);
-}
-
-SQInteger sqstd_fflush(SQFILE file)
-{
-	return fflush((FILE *)file);
-}
-
-SQInteger sqstd_fclose(SQFILE file)
-{
-	return fclose((FILE *)file);
-}
-
-SQInteger sqstd_feof(SQFILE file)
-{
-	return feof((FILE *)file);
-}
-
-//File
-struct SQFile : public SQStream {
-	SQFile() { _handle = NULL; _owns = false;}
-	SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;}
-	virtual ~SQFile() { Close(); }
-	bool Open(const SQChar *filename ,const SQChar *mode) {
-		Close();
-		if( (_handle = sqstd_fopen(filename,mode)) ) {
-			_owns = true;
-			return true;
-		}
-		return false;
-	}
-	void Close() {
-		if(_handle && _owns) { 
-			sqstd_fclose(_handle);
-			_handle = NULL;
-			_owns = false;
-		}
-	}
-	SQInteger Read(void *buffer,SQInteger size) {
-		return sqstd_fread(buffer,1,size,_handle);
-	}
-	SQInteger Write(void *buffer,SQInteger size) {
-		return sqstd_fwrite(buffer,1,size,_handle);
-	}
-	SQInteger Flush() {
-		return sqstd_fflush(_handle);
-	}
-	SQInteger Tell() {
-		return sqstd_ftell(_handle);
-	}
-	SQInteger Len() {
-		SQInteger prevpos=Tell();
-		Seek(0,SQ_SEEK_END);
-		SQInteger size=Tell();
-		Seek(prevpos,SQ_SEEK_SET);
-		return size;
-	}
-	SQInteger Seek(SQInteger offset, SQInteger origin)	{
-		return sqstd_fseek(_handle,offset,origin);
-	}
-	bool IsValid() { return _handle?true:false; }
-	bool EOS() { return Tell()==Len()?true:false;}
-	SQFILE GetHandle() {return _handle;}
-private:
-	SQFILE _handle;
-	bool _owns;
-};
-
-static SQInteger _file__typeof(HSQUIRRELVM v)
-{
-	sq_pushstring(v,_SC("file"),-1);
-	return 1;
-}
-
-static SQInteger _file_releasehook(SQUserPointer p, SQInteger size)
-{
-	SQFile *self = (SQFile*)p;
-	self->~SQFile();
-	sq_free(self,sizeof(SQFile));
-	return 1;
-}
-
-static SQInteger _file_constructor(HSQUIRRELVM v)
-{
-	const SQChar *filename,*mode;
-	bool owns = true;
-	SQFile *f;
-	SQFILE newf;
-	if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {
-		sq_getstring(v, 2, &filename);
-		sq_getstring(v, 3, &mode);
-		newf = sqstd_fopen(filename, mode);
-		if(!newf) return sq_throwerror(v, _SC("cannot open file"));
-	} else if(sq_gettype(v,2) == OT_USERPOINTER) {
-		owns = !(sq_gettype(v,3) == OT_NULL);
-		sq_getuserpointer(v,2,&newf);
-	} else {
-		return sq_throwerror(v,_SC("wrong parameter"));
-	}
-	
-	f = new (sq_malloc(sizeof(SQFile)))SQFile(newf,owns);
-	if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
-		f->~SQFile();
-		sq_free(f,sizeof(SQFile));
-		return sq_throwerror(v, _SC("cannot create blob with negative size"));
-	}
-	sq_setreleasehook(v,1,_file_releasehook);
-	return 0;
-}
-
-static SQInteger _file_close(HSQUIRRELVM v)
-{
-	SQFile *self = NULL;
-	if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG))
-		&& self != NULL)
-	{
-		self->Close();
-	}
-	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")),
-	_DECL_FILE_FUNC(close,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_ERROR;
-}
-
-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"));
-}
-
-
-
-#define IO_BUFFER_SIZE 2048
-struct IOBuffer {
-	unsigned char buffer[IO_BUFFER_SIZE];
-	SQInteger size;
-	SQInteger ptr;
-	SQFILE file;
-};
-
-SQInteger _read_byte(IOBuffer *iobuffer)
-{
-	if(iobuffer->ptr < iobuffer->size) {
-
-		SQInteger ret = iobuffer->buffer[iobuffer->ptr];
-		iobuffer->ptr++;
-		return ret;
-	}
-	else {
-		if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 )
-		{
-			SQInteger ret = iobuffer->buffer[0];
-			iobuffer->ptr = 1;
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
-SQInteger _read_two_bytes(IOBuffer *iobuffer)
-{
-	if(iobuffer->ptr < iobuffer->size) {
-		if(iobuffer->size < 2) return 0;
-		SQInteger ret = *((wchar_t*)&iobuffer->buffer[iobuffer->ptr]);
-		iobuffer->ptr += 2;
-		return ret;
-	}
-	else {
-		if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 )
-		{
-			if(iobuffer->size < 2) return 0;
-			SQInteger ret = *((wchar_t*)&iobuffer->buffer[0]);
-			iobuffer->ptr = 2;
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
-static SQInteger _io_file_lexfeed_PLAIN(SQUserPointer iobuf)
-{
-	IOBuffer *iobuffer = (IOBuffer *)iobuf;
-	return _read_byte(iobuffer);
-
-}
-
-#ifdef SQUNICODE
-static SQInteger _io_file_lexfeed_UTF8(SQUserPointer iobuf)
-{
-	IOBuffer *iobuffer = (IOBuffer *)iobuf;
-#define READ(iobuf) \
-	if((inchar = (unsigned char)_read_byte(iobuf)) == 0) \
-		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(iobuffer);
-	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(iobuffer);
-			tmp |= inchar & 0x3F;
-		}
-		c = tmp;
-	}
-	return c;
-}
-#endif
-
-static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer iobuf)
-{
-	SQInteger ret;
-	IOBuffer *iobuffer = (IOBuffer *)iobuf;
-	if( (ret = _read_two_bytes(iobuffer)) > 0 )
-		return ret;
-	return 0;
-}
-
-static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer iobuf)
-{
-	SQInteger c;
-	IOBuffer *iobuffer = (IOBuffer *)iobuf;
-	if( (c = _read_two_bytes(iobuffer)) > 0 ) {
-		c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00);
-		return c;
-	}
-	return 0;
-}
-
-SQInteger file_read(SQUserPointer file,SQUserPointer buf,SQInteger size)
-{
-	SQInteger ret;
-	if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;
-	return -1;
-}
-
-SQInteger file_write(SQUserPointer file,SQUserPointer p,SQInteger size)
-{
-	return sqstd_fwrite(p,1,size,(SQFILE)file);
-}
-
-SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror)
-{
-	SQFILE file = sqstd_fopen(filename,_SC("rb"));
-	
-	SQInteger ret;
-	unsigned short us;
-	unsigned char uc;
-	SQLEXREADFUNC func = _io_file_lexfeed_PLAIN;
-	if(file){
-		ret = sqstd_fread(&us,1,2,file);
-		if(ret != 2) {
-			//probably an empty file
-			us = 0;
-		}
-		if(us == SQ_BYTECODE_STREAM_TAG) { //BYTECODE
-			sqstd_fseek(file,0,SQ_SEEK_SET);
-			if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) {
-				sqstd_fclose(file);
-				return SQ_OK;
-			}
-		}
-		else { //SCRIPT
-			
-			switch(us)
-			{
-				//gotta swap the next 2 lines on BIG endian machines
-				case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian;
-				case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian;
-				case 0xBBEF: 
-					if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) { 
-						sqstd_fclose(file); 
-						return sq_throwerror(v,_SC("io error")); 
-					}
-					if(uc != 0xBF) { 
-						sqstd_fclose(file); 
-						return sq_throwerror(v,_SC("Unrecognozed ecoding")); 
-					}
-#ifdef SQUNICODE
-					func = _io_file_lexfeed_UTF8;
-#else
-					func = _io_file_lexfeed_PLAIN;
-#endif
-					break;//UTF-8 ;
-				default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii
-			}
-			IOBuffer buffer;
-			buffer.ptr = 0;
-			buffer.size = 0;
-			buffer.file = file;
-			if(SQ_SUCCEEDED(sq_compile(v,func,&buffer,filename,printerror))){
-				sqstd_fclose(file);
-				return SQ_OK;
-			}
-		}
-		sqstd_fclose(file);
-		return SQ_ERROR;
-	}
-	return sq_throwerror(v,_SC("cannot open the file"));
-}
-
-SQRESULT sqstd_dofile(HSQUIRRELVM v,const SQChar *filename,SQBool retval,SQBool printerror)
-{
-	if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror))) {
-		sq_push(v,-2);
-		if(SQ_SUCCEEDED(sq_call(v,1,retval,SQTrue))) {
-			sq_remove(v,retval?-2:-1); //removes the closure
-			return 1;
-		}
-		sq_pop(v,1); //removes the closure
-	}
-	return SQ_ERROR;
-}
-
-SQRESULT sqstd_writeclosuretofile(HSQUIRRELVM v,const SQChar *filename)
-{
-	SQFILE file = sqstd_fopen(filename,_SC("wb+"));
-	if(!file) return sq_throwerror(v,_SC("cannot open the file"));
-	if(SQ_SUCCEEDED(sq_writeclosure(v,file_write,file))) {
-		sqstd_fclose(file);
-		return SQ_OK;
-	}
-	sqstd_fclose(file);
-	return SQ_ERROR; //forward the error
-}
-
-SQInteger _g_io_loadfile(HSQUIRRELVM v)
-{
-	const SQChar *filename;
-	SQBool printerror = SQFalse;
-	sq_getstring(v,2,&filename);
-	if(sq_gettop(v) >= 3) {
-		sq_getbool(v,3,&printerror);
-	}
-	if(SQ_SUCCEEDED(sqstd_loadfile(v,filename,printerror)))
-		return 1;
-	return SQ_ERROR; //propagates the error
-}
-
-SQInteger _g_io_writeclosuretofile(HSQUIRRELVM v)
-{
-	const SQChar *filename;
-	sq_getstring(v,2,&filename);
-	if(SQ_SUCCEEDED(sqstd_writeclosuretofile(v,filename)))
-		return 1;
-	return SQ_ERROR; //propagates the error
-}
-
-SQInteger _g_io_dofile(HSQUIRRELVM v)
-{
-	const SQChar *filename;
-	SQBool printerror = SQFalse;
-	sq_getstring(v,2,&filename);
-	if(sq_gettop(v) >= 3) {
-		sq_getbool(v,3,&printerror);
-	}
-	sq_push(v,1); //repush the this
-	if(SQ_SUCCEEDED(sqstd_dofile(v,filename,SQTrue,printerror)))
-		return 1;
-	return SQ_ERROR; //propagates the error
-}
-
-#define _DECL_GLOBALIO_FUNC(name,nparams,typecheck) {_SC(#name),_g_io_##name,nparams,typecheck}
-static SQRegFunction iolib_funcs[]={
-	_DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")),
-	_DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")),
-	_DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")),
-	{0,0}
-};
-
-SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
-{
-	SQInteger top = sq_gettop(v);
-	//create delegate
-	declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);
-	sq_pushstring(v,_SC("stdout"),-1);
-	sqstd_createfile(v,stdout,SQFalse);
-	sq_newslot(v,-3,SQFalse);
-	sq_pushstring(v,_SC("stdin"),-1);
-	sqstd_createfile(v,stdin,SQFalse);
-	sq_newslot(v,-3,SQFalse);
-	sq_pushstring(v,_SC("stderr"),-1);
-	sqstd_createfile(v,stderr,SQFalse);
-	sq_newslot(v,-3,SQFalse);
-	sq_settop(v,top);
-	return SQ_OK;
-}
+/* see copyright notice in squirrel.h */
+#include <new>
+#include <stdio.h>
+#include <squirrel.h>
+#include <sqstdio.h>
+#include "sqstdstream.h"
+
+#define SQSTD_FILE_TYPE_TAG (SQSTD_STREAM_TYPE_TAG | 0x00000001)
+//basic API
+SQFILE sqstd_fopen(const SQChar *filename ,const SQChar *mode)
+{
+#ifndef SQUNICODE
+    return (SQFILE)fopen(filename,mode);
+#else
+    return (SQFILE)_wfopen(filename,mode);
+#endif
+}
+
+SQInteger sqstd_fread(void* buffer, SQInteger size, SQInteger count, SQFILE file)
+{
+    SQInteger ret = (SQInteger)fread(buffer,size,count,(FILE *)file);
+    return ret;
+}
+
+SQInteger sqstd_fwrite(const SQUserPointer buffer, SQInteger size, SQInteger count, SQFILE file)
+{
+    return (SQInteger)fwrite(buffer,size,count,(FILE *)file);
+}
+
+SQInteger sqstd_fseek(SQFILE file, SQInteger offset, SQInteger origin)
+{
+    SQInteger realorigin;
+    switch(origin) {
+        case SQ_SEEK_CUR: realorigin = SEEK_CUR; break;
+        case SQ_SEEK_END: realorigin = SEEK_END; break;
+        case SQ_SEEK_SET: realorigin = SEEK_SET; break;
+        default: return -1; //failed
+    }
+    return fseek((FILE *)file,(long)offset,(int)realorigin);
+}
+
+SQInteger sqstd_ftell(SQFILE file)
+{
+    return ftell((FILE *)file);
+}
+
+SQInteger sqstd_fflush(SQFILE file)
+{
+    return fflush((FILE *)file);
+}
+
+SQInteger sqstd_fclose(SQFILE file)
+{
+    return fclose((FILE *)file);
+}
+
+SQInteger sqstd_feof(SQFILE file)
+{
+    return feof((FILE *)file);
+}
+
+//File
+struct SQFile : public SQStream {
+    SQFile() { _handle = NULL; _owns = false;}
+    SQFile(SQFILE file, bool owns) { _handle = file; _owns = owns;}
+    virtual ~SQFile() { Close(); }
+    bool Open(const SQChar *filename ,const SQChar *mode) {
+        Close();
+        if( (_handle = sqstd_fopen(filename,mode)) ) {
+            _owns = true;
+            return true;
+        }
+        return false;
+    }
+    void Close() {
+        if(_handle && _owns) {
+            sqstd_fclose(_handle);
+            _handle = NULL;
+            _owns = false;
+        }
+    }
+    SQInteger Read(void *buffer,SQInteger size) {
+        return sqstd_fread(buffer,1,size,_handle);
+    }
+    SQInteger Write(void *buffer,SQInteger size) {
+        return sqstd_fwrite(buffer,1,size,_handle);
+    }
+    SQInteger Flush() {
+        return sqstd_fflush(_handle);
+    }
+    SQInteger Tell() {
+        return sqstd_ftell(_handle);
+    }
+    SQInteger Len() {
+        SQInteger prevpos=Tell();
+        Seek(0,SQ_SEEK_END);
+        SQInteger size=Tell();
+        Seek(prevpos,SQ_SEEK_SET);
+        return size;
+    }
+    SQInteger Seek(SQInteger offset, SQInteger origin)  {
+        return sqstd_fseek(_handle,offset,origin);
+    }
+    bool IsValid() { return _handle?true:false; }
+    bool EOS() { return Tell()==Len()?true:false;}
+    SQFILE GetHandle() {return _handle;}
+private:
+    SQFILE _handle;
+    bool _owns;
+};
+
+static SQInteger _file__typeof(HSQUIRRELVM v)
+{
+    sq_pushstring(v,_SC("file"),-1);
+    return 1;
+}
+
+static SQInteger _file_releasehook(SQUserPointer p, SQInteger size)
+{
+    SQFile *self = (SQFile*)p;
+    self->~SQFile();
+    sq_free(self,sizeof(SQFile));
+    return 1;
+}
+
+static SQInteger _file_constructor(HSQUIRRELVM v)
+{
+    const SQChar *filename,*mode;
+    bool owns = true;
+    SQFile *f;
+    SQFILE newf;
+    if(sq_gettype(v,2) == OT_STRING && sq_gettype(v,3) == OT_STRING) {
+        sq_getstring(v, 2, &filename);
+        sq_getstring(v, 3, &mode);
+        newf = sqstd_fopen(filename, mode);
+        if(!newf) return sq_throwerror(v, _SC("cannot open file"));
+    } else if(sq_gettype(v,2) == OT_USERPOINTER) {
+        owns = !(sq_gettype(v,3) == OT_NULL);
+        sq_getuserpointer(v,2,&newf);
+    } else {
+        return sq_throwerror(v,_SC("wrong parameter"));
+    }
+
+    f = new (sq_malloc(sizeof(SQFile)))SQFile(newf,owns);
+    if(SQ_FAILED(sq_setinstanceup(v,1,f))) {
+        f->~SQFile();
+        sq_free(f,sizeof(SQFile));
+        return sq_throwerror(v, _SC("cannot create blob with negative size"));
+    }
+    sq_setreleasehook(v,1,_file_releasehook);
+    return 0;
+}
+
+static SQInteger _file_close(HSQUIRRELVM v)
+{
+    SQFile *self = NULL;
+    if(SQ_SUCCEEDED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_FILE_TYPE_TAG))
+        && self != NULL)
+    {
+        self->Close();
+    }
+    return 0;
+}
+
+//bindings
+#define _DECL_FILE_FUNC(name,nparams,typecheck) {_SC(#name),_file_##name,nparams,typecheck}
+static const SQRegFunction _file_methods[] = {
+    _DECL_FILE_FUNC(constructor,3,_SC("x")),
+    _DECL_FILE_FUNC(_typeof,1,_SC("x")),
+    _DECL_FILE_FUNC(close,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_ERROR;
+}
+
+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"));
+}
+
+
+
+#define IO_BUFFER_SIZE 2048
+struct IOBuffer {
+    unsigned char buffer[IO_BUFFER_SIZE];
+    SQInteger size;
+    SQInteger ptr;
+    SQFILE file;
+};
+
+SQInteger _read_byte(IOBuffer *iobuffer)
+{
+    if(iobuffer->ptr < iobuffer->size) {
+
+        SQInteger ret = iobuffer->buffer[iobuffer->ptr];
+        iobuffer->ptr++;
+        return ret;
+    }
+    else {
+        if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 )
+        {
+            SQInteger ret = iobuffer->buffer[0];
+            iobuffer->ptr = 1;
+            return ret;
+        }
+    }
+
+    return 0;
+}
+
+SQInteger _read_two_bytes(IOBuffer *iobuffer)
+{
+    if(iobuffer->ptr < iobuffer->size) {
+        if(iobuffer->size < 2) return 0;
+        SQInteger ret = *((const wchar_t*)&iobuffer->buffer[iobuffer->ptr]);
+        iobuffer->ptr += 2;
+        return ret;
+    }
+    else {
+        if( (iobuffer->size = sqstd_fread(iobuffer->buffer,1,IO_BUFFER_SIZE,iobuffer->file )) > 0 )
+        {
+            if(iobuffer->size < 2) return 0;
+            SQInteger ret = *((const wchar_t*)&iobuffer->buffer[0]);
+            iobuffer->ptr = 2;
+            return ret;
+        }
+    }
+
+    return 0;
+}
+
+static SQInteger _io_file_lexfeed_PLAIN(SQUserPointer iobuf)
+{
+    IOBuffer *iobuffer = (IOBuffer *)iobuf;
+    return _read_byte(iobuffer);
+
+}
+
+#ifdef SQUNICODE
+static SQInteger _io_file_lexfeed_UTF8(SQUserPointer iobuf)
+{
+    IOBuffer *iobuffer = (IOBuffer *)iobuf;
+#define READ(iobuf) \
+    if((inchar = (unsigned char)_read_byte(iobuf)) == 0) \
+        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 const unsigned char byte_masks[5] = {0,0,0x1f,0x0f,0x07};
+    unsigned char inchar;
+    SQInteger c = 0;
+    READ(iobuffer);
+    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(iobuffer);
+            tmp |= inchar & 0x3F;
+        }
+        c = tmp;
+    }
+    return c;
+}
+#endif
+
+static SQInteger _io_file_lexfeed_UCS2_LE(SQUserPointer iobuf)
+{
+    SQInteger ret;
+    IOBuffer *iobuffer = (IOBuffer *)iobuf;
+    if( (ret = _read_two_bytes(iobuffer)) > 0 )
+        return ret;
+    return 0;
+}
+
+static SQInteger _io_file_lexfeed_UCS2_BE(SQUserPointer iobuf)
+{
+    SQInteger c;
+    IOBuffer *iobuffer = (IOBuffer *)iobuf;
+    if( (c = _read_two_bytes(iobuffer)) > 0 ) {
+        c = ((c>>8)&0x00FF)| ((c<<8)&0xFF00);
+        return c;
+    }
+    return 0;
+}
+
+SQInteger file_read(SQUserPointer file,SQUserPointer buf,SQInteger size)
+{
+    SQInteger ret;
+    if( ( ret = sqstd_fread(buf,1,size,(SQFILE)file ))!=0 )return ret;
+    return -1;
+}
+
+SQInteger file_write(SQUserPointer file,SQUserPointer p,SQInteger size)
+{
+    return sqstd_fwrite(p,1,size,(SQFILE)file);
+}
+
+SQRESULT sqstd_loadfile(HSQUIRRELVM v,const SQChar *filename,SQBool printerror)
+{
+    SQFILE file = sqstd_fopen(filename,_SC("rb"));
+
+    SQInteger ret;
+    unsigned short us;
+    unsigned char uc;
+    SQLEXREADFUNC func = _io_file_lexfeed_PLAIN;
+    if(file){
+        ret = sqstd_fread(&us,1,2,file);
+        if(ret != 2) {
+            //probably an empty file
+            us = 0;
+        }
+        if(us == SQ_BYTECODE_STREAM_TAG) { //BYTECODE
+            sqstd_fseek(file,0,SQ_SEEK_SET);
+            if(SQ_SUCCEEDED(sq_readclosure(v,file_read,file))) {
+                sqstd_fclose(file);
+                return SQ_OK;
+            }
+        }
+        else { //SCRIPT
+
+            switch(us)
+            {
+                //gotta swap the next 2 lines on BIG endian machines
+                case 0xFFFE: func = _io_file_lexfeed_UCS2_BE; break;//UTF-16 little endian;
+                case 0xFEFF: func = _io_file_lexfeed_UCS2_LE; break;//UTF-16 big endian;
+                case 0xBBEF:
+                    if(sqstd_fread(&uc,1,sizeof(uc),file) == 0) {
+                        sqstd_fclose(file);
+                        return sq_throwerror(v,_SC("io error"));
+                    }
+                    if(uc != 0xBF) {
+                        sqstd_fclose(file);
+                        return sq_throwerror(v,_SC("Unrecognozed ecoding"));
+                    }
+#ifdef SQUNICODE
+                    func = _io_file_lexfeed_UTF8;
+#else
+                    func = _io_file_lexfeed_PLAIN;
+#endif
+                    break;//UTF-8 ;
+                default: sqstd_fseek(file,0,SQ_SEEK_SET); break; // ascii
+            }
+            IOBuffer buffer;
+            buffer.ptr = 0;
+            buffer.size = 0;
+            buffer.file = file;
+            if(SQ_SUCCEEDED(sq_compile(v,func,&buffer,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 const SQRegFunction iolib_funcs[]={
+    _DECL_GLOBALIO_FUNC(loadfile,-2,_SC(".sb")),
+    _DECL_GLOBALIO_FUNC(dofile,-2,_SC(".sb")),
+    _DECL_GLOBALIO_FUNC(writeclosuretofile,3,_SC(".sc")),
+    {0,0}
+};
+
+SQRESULT sqstd_register_iolib(HSQUIRRELVM v)
+{
+    SQInteger top = sq_gettop(v);
+    //create delegate
+    declare_stream(v,_SC("file"),(SQUserPointer)SQSTD_FILE_TYPE_TAG,_SC("std_file"),_file_methods,iolib_funcs);
+    sq_pushstring(v,_SC("stdout"),-1);
+    sqstd_createfile(v,stdout,SQFalse);
+    sq_newslot(v,-3,SQFalse);
+    sq_pushstring(v,_SC("stdin"),-1);
+    sqstd_createfile(v,stdin,SQFalse);
+    sq_newslot(v,-3,SQFalse);
+    sq_pushstring(v,_SC("stderr"),-1);
+    sqstd_createfile(v,stderr,SQFalse);
+    sq_newslot(v,-3,SQFalse);
+    sq_settop(v,top);
+    return SQ_OK;
+}

+ 107 - 107
sqstdlib/sqstdmath.cpp

@@ -1,107 +1,107 @@
-/* see copyright notice in squirrel.h */
-#include <squirrel.h>
-#include <math.h>
-#include <stdlib.h>
-#include <sqstdmath.h>
-
-#define SINGLE_ARG_FUNC(_funcname) static SQInteger math_##_funcname(HSQUIRRELVM v){ \
-	SQFloat f; \
-	sq_getfloat(v,2,&f); \
-	sq_pushfloat(v,(SQFloat)_funcname(f)); \
-	return 1; \
-}
-
-#define TWO_ARGS_FUNC(_funcname) static SQInteger math_##_funcname(HSQUIRRELVM v){ \
-	SQFloat p1,p2; \
-	sq_getfloat(v,2,&p1); \
-	sq_getfloat(v,3,&p2); \
-	sq_pushfloat(v,(SQFloat)_funcname(p1,p2)); \
-	return 1; \
-}
-
-static SQInteger math_srand(HSQUIRRELVM v)
-{
-	SQInteger i;
-	if(SQ_FAILED(sq_getinteger(v,2,&i)))
-		return sq_throwerror(v,_SC("invalid param"));
-	srand((unsigned int)i);
-	return 0;
-}
-
-static SQInteger math_rand(HSQUIRRELVM v)
-{
-	sq_pushinteger(v,rand());
-	return 1;
-}
-
-static SQInteger math_abs(HSQUIRRELVM v)
-{
-	SQInteger n;
-	sq_getinteger(v,2,&n);
-	sq_pushinteger(v,(SQInteger)abs((int)n)); 
-	return 1; 
-}
-
-SINGLE_ARG_FUNC(sqrt)
-SINGLE_ARG_FUNC(fabs)
-SINGLE_ARG_FUNC(sin)
-SINGLE_ARG_FUNC(cos)
-SINGLE_ARG_FUNC(asin)
-SINGLE_ARG_FUNC(acos)
-SINGLE_ARG_FUNC(log)
-SINGLE_ARG_FUNC(log10)
-SINGLE_ARG_FUNC(tan)
-SINGLE_ARG_FUNC(atan)
-TWO_ARGS_FUNC(atan2)
-TWO_ARGS_FUNC(pow)
-SINGLE_ARG_FUNC(floor)
-SINGLE_ARG_FUNC(ceil)
-SINGLE_ARG_FUNC(exp)
-
-#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),math_##name,nparams,tycheck}
-static SQRegFunction mathlib_funcs[] = {
-	_DECL_FUNC(sqrt,2,_SC(".n")),
-	_DECL_FUNC(sin,2,_SC(".n")),
-	_DECL_FUNC(cos,2,_SC(".n")),
-	_DECL_FUNC(asin,2,_SC(".n")),
-	_DECL_FUNC(acos,2,_SC(".n")),
-	_DECL_FUNC(log,2,_SC(".n")),
-	_DECL_FUNC(log10,2,_SC(".n")),
-	_DECL_FUNC(tan,2,_SC(".n")),
-	_DECL_FUNC(atan,2,_SC(".n")),
-	_DECL_FUNC(atan2,3,_SC(".nn")),
-	_DECL_FUNC(pow,3,_SC(".nn")),
-	_DECL_FUNC(floor,2,_SC(".n")),
-	_DECL_FUNC(ceil,2,_SC(".n")),
-	_DECL_FUNC(exp,2,_SC(".n")),
-	_DECL_FUNC(srand,2,_SC(".n")),
-	_DECL_FUNC(rand,1,NULL),
-	_DECL_FUNC(fabs,2,_SC(".n")),
-	_DECL_FUNC(abs,2,_SC(".n")),
-	{0,0},
-};
-#undef _DECL_FUNC
-
-#ifndef M_PI
-#define M_PI (3.14159265358979323846)
-#endif
-
-SQRESULT sqstd_register_mathlib(HSQUIRRELVM v)
-{
-	SQInteger i=0;
-	while(mathlib_funcs[i].name!=0)	{
-		sq_pushstring(v,mathlib_funcs[i].name,-1);
-		sq_newclosure(v,mathlib_funcs[i].f,0);
-		sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask);
-		sq_setnativeclosurename(v,-1,mathlib_funcs[i].name);
-		sq_newslot(v,-3,SQFalse);
-		i++;
-	}
-	sq_pushstring(v,_SC("RAND_MAX"),-1);
-	sq_pushinteger(v,RAND_MAX);
-	sq_newslot(v,-3,SQFalse);
-	sq_pushstring(v,_SC("PI"),-1);
-	sq_pushfloat(v,(SQFloat)M_PI);
-	sq_newslot(v,-3,SQFalse);
-	return SQ_OK;
-}
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <math.h>
+#include <stdlib.h>
+#include <sqstdmath.h>
+
+#define SINGLE_ARG_FUNC(_funcname) static SQInteger math_##_funcname(HSQUIRRELVM v){ \
+    SQFloat f; \
+    sq_getfloat(v,2,&f); \
+    sq_pushfloat(v,(SQFloat)_funcname(f)); \
+    return 1; \
+}
+
+#define TWO_ARGS_FUNC(_funcname) static SQInteger math_##_funcname(HSQUIRRELVM v){ \
+    SQFloat p1,p2; \
+    sq_getfloat(v,2,&p1); \
+    sq_getfloat(v,3,&p2); \
+    sq_pushfloat(v,(SQFloat)_funcname(p1,p2)); \
+    return 1; \
+}
+
+static SQInteger math_srand(HSQUIRRELVM v)
+{
+    SQInteger i;
+    if(SQ_FAILED(sq_getinteger(v,2,&i)))
+        return sq_throwerror(v,_SC("invalid param"));
+    srand((unsigned int)i);
+    return 0;
+}
+
+static SQInteger math_rand(HSQUIRRELVM v)
+{
+    sq_pushinteger(v,rand());
+    return 1;
+}
+
+static SQInteger math_abs(HSQUIRRELVM v)
+{
+    SQInteger n;
+    sq_getinteger(v,2,&n);
+    sq_pushinteger(v,(SQInteger)abs((int)n));
+    return 1;
+}
+
+SINGLE_ARG_FUNC(sqrt)
+SINGLE_ARG_FUNC(fabs)
+SINGLE_ARG_FUNC(sin)
+SINGLE_ARG_FUNC(cos)
+SINGLE_ARG_FUNC(asin)
+SINGLE_ARG_FUNC(acos)
+SINGLE_ARG_FUNC(log)
+SINGLE_ARG_FUNC(log10)
+SINGLE_ARG_FUNC(tan)
+SINGLE_ARG_FUNC(atan)
+TWO_ARGS_FUNC(atan2)
+TWO_ARGS_FUNC(pow)
+SINGLE_ARG_FUNC(floor)
+SINGLE_ARG_FUNC(ceil)
+SINGLE_ARG_FUNC(exp)
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name),math_##name,nparams,tycheck}
+static const SQRegFunction mathlib_funcs[] = {
+    _DECL_FUNC(sqrt,2,_SC(".n")),
+    _DECL_FUNC(sin,2,_SC(".n")),
+    _DECL_FUNC(cos,2,_SC(".n")),
+    _DECL_FUNC(asin,2,_SC(".n")),
+    _DECL_FUNC(acos,2,_SC(".n")),
+    _DECL_FUNC(log,2,_SC(".n")),
+    _DECL_FUNC(log10,2,_SC(".n")),
+    _DECL_FUNC(tan,2,_SC(".n")),
+    _DECL_FUNC(atan,2,_SC(".n")),
+    _DECL_FUNC(atan2,3,_SC(".nn")),
+    _DECL_FUNC(pow,3,_SC(".nn")),
+    _DECL_FUNC(floor,2,_SC(".n")),
+    _DECL_FUNC(ceil,2,_SC(".n")),
+    _DECL_FUNC(exp,2,_SC(".n")),
+    _DECL_FUNC(srand,2,_SC(".n")),
+    _DECL_FUNC(rand,1,NULL),
+    _DECL_FUNC(fabs,2,_SC(".n")),
+    _DECL_FUNC(abs,2,_SC(".n")),
+    {0,0},
+};
+#undef _DECL_FUNC
+
+#ifndef M_PI
+#define M_PI (3.14159265358979323846)
+#endif
+
+SQRESULT sqstd_register_mathlib(HSQUIRRELVM v)
+{
+    SQInteger i=0;
+    while(mathlib_funcs[i].name!=0) {
+        sq_pushstring(v,mathlib_funcs[i].name,-1);
+        sq_newclosure(v,mathlib_funcs[i].f,0);
+        sq_setparamscheck(v,mathlib_funcs[i].nparamscheck,mathlib_funcs[i].typemask);
+        sq_setnativeclosurename(v,-1,mathlib_funcs[i].name);
+        sq_newslot(v,-3,SQFalse);
+        i++;
+    }
+    sq_pushstring(v,_SC("RAND_MAX"),-1);
+    sq_pushinteger(v,RAND_MAX);
+    sq_newslot(v,-3,SQFalse);
+    sq_pushstring(v,_SC("PI"),-1);
+    sq_pushfloat(v,(SQFloat)M_PI);
+    sq_newslot(v,-3,SQFalse);
+    return SQ_OK;
+}

+ 663 - 663
sqstdlib/sqstdrex.cpp

@@ -1,663 +1,663 @@
-/* see copyright notice in squirrel.h */
-#include <squirrel.h>
-#include <string.h>
-#include <ctype.h>
-#include <setjmp.h>
-#include <sqstdstring.h>
-
-#ifdef _DEBUG
-#include <stdio.h>
-
-static const SQChar *g_nnames[] =
-{
-	_SC("NONE"),_SC("OP_GREEDY"),	_SC("OP_OR"),
-	_SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"),	_SC("OP_CLASS"),
-	_SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),
-	_SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB"),_SC("OP_MB")
-};
-
-#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 OP_MB           (MAX_CHAR+14) //match balanced
-
-#define SQREX_SYMBOL_ANY_CHAR ('.')
-#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
-#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*')
-#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?')
-#define SQREX_SYMBOL_BRANCH ('|')
-#define SQREX_SYMBOL_END_OF_STRING ('$')
-#define SQREX_SYMBOL_BEGINNING_OF_STRING ('^')
-#define SQREX_SYMBOL_ESCAPE_CHAR ('\\')
-
-
-typedef int SQRexNodeType;
-
-typedef struct tagSQRexNode{
-	SQRexNodeType type;
-	SQInteger left;
-	SQInteger right;
-	SQInteger next;
-}SQRexNode;
-
-struct SQRex{
-	const SQChar *_eol;
-	const SQChar *_bol;
-	const SQChar *_p;
-	SQInteger _first;
-	SQInteger _op;
-	SQRexNode *_nodes;
-	SQInteger _nallocated;
-	SQInteger _nsize;
-	SQInteger _nsubexpr;
-	SQRexMatch *_matches;
-	SQInteger _currsubexp;
-	void *_jmpbuf;
-	const SQChar **_error;
-};
-
-static SQInteger sqstd_rex_list(SQRex *exp);
-
-static SQInteger sqstd_rex_newnode(SQRex *exp, SQRexNodeType type)
-{
-	SQRexNode n;
-	n.type = type;
-	n.next = n.right = n.left = -1;
-	if(type == OP_EXPR)
-		n.right = exp->_nsubexpr++;
-	if(exp->_nallocated < (exp->_nsize + 1)) {
-		SQInteger oldsize = exp->_nallocated;
-		exp->_nallocated *= 2;
-		exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode));
-	}
-	exp->_nodes[exp->_nsize++] = n;
-	SQInteger newid = exp->_nsize - 1;
-	return (SQInteger)newid;
-}
-
-static void sqstd_rex_error(SQRex *exp,const SQChar *error)
-{
-	if(exp->_error) *exp->_error = error;
-	longjmp(*((jmp_buf*)exp->_jmpbuf),-1);
-}
-
-static void sqstd_rex_expect(SQRex *exp, SQInteger n){
-	if((*exp->_p) != n) 
-		sqstd_rex_error(exp, _SC("expected paren"));
-	exp->_p++;
-}
-
-static SQChar sqstd_rex_escapechar(SQRex *exp)
-{
-	if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){
-		exp->_p++;
-		switch(*exp->_p) {
-		case 'v': exp->_p++; return '\v';
-		case 'n': exp->_p++; return '\n';
-		case 't': exp->_p++; return '\t';
-		case 'r': exp->_p++; return '\r';
-		case 'f': exp->_p++; return '\f';
-		default: return (*exp->_p++);
-		}
-	} else if(!scisprint(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected"));
-	return (*exp->_p++);
-}
-
-static SQInteger sqstd_rex_charclass(SQRex *exp,SQInteger classid)
-{
-	SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS);
-	exp->_nodes[n].left = classid;
-	return n;
-}
-
-static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass)
-{
-	SQChar t;
-	if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) {
-		exp->_p++;
-		switch(*exp->_p) {
-			case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n');
-			case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t');
-			case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r');
-			case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f');
-			case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v');
-			case 'a': case 'A': case 'w': case 'W': case 's': case 'S': 
-			case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': 
-			case 'p': case 'P': case 'l': case 'u': 
-				{
-				t = *exp->_p; exp->_p++; 
-				return sqstd_rex_charclass(exp,t);
-				}
-            case 'm':
-                {
-                     SQChar cb, ce; //cb = character begin match ce = character end match
-                     cb = *++exp->_p; //skip 'm'
-                     ce = *++exp->_p;
-                     exp->_p++; //points to the next char to be parsed
-                     if ((!cb) || (!ce)) sqstd_rex_error(exp,_SC("balanced chars expected"));
-                     if ( cb == ce ) sqstd_rex_error(exp,_SC("open/close char can't be the same"));
-                     SQInteger node =  sqstd_rex_newnode(exp,OP_MB);
-                     exp->_nodes[node].left = cb;
-                     exp->_nodes[node].right = ce;
-                     return node;
-                }
-			case 'b':
-			case 'B':
-				if(!isclass) {
-					SQInteger node = sqstd_rex_newnode(exp,OP_WB);
-					exp->_nodes[node].left = *exp->_p;
-					exp->_p++; 
-					return node;
-				} //else default
-			default: 
-				t = *exp->_p; exp->_p++; 
-				return sqstd_rex_newnode(exp,t);
-		}
-	}
-	else if(!scisprint(*exp->_p)) {
-		
-		sqstd_rex_error(exp,_SC("letter expected"));
-	}
-	t = *exp->_p; exp->_p++; 
-	return sqstd_rex_newnode(exp,t);
-}
-static SQInteger sqstd_rex_class(SQRex *exp)
-{
-	SQInteger ret = -1;
-	SQInteger first = -1,chain;
-	if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){
-		ret = sqstd_rex_newnode(exp,OP_NCLASS);
-		exp->_p++;
-	}else ret = sqstd_rex_newnode(exp,OP_CLASS);
-	
-	if(*exp->_p == ']') sqstd_rex_error(exp,_SC("empty class"));
-	chain = ret;
-	while(*exp->_p != ']' && exp->_p != exp->_eol) {
-		if(*exp->_p == '-' && first != -1){ 
-			SQInteger r;
-			if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range"));
-			r = sqstd_rex_newnode(exp,OP_RANGE);
-			if(exp->_nodes[first].type>*exp->_p) sqstd_rex_error(exp,_SC("invalid range"));
-			if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges"));
-			exp->_nodes[r].left = exp->_nodes[first].type;
-			SQInteger t = sqstd_rex_escapechar(exp);
-			exp->_nodes[r].right = t;
-            exp->_nodes[chain].next = r;
-			chain = r;
-			first = -1;
-		}
-		else{
-			if(first!=-1){
-				SQInteger c = first;
-				exp->_nodes[chain].next = c;
-				chain = c;
-				first = sqstd_rex_charnode(exp,SQTrue);
-			}
-			else{
-				first = sqstd_rex_charnode(exp,SQTrue);
-			}
-		}
-	}
-	if(first!=-1){
-		SQInteger c = first;
-		exp->_nodes[chain].next = c;
-	}
-	/* hack? */
-	exp->_nodes[ret].left = exp->_nodes[ret].next;
-	exp->_nodes[ret].next = -1;
-	return ret;
-}
-
-static SQInteger sqstd_rex_parsenumber(SQRex *exp)
-{
-	SQInteger ret = *exp->_p-'0';
-	SQInteger positions = 10;
-	exp->_p++;
-	while(isdigit(*exp->_p)) {
-		ret = ret*10+(*exp->_p++-'0');
-		if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant"));
-		positions *= 10;
-	};
-	return ret;
-}
-
-static SQInteger sqstd_rex_element(SQRex *exp)
-{
-	SQInteger ret = -1;
-	switch(*exp->_p)
-	{
-	case '(': {
-		SQInteger expr;
-		exp->_p++;
-
-
-		if(*exp->_p =='?') {
-			exp->_p++;
-			sqstd_rex_expect(exp,':');
-			expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR);
-		}
-		else
-			expr = sqstd_rex_newnode(exp,OP_EXPR);
-		SQInteger newn = sqstd_rex_list(exp);
-		exp->_nodes[expr].left = newn;
-		ret = expr;
-		sqstd_rex_expect(exp,')');
-			  }
-			  break;
-	case '[':
-		exp->_p++;
-		ret = sqstd_rex_class(exp);
-		sqstd_rex_expect(exp,']');
-		break;
-	case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break;
-	case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break;
-	default:
-		ret = sqstd_rex_charnode(exp,SQFalse);
-		break;
-	}
-
-
-	SQBool isgreedy = SQFalse;
-	unsigned short p0 = 0, p1 = 0;
-	switch(*exp->_p){
-		case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
-		case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
-		case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = SQTrue; break;
-		case '{':
-			exp->_p++;
-			if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected"));
-			p0 = (unsigned short)sqstd_rex_parsenumber(exp);
-			/*******************************/
-			switch(*exp->_p) {
-		case '}':
-			p1 = p0; exp->_p++;
-			break;
-		case ',':
-			exp->_p++;
-			p1 = 0xFFFF;
-			if(isdigit(*exp->_p)){
-				p1 = (unsigned short)sqstd_rex_parsenumber(exp);
-			}
-			sqstd_rex_expect(exp,'}');
-			break;
-		default:
-			sqstd_rex_error(exp,_SC(", or } expected"));
-			}
-			/*******************************/
-			isgreedy = SQTrue; 
-			break;
-
-	}
-	if(isgreedy) {
-		SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY);
-		exp->_nodes[nnode].left = ret;
-		exp->_nodes[nnode].right = ((p0)<<16)|p1;
-		ret = nnode;
-	}
-
-	if((*exp->_p != SQREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) {
-		SQInteger nnode = sqstd_rex_element(exp);
-		exp->_nodes[ret].next = nnode;
-	}
-
-	return ret;
-}
-
-static SQInteger sqstd_rex_list(SQRex *exp)
-{
-	SQInteger ret=-1,e;
-	if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) {
-		exp->_p++;
-		ret = sqstd_rex_newnode(exp,OP_BOL);
-	}
-	e = sqstd_rex_element(exp);
-	if(ret != -1) {
-		exp->_nodes[ret].next = e;
-	}
-	else ret = e;
-
-	if(*exp->_p == SQREX_SYMBOL_BRANCH) {
-		SQInteger temp,tright;
-		exp->_p++;
-		temp = sqstd_rex_newnode(exp,OP_OR);
-		exp->_nodes[temp].left = ret;
-		tright = sqstd_rex_list(exp);
-		exp->_nodes[temp].right = tright;
-		ret = temp;
-	}
-	return ret;
-}
-
-static SQBool sqstd_rex_matchcclass(SQInteger cclass,SQChar c)
-{
-	switch(cclass) {
-	case 'a': return isalpha(c)?SQTrue:SQFalse;
-	case 'A': return !isalpha(c)?SQTrue:SQFalse;
-	case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse;
-	case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse;
-	case 's': return isspace(c)?SQTrue:SQFalse;
-	case 'S': return !isspace(c)?SQTrue:SQFalse;
-	case 'd': return isdigit(c)?SQTrue:SQFalse;
-	case 'D': return !isdigit(c)?SQTrue:SQFalse;
-	case 'x': return isxdigit(c)?SQTrue:SQFalse;
-	case 'X': return !isxdigit(c)?SQTrue:SQFalse;
-	case 'c': return iscntrl(c)?SQTrue:SQFalse;
-	case 'C': return !iscntrl(c)?SQTrue:SQFalse;
-	case 'p': return ispunct(c)?SQTrue:SQFalse;
-	case 'P': return !ispunct(c)?SQTrue:SQFalse;
-	case 'l': return islower(c)?SQTrue:SQFalse;
-	case 'u': return isupper(c)?SQTrue:SQFalse;
-	}
-	return SQFalse; /*cannot happen*/
-}
-
-static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c)
-{
-	do {
-		switch(node->type) {
-			case OP_RANGE:
-				if(c >= node->left && c <= node->right) return SQTrue;
-				break;
-			case OP_CCLASS:
-				if(sqstd_rex_matchcclass(node->left,c)) return SQTrue;
-				break;
-			default:
-				if(c == node->type)return SQTrue;
-		}
-	} while((node->next != -1) && (node = &exp->_nodes[node->next]));
-	return SQFalse;
-}
-
-static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str,SQRexNode *next)
-{
-	
-	SQRexNodeType type = node->type;
-	switch(type) {
-	case OP_GREEDY: {
-		//SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL;
-		SQRexNode *greedystop = NULL;
-		SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
-		const SQChar *s=str, *good = str;
-
-		if(node->next != -1) {
-			greedystop = &exp->_nodes[node->next];
-		}
-		else {
-			greedystop = next;
-		}
-
-		while((nmaches == 0xFFFF || nmaches < p1)) {
-
-			const SQChar *stop;
-			if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop)))
-				break;
-			nmaches++;
-			good=s;
-			if(greedystop) {
-				//checks that 0 matches satisfy the expression(if so skips)
-				//if not would always stop(for instance if is a '?')
-				if(greedystop->type != OP_GREEDY ||
-				(greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0))
-				{
-					SQRexNode *gnext = NULL;
-					if(greedystop->next != -1) {
-						gnext = &exp->_nodes[greedystop->next];
-					}else if(next && next->next != -1){
-						gnext = &exp->_nodes[next->next];
-					}
-					stop = sqstd_rex_matchnode(exp,greedystop,s,gnext);
-					if(stop) {
-						//if satisfied stop it
-						if(p0 == p1 && p0 == nmaches) break;
-						else if(nmaches >= p0 && p1 == 0xFFFF) break;
-						else if(nmaches >= p0 && nmaches <= p1) break;
-					}
-				}
-			}
-			
-			if(s >= exp->_eol)
-				break;
-		}
-		if(p0 == p1 && p0 == nmaches) return good;
-		else if(nmaches >= p0 && p1 == 0xFFFF) return good;
-		else if(nmaches >= p0 && nmaches <= p1) return good;
-		return NULL;
-	}
-	case OP_OR: {
-			const SQChar *asd = str;
-			SQRexNode *temp=&exp->_nodes[node->left];
-			while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) {
-				if(temp->next != -1)
-					temp = &exp->_nodes[temp->next];
-				else
-					return asd;
-			}
-			asd = str;
-			temp = &exp->_nodes[node->right];
-			while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) {
-				if(temp->next != -1)
-					temp = &exp->_nodes[temp->next];
-				else
-					return asd;
-			}
-			return NULL;
-			break;
-	}
-	case OP_EXPR:
-	case OP_NOCAPEXPR:{
-			SQRexNode *n = &exp->_nodes[node->left];
-			const SQChar *cur = str;
-			SQInteger capture = -1;
-			if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
-				capture = exp->_currsubexp;
-				exp->_matches[capture].begin = cur;
-				exp->_currsubexp++;
-			}
-			SQInteger tempcap = exp->_currsubexp;
-			do {
-				SQRexNode *subnext = NULL;
-				if(n->next != -1) {
-					subnext = &exp->_nodes[n->next];
-				}else {
-					subnext = next;
-				}
-				if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) {
-					if(capture != -1){
-						exp->_matches[capture].begin = 0;
-						exp->_matches[capture].len = 0;
-					}
-					return NULL;
-				}
-			} while((n->next != -1) && (n = &exp->_nodes[n->next]));
-
-			exp->_currsubexp = tempcap;
-			if(capture != -1) 
-				exp->_matches[capture].len = cur - exp->_matches[capture].begin;
-			return cur;
-	}				 
-	case OP_WB:
-		if((str == exp->_bol && !isspace(*str))
-		 || (str == exp->_eol && !isspace(*(str-1)))
-		 || (!isspace(*str) && isspace(*(str+1)))
-		 || (isspace(*str) && !isspace(*(str+1))) ) {
-			return (node->left == 'b')?str:NULL;
-		}
-		return (node->left == 'b')?NULL:str;
-	case OP_BOL:
-		if(str == exp->_bol) return str;
-		return NULL;
-	case OP_EOL:
-		if(str == exp->_eol) return str;
-		return NULL;
-	case OP_DOT:{
-		if (str == exp->_eol) return NULL;
-		str++;
-				}
-		return str;
-	case OP_NCLASS:
-	case OP_CLASS:
-		if (str == exp->_eol) return NULL;
-		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 (str == exp->_eol) return NULL;
-		if(sqstd_rex_matchcclass(node->left,*str)) {
-			str++;
-			return str;
-		}
-		return NULL;
-    case OP_MB:
-        {
-            int cb = node->left; //char that opens a balanced expression
-            if(*str != cb) return NULL; // string doesnt start with open char
-            int ce = node->right; //char that closes a balanced expression
-            int cont = 1;
-            const SQChar *streol = exp->_eol;
-            while (++str < streol) {
-              if (*str == ce) {
-                if (--cont == 0) {
-                    return ++str;
-                }
-              }
-              else if (*str == cb) cont++;
-            }
-        }
-        return NULL; // string ends out of balance
-	default: /* char */
-		if (str == exp->_eol) return NULL;
-		if(*str != node->type) return NULL;
-		str++;
-		return str;
-	}
-	return NULL;
-}
-
-/* public api */
-SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error)
-{
-	SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex));
-	exp->_eol = exp->_bol = NULL;
-	exp->_p = pattern;
-	exp->_nallocated = (SQInteger)scstrlen(pattern) * sizeof(SQChar);
-	exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode));
-	exp->_nsize = 0;
-	exp->_matches = 0;
-	exp->_nsubexpr = 0;
-	exp->_first = sqstd_rex_newnode(exp,OP_EXPR);
-	exp->_error = error;
-	exp->_jmpbuf = sq_malloc(sizeof(jmp_buf));
-	if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {
-		SQInteger res = sqstd_rex_list(exp);
-		exp->_nodes[exp->_first].left = res;
-		if(*exp->_p!='\0')
-			sqstd_rex_error(exp,_SC("unexpected character"));
-#ifdef _DEBUG
-		{
-			SQInteger nsize,i;
-			SQRexNode *t;
-			nsize = exp->_nsize;
-			t = &exp->_nodes[0];
-			scprintf(_SC("\n"));
-			for(i = 0;i < nsize; i++) {
-				if(exp->_nodes[i].type>MAX_CHAR)
-					scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);
-				else
-					scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type);
-				scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next);
-			}
-			scprintf(_SC("\n"));
-		}
-#endif
-		exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch));
-		memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch));
-	}
-	else{
-		sqstd_rex_free(exp);
-		return NULL;
-	}
-	return exp;
-}
-
-void sqstd_rex_free(SQRex *exp)
-{
-	if(exp)	{
-		if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode));
-		if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf));
-		if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch));
-		sq_free(exp,sizeof(SQRex));
-	}
-}
-
-SQBool sqstd_rex_match(SQRex* exp,const SQChar* text)
-{
-	const SQChar* res = NULL;
-	exp->_bol = text;
-	exp->_eol = text + scstrlen(text);
-	exp->_currsubexp = 0;
-	res = sqstd_rex_matchnode(exp,exp->_nodes,text,NULL);
-	if(res == NULL || res != exp->_eol)
-		return SQFalse;
-	return SQTrue;
-}
-
-SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end)
-{
-	const SQChar *cur = NULL;
-	SQInteger node = exp->_first;
-	if(text_begin >= text_end) return SQFalse;
-	exp->_bol = text_begin;
-	exp->_eol = text_end;
-	do {
-		cur = text_begin;
-		while(node != -1) {
-			exp->_currsubexp = 0;
-			cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,NULL);
-			if(!cur)
-				break;
-			node = exp->_nodes[node].next;
-		}
-		text_begin++;
-	} while(cur == NULL && text_begin != text_end);
-
-	if(cur == NULL)
-		return SQFalse;
-
-	--text_begin;
-
-	if(out_begin) *out_begin = text_begin;
-	if(out_end) *out_end = cur;
-	return SQTrue;
-}
-
-SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end)
-{
-	return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end);
-}
-
-SQInteger sqstd_rex_getsubexpcount(SQRex* exp)
-{
-	return exp->_nsubexpr;
-}
-
-SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp)
-{
-	if( n<0 || n >= exp->_nsubexpr) return SQFalse;
-	*subexp = exp->_matches[n];
-	return SQTrue;
-}
-
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <string.h>
+#include <ctype.h>
+#include <setjmp.h>
+#include <sqstdstring.h>
+
+#ifdef _DEBUG
+#include <stdio.h>
+
+static const SQChar *g_nnames[] =
+{
+    _SC("NONE"),_SC("OP_GREEDY"),   _SC("OP_OR"),
+    _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"),   _SC("OP_CLASS"),
+    _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"),
+    _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB"),_SC("OP_MB")
+};
+
+#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 OP_MB           (MAX_CHAR+14) //match balanced
+
+#define SQREX_SYMBOL_ANY_CHAR ('.')
+#define SQREX_SYMBOL_GREEDY_ONE_OR_MORE ('+')
+#define SQREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*')
+#define SQREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?')
+#define SQREX_SYMBOL_BRANCH ('|')
+#define SQREX_SYMBOL_END_OF_STRING ('$')
+#define SQREX_SYMBOL_BEGINNING_OF_STRING ('^')
+#define SQREX_SYMBOL_ESCAPE_CHAR ('\\')
+
+
+typedef int SQRexNodeType;
+
+typedef struct tagSQRexNode{
+    SQRexNodeType type;
+    SQInteger left;
+    SQInteger right;
+    SQInteger next;
+}SQRexNode;
+
+struct SQRex{
+    const SQChar *_eol;
+    const SQChar *_bol;
+    const SQChar *_p;
+    SQInteger _first;
+    SQInteger _op;
+    SQRexNode *_nodes;
+    SQInteger _nallocated;
+    SQInteger _nsize;
+    SQInteger _nsubexpr;
+    SQRexMatch *_matches;
+    SQInteger _currsubexp;
+    void *_jmpbuf;
+    const SQChar **_error;
+};
+
+static SQInteger sqstd_rex_list(SQRex *exp);
+
+static SQInteger sqstd_rex_newnode(SQRex *exp, SQRexNodeType type)
+{
+    SQRexNode n;
+    n.type = type;
+    n.next = n.right = n.left = -1;
+    if(type == OP_EXPR)
+        n.right = exp->_nsubexpr++;
+    if(exp->_nallocated < (exp->_nsize + 1)) {
+        SQInteger oldsize = exp->_nallocated;
+        exp->_nallocated *= 2;
+        exp->_nodes = (SQRexNode *)sq_realloc(exp->_nodes, oldsize * sizeof(SQRexNode) ,exp->_nallocated * sizeof(SQRexNode));
+    }
+    exp->_nodes[exp->_nsize++] = n;
+    SQInteger newid = exp->_nsize - 1;
+    return (SQInteger)newid;
+}
+
+static void sqstd_rex_error(SQRex *exp,const SQChar *error)
+{
+    if(exp->_error) *exp->_error = error;
+    longjmp(*((jmp_buf*)exp->_jmpbuf),-1);
+}
+
+static void sqstd_rex_expect(SQRex *exp, SQInteger n){
+    if((*exp->_p) != n)
+        sqstd_rex_error(exp, _SC("expected paren"));
+    exp->_p++;
+}
+
+static SQChar sqstd_rex_escapechar(SQRex *exp)
+{
+    if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR){
+        exp->_p++;
+        switch(*exp->_p) {
+        case 'v': exp->_p++; return '\v';
+        case 'n': exp->_p++; return '\n';
+        case 't': exp->_p++; return '\t';
+        case 'r': exp->_p++; return '\r';
+        case 'f': exp->_p++; return '\f';
+        default: return (*exp->_p++);
+        }
+    } else if(!scisprint(*exp->_p)) sqstd_rex_error(exp,_SC("letter expected"));
+    return (*exp->_p++);
+}
+
+static SQInteger sqstd_rex_charclass(SQRex *exp,SQInteger classid)
+{
+    SQInteger n = sqstd_rex_newnode(exp,OP_CCLASS);
+    exp->_nodes[n].left = classid;
+    return n;
+}
+
+static SQInteger sqstd_rex_charnode(SQRex *exp,SQBool isclass)
+{
+    SQChar t;
+    if(*exp->_p == SQREX_SYMBOL_ESCAPE_CHAR) {
+        exp->_p++;
+        switch(*exp->_p) {
+            case 'n': exp->_p++; return sqstd_rex_newnode(exp,'\n');
+            case 't': exp->_p++; return sqstd_rex_newnode(exp,'\t');
+            case 'r': exp->_p++; return sqstd_rex_newnode(exp,'\r');
+            case 'f': exp->_p++; return sqstd_rex_newnode(exp,'\f');
+            case 'v': exp->_p++; return sqstd_rex_newnode(exp,'\v');
+            case 'a': case 'A': case 'w': case 'W': case 's': case 'S':
+            case 'd': case 'D': case 'x': case 'X': case 'c': case 'C':
+            case 'p': case 'P': case 'l': case 'u':
+                {
+                t = *exp->_p; exp->_p++;
+                return sqstd_rex_charclass(exp,t);
+                }
+            case 'm':
+                {
+                     SQChar cb, ce; //cb = character begin match ce = character end match
+                     cb = *++exp->_p; //skip 'm'
+                     ce = *++exp->_p;
+                     exp->_p++; //points to the next char to be parsed
+                     if ((!cb) || (!ce)) sqstd_rex_error(exp,_SC("balanced chars expected"));
+                     if ( cb == ce ) sqstd_rex_error(exp,_SC("open/close char can't be the same"));
+                     SQInteger node =  sqstd_rex_newnode(exp,OP_MB);
+                     exp->_nodes[node].left = cb;
+                     exp->_nodes[node].right = ce;
+                     return node;
+                }
+            case 'b':
+            case 'B':
+                if(!isclass) {
+                    SQInteger node = sqstd_rex_newnode(exp,OP_WB);
+                    exp->_nodes[node].left = *exp->_p;
+                    exp->_p++;
+                    return node;
+                } //else default
+            default:
+                t = *exp->_p; exp->_p++;
+                return sqstd_rex_newnode(exp,t);
+        }
+    }
+    else if(!scisprint(*exp->_p)) {
+
+        sqstd_rex_error(exp,_SC("letter expected"));
+    }
+    t = *exp->_p; exp->_p++;
+    return sqstd_rex_newnode(exp,t);
+}
+static SQInteger sqstd_rex_class(SQRex *exp)
+{
+    SQInteger ret = -1;
+    SQInteger first = -1,chain;
+    if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING){
+        ret = sqstd_rex_newnode(exp,OP_NCLASS);
+        exp->_p++;
+    }else ret = sqstd_rex_newnode(exp,OP_CLASS);
+
+    if(*exp->_p == ']') sqstd_rex_error(exp,_SC("empty class"));
+    chain = ret;
+    while(*exp->_p != ']' && exp->_p != exp->_eol) {
+        if(*exp->_p == '-' && first != -1){
+            SQInteger r;
+            if(*exp->_p++ == ']') sqstd_rex_error(exp,_SC("unfinished range"));
+            r = sqstd_rex_newnode(exp,OP_RANGE);
+            if(exp->_nodes[first].type>*exp->_p) sqstd_rex_error(exp,_SC("invalid range"));
+            if(exp->_nodes[first].type == OP_CCLASS) sqstd_rex_error(exp,_SC("cannot use character classes in ranges"));
+            exp->_nodes[r].left = exp->_nodes[first].type;
+            SQInteger t = sqstd_rex_escapechar(exp);
+            exp->_nodes[r].right = t;
+            exp->_nodes[chain].next = r;
+            chain = r;
+            first = -1;
+        }
+        else{
+            if(first!=-1){
+                SQInteger c = first;
+                exp->_nodes[chain].next = c;
+                chain = c;
+                first = sqstd_rex_charnode(exp,SQTrue);
+            }
+            else{
+                first = sqstd_rex_charnode(exp,SQTrue);
+            }
+        }
+    }
+    if(first!=-1){
+        SQInteger c = first;
+        exp->_nodes[chain].next = c;
+    }
+    /* hack? */
+    exp->_nodes[ret].left = exp->_nodes[ret].next;
+    exp->_nodes[ret].next = -1;
+    return ret;
+}
+
+static SQInteger sqstd_rex_parsenumber(SQRex *exp)
+{
+    SQInteger ret = *exp->_p-'0';
+    SQInteger positions = 10;
+    exp->_p++;
+    while(isdigit(*exp->_p)) {
+        ret = ret*10+(*exp->_p++-'0');
+        if(positions==1000000000) sqstd_rex_error(exp,_SC("overflow in numeric constant"));
+        positions *= 10;
+    };
+    return ret;
+}
+
+static SQInteger sqstd_rex_element(SQRex *exp)
+{
+    SQInteger ret = -1;
+    switch(*exp->_p)
+    {
+    case '(': {
+        SQInteger expr;
+        exp->_p++;
+
+
+        if(*exp->_p =='?') {
+            exp->_p++;
+            sqstd_rex_expect(exp,':');
+            expr = sqstd_rex_newnode(exp,OP_NOCAPEXPR);
+        }
+        else
+            expr = sqstd_rex_newnode(exp,OP_EXPR);
+        SQInteger newn = sqstd_rex_list(exp);
+        exp->_nodes[expr].left = newn;
+        ret = expr;
+        sqstd_rex_expect(exp,')');
+              }
+              break;
+    case '[':
+        exp->_p++;
+        ret = sqstd_rex_class(exp);
+        sqstd_rex_expect(exp,']');
+        break;
+    case SQREX_SYMBOL_END_OF_STRING: exp->_p++; ret = sqstd_rex_newnode(exp,OP_EOL);break;
+    case SQREX_SYMBOL_ANY_CHAR: exp->_p++; ret = sqstd_rex_newnode(exp,OP_DOT);break;
+    default:
+        ret = sqstd_rex_charnode(exp,SQFalse);
+        break;
+    }
+
+
+    SQBool isgreedy = SQFalse;
+    unsigned short p0 = 0, p1 = 0;
+    switch(*exp->_p){
+        case SQREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
+        case SQREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = SQTrue; break;
+        case SQREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = SQTrue; break;
+        case '{':
+            exp->_p++;
+            if(!isdigit(*exp->_p)) sqstd_rex_error(exp,_SC("number expected"));
+            p0 = (unsigned short)sqstd_rex_parsenumber(exp);
+            /*******************************/
+            switch(*exp->_p) {
+        case '}':
+            p1 = p0; exp->_p++;
+            break;
+        case ',':
+            exp->_p++;
+            p1 = 0xFFFF;
+            if(isdigit(*exp->_p)){
+                p1 = (unsigned short)sqstd_rex_parsenumber(exp);
+            }
+            sqstd_rex_expect(exp,'}');
+            break;
+        default:
+            sqstd_rex_error(exp,_SC(", or } expected"));
+            }
+            /*******************************/
+            isgreedy = SQTrue;
+            break;
+
+    }
+    if(isgreedy) {
+        SQInteger nnode = sqstd_rex_newnode(exp,OP_GREEDY);
+        exp->_nodes[nnode].left = ret;
+        exp->_nodes[nnode].right = ((p0)<<16)|p1;
+        ret = nnode;
+    }
+
+    if((*exp->_p != SQREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != SQREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != SQREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) {
+        SQInteger nnode = sqstd_rex_element(exp);
+        exp->_nodes[ret].next = nnode;
+    }
+
+    return ret;
+}
+
+static SQInteger sqstd_rex_list(SQRex *exp)
+{
+    SQInteger ret=-1,e;
+    if(*exp->_p == SQREX_SYMBOL_BEGINNING_OF_STRING) {
+        exp->_p++;
+        ret = sqstd_rex_newnode(exp,OP_BOL);
+    }
+    e = sqstd_rex_element(exp);
+    if(ret != -1) {
+        exp->_nodes[ret].next = e;
+    }
+    else ret = e;
+
+    if(*exp->_p == SQREX_SYMBOL_BRANCH) {
+        SQInteger temp,tright;
+        exp->_p++;
+        temp = sqstd_rex_newnode(exp,OP_OR);
+        exp->_nodes[temp].left = ret;
+        tright = sqstd_rex_list(exp);
+        exp->_nodes[temp].right = tright;
+        ret = temp;
+    }
+    return ret;
+}
+
+static SQBool sqstd_rex_matchcclass(SQInteger cclass,SQChar c)
+{
+    switch(cclass) {
+    case 'a': return isalpha(c)?SQTrue:SQFalse;
+    case 'A': return !isalpha(c)?SQTrue:SQFalse;
+    case 'w': return (isalnum(c) || c == '_')?SQTrue:SQFalse;
+    case 'W': return (!isalnum(c) && c != '_')?SQTrue:SQFalse;
+    case 's': return isspace(c)?SQTrue:SQFalse;
+    case 'S': return !isspace(c)?SQTrue:SQFalse;
+    case 'd': return isdigit(c)?SQTrue:SQFalse;
+    case 'D': return !isdigit(c)?SQTrue:SQFalse;
+    case 'x': return isxdigit(c)?SQTrue:SQFalse;
+    case 'X': return !isxdigit(c)?SQTrue:SQFalse;
+    case 'c': return iscntrl(c)?SQTrue:SQFalse;
+    case 'C': return !iscntrl(c)?SQTrue:SQFalse;
+    case 'p': return ispunct(c)?SQTrue:SQFalse;
+    case 'P': return !ispunct(c)?SQTrue:SQFalse;
+    case 'l': return islower(c)?SQTrue:SQFalse;
+    case 'u': return isupper(c)?SQTrue:SQFalse;
+    }
+    return SQFalse; /*cannot happen*/
+}
+
+static SQBool sqstd_rex_matchclass(SQRex* exp,SQRexNode *node,SQChar c)
+{
+    do {
+        switch(node->type) {
+            case OP_RANGE:
+                if(c >= node->left && c <= node->right) return SQTrue;
+                break;
+            case OP_CCLASS:
+                if(sqstd_rex_matchcclass(node->left,c)) return SQTrue;
+                break;
+            default:
+                if(c == node->type)return SQTrue;
+        }
+    } while((node->next != -1) && (node = &exp->_nodes[node->next]));
+    return SQFalse;
+}
+
+static const SQChar *sqstd_rex_matchnode(SQRex* exp,SQRexNode *node,const SQChar *str,SQRexNode *next)
+{
+
+    SQRexNodeType type = node->type;
+    switch(type) {
+    case OP_GREEDY: {
+        //SQRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL;
+        SQRexNode *greedystop = NULL;
+        SQInteger p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0;
+        const SQChar *s=str, *good = str;
+
+        if(node->next != -1) {
+            greedystop = &exp->_nodes[node->next];
+        }
+        else {
+            greedystop = next;
+        }
+
+        while((nmaches == 0xFFFF || nmaches < p1)) {
+
+            const SQChar *stop;
+            if(!(s = sqstd_rex_matchnode(exp,&exp->_nodes[node->left],s,greedystop)))
+                break;
+            nmaches++;
+            good=s;
+            if(greedystop) {
+                //checks that 0 matches satisfy the expression(if so skips)
+                //if not would always stop(for instance if is a '?')
+                if(greedystop->type != OP_GREEDY ||
+                (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0))
+                {
+                    SQRexNode *gnext = NULL;
+                    if(greedystop->next != -1) {
+                        gnext = &exp->_nodes[greedystop->next];
+                    }else if(next && next->next != -1){
+                        gnext = &exp->_nodes[next->next];
+                    }
+                    stop = sqstd_rex_matchnode(exp,greedystop,s,gnext);
+                    if(stop) {
+                        //if satisfied stop it
+                        if(p0 == p1 && p0 == nmaches) break;
+                        else if(nmaches >= p0 && p1 == 0xFFFF) break;
+                        else if(nmaches >= p0 && nmaches <= p1) break;
+                    }
+                }
+            }
+
+            if(s >= exp->_eol)
+                break;
+        }
+        if(p0 == p1 && p0 == nmaches) return good;
+        else if(nmaches >= p0 && p1 == 0xFFFF) return good;
+        else if(nmaches >= p0 && nmaches <= p1) return good;
+        return NULL;
+    }
+    case OP_OR: {
+            const SQChar *asd = str;
+            SQRexNode *temp=&exp->_nodes[node->left];
+            while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) {
+                if(temp->next != -1)
+                    temp = &exp->_nodes[temp->next];
+                else
+                    return asd;
+            }
+            asd = str;
+            temp = &exp->_nodes[node->right];
+            while( (asd = sqstd_rex_matchnode(exp,temp,asd,NULL)) ) {
+                if(temp->next != -1)
+                    temp = &exp->_nodes[temp->next];
+                else
+                    return asd;
+            }
+            return NULL;
+            break;
+    }
+    case OP_EXPR:
+    case OP_NOCAPEXPR:{
+            SQRexNode *n = &exp->_nodes[node->left];
+            const SQChar *cur = str;
+            SQInteger capture = -1;
+            if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) {
+                capture = exp->_currsubexp;
+                exp->_matches[capture].begin = cur;
+                exp->_currsubexp++;
+            }
+            SQInteger tempcap = exp->_currsubexp;
+            do {
+                SQRexNode *subnext = NULL;
+                if(n->next != -1) {
+                    subnext = &exp->_nodes[n->next];
+                }else {
+                    subnext = next;
+                }
+                if(!(cur = sqstd_rex_matchnode(exp,n,cur,subnext))) {
+                    if(capture != -1){
+                        exp->_matches[capture].begin = 0;
+                        exp->_matches[capture].len = 0;
+                    }
+                    return NULL;
+                }
+            } while((n->next != -1) && (n = &exp->_nodes[n->next]));
+
+            exp->_currsubexp = tempcap;
+            if(capture != -1)
+                exp->_matches[capture].len = cur - exp->_matches[capture].begin;
+            return cur;
+    }
+    case OP_WB:
+        if((str == exp->_bol && !isspace(*str))
+         || (str == exp->_eol && !isspace(*(str-1)))
+         || (!isspace(*str) && isspace(*(str+1)))
+         || (isspace(*str) && !isspace(*(str+1))) ) {
+            return (node->left == 'b')?str:NULL;
+        }
+        return (node->left == 'b')?NULL:str;
+    case OP_BOL:
+        if(str == exp->_bol) return str;
+        return NULL;
+    case OP_EOL:
+        if(str == exp->_eol) return str;
+        return NULL;
+    case OP_DOT:{
+        if (str == exp->_eol) return NULL;
+        str++;
+                }
+        return str;
+    case OP_NCLASS:
+    case OP_CLASS:
+        if (str == exp->_eol) return NULL;
+        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 (str == exp->_eol) return NULL;
+        if(sqstd_rex_matchcclass(node->left,*str)) {
+            str++;
+            return str;
+        }
+        return NULL;
+    case OP_MB:
+        {
+            int cb = node->left; //char that opens a balanced expression
+            if(*str != cb) return NULL; // string doesnt start with open char
+            int ce = node->right; //char that closes a balanced expression
+            int cont = 1;
+            const SQChar *streol = exp->_eol;
+            while (++str < streol) {
+              if (*str == ce) {
+                if (--cont == 0) {
+                    return ++str;
+                }
+              }
+              else if (*str == cb) cont++;
+            }
+        }
+        return NULL; // string ends out of balance
+    default: /* char */
+        if (str == exp->_eol) return NULL;
+        if(*str != node->type) return NULL;
+        str++;
+        return str;
+    }
+    return NULL;
+}
+
+/* public api */
+SQRex *sqstd_rex_compile(const SQChar *pattern,const SQChar **error)
+{
+    SQRex *exp = (SQRex *)sq_malloc(sizeof(SQRex));
+    exp->_eol = exp->_bol = NULL;
+    exp->_p = pattern;
+    exp->_nallocated = (SQInteger)scstrlen(pattern) * sizeof(SQChar);
+    exp->_nodes = (SQRexNode *)sq_malloc(exp->_nallocated * sizeof(SQRexNode));
+    exp->_nsize = 0;
+    exp->_matches = 0;
+    exp->_nsubexpr = 0;
+    exp->_first = sqstd_rex_newnode(exp,OP_EXPR);
+    exp->_error = error;
+    exp->_jmpbuf = sq_malloc(sizeof(jmp_buf));
+    if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) {
+        SQInteger res = sqstd_rex_list(exp);
+        exp->_nodes[exp->_first].left = res;
+        if(*exp->_p!='\0')
+            sqstd_rex_error(exp,_SC("unexpected character"));
+#ifdef _DEBUG
+        {
+            SQInteger nsize,i;
+            SQRexNode *t;
+            nsize = exp->_nsize;
+            t = &exp->_nodes[0];
+            scprintf(_SC("\n"));
+            for(i = 0;i < nsize; i++) {
+                if(exp->_nodes[i].type>MAX_CHAR)
+                    scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]);
+                else
+                    scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type);
+                scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next);
+            }
+            scprintf(_SC("\n"));
+        }
+#endif
+        exp->_matches = (SQRexMatch *) sq_malloc(exp->_nsubexpr * sizeof(SQRexMatch));
+        memset(exp->_matches,0,exp->_nsubexpr * sizeof(SQRexMatch));
+    }
+    else{
+        sqstd_rex_free(exp);
+        return NULL;
+    }
+    return exp;
+}
+
+void sqstd_rex_free(SQRex *exp)
+{
+    if(exp) {
+        if(exp->_nodes) sq_free(exp->_nodes,exp->_nallocated * sizeof(SQRexNode));
+        if(exp->_jmpbuf) sq_free(exp->_jmpbuf,sizeof(jmp_buf));
+        if(exp->_matches) sq_free(exp->_matches,exp->_nsubexpr * sizeof(SQRexMatch));
+        sq_free(exp,sizeof(SQRex));
+    }
+}
+
+SQBool sqstd_rex_match(SQRex* exp,const SQChar* text)
+{
+    const SQChar* res = NULL;
+    exp->_bol = text;
+    exp->_eol = text + scstrlen(text);
+    exp->_currsubexp = 0;
+    res = sqstd_rex_matchnode(exp,exp->_nodes,text,NULL);
+    if(res == NULL || res != exp->_eol)
+        return SQFalse;
+    return SQTrue;
+}
+
+SQBool sqstd_rex_searchrange(SQRex* exp,const SQChar* text_begin,const SQChar* text_end,const SQChar** out_begin, const SQChar** out_end)
+{
+    const SQChar *cur = NULL;
+    SQInteger node = exp->_first;
+    if(text_begin >= text_end) return SQFalse;
+    exp->_bol = text_begin;
+    exp->_eol = text_end;
+    do {
+        cur = text_begin;
+        while(node != -1) {
+            exp->_currsubexp = 0;
+            cur = sqstd_rex_matchnode(exp,&exp->_nodes[node],cur,NULL);
+            if(!cur)
+                break;
+            node = exp->_nodes[node].next;
+        }
+        text_begin++;
+    } while(cur == NULL && text_begin != text_end);
+
+    if(cur == NULL)
+        return SQFalse;
+
+    --text_begin;
+
+    if(out_begin) *out_begin = text_begin;
+    if(out_end) *out_end = cur;
+    return SQTrue;
+}
+
+SQBool sqstd_rex_search(SQRex* exp,const SQChar* text, const SQChar** out_begin, const SQChar** out_end)
+{
+    return sqstd_rex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end);
+}
+
+SQInteger sqstd_rex_getsubexpcount(SQRex* exp)
+{
+    return exp->_nsubexpr;
+}
+
+SQBool sqstd_rex_getsubexp(SQRex* exp, SQInteger n, SQRexMatch *subexp)
+{
+    if( n<0 || n >= exp->_nsubexpr) return SQFalse;
+    *subexp = exp->_matches[n];
+    return SQTrue;
+}
+

+ 336 - 336
sqstdlib/sqstdstream.cpp

@@ -1,336 +1,336 @@
-/* see copyright notice in squirrel.h */
-#include <new>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <squirrel.h>
-#include <sqstdio.h>
-#include <sqstdblob.h>
-#include "sqstdstream.h"
-#include "sqstdblobimpl.h"
-
-#define SETUP_STREAM(v) \
-	SQStream *self = NULL; \
-	if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_STREAM_TYPE_TAG))) \
-		return sq_throwerror(v,_SC("invalid type tag")); \
-	if(!self || !self->IsValid())  \
-		return sq_throwerror(v,_SC("the stream is invalid"));
-
-SQInteger _stream_readblob(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	SQUserPointer data,blobp;
-	SQInteger size,res;
-	sq_getinteger(v,2,&size);
-	if(size > self->Len()) {
-		size = self->Len();
-	}
-	data = sq_getscratchpad(v,size);
-	res = self->Read(data,size);
-	if(res <= 0)
-		return sq_throwerror(v,_SC("no data left to read"));
-	blobp = sqstd_createblob(v,res);
-	memcpy(blobp,data,res);
-	return 1;
-}
-
-#define SAFE_READN(ptr,len) { \
-	if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \
-	}
-SQInteger _stream_readn(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	SQInteger format;
-	sq_getinteger(v, 2, &format);
-	switch(format) {
-	case 'l': {
-		SQInteger i;
-		SAFE_READN(&i, sizeof(i));
-		sq_pushinteger(v, i);
-			  }
-		break;
-	case 'i': {
-		SQInt32 i;
-		SAFE_READN(&i, sizeof(i));
-		sq_pushinteger(v, i);
-			  }
-		break;
-	case 's': {
-		short s;
-		SAFE_READN(&s, sizeof(short));
-		sq_pushinteger(v, s);
-			  }
-		break;
-	case 'w': {
-		unsigned short w;
-		SAFE_READN(&w, sizeof(unsigned short));
-		sq_pushinteger(v, w);
-			  }
-		break;
-	case 'c': {
-		char c;
-		SAFE_READN(&c, sizeof(char));
-		sq_pushinteger(v, c);
-			  }
-		break;
-	case 'b': {
-		unsigned char c;
-		SAFE_READN(&c, sizeof(unsigned char));
-		sq_pushinteger(v, c);
-			  }
-		break;
-	case 'f': {
-		float f;
-		SAFE_READN(&f, sizeof(float));
-		sq_pushfloat(v, f);
-			  }
-		break;
-	case 'd': {
-		double d;
-		SAFE_READN(&d, sizeof(double));
-		sq_pushfloat(v, (SQFloat)d);
-			  }
-		break;
-	default:
-		return sq_throwerror(v, _SC("invalid format"));
-	}
-	return 1;
-}
-
-SQInteger _stream_writeblob(HSQUIRRELVM v)
-{
-	SQUserPointer data;
-	SQInteger size;
-	SETUP_STREAM(v);
-	if(SQ_FAILED(sqstd_getblob(v,2,&data)))
-		return sq_throwerror(v,_SC("invalid parameter"));
-	size = sqstd_getblobsize(v,2);
-	if(self->Write(data,size) != size)
-		return sq_throwerror(v,_SC("io error"));
-	sq_pushinteger(v,size);
-	return 1;
-}
-
-SQInteger _stream_writen(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	SQInteger format, ti;
-	SQFloat tf;
-	sq_getinteger(v, 3, &format);
-	switch(format) {
-	case 'l': {
-		SQInteger i;
-		sq_getinteger(v, 2, &ti);
-		i = ti;
-		self->Write(&i, sizeof(SQInteger));
-			  }
-		break;
-	case 'i': {
-		SQInt32 i;
-		sq_getinteger(v, 2, &ti);
-		i = (SQInt32)ti;
-		self->Write(&i, sizeof(SQInt32));
-			  }
-		break;
-	case 's': {
-		short s;
-		sq_getinteger(v, 2, &ti);
-		s = (short)ti;
-		self->Write(&s, sizeof(short));
-			  }
-		break;
-	case 'w': {
-		unsigned short w;
-		sq_getinteger(v, 2, &ti);
-		w = (unsigned short)ti;
-		self->Write(&w, sizeof(unsigned short));
-			  }
-		break;
-	case 'c': {
-		char c;
-		sq_getinteger(v, 2, &ti);
-		c = (char)ti;
-		self->Write(&c, sizeof(char));
-				  }
-		break;
-	case 'b': {
-		unsigned char b;
-		sq_getinteger(v, 2, &ti);
-		b = (unsigned char)ti;
-		self->Write(&b, sizeof(unsigned char));
-			  }
-		break;
-	case 'f': {
-		float f;
-		sq_getfloat(v, 2, &tf);
-		f = (float)tf;
-		self->Write(&f, sizeof(float));
-			  }
-		break;
-	case 'd': {
-		double d;
-		sq_getfloat(v, 2, &tf);
-		d = tf;
-		self->Write(&d, sizeof(double));
-			  }
-		break;
-	default:
-		return sq_throwerror(v, _SC("invalid format"));
-	}
-	return 0;
-}
-
-SQInteger _stream_seek(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	SQInteger offset, origin = SQ_SEEK_SET;
-	sq_getinteger(v, 2, &offset);
-	if(sq_gettop(v) > 2) {
-		SQInteger t;
-		sq_getinteger(v, 3, &t);
-		switch(t) {
-			case 'b': origin = SQ_SEEK_SET; break;
-			case 'c': origin = SQ_SEEK_CUR; break;
-			case 'e': origin = SQ_SEEK_END; break;
-			default: return sq_throwerror(v,_SC("invalid origin"));
-		}
-	}
-	sq_pushinteger(v, self->Seek(offset, origin));
-	return 1;
-}
-
-SQInteger _stream_tell(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	sq_pushinteger(v, self->Tell());
-	return 1;
-}
-
-SQInteger _stream_len(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	sq_pushinteger(v, self->Len());
-	return 1;
-}
-
-SQInteger _stream_flush(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	if(!self->Flush())
-		sq_pushinteger(v, 1);
-	else
-		sq_pushnull(v);
-	return 1;
-}
-
-SQInteger _stream_eos(HSQUIRRELVM v)
-{
-	SETUP_STREAM(v);
-	if(self->EOS())
-		sq_pushinteger(v, 1);
-	else
-		sq_pushnull(v);
-	return 1;
-}
-
- SQInteger _stream__cloned(HSQUIRRELVM v)
- {
-	 return sq_throwerror(v,_SC("this object cannot be cloned"));
- }
-
-static SQRegFunction _stream_methods[] = {
-	_DECL_STREAM_FUNC(readblob,2,_SC("xn")),
-	_DECL_STREAM_FUNC(readn,2,_SC("xn")),
-	_DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
-	_DECL_STREAM_FUNC(writen,3,_SC("xnn")),
-	_DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
-	_DECL_STREAM_FUNC(tell,1,_SC("x")),
-	_DECL_STREAM_FUNC(len,1,_SC("x")),
-	_DECL_STREAM_FUNC(eos,1,_SC("x")),
-	_DECL_STREAM_FUNC(flush,1,_SC("x")),
-	_DECL_STREAM_FUNC(_cloned,0,NULL),
-	{0,0}
-};
-
-void init_streamclass(HSQUIRRELVM v)
-{
-	sq_pushregistrytable(v);
-	sq_pushstring(v,_SC("std_stream"),-1);
-	if(SQ_FAILED(sq_get(v,-2))) {
-		sq_pushstring(v,_SC("std_stream"),-1);
-		sq_newclass(v,SQFalse);
-		sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG);
-		SQInteger i = 0;
-		while(_stream_methods[i].name != 0) {
-			SQRegFunction &f = _stream_methods[i];
-			sq_pushstring(v,f.name,-1);
-			sq_newclosure(v,f.f,0);
-			sq_setparamscheck(v,f.nparamscheck,f.typemask);
-			sq_newslot(v,-3,SQFalse);
-			i++;
-		}
-		sq_newslot(v,-3,SQFalse);
-		sq_pushroottable(v);
-		sq_pushstring(v,_SC("stream"),-1);
-		sq_pushstring(v,_SC("std_stream"),-1);
-		sq_get(v,-4);
-		sq_newslot(v,-3,SQFalse);
-		sq_pop(v,1);
-	}
-	else {
-		sq_pop(v,1); //result
-	}
-	sq_pop(v,1);
-}
-
-SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,SQRegFunction *methods,SQRegFunction *globals)
-{
-	if(sq_gettype(v,-1) != OT_TABLE)
-		return sq_throwerror(v,_SC("table expected"));
-	SQInteger top = sq_gettop(v);
-	//create delegate
-    init_streamclass(v);
-	sq_pushregistrytable(v);
-	sq_pushstring(v,reg_name,-1);
-	sq_pushstring(v,_SC("std_stream"),-1);
-	if(SQ_SUCCEEDED(sq_get(v,-3))) {
-		sq_newclass(v,SQTrue);
-		sq_settypetag(v,-1,typetag);
-		SQInteger i = 0;
-		while(methods[i].name != 0) {
-			SQRegFunction &f = methods[i];
-			sq_pushstring(v,f.name,-1);
-			sq_newclosure(v,f.f,0);
-			sq_setparamscheck(v,f.nparamscheck,f.typemask);
-			sq_setnativeclosurename(v,-1,f.name);
-			sq_newslot(v,-3,SQFalse);
-			i++;
-		}
-		sq_newslot(v,-3,SQFalse);
-		sq_pop(v,1);
-		
-		i = 0;
-		while(globals[i].name!=0)
-		{
-			SQRegFunction &f = globals[i];
-			sq_pushstring(v,f.name,-1);
-			sq_newclosure(v,f.f,0);
-			sq_setparamscheck(v,f.nparamscheck,f.typemask);
-			sq_setnativeclosurename(v,-1,f.name);
-			sq_newslot(v,-3,SQFalse);
-			i++;
-		}
-		//register the class in the target table
-		sq_pushstring(v,name,-1);
-		sq_pushregistrytable(v);
-		sq_pushstring(v,reg_name,-1);
-		sq_get(v,-2);
-		sq_remove(v,-2);
-		sq_newslot(v,-3,SQFalse);
-
-		sq_settop(v,top);
-		return SQ_OK;
-	}
-	sq_settop(v,top);
-	return SQ_ERROR;
-}
+/* see copyright notice in squirrel.h */
+#include <new>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <squirrel.h>
+#include <sqstdio.h>
+#include <sqstdblob.h>
+#include "sqstdstream.h"
+#include "sqstdblobimpl.h"
+
+#define SETUP_STREAM(v) \
+    SQStream *self = NULL; \
+    if(SQ_FAILED(sq_getinstanceup(v,1,(SQUserPointer*)&self,(SQUserPointer)SQSTD_STREAM_TYPE_TAG))) \
+        return sq_throwerror(v,_SC("invalid type tag")); \
+    if(!self || !self->IsValid())  \
+        return sq_throwerror(v,_SC("the stream is invalid"));
+
+SQInteger _stream_readblob(HSQUIRRELVM v)
+{
+    SETUP_STREAM(v);
+    SQUserPointer data,blobp;
+    SQInteger size,res;
+    sq_getinteger(v,2,&size);
+    if(size > self->Len()) {
+        size = self->Len();
+    }
+    data = sq_getscratchpad(v,size);
+    res = self->Read(data,size);
+    if(res <= 0)
+        return sq_throwerror(v,_SC("no data left to read"));
+    blobp = sqstd_createblob(v,res);
+    memcpy(blobp,data,res);
+    return 1;
+}
+
+#define SAFE_READN(ptr,len) { \
+    if(self->Read(ptr,len) != len) return sq_throwerror(v,_SC("io error")); \
+    }
+SQInteger _stream_readn(HSQUIRRELVM v)
+{
+    SETUP_STREAM(v);
+    SQInteger format;
+    sq_getinteger(v, 2, &format);
+    switch(format) {
+    case 'l': {
+        SQInteger i;
+        SAFE_READN(&i, sizeof(i));
+        sq_pushinteger(v, i);
+              }
+        break;
+    case 'i': {
+        SQInt32 i;
+        SAFE_READN(&i, sizeof(i));
+        sq_pushinteger(v, i);
+              }
+        break;
+    case 's': {
+        short s;
+        SAFE_READN(&s, sizeof(short));
+        sq_pushinteger(v, s);
+              }
+        break;
+    case 'w': {
+        unsigned short w;
+        SAFE_READN(&w, sizeof(unsigned short));
+        sq_pushinteger(v, w);
+              }
+        break;
+    case 'c': {
+        char c;
+        SAFE_READN(&c, sizeof(char));
+        sq_pushinteger(v, c);
+              }
+        break;
+    case 'b': {
+        unsigned char c;
+        SAFE_READN(&c, sizeof(unsigned char));
+        sq_pushinteger(v, c);
+              }
+        break;
+    case 'f': {
+        float f;
+        SAFE_READN(&f, sizeof(float));
+        sq_pushfloat(v, f);
+              }
+        break;
+    case 'd': {
+        double d;
+        SAFE_READN(&d, sizeof(double));
+        sq_pushfloat(v, (SQFloat)d);
+              }
+        break;
+    default:
+        return sq_throwerror(v, _SC("invalid format"));
+    }
+    return 1;
+}
+
+SQInteger _stream_writeblob(HSQUIRRELVM v)
+{
+    SQUserPointer data;
+    SQInteger size;
+    SETUP_STREAM(v);
+    if(SQ_FAILED(sqstd_getblob(v,2,&data)))
+        return sq_throwerror(v,_SC("invalid parameter"));
+    size = sqstd_getblobsize(v,2);
+    if(self->Write(data,size) != size)
+        return sq_throwerror(v,_SC("io error"));
+    sq_pushinteger(v,size);
+    return 1;
+}
+
+SQInteger _stream_writen(HSQUIRRELVM v)
+{
+    SETUP_STREAM(v);
+    SQInteger format, ti;
+    SQFloat tf;
+    sq_getinteger(v, 3, &format);
+    switch(format) {
+    case 'l': {
+        SQInteger i;
+        sq_getinteger(v, 2, &ti);
+        i = ti;
+        self->Write(&i, sizeof(SQInteger));
+              }
+        break;
+    case 'i': {
+        SQInt32 i;
+        sq_getinteger(v, 2, &ti);
+        i = (SQInt32)ti;
+        self->Write(&i, sizeof(SQInt32));
+              }
+        break;
+    case 's': {
+        short s;
+        sq_getinteger(v, 2, &ti);
+        s = (short)ti;
+        self->Write(&s, sizeof(short));
+              }
+        break;
+    case 'w': {
+        unsigned short w;
+        sq_getinteger(v, 2, &ti);
+        w = (unsigned short)ti;
+        self->Write(&w, sizeof(unsigned short));
+              }
+        break;
+    case 'c': {
+        char c;
+        sq_getinteger(v, 2, &ti);
+        c = (char)ti;
+        self->Write(&c, sizeof(char));
+                  }
+        break;
+    case 'b': {
+        unsigned char b;
+        sq_getinteger(v, 2, &ti);
+        b = (unsigned char)ti;
+        self->Write(&b, sizeof(unsigned char));
+              }
+        break;
+    case 'f': {
+        float f;
+        sq_getfloat(v, 2, &tf);
+        f = (float)tf;
+        self->Write(&f, sizeof(float));
+              }
+        break;
+    case 'd': {
+        double d;
+        sq_getfloat(v, 2, &tf);
+        d = tf;
+        self->Write(&d, sizeof(double));
+              }
+        break;
+    default:
+        return sq_throwerror(v, _SC("invalid format"));
+    }
+    return 0;
+}
+
+SQInteger _stream_seek(HSQUIRRELVM v)
+{
+    SETUP_STREAM(v);
+    SQInteger offset, origin = SQ_SEEK_SET;
+    sq_getinteger(v, 2, &offset);
+    if(sq_gettop(v) > 2) {
+        SQInteger t;
+        sq_getinteger(v, 3, &t);
+        switch(t) {
+            case 'b': origin = SQ_SEEK_SET; break;
+            case 'c': origin = SQ_SEEK_CUR; break;
+            case 'e': origin = SQ_SEEK_END; break;
+            default: return sq_throwerror(v,_SC("invalid origin"));
+        }
+    }
+    sq_pushinteger(v, self->Seek(offset, origin));
+    return 1;
+}
+
+SQInteger _stream_tell(HSQUIRRELVM v)
+{
+    SETUP_STREAM(v);
+    sq_pushinteger(v, self->Tell());
+    return 1;
+}
+
+SQInteger _stream_len(HSQUIRRELVM v)
+{
+    SETUP_STREAM(v);
+    sq_pushinteger(v, self->Len());
+    return 1;
+}
+
+SQInteger _stream_flush(HSQUIRRELVM v)
+{
+    SETUP_STREAM(v);
+    if(!self->Flush())
+        sq_pushinteger(v, 1);
+    else
+        sq_pushnull(v);
+    return 1;
+}
+
+SQInteger _stream_eos(HSQUIRRELVM v)
+{
+    SETUP_STREAM(v);
+    if(self->EOS())
+        sq_pushinteger(v, 1);
+    else
+        sq_pushnull(v);
+    return 1;
+}
+
+ SQInteger _stream__cloned(HSQUIRRELVM v)
+ {
+     return sq_throwerror(v,_SC("this object cannot be cloned"));
+ }
+
+static const SQRegFunction _stream_methods[] = {
+    _DECL_STREAM_FUNC(readblob,2,_SC("xn")),
+    _DECL_STREAM_FUNC(readn,2,_SC("xn")),
+    _DECL_STREAM_FUNC(writeblob,-2,_SC("xx")),
+    _DECL_STREAM_FUNC(writen,3,_SC("xnn")),
+    _DECL_STREAM_FUNC(seek,-2,_SC("xnn")),
+    _DECL_STREAM_FUNC(tell,1,_SC("x")),
+    _DECL_STREAM_FUNC(len,1,_SC("x")),
+    _DECL_STREAM_FUNC(eos,1,_SC("x")),
+    _DECL_STREAM_FUNC(flush,1,_SC("x")),
+    _DECL_STREAM_FUNC(_cloned,0,NULL),
+    {0,0}
+};
+
+void init_streamclass(HSQUIRRELVM v)
+{
+    sq_pushregistrytable(v);
+    sq_pushstring(v,_SC("std_stream"),-1);
+    if(SQ_FAILED(sq_get(v,-2))) {
+        sq_pushstring(v,_SC("std_stream"),-1);
+        sq_newclass(v,SQFalse);
+        sq_settypetag(v,-1,(SQUserPointer)SQSTD_STREAM_TYPE_TAG);
+        SQInteger i = 0;
+        while(_stream_methods[i].name != 0) {
+            const SQRegFunction &f = _stream_methods[i];
+            sq_pushstring(v,f.name,-1);
+            sq_newclosure(v,f.f,0);
+            sq_setparamscheck(v,f.nparamscheck,f.typemask);
+            sq_newslot(v,-3,SQFalse);
+            i++;
+        }
+        sq_newslot(v,-3,SQFalse);
+        sq_pushroottable(v);
+        sq_pushstring(v,_SC("stream"),-1);
+        sq_pushstring(v,_SC("std_stream"),-1);
+        sq_get(v,-4);
+        sq_newslot(v,-3,SQFalse);
+        sq_pop(v,1);
+    }
+    else {
+        sq_pop(v,1); //result
+    }
+    sq_pop(v,1);
+}
+
+SQRESULT declare_stream(HSQUIRRELVM v,const SQChar* name,SQUserPointer typetag,const SQChar* reg_name,const SQRegFunction *methods,const 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) {
+            const SQRegFunction &f = methods[i];
+            sq_pushstring(v,f.name,-1);
+            sq_newclosure(v,f.f,0);
+            sq_setparamscheck(v,f.nparamscheck,f.typemask);
+            sq_setnativeclosurename(v,-1,f.name);
+            sq_newslot(v,-3,SQFalse);
+            i++;
+        }
+        sq_newslot(v,-3,SQFalse);
+        sq_pop(v,1);
+
+        i = 0;
+        while(globals[i].name!=0)
+        {
+            const SQRegFunction &f = globals[i];
+            sq_pushstring(v,f.name,-1);
+            sq_newclosure(v,f.f,0);
+            sq_setparamscheck(v,f.nparamscheck,f.typemask);
+            sq_setnativeclosurename(v,-1,f.name);
+            sq_newslot(v,-3,SQFalse);
+            i++;
+        }
+        //register the class in the target table
+        sq_pushstring(v,name,-1);
+        sq_pushregistrytable(v);
+        sq_pushstring(v,reg_name,-1);
+        sq_get(v,-2);
+        sq_remove(v,-2);
+        sq_newslot(v,-3,SQFalse);
+
+        sq_settop(v,top);
+        return SQ_OK;
+    }
+    sq_settop(v,top);
+    return SQ_ERROR;
+}

+ 18 - 18
sqstdlib/sqstdstream.h

@@ -1,18 +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_*/
+/*  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,const SQRegFunction *methods,const SQRegFunction *globals);
+#endif /*_SQSTD_STREAM_H_*/

+ 488 - 488
sqstdlib/sqstdstring.cpp

@@ -1,488 +1,488 @@
-/* see copyright notice in squirrel.h */
-#include <squirrel.h>
-#include <sqstdstring.h>
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <assert.h>
-
-#define MAX_FORMAT_LEN	20
-#define MAX_WFORMAT_LEN	3
-#define ADDITIONAL_FORMAT_SPACE (100*sizeof(SQChar))
-
-static SQBool isfmtchr(SQChar ch)
-{
-	switch(ch) {
-	case '-': case '+': case ' ': case '#': case '0': return SQTrue;
-	}
-	return SQFalse;
-}
-
-static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, SQInteger n,SQInteger &width)
-{
-	SQChar *dummy;
-	SQChar swidth[MAX_WFORMAT_LEN];
-	SQInteger wc = 0;
-	SQInteger start = n;
-	fmt[0] = '%';
-	while (isfmtchr(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 = scstrtol(swidth,&dummy,10);
-	}
-	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 += scstrtol(swidth,&dummy,10);
-
-		}
-	}
-	if (n-start > MAX_FORMAT_LEN )
-		return sq_throwerror(v,_SC("format too long"));
-	memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar));
-	fmt[(n-start)+2] = '\0';
-	return n;
-}
-
-SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output)
-{
-	const SQChar *format;
-	SQChar *dest;
-	SQChar fmt[MAX_FORMAT_LEN];
-	sq_getstring(v,nformatstringidx,&format);
-	SQInteger format_size = sq_getsize(v,nformatstringidx); 
-	SQInteger allocated = (format_size+2)*sizeof(SQChar);
-	dest = sq_getscratchpad(v,allocated);
-	SQInteger n = 0,i = 0, nparam = nformatstringidx+1, w = 0;
-	//while(format[n] != '\0') 
-	while(n < format_size)
-	{
-		if(format[n] != '%') {
-			assert(i < allocated);
-			dest[i++] = format[n];
-			n++;
-		}
-		else if(format[n+1] == '%') { //handles %%
-				dest[i++] = '%';
-				n += 2; 
-		}
-		else {
-			n++;
-			if( nparam > sq_gettop(v) )
-				return sq_throwerror(v,_SC("not enough paramters for the given format string"));
-			n = validate_format(v,fmt,format,n,w);
-			if(n < 0) return -1;
-			SQInteger addlen = 0;
-			SQInteger valtype = 0;
-			const SQChar *ts;
-			SQInteger ti;
-			SQFloat tf;
-			switch(format[n]) {
-			case 's':
-				if(SQ_FAILED(sq_getstring(v,nparam,&ts))) 
-					return sq_throwerror(v,_SC("string expected for the specified format"));
-				addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar));
-				valtype = 's';
-				break;
-			case 'i': case 'd': case 'o': case 'u':  case 'x':  case 'X':
-#ifdef _SQ64
-				{
-				size_t flen = scstrlen(fmt);
-				SQInteger fpos = flen - 1;
-				SQChar f = fmt[fpos];
-				SQChar *prec = (SQChar *)_PRINT_INT_PREC;
-				while(*prec != _SC('\0')) {
-					fmt[fpos++] = *prec++;
-				}
-				fmt[fpos++] = f;
-				fmt[fpos++] = _SC('\0');
-				}
-#endif
-			case 'c':
-				if(SQ_FAILED(sq_getinteger(v,nparam,&ti))) 
-					return sq_throwerror(v,_SC("integer expected for the specified format"));
-				addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
-				valtype = 'i';
-				break;
-			case 'f': case 'g': case 'G': case 'e':  case 'E':
-				if(SQ_FAILED(sq_getfloat(v,nparam,&tf))) 
-					return sq_throwerror(v,_SC("float expected for the specified format"));
-				addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
-				valtype = 'f';
-				break;
-			default:
-				return sq_throwerror(v,_SC("invalid format"));
-			}
-			n++;
-			allocated += addlen + sizeof(SQChar);
-			dest = sq_getscratchpad(v,allocated);
-			switch(valtype) {
-			case 's': i += scsprintf(&dest[i],allocated,fmt,ts); break;
-			case 'i': i += scsprintf(&dest[i],allocated,fmt,ti); break;
-			case 'f': i += scsprintf(&dest[i],allocated,fmt,tf); break;
-			};
-			nparam ++;
-		}
-	}
-	*outlen = i;
-	dest[i] = '\0';
-	*output = dest;
-	return SQ_OK;
-}
-
-static SQInteger _string_format(HSQUIRRELVM v)
-{
-	SQChar *dest = NULL;
-	SQInteger length = 0;
-	if(SQ_FAILED(sqstd_format(v,2,&length,&dest)))
-		return -1;
-	sq_pushstring(v,dest,length);
-	return 1;
-}
-
-static void __strip_l(const SQChar *str,const SQChar **start)
-{
-	const SQChar *t = str;
-	while(((*t) != '\0') && scisspace(*t)){ t++; }
-	*start = t;
-}
-
-static void __strip_r(const SQChar *str,SQInteger len,const SQChar **end)
-{
-	if(len == 0) {
-		*end = str;
-		return;
-	}
-	const SQChar *t = &str[len-1];
-	while(t >= str && scisspace(*t)) { t--; }
-	*end = t + 1;
-}
-
-static SQInteger _string_strip(HSQUIRRELVM v)
-{
-	const SQChar *str,*start,*end;
-	sq_getstring(v,2,&str);
-	SQInteger len = sq_getsize(v,2);
-	__strip_l(str,&start);
-	__strip_r(str,len,&end);
-	sq_pushstring(v,start,end - start);
-	return 1;
-}
-
-static SQInteger _string_lstrip(HSQUIRRELVM v)
-{
-	const SQChar *str,*start;
-	sq_getstring(v,2,&str);
-	__strip_l(str,&start);
-	sq_pushstring(v,start,-1);
-	return 1;
-}
-
-static SQInteger _string_rstrip(HSQUIRRELVM v)
-{
-	const SQChar *str,*end;
-	sq_getstring(v,2,&str);
-	SQInteger len = sq_getsize(v,2);
-	__strip_r(str,len,&end);
-	sq_pushstring(v,str,end - str);
-	return 1;
-}
-
-static SQInteger _string_split(HSQUIRRELVM v)
-{
-	const SQChar *str,*seps;
-	SQChar *stemp;
-	sq_getstring(v,2,&str);
-	sq_getstring(v,3,&seps);
-	SQInteger sepsize = sq_getsize(v,3);
-	if(sepsize == 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);
-	SQChar *start = stemp;
-	SQChar *end = stemp;
-	sq_newarray(v,0);
-	while(*end != '\0')
-	{
-		SQChar cur = *end;
-		for(SQInteger i = 0; i < sepsize; i++)
-		{
-			if(cur == seps[i])
-			{
-				*end = 0;
-				sq_pushstring(v,start,-1);
-				sq_arrayappend(v,-2);
-				start = end + 1;
-				break;
-			}
-		}
-		end++;
-	}
-	if(end != start)
-	{
-		sq_pushstring(v,start,-1);
-		sq_arrayappend(v,-2);
-	}
-	return 1;
-}
-
-static SQInteger _string_escape(HSQUIRRELVM v)
-{
-	const SQChar *str;
-	SQChar *dest,*resstr;
-	SQInteger size;
-	sq_getstring(v,2,&str);
-	size = sq_getsize(v,2);
-	if(size == 0) {
-		sq_push(v,2);
-		return 1;
-	}
-	SQInteger destcharsize = (size * 6); //assumes every char could be escaped
-	resstr = dest = (SQChar *)sq_getscratchpad(v,destcharsize * sizeof(SQChar));
-	SQChar c;
-	SQChar escch;
-	SQInteger escaped = 0;
-	for(int n = 0; n < size; n++){
-		c = *str++;
-		escch = 0;
-		if(scisprint(c) || c == 0) {
-			switch(c) {
-			case '\a': escch = 'a'; break;
-			case '\b': escch = 'b'; break;
-			case '\t': escch = 't'; break;
-			case '\n': escch = 'n'; break;
-			case '\v': escch = 'v'; break;
-			case '\f': escch = 'f'; break;
-			case '\r': escch = 'r'; break;
-			case '\\': escch = '\\'; break;
-			case '\"': escch = '\"'; break;
-			case '\'': escch = '\''; break;
-			case 0: escch = '0'; break;
-			}
-			if(escch) {
-				*dest++ = '\\';
-				*dest++ = escch;
-				escaped++;
-			}
-			else {
-				*dest++ = c;
-			}
-		}
-		else {
-			dest += scsprintf(dest,destcharsize,_SC("\\x%x"),c);
-			escaped++;
-		}
-	}
-
-	if(escaped) {
-		sq_pushstring(v,resstr,dest - resstr);
-	}
-	else {
-		sq_push(v,2); //nothing escaped
-	}
-	return 1;
-}
-
-static SQInteger _string_startswith(HSQUIRRELVM v)
-{
-	const SQChar *str,*cmp;
-	sq_getstring(v,2,&str);
-	sq_getstring(v,3,&cmp);
-	SQInteger len = sq_getsize(v,2);
-	SQInteger cmplen = sq_getsize(v,3);
-	SQBool ret = SQFalse;
-	if(cmplen <= len) {
-		ret = memcmp(str,cmp,sq_rsl(cmplen)) == 0 ? SQTrue : SQFalse;
-	}
-	sq_pushbool(v,ret);
-	return 1;
-}
-
-static SQInteger _string_endswith(HSQUIRRELVM v)
-{
-	const SQChar *str,*cmp;
-	sq_getstring(v,2,&str);
-	sq_getstring(v,3,&cmp);
-	SQInteger len = sq_getsize(v,2);
-	SQInteger cmplen = sq_getsize(v,3);
-	SQBool ret = SQFalse;
-	if(cmplen <= len) {
-		ret = memcmp(&str[len - cmplen],cmp,sq_rsl(cmplen)) == 0 ? SQTrue : SQFalse;
-	}
-	sq_pushbool(v,ret);
-	return 1;
-}
-
-#define SETUP_REX(v) \
-	SQRex *self = NULL; \
-	sq_getinstanceup(v,1,(SQUserPointer *)&self,0); 
-
-static SQInteger _rexobj_releasehook(SQUserPointer p, SQInteger size)
-{
-	SQRex *self = ((SQRex *)p);
-	sqstd_rex_free(self);
-	return 1;
-}
-
-static SQInteger _regexp_match(HSQUIRRELVM v)
-{
-	SETUP_REX(v);
-	const SQChar *str;
-	sq_getstring(v,2,&str);
-	if(sqstd_rex_match(self,str) == SQTrue)
-	{
-		sq_pushbool(v,SQTrue);
-		return 1;
-	}
-	sq_pushbool(v,SQFalse);
-	return 1;
-}
-
-static void _addrexmatch(HSQUIRRELVM v,const SQChar *str,const SQChar *begin,const SQChar *end)
-{
-	sq_newtable(v);
-	sq_pushstring(v,_SC("begin"),-1);
-	sq_pushinteger(v,begin - str);
-	sq_rawset(v,-3);
-	sq_pushstring(v,_SC("end"),-1);
-	sq_pushinteger(v,end - str);
-	sq_rawset(v,-3);
-}
-
-static SQInteger _regexp_search(HSQUIRRELVM v)
-{
-	SETUP_REX(v);
-	const SQChar *str,*begin,*end;
-	SQInteger start = 0;
-	sq_getstring(v,2,&str);
-	if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
-	if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
-		_addrexmatch(v,str,begin,end);
-		return 1;
-	}
-	return 0;
-}
-
-static SQInteger _regexp_capture(HSQUIRRELVM v)
-{
-	SETUP_REX(v);
-	const SQChar *str,*begin,*end;
-	SQInteger start = 0;
-	sq_getstring(v,2,&str);
-	if(sq_gettop(v) > 2) sq_getinteger(v,3,&start);
-	if(sqstd_rex_search(self,str+start,&begin,&end) == SQTrue) {
-		SQInteger n = sqstd_rex_getsubexpcount(self);
-		SQRexMatch match;
-		sq_newarray(v,0);
-		for(SQInteger i = 0;i < n; i++) {
-			sqstd_rex_getsubexp(self,i,&match);
-			if(match.len > 0)
-				_addrexmatch(v,str,match.begin,match.begin+match.len);
-			else
-				_addrexmatch(v,str,str,str); //empty match
-			sq_arrayappend(v,-2);
-		}
-		return 1;
-	}
-	return 0;
-}
-
-static SQInteger _regexp_subexpcount(HSQUIRRELVM v)
-{
-	SETUP_REX(v);
-	sq_pushinteger(v,sqstd_rex_getsubexpcount(self));
-	return 1;
-}
-
-static SQInteger _regexp_constructor(HSQUIRRELVM v)
-{
-	const SQChar *error,*pattern;
-	sq_getstring(v,2,&pattern);
-	SQRex *rex = sqstd_rex_compile(pattern,&error);
-	if(!rex) return sq_throwerror(v,error);
-	sq_setinstanceup(v,1,rex);
-	sq_setreleasehook(v,1,_rexobj_releasehook);
-	return 0;
-}
-
-static SQInteger _regexp__typeof(HSQUIRRELVM v)
-{
-	sq_pushstring(v,_SC("regexp"),-1);
-	return 1;
-}
-
-#define _DECL_REX_FUNC(name,nparams,pmask) {_SC(#name),_regexp_##name,nparams,pmask}
-static SQRegFunction rexobj_funcs[]={
-	_DECL_REX_FUNC(constructor,2,_SC(".s")),
-	_DECL_REX_FUNC(search,-2,_SC("xsn")),
-	_DECL_REX_FUNC(match,2,_SC("xs")),
-	_DECL_REX_FUNC(capture,-2,_SC("xsn")),
-	_DECL_REX_FUNC(subexpcount,1,_SC("x")),
-	_DECL_REX_FUNC(_typeof,1,_SC("x")),
-	{0,0}
-};
-#undef _DECL_REX_FUNC
-
-#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask}
-static SQRegFunction stringlib_funcs[]={
-	_DECL_FUNC(format,-2,_SC(".s")),
-	_DECL_FUNC(strip,2,_SC(".s")),
-	_DECL_FUNC(lstrip,2,_SC(".s")),
-	_DECL_FUNC(rstrip,2,_SC(".s")),
-	_DECL_FUNC(split,3,_SC(".ss")),
-	_DECL_FUNC(escape,2,_SC(".s")),
-	_DECL_FUNC(startswith,3,_SC(".ss")),
-	_DECL_FUNC(endswith,3,_SC(".ss")),
-	{0,0}
-};
-#undef _DECL_FUNC
-
-
-SQInteger sqstd_register_stringlib(HSQUIRRELVM v)
-{
-	sq_pushstring(v,_SC("regexp"),-1);
-	sq_newclass(v,SQFalse);
-	SQInteger i = 0;
-	while(rexobj_funcs[i].name != 0) {
-		SQRegFunction &f = rexobj_funcs[i];
-		sq_pushstring(v,f.name,-1);
-		sq_newclosure(v,f.f,0);
-		sq_setparamscheck(v,f.nparamscheck,f.typemask);
-		sq_setnativeclosurename(v,-1,f.name);
-		sq_newslot(v,-3,SQFalse);
-		i++;
-	}
-	sq_newslot(v,-3,SQFalse);
-
-	i = 0;
-	while(stringlib_funcs[i].name!=0)
-	{
-		sq_pushstring(v,stringlib_funcs[i].name,-1);
-		sq_newclosure(v,stringlib_funcs[i].f,0);
-		sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask);
-		sq_setnativeclosurename(v,-1,stringlib_funcs[i].name);
-		sq_newslot(v,-3,SQFalse);
-		i++;
-	}
-	return 1;
-}
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <sqstdstring.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <assert.h>
+
+#define MAX_FORMAT_LEN  20
+#define MAX_WFORMAT_LEN 3
+#define ADDITIONAL_FORMAT_SPACE (100*sizeof(SQChar))
+
+static SQBool isfmtchr(SQChar ch)
+{
+    switch(ch) {
+    case '-': case '+': case ' ': case '#': case '0': return SQTrue;
+    }
+    return SQFalse;
+}
+
+static SQInteger validate_format(HSQUIRRELVM v, SQChar *fmt, const SQChar *src, SQInteger n,SQInteger &width)
+{
+    SQChar *dummy;
+    SQChar swidth[MAX_WFORMAT_LEN];
+    SQInteger wc = 0;
+    SQInteger start = n;
+    fmt[0] = '%';
+    while (isfmtchr(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 = scstrtol(swidth,&dummy,10);
+    }
+    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 += scstrtol(swidth,&dummy,10);
+
+        }
+    }
+    if (n-start > MAX_FORMAT_LEN )
+        return sq_throwerror(v,_SC("format too long"));
+    memcpy(&fmt[1],&src[start],((n-start)+1)*sizeof(SQChar));
+    fmt[(n-start)+2] = '\0';
+    return n;
+}
+
+SQRESULT sqstd_format(HSQUIRRELVM v,SQInteger nformatstringidx,SQInteger *outlen,SQChar **output)
+{
+    const SQChar *format;
+    SQChar *dest;
+    SQChar fmt[MAX_FORMAT_LEN];
+    sq_getstring(v,nformatstringidx,&format);
+    SQInteger format_size = sq_getsize(v,nformatstringidx);
+    SQInteger allocated = (format_size+2)*sizeof(SQChar);
+    dest = sq_getscratchpad(v,allocated);
+    SQInteger n = 0,i = 0, nparam = nformatstringidx+1, w = 0;
+    //while(format[n] != '\0')
+    while(n < format_size)
+    {
+        if(format[n] != '%') {
+            assert(i < allocated);
+            dest[i++] = format[n];
+            n++;
+        }
+        else if(format[n+1] == '%') { //handles %%
+                dest[i++] = '%';
+                n += 2;
+        }
+        else {
+            n++;
+            if( nparam > sq_gettop(v) )
+                return sq_throwerror(v,_SC("not enough paramters for the given format string"));
+            n = validate_format(v,fmt,format,n,w);
+            if(n < 0) return -1;
+            SQInteger addlen = 0;
+            SQInteger valtype = 0;
+            const SQChar *ts;
+            SQInteger ti;
+            SQFloat tf;
+            switch(format[n]) {
+            case 's':
+                if(SQ_FAILED(sq_getstring(v,nparam,&ts)))
+                    return sq_throwerror(v,_SC("string expected for the specified format"));
+                addlen = (sq_getsize(v,nparam)*sizeof(SQChar))+((w+1)*sizeof(SQChar));
+                valtype = 's';
+                break;
+            case 'i': case 'd': case 'o': case 'u':  case 'x':  case 'X':
+#ifdef _SQ64
+                {
+                size_t flen = scstrlen(fmt);
+                SQInteger fpos = flen - 1;
+                SQChar f = fmt[fpos];
+                const SQChar *prec = (const SQChar *)_PRINT_INT_PREC;
+                while(*prec != _SC('\0')) {
+                    fmt[fpos++] = *prec++;
+                }
+                fmt[fpos++] = f;
+                fmt[fpos++] = _SC('\0');
+                }
+#endif
+            case 'c':
+                if(SQ_FAILED(sq_getinteger(v,nparam,&ti)))
+                    return sq_throwerror(v,_SC("integer expected for the specified format"));
+                addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
+                valtype = 'i';
+                break;
+            case 'f': case 'g': case 'G': case 'e':  case 'E':
+                if(SQ_FAILED(sq_getfloat(v,nparam,&tf)))
+                    return sq_throwerror(v,_SC("float expected for the specified format"));
+                addlen = (ADDITIONAL_FORMAT_SPACE)+((w+1)*sizeof(SQChar));
+                valtype = 'f';
+                break;
+            default:
+                return sq_throwerror(v,_SC("invalid format"));
+            }
+            n++;
+            allocated += addlen + sizeof(SQChar);
+            dest = sq_getscratchpad(v,allocated);
+            switch(valtype) {
+            case 's': i += scsprintf(&dest[i],allocated,fmt,ts); break;
+            case 'i': i += scsprintf(&dest[i],allocated,fmt,ti); break;
+            case 'f': i += scsprintf(&dest[i],allocated,fmt,tf); break;
+            };
+            nparam ++;
+        }
+    }
+    *outlen = i;
+    dest[i] = '\0';
+    *output = dest;
+    return SQ_OK;
+}
+
+static SQInteger _string_format(HSQUIRRELVM v)
+{
+    SQChar *dest = NULL;
+    SQInteger length = 0;
+    if(SQ_FAILED(sqstd_format(v,2,&length,&dest)))
+        return -1;
+    sq_pushstring(v,dest,length);
+    return 1;
+}
+
+static void __strip_l(const SQChar *str,const SQChar **start)
+{
+    const SQChar *t = str;
+    while(((*t) != '\0') && scisspace(*t)){ t++; }
+    *start = t;
+}
+
+static void __strip_r(const SQChar *str,SQInteger len,const SQChar **end)
+{
+    if(len == 0) {
+        *end = str;
+        return;
+    }
+    const SQChar *t = &str[len-1];
+    while(t >= str && scisspace(*t)) { t--; }
+    *end = t + 1;
+}
+
+static SQInteger _string_strip(HSQUIRRELVM v)
+{
+    const SQChar *str,*start,*end;
+    sq_getstring(v,2,&str);
+    SQInteger len = sq_getsize(v,2);
+    __strip_l(str,&start);
+    __strip_r(str,len,&end);
+    sq_pushstring(v,start,end - start);
+    return 1;
+}
+
+static SQInteger _string_lstrip(HSQUIRRELVM v)
+{
+    const SQChar *str,*start;
+    sq_getstring(v,2,&str);
+    __strip_l(str,&start);
+    sq_pushstring(v,start,-1);
+    return 1;
+}
+
+static SQInteger _string_rstrip(HSQUIRRELVM v)
+{
+    const SQChar *str,*end;
+    sq_getstring(v,2,&str);
+    SQInteger len = sq_getsize(v,2);
+    __strip_r(str,len,&end);
+    sq_pushstring(v,str,end - str);
+    return 1;
+}
+
+static SQInteger _string_split(HSQUIRRELVM v)
+{
+    const SQChar *str,*seps;
+    SQChar *stemp;
+    sq_getstring(v,2,&str);
+    sq_getstring(v,3,&seps);
+    SQInteger sepsize = sq_getsize(v,3);
+    if(sepsize == 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);
+    SQChar *start = stemp;
+    SQChar *end = stemp;
+    sq_newarray(v,0);
+    while(*end != '\0')
+    {
+        SQChar cur = *end;
+        for(SQInteger i = 0; i < sepsize; i++)
+        {
+            if(cur == seps[i])
+            {
+                *end = 0;
+                sq_pushstring(v,start,-1);
+                sq_arrayappend(v,-2);
+                start = end + 1;
+                break;
+            }
+        }
+        end++;
+    }
+    if(end != start)
+    {
+        sq_pushstring(v,start,-1);
+        sq_arrayappend(v,-2);
+    }
+    return 1;
+}
+
+static SQInteger _string_escape(HSQUIRRELVM v)
+{
+    const SQChar *str;
+    SQChar *dest,*resstr;
+    SQInteger size;
+    sq_getstring(v,2,&str);
+    size = sq_getsize(v,2);
+    if(size == 0) {
+        sq_push(v,2);
+        return 1;
+    }
+    SQInteger destcharsize = (size * 6); //assumes every char could be escaped
+    resstr = dest = (SQChar *)sq_getscratchpad(v,destcharsize * sizeof(SQChar));
+    SQChar c;
+    SQChar escch;
+    SQInteger escaped = 0;
+    for(int n = 0; n < size; n++){
+        c = *str++;
+        escch = 0;
+        if(scisprint(c) || c == 0) {
+            switch(c) {
+            case '\a': escch = 'a'; break;
+            case '\b': escch = 'b'; break;
+            case '\t': escch = 't'; break;
+            case '\n': escch = 'n'; break;
+            case '\v': escch = 'v'; break;
+            case '\f': escch = 'f'; break;
+            case '\r': escch = 'r'; break;
+            case '\\': escch = '\\'; break;
+            case '\"': escch = '\"'; break;
+            case '\'': escch = '\''; break;
+            case 0: escch = '0'; break;
+            }
+            if(escch) {
+                *dest++ = '\\';
+                *dest++ = escch;
+                escaped++;
+            }
+            else {
+                *dest++ = c;
+            }
+        }
+        else {
+            dest += scsprintf(dest,destcharsize,_SC("\\x%x"),c);
+            escaped++;
+        }
+    }
+
+    if(escaped) {
+        sq_pushstring(v,resstr,dest - resstr);
+    }
+    else {
+        sq_push(v,2); //nothing escaped
+    }
+    return 1;
+}
+
+static SQInteger _string_startswith(HSQUIRRELVM v)
+{
+    const SQChar *str,*cmp;
+    sq_getstring(v,2,&str);
+    sq_getstring(v,3,&cmp);
+    SQInteger len = sq_getsize(v,2);
+    SQInteger cmplen = sq_getsize(v,3);
+    SQBool ret = SQFalse;
+    if(cmplen <= len) {
+        ret = memcmp(str,cmp,sq_rsl(cmplen)) == 0 ? SQTrue : SQFalse;
+    }
+    sq_pushbool(v,ret);
+    return 1;
+}
+
+static SQInteger _string_endswith(HSQUIRRELVM v)
+{
+    const SQChar *str,*cmp;
+    sq_getstring(v,2,&str);
+    sq_getstring(v,3,&cmp);
+    SQInteger len = sq_getsize(v,2);
+    SQInteger cmplen = sq_getsize(v,3);
+    SQBool ret = SQFalse;
+    if(cmplen <= len) {
+        ret = memcmp(&str[len - cmplen],cmp,sq_rsl(cmplen)) == 0 ? SQTrue : SQFalse;
+    }
+    sq_pushbool(v,ret);
+    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 const SQRegFunction rexobj_funcs[]={
+    _DECL_REX_FUNC(constructor,2,_SC(".s")),
+    _DECL_REX_FUNC(search,-2,_SC("xsn")),
+    _DECL_REX_FUNC(match,2,_SC("xs")),
+    _DECL_REX_FUNC(capture,-2,_SC("xsn")),
+    _DECL_REX_FUNC(subexpcount,1,_SC("x")),
+    _DECL_REX_FUNC(_typeof,1,_SC("x")),
+    {0,0}
+};
+#undef _DECL_REX_FUNC
+
+#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_string_##name,nparams,pmask}
+static const 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")),
+    _DECL_FUNC(escape,2,_SC(".s")),
+    _DECL_FUNC(startswith,3,_SC(".ss")),
+    _DECL_FUNC(endswith,3,_SC(".ss")),
+    {0,0}
+};
+#undef _DECL_FUNC
+
+
+SQInteger sqstd_register_stringlib(HSQUIRRELVM v)
+{
+    sq_pushstring(v,_SC("regexp"),-1);
+    sq_newclass(v,SQFalse);
+    SQInteger i = 0;
+    while(rexobj_funcs[i].name != 0) {
+        const SQRegFunction &f = rexobj_funcs[i];
+        sq_pushstring(v,f.name,-1);
+        sq_newclosure(v,f.f,0);
+        sq_setparamscheck(v,f.nparamscheck,f.typemask);
+        sq_setnativeclosurename(v,-1,f.name);
+        sq_newslot(v,-3,SQFalse);
+        i++;
+    }
+    sq_newslot(v,-3,SQFalse);
+
+    i = 0;
+    while(stringlib_funcs[i].name!=0)
+    {
+        sq_pushstring(v,stringlib_funcs[i].name,-1);
+        sq_newclosure(v,stringlib_funcs[i].f,0);
+        sq_setparamscheck(v,stringlib_funcs[i].nparamscheck,stringlib_funcs[i].typemask);
+        sq_setnativeclosurename(v,-1,stringlib_funcs[i].name);
+        sq_newslot(v,-3,SQFalse);
+        i++;
+    }
+    return 1;
+}

+ 146 - 146
sqstdlib/sqstdsystem.cpp

@@ -1,146 +1,146 @@
-/* see copyright notice in squirrel.h */
-#include <squirrel.h>
-#include <time.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sqstdsystem.h>
-
-#ifdef SQUNICODE
-#include <wchar.h>
-#define scgetenv _wgetenv
-#define scsystem _wsystem
-#define scasctime _wasctime
-#define scremove _wremove
-#define screname _wrename
-#else
-#define scgetenv getenv
-#define scsystem system
-#define scasctime asctime
-#define scremove remove
-#define screname rename
-#endif
-
-static SQInteger _system_getenv(HSQUIRRELVM v)
-{
-	const SQChar *s;
-	if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){
-        sq_pushstring(v,scgetenv(s),-1);
-		return 1;
-	}
-	return 0;
-}
-
-
-static SQInteger _system_system(HSQUIRRELVM v)
-{
-	const SQChar *s;
-	if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){
-		sq_pushinteger(v,scsystem(s));
-		return 1;
-	}
-	return sq_throwerror(v,_SC("wrong param"));
-}
-
-
-static SQInteger _system_clock(HSQUIRRELVM v)
-{
-	sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC);
-	return 1;
-}
-
-static SQInteger _system_time(HSQUIRRELVM v)
-{
-	SQInteger t = (SQInteger)time(NULL);
-	sq_pushinteger(v,t);
-	return 1;
-}
-
-static SQInteger _system_remove(HSQUIRRELVM v)
-{
-	const SQChar *s;
-	sq_getstring(v,2,&s);
-	if(scremove(s)==-1)
-		return sq_throwerror(v,_SC("remove() failed"));
-	return 0;
-}
-
-static SQInteger _system_rename(HSQUIRRELVM v)
-{
-	const SQChar *oldn,*newn;
-	sq_getstring(v,2,&oldn);
-	sq_getstring(v,3,&newn);
-	if(screname(oldn,newn)==-1)
-		return sq_throwerror(v,_SC("rename() failed"));
-	return 0;
-}
-
-static void _set_integer_slot(HSQUIRRELVM v,const SQChar *name,SQInteger val)
-{
-	sq_pushstring(v,name,-1);
-	sq_pushinteger(v,val);
-	sq_rawset(v,-3);
-}
-
-static SQInteger _system_date(HSQUIRRELVM v)
-{
-	time_t t;
-	SQInteger it;
-	SQInteger format = 'l';
-	if(sq_gettop(v) > 1) {
-		sq_getinteger(v,2,&it);
-		t = it;
-		if(sq_gettop(v) > 2) {
-			sq_getinteger(v,3,(SQInteger*)&format);
-		}
-	}
-	else {
-		time(&t);
-	}
-	tm *date;
-    if(format == 'u')
-		date = gmtime(&t);
-	else
-		date = localtime(&t);
-	if(!date)
-		return sq_throwerror(v,_SC("crt api failure"));
-	sq_newtable(v);
-	_set_integer_slot(v, _SC("sec"), date->tm_sec);
-    _set_integer_slot(v, _SC("min"), date->tm_min);
-    _set_integer_slot(v, _SC("hour"), date->tm_hour);
-    _set_integer_slot(v, _SC("day"), date->tm_mday);
-    _set_integer_slot(v, _SC("month"), date->tm_mon);
-    _set_integer_slot(v, _SC("year"), date->tm_year+1900);
-    _set_integer_slot(v, _SC("wday"), date->tm_wday);
-    _set_integer_slot(v, _SC("yday"), date->tm_yday);
-	return 1;
-}
-
-
-
-#define _DECL_FUNC(name,nparams,pmask) {_SC(#name),_system_##name,nparams,pmask}
-static SQRegFunction systemlib_funcs[]={
-	_DECL_FUNC(getenv,2,_SC(".s")),
-	_DECL_FUNC(system,2,_SC(".s")),
-	_DECL_FUNC(clock,0,NULL),
-	_DECL_FUNC(time,1,NULL),
-	_DECL_FUNC(date,-1,_SC(".nn")),
-	_DECL_FUNC(remove,2,_SC(".s")),
-	_DECL_FUNC(rename,3,_SC(".ss")),
-	{0,0}
-};
-#undef _DECL_FUNC
-
-SQInteger sqstd_register_systemlib(HSQUIRRELVM v)
-{
-	SQInteger i=0;
-	while(systemlib_funcs[i].name!=0)
-	{
-		sq_pushstring(v,systemlib_funcs[i].name,-1);
-		sq_newclosure(v,systemlib_funcs[i].f,0);
-		sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask);
-		sq_setnativeclosurename(v,-1,systemlib_funcs[i].name);
-		sq_newslot(v,-3,SQFalse);
-		i++;
-	}
-	return 1;
-}
+/* see copyright notice in squirrel.h */
+#include <squirrel.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sqstdsystem.h>
+
+#ifdef SQUNICODE
+#include <wchar.h>
+#define scgetenv _wgetenv
+#define scsystem _wsystem
+#define scasctime _wasctime
+#define scremove _wremove
+#define screname _wrename
+#else
+#define scgetenv getenv
+#define scsystem system
+#define scasctime asctime
+#define scremove remove
+#define screname rename
+#endif
+
+static SQInteger _system_getenv(HSQUIRRELVM v)
+{
+    const SQChar *s;
+    if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){
+        sq_pushstring(v,scgetenv(s),-1);
+        return 1;
+    }
+    return 0;
+}
+
+
+static SQInteger _system_system(HSQUIRRELVM v)
+{
+    const SQChar *s;
+    if(SQ_SUCCEEDED(sq_getstring(v,2,&s))){
+        sq_pushinteger(v,scsystem(s));
+        return 1;
+    }
+    return sq_throwerror(v,_SC("wrong param"));
+}
+
+
+static SQInteger _system_clock(HSQUIRRELVM v)
+{
+    sq_pushfloat(v,((SQFloat)clock())/(SQFloat)CLOCKS_PER_SEC);
+    return 1;
+}
+
+static SQInteger _system_time(HSQUIRRELVM v)
+{
+    SQInteger t = (SQInteger)time(NULL);
+    sq_pushinteger(v,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 const SQRegFunction systemlib_funcs[]={
+    _DECL_FUNC(getenv,2,_SC(".s")),
+    _DECL_FUNC(system,2,_SC(".s")),
+    _DECL_FUNC(clock,0,NULL),
+    _DECL_FUNC(time,1,NULL),
+    _DECL_FUNC(date,-1,_SC(".nn")),
+    _DECL_FUNC(remove,2,_SC(".s")),
+    _DECL_FUNC(rename,3,_SC(".ss")),
+    {0,0}
+};
+#undef _DECL_FUNC
+
+SQInteger sqstd_register_systemlib(HSQUIRRELVM v)
+{
+    SQInteger i=0;
+    while(systemlib_funcs[i].name!=0)
+    {
+        sq_pushstring(v,systemlib_funcs[i].name,-1);
+        sq_newclosure(v,systemlib_funcs[i].f,0);
+        sq_setparamscheck(v,systemlib_funcs[i].nparamscheck,systemlib_funcs[i].typemask);
+        sq_setnativeclosurename(v,-1,systemlib_funcs[i].name);
+        sq_newslot(v,-3,SQFalse);
+        i++;
+    }
+    return 1;
+}

+ 52 - 52
squirrel/Makefile

@@ -1,52 +1,52 @@
-SQUIRREL= ..
-
-
-OUT= $(SQUIRREL)/lib/libsquirrel.a
-INCZ= -I$(SQUIRREL)/include -I. -Iinclude
-DEFS= 
-LIB=	
-
-OBJS= \
-	sqapi.o \
-	sqbaselib.o \
-	sqfuncstate.o \
-	sqdebug.o \
-	sqlexer.o \
-	sqobject.o \
-	sqcompiler.o \
-	sqstate.o \
-	sqtable.o \
-	sqmem.o \
-	sqvm.o \
-	sqclass.o
-	
-SRCS= \
-	sqapi.cpp \
-	sqbaselib.cpp \
-	sqfuncstate.cpp \
-	sqdebug.cpp \
-	sqlexer.cpp \
-	sqobject.cpp \
-	sqcompiler.cpp \
-	sqstate.cpp \
-	sqtable.cpp \
-	sqmem.cpp \
-	sqvm.cpp \
-	sqclass.cpp
-
-	
-	
-sq32:
-	gcc -O2 -fno-exceptions -fno-rtti -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ) $(DEFS)
-	ar rc $(OUT) *.o
-	rm *.o
-
-sqprof:
-	gcc -O2 -pg -fno-exceptions -fno-rtti -pie -gstabs -g3 -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ) $(DEFS)
-	ar rc $(OUT) *.o
-	rm *.o
-
-sq64:
-	gcc -O2 -m64 -D_SQ64 -fno-exceptions -fno-rtti -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ) $(DEFS)
-	ar rc $(OUT) *.o
-	rm *.o
+SQUIRREL= ..
+
+
+OUT= $(SQUIRREL)/lib/libsquirrel.a
+INCZ= -I$(SQUIRREL)/include -I. -Iinclude
+DEFS=
+LIB=
+
+OBJS= \
+	sqapi.o \
+	sqbaselib.o \
+	sqfuncstate.o \
+	sqdebug.o \
+	sqlexer.o \
+	sqobject.o \
+	sqcompiler.o \
+	sqstate.o \
+	sqtable.o \
+	sqmem.o \
+	sqvm.o \
+	sqclass.o
+
+SRCS= \
+	sqapi.cpp \
+	sqbaselib.cpp \
+	sqfuncstate.cpp \
+	sqdebug.cpp \
+	sqlexer.cpp \
+	sqobject.cpp \
+	sqcompiler.cpp \
+	sqstate.cpp \
+	sqtable.cpp \
+	sqmem.cpp \
+	sqvm.cpp \
+	sqclass.cpp
+
+
+
+sq32:
+	gcc -O2 -fno-exceptions -fno-rtti -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ) $(DEFS)
+	ar rc $(OUT) *.o
+	rm *.o
+
+sqprof:
+	gcc -O2 -pg -fno-exceptions -fno-rtti -pie -gstabs -g3 -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ) $(DEFS)
+	ar rc $(OUT) *.o
+	rm *.o
+
+sq64:
+	gcc -O2 -m64 -D_SQ64 -fno-exceptions -fno-rtti -Wall -fno-strict-aliasing -c $(SRCS) $(INCZ) $(DEFS)
+	ar rc $(OUT) *.o
+	rm *.o

+ 1602 - 1602
squirrel/sqapi.cpp

@@ -1,1602 +1,1602 @@
-/*
-	see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include "sqvm.h"
-#include "sqstring.h"
-#include "sqtable.h"
-#include "sqarray.h"
-#include "sqfuncproto.h"
-#include "sqclosure.h"
-#include "squserdata.h"
-#include "sqcompiler.h"
-#include "sqfuncstate.h"
-#include "sqclass.h"
-
-static bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPtr **o)
-{
-	*o = &stack_get(v,idx);
-	if(type(**o) != type){
-		SQObjectPtr oval = v->PrintObjVal(**o);
-		v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval));
-		return false;
-	}
-	return true;
-}
-
-#define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; }
-
-#define sq_aux_paramscheck(v,count) \
-{ \
-	if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\
-}		
-
-
-SQInteger sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type)
-{
-	SQUnsignedInteger buf_size = 100 *sizeof(SQChar);
-	scsprintf(_ss(v)->GetScratchPad(buf_size), buf_size, _SC("unexpected type %s"), IdType2Name(type));
-	return sq_throwerror(v, _ss(v)->GetScratchPad(-1));
-}
-
-HSQUIRRELVM sq_open(SQInteger initialstacksize)
-{
-	SQSharedState *ss;
-	SQVM *v;
-	sq_new(ss, SQSharedState);
-	ss->Init();
-	v = (SQVM *)SQ_MALLOC(sizeof(SQVM));
-	new (v) SQVM(ss);
-	ss->_root_vm = v;
-	if(v->Init(NULL, initialstacksize)) {
-		return v;
-	} else {
-		sq_delete(v, SQVM);
-		return NULL;
-	}
-	return v;
-}
-
-HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize)
-{
-	SQSharedState *ss;
-	SQVM *v;
-	ss=_ss(friendvm);
-	
-	v= (SQVM *)SQ_MALLOC(sizeof(SQVM));
-	new (v) SQVM(ss);
-	
-	if(v->Init(friendvm, initialstacksize)) {
-		friendvm->Push(v);
-		return v;
-	} else {
-		sq_delete(v, SQVM);
-		return NULL;
-	}
-}
-
-SQInteger sq_getvmstate(HSQUIRRELVM v)
-{
-	if(v->_suspended)
-		return SQ_VMSTATE_SUSPENDED;
-	else { 
-		if(v->_callsstacksize != 0) return SQ_VMSTATE_RUNNING;
-		else return SQ_VMSTATE_IDLE;
-	}
-}
-
-void sq_seterrorhandler(HSQUIRRELVM v)
-{
-	SQObject o = stack_get(v, -1);
-	if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
-		v->_errorhandler = o;
-		v->Pop();
-	}
-}
-
-void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook)
-{
-	v->_debughook_native = hook;
-	v->_debughook_closure.Null();
-	v->_debughook = hook?true:false;
-}
-
-void sq_setdebughook(HSQUIRRELVM v)
-{
-	SQObject o = stack_get(v,-1);
-	if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
-		v->_debughook_closure = o;
-		v->_debughook_native = NULL;
-		v->_debughook = !sq_isnull(o);
-		v->Pop();
-	}
-}
-
-void sq_close(HSQUIRRELVM v)
-{
-	SQSharedState *ss = _ss(v);
-	_thread(ss->_root_vm)->Finalize();
-	sq_delete(ss, SQSharedState);
-}
-
-SQInteger sq_getversion()
-{
-	return SQUIRREL_VERSION_NUMBER;
-}
-
-SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror)
-{
-	SQObjectPtr o;
-#ifndef NO_COMPILER
-	if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) {
-		v->Push(SQClosure::Create(_ss(v), _funcproto(o), _table(v->_roottable)->GetWeakRef(OT_TABLE)));
-		return SQ_OK;
-	}
-	return SQ_ERROR;
-#else
-	return sq_throwerror(v,_SC("this is a no compiler build"));
-#endif
-}
-
-void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable)
-{
-	_ss(v)->_debuginfo = enable?true:false;
-}
-
-void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable)
-{
-	_ss(v)->_notifyallexceptions = enable?true:false;
-}
-
-void sq_addref(HSQUIRRELVM v,HSQOBJECT *po)
-{
-	if(!ISREFCOUNTED(type(*po))) return;
-#ifdef NO_GARBAGE_COLLECTOR
-	__AddRef(po->_type,po->_unVal);
-#else
-	_ss(v)->_refs_table.AddRef(*po);
-#endif
-}
-
-SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po)
-{
-	if(!ISREFCOUNTED(type(*po))) return 0;
-#ifdef NO_GARBAGE_COLLECTOR
-   return po->_unVal.pRefCounted->_uiRef; 
-#else
-   return _ss(v)->_refs_table.GetRefCount(*po); 
-#endif 
-}
-
-SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)
-{
-	if(!ISREFCOUNTED(type(*po))) return SQTrue;
-#ifdef NO_GARBAGE_COLLECTOR
-	bool ret = (po->_unVal.pRefCounted->_uiRef <= 1) ? SQTrue : SQFalse;
-	__Release(po->_type,po->_unVal);
-	return ret; //the ret val doesn't work(and cannot be fixed)
-#else
-	return _ss(v)->_refs_table.Release(*po);
-#endif
-}
-
-SQUnsignedInteger sq_getvmrefcount(HSQUIRRELVM v, const HSQOBJECT *po)
-{
-	if (!ISREFCOUNTED(type(*po))) return 0;
-	return po->_unVal.pRefCounted->_uiRef;
-}
-
-const SQChar *sq_objtostring(const HSQOBJECT *o) 
-{
-	if(sq_type(*o) == OT_STRING) {
-		return _stringval(*o);
-	}
-	return NULL;
-}
-
-SQInteger sq_objtointeger(const HSQOBJECT *o) 
-{
-	if(sq_isnumeric(*o)) {
-		return tointeger(*o);
-	}
-	return 0;
-}
-
-SQFloat sq_objtofloat(const HSQOBJECT *o) 
-{
-	if(sq_isnumeric(*o)) {
-		return tofloat(*o);
-	}
-	return 0;
-}
-
-SQBool sq_objtobool(const HSQOBJECT *o) 
-{
-	if(sq_isbool(*o)) {
-		return _integer(*o);
-	}
-	return SQFalse;
-}
-
-SQUserPointer sq_objtouserpointer(const HSQOBJECT *o)
-{
-	if(sq_isuserpointer(*o)) {
-		return _userpointer(*o);
-	}
-	return 0;
-}
-
-void sq_pushnull(HSQUIRRELVM v)
-{
-	v->PushNull();
-}
-
-void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len)
-{
-	if(s)
-		v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len)));
-	else v->PushNull();
-}
-
-void sq_pushinteger(HSQUIRRELVM v,SQInteger n)
-{
-	v->Push(n);
-}
-
-void sq_pushbool(HSQUIRRELVM v,SQBool b)
-{
-	v->Push(b?true:false);
-}
-
-void sq_pushfloat(HSQUIRRELVM v,SQFloat n)
-{
-	v->Push(n);
-}
-
-void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p)
-{
-	v->Push(p);
-}
-
-void sq_pushthread(HSQUIRRELVM v, HSQUIRRELVM thread)
-{
-	v->Push(thread);
-}
-
-SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size)
-{
-	SQUserData *ud = SQUserData::Create(_ss(v), size + SQ_ALIGNMENT);
-	v->Push(ud);
-	return (SQUserPointer)sq_aligning(ud + 1);
-}
-
-void sq_newtable(HSQUIRRELVM v)
-{
-	v->Push(SQTable::Create(_ss(v), 0));	
-}
-
-void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity)
-{
-	v->Push(SQTable::Create(_ss(v), initialcapacity));	
-}
-
-void sq_newarray(HSQUIRRELVM v,SQInteger size)
-{
-	v->Push(SQArray::Create(_ss(v), size));	
-}
-
-SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase)
-{
-	SQClass *baseclass = NULL;
-	if(hasbase) {
-		SQObjectPtr &base = stack_get(v,-1);
-		if(type(base) != OT_CLASS)
-			return sq_throwerror(v,_SC("invalid base type"));
-		baseclass = _class(base);
-	}
-	SQClass *newclass = SQClass::Create(_ss(v), baseclass);
-	if(baseclass) v->Pop();
-	v->Push(newclass);	
-	return SQ_OK;
-}
-
-SQBool sq_instanceof(HSQUIRRELVM v)
-{
-	SQObjectPtr &inst = stack_get(v,-1);
-	SQObjectPtr &cl = stack_get(v,-2);
-	if(type(inst) != OT_INSTANCE || type(cl) != OT_CLASS)
-		return sq_throwerror(v,_SC("invalid param type"));
-	return _instance(inst)->InstanceOf(_class(cl))?SQTrue:SQFalse;
-}
-
-SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx)
-{
-	sq_aux_paramscheck(v,2);
-	SQObjectPtr *arr;
-	_GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
-	_array(*arr)->Append(v->GetUp(-1));
-	v->Pop();
-	return SQ_OK;
-}
-
-SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
-{
-	sq_aux_paramscheck(v, 1);
-	SQObjectPtr *arr;
-	_GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
-	if(_array(*arr)->Size() > 0) {
-        if(pushval != 0){ v->Push(_array(*arr)->Top()); }
-		_array(*arr)->Pop();
-		return SQ_OK;
-	}
-	return sq_throwerror(v, _SC("empty array"));
-}
-
-SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize)
-{
-	sq_aux_paramscheck(v,1);
-	SQObjectPtr *arr;
-	_GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
-	if(newsize >= 0) {
-		_array(*arr)->Resize(newsize);
-		return SQ_OK;
-	}
-	return sq_throwerror(v,_SC("negative size"));
-}
-
-
-SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx)
-{
-	sq_aux_paramscheck(v, 1);
-	SQObjectPtr *o;
-	_GETSAFE_OBJ(v, idx, OT_ARRAY,o);
-	SQArray *arr = _array(*o);
-	if(arr->Size() > 0) {
-		SQObjectPtr t;
-		SQInteger size = arr->Size();
-		SQInteger n = size >> 1; size -= 1;
-		for(SQInteger i = 0; i < n; i++) {
-			t = arr->_values[i];
-			arr->_values[i] = arr->_values[size-i];
-			arr->_values[size-i] = t;
-		}
-		return SQ_OK;
-	}
-	return SQ_OK;
-}
-
-SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx)
-{
-	sq_aux_paramscheck(v, 1); 
-	SQObjectPtr *arr;
-	_GETSAFE_OBJ(v, idx, OT_ARRAY,arr); 
-	return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range")); 
-}
-
-SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos)
-{
-	sq_aux_paramscheck(v, 1); 
-	SQObjectPtr *arr;
-	_GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
-	SQRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));
-	v->Pop();
-	return ret;
-}
-
-void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars)
-{
-	SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func,nfreevars);
-	nc->_nparamscheck = 0;
-	for(SQUnsignedInteger i = 0; i < nfreevars; i++) {
-		nc->_outervalues[i] = v->Top();
-		v->Pop();
-	}
-	v->Push(SQObjectPtr(nc));	
-}
-
-SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars)
-{
-	SQObject o = stack_get(v, idx);
-	if(type(o) == OT_CLOSURE) {
-		SQClosure *c = _closure(o);
-		SQFunctionProto *proto = c->_function;
-		*nparams = (SQUnsignedInteger)proto->_nparameters;
-		*nfreevars = (SQUnsignedInteger)proto->_noutervalues;
-		return SQ_OK;
-	}
-	else if(type(o) == OT_NATIVECLOSURE)
-	{
-		SQNativeClosure *c = _nativeclosure(o);
-		*nparams = (SQUnsignedInteger)c->_nparamscheck;
-		*nfreevars = c->_noutervalues;
-		return SQ_OK;
-	}
-	return sq_throwerror(v,_SC("the object is not a closure"));
-}
-
-SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name)
-{
-	SQObject o = stack_get(v, idx);
-	if(sq_isnativeclosure(o)) {
-		SQNativeClosure *nc = _nativeclosure(o);
-		nc->_name = SQString::Create(_ss(v),name);
-		return SQ_OK;
-	}
-	return sq_throwerror(v,_SC("the object is not a nativeclosure"));
-}
-
-SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask)
-{
-	SQObject o = stack_get(v, -1);
-	if(!sq_isnativeclosure(o))
-		return sq_throwerror(v, _SC("native closure expected"));
-	SQNativeClosure *nc = _nativeclosure(o);
-	nc->_nparamscheck = nparamscheck;
-	if(typemask) {
-		SQIntVec res;
-		if(!CompileTypemask(res, typemask))
-			return sq_throwerror(v, _SC("invalid typemask"));
-		nc->_typecheck.copy(res);
-	}
-	else {
-		nc->_typecheck.resize(0);
-	}
-	if(nparamscheck == SQ_MATCHTYPEMASKSTRING) {
-		nc->_nparamscheck = nc->_typecheck.size();
-	}
-	return SQ_OK;
-}
-
-SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &o = stack_get(v,idx);
-	if(!sq_isnativeclosure(o) &&
-		!sq_isclosure(o))
-		return sq_throwerror(v,_SC("the target is not a closure"));
-    SQObjectPtr &env = stack_get(v,-1);
-	if(!sq_istable(env) &&
-		!sq_isarray(env) &&
-		!sq_isclass(env) &&
-		!sq_isinstance(env))
-		return sq_throwerror(v,_SC("invalid environment"));
-	SQWeakRef *w = _refcounted(env)->GetWeakRef(type(env));
-	SQObjectPtr ret;
-	if(sq_isclosure(o)) {
-		SQClosure *c = _closure(o)->Clone();
-		__ObjRelease(c->_env);
-		c->_env = w;
-		__ObjAddRef(c->_env);
-		if(_closure(o)->_base) {
-			c->_base = _closure(o)->_base;
-			__ObjAddRef(c->_base);
-		}
-		ret = c;
-	}
-	else { //then must be a native closure
-		SQNativeClosure *c = _nativeclosure(o)->Clone();
-		__ObjRelease(c->_env);
-		c->_env = w;
-		__ObjAddRef(c->_env);
-		ret = c;
-	}
-	v->Pop();
-	v->Push(ret);
-	return SQ_OK;
-}
-
-SQRESULT sq_getclosurename(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"));
-	if(sq_isnativeclosure(o))
-	{
-		v->Push(_nativeclosure(o)->_name);
-	}
-	else { //closure
-		v->Push(_closure(o)->_function->_name);
-	}
-	return SQ_OK;
-}
-
-SQRESULT sq_setclosureroot(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &c = stack_get(v,idx);
-	SQObject o = stack_get(v, -1);
-	if(!sq_isclosure(c)) return sq_throwerror(v, _SC("closure expected"));
-	if(sq_istable(o)) {
-		_closure(c)->SetRoot(_table(o)->GetWeakRef(OT_TABLE));
-		v->Pop();
-		return SQ_OK;
-	}
-	return sq_throwerror(v, _SC("ivalid type"));
-}
-
-SQRESULT sq_getclosureroot(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &c = stack_get(v,idx);
-	if(!sq_isclosure(c)) return sq_throwerror(v, _SC("closure expected"));
-	v->Push(_closure(c)->_root->_obj);
-	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_setsharedforeignptr(HSQUIRRELVM v,SQUserPointer p)
-{
-	_ss(v)->_foreignptr = p;
-}
-
-SQUserPointer sq_getsharedforeignptr(HSQUIRRELVM v)
-{
-	return _ss(v)->_foreignptr;
-}
-
-void sq_setvmreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook)
-{
-	v->_releasehook = hook;
-}
-
-SQRELEASEHOOK sq_getvmreleasehook(HSQUIRRELVM v)
-{
-	return v->_releasehook;
-}
-
-void sq_setsharedreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook)
-{
-	_ss(v)->_releasehook = hook;
-}
-
-SQRELEASEHOOK sq_getsharedreleasehook(HSQUIRRELVM v)
-{
-	return _ss(v)->_releasehook;
-}
-
-void sq_push(HSQUIRRELVM v,SQInteger idx)
-{
-	v->Push(stack_get(v, idx));
-}
-
-SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx)
-{
-	return type(stack_get(v, idx));
-}
-
-SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &o = stack_get(v, idx);
-	SQObjectPtr res;
-	if(!v->TypeOf(o,res)) {
-		return SQ_ERROR;
-	}
-	v->Push(res);
-	return SQ_OK;
-}
-
-SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &o = stack_get(v, idx);
-	SQObjectPtr res;
-	if(!v->ToString(o,res)) {
-		return SQ_ERROR;
-	}
-	v->Push(res);
-	return SQ_OK;
-}
-
-void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b)
-{
-	SQObjectPtr &o = stack_get(v, idx);
-	*b = SQVM::IsFalse(o)?SQFalse:SQTrue;
-}
-
-SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i)
-{
-	SQObjectPtr &o = stack_get(v, idx);
-	if(sq_isnumeric(o)) {
-		*i = tointeger(o);
-		return SQ_OK;
-	}
-	return SQ_ERROR;
-}
-
-SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f)
-{
-	SQObjectPtr &o = stack_get(v, idx);
-	if(sq_isnumeric(o)) {
-		*f = tofloat(o);
-		return SQ_OK;
-	}
-	return SQ_ERROR;
-}
-
-SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b)
-{
-	SQObjectPtr &o = stack_get(v, idx);
-	if(sq_isbool(o)) {
-		*b = _integer(o);
-		return SQ_OK;
-	}
-	return SQ_ERROR;
-}
-
-SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c)
-{
-	SQObjectPtr *o = NULL;
-	_GETSAFE_OBJ(v, idx, OT_STRING,o);
-	*c = _stringval(*o);
-	return SQ_OK;
-}
-
-SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread)
-{
-	SQObjectPtr *o = NULL;
-	_GETSAFE_OBJ(v, idx, OT_THREAD,o);
-	*thread = _thread(*o);
-	return SQ_OK;
-}
-
-SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &o = stack_get(v,idx);
-	v->PushNull();
-	if(!v->Clone(o, stack_get(v, -1))){
-		v->Pop();
-		return SQ_ERROR;
-	}
-	return SQ_OK;
-}
-
-SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx)
-{
-	SQObjectPtr &o = stack_get(v, idx);
-	SQObjectType type = type(o);
-	switch(type) {
-	case OT_STRING:		return _string(o)->_len;
-	case OT_TABLE:		return _table(o)->CountUsed();
-	case OT_ARRAY:		return _array(o)->Size();
-	case OT_USERDATA:	return _userdata(o)->_size;
-	case OT_INSTANCE:	return _instance(o)->_class->_udsize;
-	case OT_CLASS:		return _class(o)->_udsize;
-	default:
-		return sq_aux_invalidtype(v, type);
-	}
-}
-
-SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx)
-{
-	SQObjectPtr &o = stack_get(v, idx);
-	return HashObj(o);
-}
-
-SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag)
-{
-	SQObjectPtr *o = NULL;
-	_GETSAFE_OBJ(v, idx, OT_USERDATA,o);
-	(*p) = _userdataval(*o);
-	if(typetag) *typetag = _userdata(*o)->_typetag;
-	return SQ_OK;
-}
-
-SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag)
-{
-	SQObjectPtr &o = stack_get(v,idx);
-	switch(type(o)) {
-		case OT_USERDATA:	_userdata(o)->_typetag = typetag;	break;
-		case OT_CLASS:		_class(o)->_typetag = typetag;		break;
-		default:			return sq_throwerror(v,_SC("invalid object type"));
-	}
-	return SQ_OK;
-}
-
-SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag)
-{
-  switch(type(*o)) {
-    case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break;
-    case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break;
-    case OT_CLASS:    *typetag = _class(*o)->_typetag; break;
-    default: return SQ_ERROR;
-  }
-  return SQ_OK;
-}
-
-SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag)
-{
-	SQObjectPtr &o = stack_get(v,idx);
-	if(SQ_FAILED(sq_getobjtypetag(&o,typetag)))
-		return sq_throwerror(v,_SC("invalid object type"));
-	return SQ_OK;
-}
-
-SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p)
-{
-	SQObjectPtr *o = NULL;
-	_GETSAFE_OBJ(v, idx, OT_USERPOINTER,o);
-	(*p) = _userpointer(*o);
-	return SQ_OK;
-}
-
-SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p)
-{
-	SQObjectPtr &o = stack_get(v,idx);
-	if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));
-	_instance(o)->_userpointer = p;
-	return SQ_OK;
-}
-
-SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize)
-{
-	SQObjectPtr &o = stack_get(v,idx);
-	if(type(o) != OT_CLASS) return sq_throwerror(v,_SC("the object is not a class"));
-	if(_class(o)->_locked) return sq_throwerror(v,_SC("the class is locked"));
-	_class(o)->_udsize = udsize;
-	return SQ_OK;
-}
-
-
-SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag)
-{
-	SQObjectPtr &o = stack_get(v,idx);
-	if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));
-	(*p) = _instance(o)->_userpointer;
-	if(typetag != 0) {
-		SQClass *cl = _instance(o)->_class;
-		do{
-			if(cl->_typetag == typetag)
-				return SQ_OK;
-			cl = cl->_base;
-		}while(cl != NULL);
-		return sq_throwerror(v,_SC("invalid type tag"));
-	}
-	return SQ_OK;
-}
-
-SQInteger sq_gettop(HSQUIRRELVM v)
-{
-	return (v->_top) - v->_stackbase;
-}
-
-void sq_settop(HSQUIRRELVM v, SQInteger newtop)
-{
-	SQInteger top = sq_gettop(v);
-	if(top > newtop)
-		sq_pop(v, top - newtop);
-	else
-		while(top++ < newtop) sq_pushnull(v);
-}
-
-void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop)
-{
-	assert(v->_top >= nelemstopop);
-	v->Pop(nelemstopop);
-}
-
-void sq_poptop(HSQUIRRELVM v)
-{
-	assert(v->_top >= 1);
-    v->Pop();
-}
-
-
-void sq_remove(HSQUIRRELVM v, SQInteger idx)
-{
-	v->Remove(idx);
-}
-
-SQInteger sq_cmp(HSQUIRRELVM v)
-{
-	SQInteger res;
-	v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res);
-	return res;
-}
-
-SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic)
-{
-	sq_aux_paramscheck(v, 3);
-	SQObjectPtr &self = stack_get(v, idx);
-	if(type(self) == OT_TABLE || type(self) == OT_CLASS) {
-		SQObjectPtr &key = v->GetUp(-2);
-		if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));
-		v->NewSlot(self, key, v->GetUp(-1),bstatic?true:false);
-		v->Pop(2);
-	}
-	return SQ_OK;
-}
-
-SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
-{
-	sq_aux_paramscheck(v, 2);
-	SQObjectPtr *self;
-	_GETSAFE_OBJ(v, idx, OT_TABLE,self);
-	SQObjectPtr &key = v->GetUp(-1);
-	if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));
-	SQObjectPtr res;
-	if(!v->DeleteSlot(*self, key, res)){
-		v->Pop();
-		return SQ_ERROR;
-	}
-	if(pushval)	v->GetUp(-1) = res;
-	else v->Pop();
-	return SQ_OK;
-}
-
-SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &self = stack_get(v, idx);
-	if(v->Set(self, v->GetUp(-2), v->GetUp(-1),DONT_FALL_BACK)) {
-		v->Pop(2);
-		return SQ_OK;
-	}
-	return SQ_ERROR;
-}
-
-SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &self = stack_get(v, idx);
-	SQObjectPtr &key = v->GetUp(-2);
-	if(type(key) == OT_NULL) {
-		v->Pop(2);
-		return sq_throwerror(v, _SC("null key"));
-	}
-	switch(type(self)) {
-	case OT_TABLE:
-		_table(self)->NewSlot(key, v->GetUp(-1));
-		v->Pop(2);
-		return SQ_OK;
-	break;
-	case OT_CLASS:
-		_class(self)->NewSlot(_ss(v), key, v->GetUp(-1),false);
-		v->Pop(2);
-		return SQ_OK;
-	break;
-	case OT_INSTANCE:
-		if(_instance(self)->Set(key, v->GetUp(-1))) {
-			v->Pop(2);
-			return SQ_OK;
-		}
-	break;
-	case OT_ARRAY:
-		if(v->Set(self, key, 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_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)
-{
-	SQObjectPtr &self = stack_get(v, idx);
-	if(type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));
-	SQObjectPtr &key = v->GetUp(-3);
-	if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null key"));
-	if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,false))
-		return SQ_ERROR;
-	return SQ_OK; 
-}
-
-SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)
-{
-	SQObjectPtr &self = stack_get(v, idx);
-	if(type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));
-	SQObjectPtr &key = v->GetUp(-3);
-	if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null key"));
-	if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,true))
-		return SQ_ERROR;
-	return SQ_OK; 
-}
-
-SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &self = stack_get(v, idx);
-	SQObjectPtr &mt = v->GetUp(-1);
-	SQObjectType type = type(self);
-	switch(type) {
-	case OT_TABLE:
-		if(type(mt) == OT_TABLE) {
-			if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, _SC("delagate cycle")); v->Pop();}
-		else if(type(mt)==OT_NULL) {
-			_table(self)->SetDelegate(NULL); v->Pop(); }
-		else return sq_aux_invalidtype(v,type);
-		break;
-	case OT_USERDATA:
-		if(type(mt)==OT_TABLE) {
-			_userdata(self)->SetDelegate(_table(mt)); v->Pop(); }
-		else if(type(mt)==OT_NULL) {
-			_userdata(self)->SetDelegate(NULL); v->Pop(); }
-		else return sq_aux_invalidtype(v, type);
-		break;
-	default:
-			return sq_aux_invalidtype(v, type);
-		break;
-	}
-	return SQ_OK;
-}
-
-SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
-{
-	sq_aux_paramscheck(v, 2);
-	SQObjectPtr *self;
-	_GETSAFE_OBJ(v, idx, OT_TABLE,self);
-	SQObjectPtr &key = v->GetUp(-1);
-	SQObjectPtr t;
-	if(_table(*self)->Get(key,t)) {
-		_table(*self)->Remove(key);
-	}
-	if(pushval != 0)
-		v->GetUp(-1) = t;
-	else
-		v->Pop();
-	return SQ_OK;
-}
-
-SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &self=stack_get(v,idx);
-	switch(type(self)){
-	case OT_TABLE:
-	case OT_USERDATA:
-		if(!_delegable(self)->_delegate){
-			v->PushNull();
-			break;
-		}
-		v->Push(SQObjectPtr(_delegable(self)->_delegate));
-		break;
-	default: return sq_throwerror(v,_SC("wrong type")); break;
-	}
-	return SQ_OK;
-	
-}
-
-SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &self=stack_get(v,idx);
-	SQObjectPtr &obj = v->GetUp(-1);
-	if(v->Get(self,obj,obj,false,DONT_FALL_BACK))
-		return SQ_OK;
-	v->Pop();
-	return SQ_ERROR;
-}
-
-SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &self=stack_get(v,idx);
-	SQObjectPtr &obj = v->GetUp(-1);
-	switch(type(self)) {
-	case OT_TABLE:
-		if(_table(self)->Get(obj,obj))
-			return SQ_OK;
-		break;
-	case OT_CLASS:
-		if(_class(self)->Get(obj,obj))
-			return SQ_OK;
-		break;
-	case OT_INSTANCE:
-		if(_instance(self)->Get(obj,obj))
-			return SQ_OK;
-		break;
-	case OT_ARRAY:{
-		if(sq_isnumeric(obj)){
-			if(_array(self)->Get(tointeger(obj),obj)) {
-				return SQ_OK;
-			}
-		}
-		else {
-			v->Pop();
-			return sq_throwerror(v,_SC("invalid index type for an array"));
-		}
-				  }
-		break;
-	default:
-		v->Pop();
-		return sq_throwerror(v,_SC("rawget works only on array/table/instance and class"));
-	}
-	v->Pop();
-	return sq_throwerror(v,_SC("the index doesn't exist"));
-}
-
-SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po)
-{
-	*po=stack_get(v,idx);
-	return SQ_OK;
-}
-
-const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx)
-{
-	SQUnsignedInteger cstksize=v->_callsstacksize;
-	SQUnsignedInteger lvl=(cstksize-level)-1;
-	SQInteger stackbase=v->_stackbase;
-	if(lvl<cstksize){
-		for(SQUnsignedInteger i=0;i<level;i++){
-			SQVM::CallInfo &ci=v->_callsstack[(cstksize-i)-1];
-			stackbase-=ci._prevstkbase;
-		}
-		SQVM::CallInfo &ci=v->_callsstack[lvl];
-		if(type(ci._closure)!=OT_CLOSURE)
-			return NULL;
-		SQClosure *c=_closure(ci._closure);
-		SQFunctionProto *func=c->_function;
-		if(func->_noutervalues > (SQInteger)idx) {
-			v->Push(*_outer(c->_outervalues[idx])->_valptr);
-			return _stringval(func->_outervalues[idx]._name);
-		}
-		idx -= func->_noutervalues;
-		return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-1);
-	}
-	return NULL;
-}
-
-void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj)
-{
-	v->Push(SQObjectPtr(obj));
-}
-
-void sq_resetobject(HSQOBJECT *po)
-{
-	po->_unVal.pUserPointer=NULL;po->_type=OT_NULL;
-}
-
-SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err)
-{
-	v->_lasterror=SQString::Create(_ss(v),err);
-	return SQ_ERROR;
-}
-
-SQRESULT sq_throwobject(HSQUIRRELVM v)
-{
-	v->_lasterror = v->GetUp(-1);
-	v->Pop();
-	return SQ_ERROR;
-}
-
-
-void sq_reseterror(HSQUIRRELVM v)
-{
-	v->_lasterror.Null();
-}
-
-void sq_getlasterror(HSQUIRRELVM v)
-{
-	v->Push(v->_lasterror);
-}
-
-SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize)
-{
-	if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) {
-		if(v->_nmetamethodscall) {
-			return sq_throwerror(v,_SC("cannot resize stack while in  a metamethod"));
-		}
-		v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size()));
-	}
-	return SQ_OK;
-}
-
-SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror)
-{
-	if (type(v->GetUp(-1)) == OT_GENERATOR)
-	{
-		v->PushNull(); //retval
-		if (!v->Execute(v->GetUp(-2), 0, v->_top, v->GetUp(-1), raiseerror, SQVM::ET_RESUME_GENERATOR))
-		{v->Raise_Error(v->_lasterror); return SQ_ERROR;}
-		if(!retval)
-			v->Pop();
-		return SQ_OK;
-	}
-	return sq_throwerror(v,_SC("only generators can be resumed"));
-}
-
-SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror)
-{
-	SQObjectPtr res;
-	if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){
-
-		if(!v->_suspended) {
-			v->Pop(params);//pop closure and args
-		}
-		if(retval){
-			v->Push(res); return SQ_OK;
-		}
-		return SQ_OK;
-	}
-	else {
-		v->Pop(params);
-		return SQ_ERROR;
-	}
-	if(!v->_suspended)
-		v->Pop(params);
-	return sq_throwerror(v,_SC("call failed"));
-}
-
-SQRESULT sq_suspendvm(HSQUIRRELVM v)
-{
-	return v->Suspend();
-}
-
-SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval,SQBool raiseerror,SQBool throwerror)
-{
-	SQObjectPtr ret;
-	if(!v->_suspended)
-		return sq_throwerror(v,_SC("cannot resume a vm that is not running any code"));
-	SQInteger target = v->_suspended_target;
-	if(wakeupret) {
-		if(target != -1) {
-			v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval
-		}
-		v->Pop();
-	} else if(target != -1) { v->GetAt(v->_stackbase+v->_suspended_target).Null(); }
-	SQObjectPtr dummy;
-	if(!v->Execute(dummy,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM)) {
-		return SQ_ERROR;
-	}
-	if(retval)
-		v->Push(ret);
-	return SQ_OK;
-}
-
-void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook)
-{
-	if(sq_gettop(v) >= 1){
-		SQObjectPtr &ud=stack_get(v,idx);
-		switch( type(ud) ) {
-		case OT_USERDATA:	_userdata(ud)->_hook = hook;	break;
-		case OT_INSTANCE:	_instance(ud)->_hook = hook;	break;
-		case OT_CLASS:		_class(ud)->_hook = hook;		break;
-		default: break; //shutup compiler
-		}
-	}
-}
-
-SQRELEASEHOOK sq_getreleasehook(HSQUIRRELVM v,SQInteger idx)
-{
-	if(sq_gettop(v) >= 1){
-		SQObjectPtr &ud=stack_get(v,idx);
-		switch( type(ud) ) {
-		case OT_USERDATA:	return _userdata(ud)->_hook;	break;
-		case OT_INSTANCE:	return _instance(ud)->_hook;	break;
-		case OT_CLASS:		return _class(ud)->_hook;		break;
-		default: break; //shutup compiler
-		}
-	}
-	return NULL;
-}
-
-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(_closure(*o)->_function->_noutervalues) 
-		return sq_throwerror(v,_SC("a closure with free valiables bound it cannot be serialized"));
-	if(w(up,&tag,2) != 2)
-		return sq_throwerror(v,_SC("io error"));
-	if(!_closure(*o)->Save(v,up,w))
-		return SQ_ERROR;
-	return SQ_OK;
-}
-
-SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)
-{
-	SQObjectPtr closure;
-	
-	unsigned short tag;
-	if(r(up,&tag,2) != 2)
-		return sq_throwerror(v,_SC("io error"));
-	if(tag != SQ_BYTECODE_STREAM_TAG)
-		return sq_throwerror(v,_SC("invalid stream"));
-	if(!SQClosure::Load(v,up,r,closure))
-		return SQ_ERROR;
-	v->Push(closure);
-	return SQ_OK;
-}
-
-SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)
-{
-	return _ss(v)->GetScratchPad(minsize);
-}
-
-SQRESULT sq_resurrectunreachable(HSQUIRRELVM v)
-{
-#ifndef NO_GARBAGE_COLLECTOR
-	_ss(v)->ResurrectUnreachable(v);
-	return SQ_OK;
-#else
-	return sq_throwerror(v,_SC("sq_resurrectunreachable requires a garbage collector build"));
-#endif
-}
-
-SQInteger sq_collectgarbage(HSQUIRRELVM v)
-{
-#ifndef NO_GARBAGE_COLLECTOR
-	return _ss(v)->CollectGarbage(v);
-#else
-	return -1;
-#endif
-}
-
-SQRESULT sq_getcallee(HSQUIRRELVM v)
-{
-	if(v->_callsstacksize > 1)
-	{
-		v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);
-		return SQ_OK;
-	}
-	return sq_throwerror(v,_SC("no closure in the calls stack"));
-}
-
-const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
-{
-	SQObjectPtr &self=stack_get(v,idx);
-	const SQChar *name = NULL;
-	switch(type(self))
-	{
-	case OT_CLOSURE:{
-		SQClosure *clo = _closure(self);
-		SQFunctionProto *fp = clo->_function;
-		if(((SQUnsignedInteger)fp->_noutervalues) > nval) {
-			v->Push(*(_outer(clo->_outervalues[nval])->_valptr));
-			SQOuterVar &ov = fp->_outervalues[nval];
-			name = _stringval(ov._name);
-		}
-					}
-		break;
-	case OT_NATIVECLOSURE:{
-		SQNativeClosure *clo = _nativeclosure(self);
-		if(clo->_noutervalues > nval) {
-			v->Push(clo->_outervalues[nval]);
-			name = _SC("@NATIVE");
-		}
-						  }
-		break;
-	default: break; //shutup compiler
-	}
-	return name;
-}
-
-SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
-{
-	SQObjectPtr &self=stack_get(v,idx);
-	switch(type(self))
-	{
-	case OT_CLOSURE:{
-		SQFunctionProto *fp = _closure(self)->_function;
-		if(((SQUnsignedInteger)fp->_noutervalues) > nval){
-			*(_outer(_closure(self)->_outervalues[nval])->_valptr) = stack_get(v,-1);
-		}
-		else return sq_throwerror(v,_SC("invalid free var index"));
-					}
-		break;
-	case OT_NATIVECLOSURE:
-		if(_nativeclosure(self)->_noutervalues > nval){
-			_nativeclosure(self)->_outervalues[nval] = stack_get(v,-1);
-		}
-		else return sq_throwerror(v,_SC("invalid free var index"));
-		break;
-	default:
-		return sq_aux_invalidtype(v,type(self));
-	}
-	v->Pop();
-	return SQ_OK;
-}
-
-SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr *o = NULL;
-	_GETSAFE_OBJ(v, idx, OT_CLASS,o);
-	SQObjectPtr &key = stack_get(v,-2);
-	SQObjectPtr &val = stack_get(v,-1);
-	SQObjectPtr attrs;
-	if(type(key) == OT_NULL) {
-		attrs = _class(*o)->_attributes;
-		_class(*o)->_attributes = val;
-		v->Pop(2);
-		v->Push(attrs);
-		return SQ_OK;
-	}else if(_class(*o)->GetAttributes(key,attrs)) {
-		_class(*o)->SetAttributes(key,val);
-		v->Pop(2);
-		v->Push(attrs);
-		return SQ_OK;
-	}
-	return sq_throwerror(v,_SC("wrong index"));
-}
-
-SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr *o = NULL;
-	_GETSAFE_OBJ(v, idx, OT_CLASS,o);
-	SQObjectPtr &key = stack_get(v,-1);
-	SQObjectPtr attrs;
-	if(type(key) == OT_NULL) {
-		attrs = _class(*o)->_attributes;
-		v->Pop();
-		v->Push(attrs); 
-		return SQ_OK;
-	}
-	else if(_class(*o)->GetAttributes(key,attrs)) {
-		v->Pop();
-		v->Push(attrs);
-		return SQ_OK;
-	}
-	return sq_throwerror(v,_SC("wrong index"));
-}
-
-SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle)
-{
-	SQObjectPtr *o = NULL;
-	_GETSAFE_OBJ(v, idx, OT_CLASS,o);
-	SQObjectPtr &key = stack_get(v,-1);
-	SQTable *m = _class(*o)->_members;
-	SQObjectPtr val;
-	if(m->Get(key,val)) {
-		handle->_static = _isfield(val) ? SQFalse : SQTrue;
-		handle->_index = _member_idx(val);
-		v->Pop();
-		return SQ_OK;
-	}
-	return sq_throwerror(v,_SC("wrong index"));
-}
-
-SQRESULT _getmemberbyhandle(HSQUIRRELVM v,SQObjectPtr &self,const HSQMEMBERHANDLE *handle,SQObjectPtr *&val)
-{
-	switch(type(self)) {
-		case OT_INSTANCE: {
-				SQInstance *i = _instance(self);
-				if(handle->_static) {
-					SQClass *c = i->_class;
-					val = &c->_methods[handle->_index].val;
-				}
-				else {
-					val = &i->_values[handle->_index];
-					
-				}
-			}
-			break;
-		case OT_CLASS: {
-				SQClass *c = _class(self);
-				if(handle->_static) {
-					val = &c->_methods[handle->_index].val;
-				}
-				else {
-					val = &c->_defaultvalues[handle->_index].val;
-				}
-			}
-			break;
-		default:
-			return sq_throwerror(v,_SC("wrong type(expected class or instance)"));
-	}
-	return SQ_OK;
-}
-
-SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle)
-{
-	SQObjectPtr &self = stack_get(v,idx);
-	SQObjectPtr *val = NULL;
-	if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) {
-		return SQ_ERROR;
-	}
-	v->Push(_realval(*val));
-	return SQ_OK;
-}
-
-SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle)
-{
-	SQObjectPtr &self = stack_get(v,idx);
-	SQObjectPtr &newval = stack_get(v,-1);
-	SQObjectPtr *val = NULL;
-	if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) {
-		return SQ_ERROR;
-	}
-	*val = newval;
-	v->Pop();
-	return SQ_OK;
-}
-
-SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr *o = NULL;
-	_GETSAFE_OBJ(v, idx, OT_CLASS,o);
-	if(_class(*o)->_base)
-		v->Push(SQObjectPtr(_class(*o)->_base));
-	else
-		v->PushNull();
-	return SQ_OK;
-}
-
-SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr *o = NULL;
-	_GETSAFE_OBJ(v, idx, OT_INSTANCE,o);
-	v->Push(SQObjectPtr(_instance(*o)->_class));
-	return SQ_OK;
-}
-
-SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr *o = NULL;
-	_GETSAFE_OBJ(v, idx, OT_CLASS,o);
-	v->Push(_class(*o)->CreateInstance());
-	return SQ_OK;
-}
-
-void sq_weakref(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObject &o=stack_get(v,idx);
-	if(ISREFCOUNTED(type(o))) {
-		v->Push(_refcounted(o)->GetWeakRef(type(o)));
-		return;
-	}
-	v->Push(o);
-}
-
-SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr &o = stack_get(v,idx);
-	if(type(o) != OT_WEAKREF) {
-		return sq_throwerror(v,_SC("the object must be a weakref"));
-	}
-	v->Push(_weakref(o)->_obj);
-	return SQ_OK;
-}
-
-SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t)
-{
-	SQSharedState *ss = _ss(v);
-	switch(t) {
-	case OT_TABLE: v->Push(ss->_table_default_delegate); break;
-	case OT_ARRAY: v->Push(ss->_array_default_delegate); break;
-	case OT_STRING: v->Push(ss->_string_default_delegate); break;
-	case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break;
-	case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break;
-	case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break;
-	case OT_THREAD: v->Push(ss->_thread_default_delegate); break;
-	case OT_CLASS: v->Push(ss->_class_default_delegate); break;
-	case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break;
-	case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break;
-	default: return sq_throwerror(v,_SC("the type doesn't have a default delegate"));
-	}
-	return SQ_OK;
-}
-
-SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx)
-{
-	SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val;
-	if(type(o) == OT_GENERATOR) {
-		return sq_throwerror(v,_SC("cannot iterate a generator"));
-	}
-	int faketojump;
-	if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump))
-		return SQ_ERROR;
-	if(faketojump != 666) {
-		v->Push(realkey);
-		v->Push(val);
-		return SQ_OK;
-	}
-	return SQ_ERROR;
-}
-
-struct BufState{
-	const SQChar *buf;
-	SQInteger ptr;
-	SQInteger size;
-};
-
-SQInteger buf_lexfeed(SQUserPointer file)
-{
-	BufState *buf=(BufState*)file;
-	if(buf->size<(buf->ptr+1))
-		return 0;
-	return buf->buf[buf->ptr++];
-}
-
-SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror) {
-	BufState buf;
-	buf.buf = s;
-	buf.size = size;
-	buf.ptr = 0;
-	return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror);
-}
-
-void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx)
-{
-	dest->Push(stack_get(src,idx));
-}
-
-void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc)
-{
-	_ss(v)->_printfunc = printfunc;
-	_ss(v)->_errorfunc = errfunc;
-}
-
-SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)
-{
-	return _ss(v)->_printfunc;
-}
-
-SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v)
-{
-	return _ss(v)->_errorfunc;
-}
-
-void *sq_malloc(SQUnsignedInteger size)
-{
-	return SQ_MALLOC(size);
-}
-
-void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize)
-{
-	return SQ_REALLOC(p,oldsize,newsize);
-}
-
-void sq_free(void *p,SQUnsignedInteger size)
-{
-	SQ_FREE(p,size);
-}
+/*
+    see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqvm.h"
+#include "sqstring.h"
+#include "sqtable.h"
+#include "sqarray.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+#include "squserdata.h"
+#include "sqcompiler.h"
+#include "sqfuncstate.h"
+#include "sqclass.h"
+
+static bool sq_aux_gettypedarg(HSQUIRRELVM v,SQInteger idx,SQObjectType type,SQObjectPtr **o)
+{
+    *o = &stack_get(v,idx);
+    if(type(**o) != type){
+        SQObjectPtr oval = v->PrintObjVal(**o);
+        v->Raise_Error(_SC("wrong argument type, expected '%s' got '%.50s'"),IdType2Name(type),_stringval(oval));
+        return false;
+    }
+    return true;
+}
+
+#define _GETSAFE_OBJ(v,idx,type,o) { if(!sq_aux_gettypedarg(v,idx,type,&o)) return SQ_ERROR; }
+
+#define sq_aux_paramscheck(v,count) \
+{ \
+    if(sq_gettop(v) < count){ v->Raise_Error(_SC("not enough params in the stack")); return SQ_ERROR; }\
+}
+
+
+SQInteger sq_aux_invalidtype(HSQUIRRELVM v,SQObjectType type)
+{
+    SQUnsignedInteger buf_size = 100 *sizeof(SQChar);
+    scsprintf(_ss(v)->GetScratchPad(buf_size), buf_size, _SC("unexpected type %s"), IdType2Name(type));
+    return sq_throwerror(v, _ss(v)->GetScratchPad(-1));
+}
+
+HSQUIRRELVM sq_open(SQInteger initialstacksize)
+{
+    SQSharedState *ss;
+    SQVM *v;
+    sq_new(ss, SQSharedState);
+    ss->Init();
+    v = (SQVM *)SQ_MALLOC(sizeof(SQVM));
+    new (v) SQVM(ss);
+    ss->_root_vm = v;
+    if(v->Init(NULL, initialstacksize)) {
+        return v;
+    } else {
+        sq_delete(v, SQVM);
+        return NULL;
+    }
+    return v;
+}
+
+HSQUIRRELVM sq_newthread(HSQUIRRELVM friendvm, SQInteger initialstacksize)
+{
+    SQSharedState *ss;
+    SQVM *v;
+    ss=_ss(friendvm);
+
+    v= (SQVM *)SQ_MALLOC(sizeof(SQVM));
+    new (v) SQVM(ss);
+
+    if(v->Init(friendvm, initialstacksize)) {
+        friendvm->Push(v);
+        return v;
+    } else {
+        sq_delete(v, SQVM);
+        return NULL;
+    }
+}
+
+SQInteger sq_getvmstate(HSQUIRRELVM v)
+{
+    if(v->_suspended)
+        return SQ_VMSTATE_SUSPENDED;
+    else {
+        if(v->_callsstacksize != 0) return SQ_VMSTATE_RUNNING;
+        else return SQ_VMSTATE_IDLE;
+    }
+}
+
+void sq_seterrorhandler(HSQUIRRELVM v)
+{
+    SQObject o = stack_get(v, -1);
+    if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
+        v->_errorhandler = o;
+        v->Pop();
+    }
+}
+
+void sq_setnativedebughook(HSQUIRRELVM v,SQDEBUGHOOK hook)
+{
+    v->_debughook_native = hook;
+    v->_debughook_closure.Null();
+    v->_debughook = hook?true:false;
+}
+
+void sq_setdebughook(HSQUIRRELVM v)
+{
+    SQObject o = stack_get(v,-1);
+    if(sq_isclosure(o) || sq_isnativeclosure(o) || sq_isnull(o)) {
+        v->_debughook_closure = o;
+        v->_debughook_native = NULL;
+        v->_debughook = !sq_isnull(o);
+        v->Pop();
+    }
+}
+
+void sq_close(HSQUIRRELVM v)
+{
+    SQSharedState *ss = _ss(v);
+    _thread(ss->_root_vm)->Finalize();
+    sq_delete(ss, SQSharedState);
+}
+
+SQInteger sq_getversion()
+{
+    return SQUIRREL_VERSION_NUMBER;
+}
+
+SQRESULT sq_compile(HSQUIRRELVM v,SQLEXREADFUNC read,SQUserPointer p,const SQChar *sourcename,SQBool raiseerror)
+{
+    SQObjectPtr o;
+#ifndef NO_COMPILER
+    if(Compile(v, read, p, sourcename, o, raiseerror?true:false, _ss(v)->_debuginfo)) {
+        v->Push(SQClosure::Create(_ss(v), _funcproto(o), _table(v->_roottable)->GetWeakRef(OT_TABLE)));
+        return SQ_OK;
+    }
+    return SQ_ERROR;
+#else
+    return sq_throwerror(v,_SC("this is a no compiler build"));
+#endif
+}
+
+void sq_enabledebuginfo(HSQUIRRELVM v, SQBool enable)
+{
+    _ss(v)->_debuginfo = enable?true:false;
+}
+
+void sq_notifyallexceptions(HSQUIRRELVM v, SQBool enable)
+{
+    _ss(v)->_notifyallexceptions = enable?true:false;
+}
+
+void sq_addref(HSQUIRRELVM v,HSQOBJECT *po)
+{
+    if(!ISREFCOUNTED(type(*po))) return;
+#ifdef NO_GARBAGE_COLLECTOR
+    __AddRef(po->_type,po->_unVal);
+#else
+    _ss(v)->_refs_table.AddRef(*po);
+#endif
+}
+
+SQUnsignedInteger sq_getrefcount(HSQUIRRELVM v,HSQOBJECT *po)
+{
+    if(!ISREFCOUNTED(type(*po))) return 0;
+#ifdef NO_GARBAGE_COLLECTOR
+   return po->_unVal.pRefCounted->_uiRef;
+#else
+   return _ss(v)->_refs_table.GetRefCount(*po);
+#endif
+}
+
+SQBool sq_release(HSQUIRRELVM v,HSQOBJECT *po)
+{
+    if(!ISREFCOUNTED(type(*po))) return SQTrue;
+#ifdef NO_GARBAGE_COLLECTOR
+    bool ret = (po->_unVal.pRefCounted->_uiRef <= 1) ? SQTrue : SQFalse;
+    __Release(po->_type,po->_unVal);
+    return ret; //the ret val doesn't work(and cannot be fixed)
+#else
+    return _ss(v)->_refs_table.Release(*po);
+#endif
+}
+
+SQUnsignedInteger sq_getvmrefcount(HSQUIRRELVM v, const HSQOBJECT *po)
+{
+    if (!ISREFCOUNTED(type(*po))) return 0;
+    return po->_unVal.pRefCounted->_uiRef;
+}
+
+const SQChar *sq_objtostring(const HSQOBJECT *o)
+{
+    if(sq_type(*o) == OT_STRING) {
+        return _stringval(*o);
+    }
+    return NULL;
+}
+
+SQInteger sq_objtointeger(const HSQOBJECT *o)
+{
+    if(sq_isnumeric(*o)) {
+        return tointeger(*o);
+    }
+    return 0;
+}
+
+SQFloat sq_objtofloat(const HSQOBJECT *o)
+{
+    if(sq_isnumeric(*o)) {
+        return tofloat(*o);
+    }
+    return 0;
+}
+
+SQBool sq_objtobool(const HSQOBJECT *o)
+{
+    if(sq_isbool(*o)) {
+        return _integer(*o);
+    }
+    return SQFalse;
+}
+
+SQUserPointer sq_objtouserpointer(const HSQOBJECT *o)
+{
+    if(sq_isuserpointer(*o)) {
+        return _userpointer(*o);
+    }
+    return 0;
+}
+
+void sq_pushnull(HSQUIRRELVM v)
+{
+    v->PushNull();
+}
+
+void sq_pushstring(HSQUIRRELVM v,const SQChar *s,SQInteger len)
+{
+    if(s)
+        v->Push(SQObjectPtr(SQString::Create(_ss(v), s, len)));
+    else v->PushNull();
+}
+
+void sq_pushinteger(HSQUIRRELVM v,SQInteger n)
+{
+    v->Push(n);
+}
+
+void sq_pushbool(HSQUIRRELVM v,SQBool b)
+{
+    v->Push(b?true:false);
+}
+
+void sq_pushfloat(HSQUIRRELVM v,SQFloat n)
+{
+    v->Push(n);
+}
+
+void sq_pushuserpointer(HSQUIRRELVM v,SQUserPointer p)
+{
+    v->Push(p);
+}
+
+void sq_pushthread(HSQUIRRELVM v, HSQUIRRELVM thread)
+{
+    v->Push(thread);
+}
+
+SQUserPointer sq_newuserdata(HSQUIRRELVM v,SQUnsignedInteger size)
+{
+    SQUserData *ud = SQUserData::Create(_ss(v), size + SQ_ALIGNMENT);
+    v->Push(ud);
+    return (SQUserPointer)sq_aligning(ud + 1);
+}
+
+void sq_newtable(HSQUIRRELVM v)
+{
+    v->Push(SQTable::Create(_ss(v), 0));
+}
+
+void sq_newtableex(HSQUIRRELVM v,SQInteger initialcapacity)
+{
+    v->Push(SQTable::Create(_ss(v), initialcapacity));
+}
+
+void sq_newarray(HSQUIRRELVM v,SQInteger size)
+{
+    v->Push(SQArray::Create(_ss(v), size));
+}
+
+SQRESULT sq_newclass(HSQUIRRELVM v,SQBool hasbase)
+{
+    SQClass *baseclass = NULL;
+    if(hasbase) {
+        SQObjectPtr &base = stack_get(v,-1);
+        if(type(base) != OT_CLASS)
+            return sq_throwerror(v,_SC("invalid base type"));
+        baseclass = _class(base);
+    }
+    SQClass *newclass = SQClass::Create(_ss(v), baseclass);
+    if(baseclass) v->Pop();
+    v->Push(newclass);
+    return SQ_OK;
+}
+
+SQBool sq_instanceof(HSQUIRRELVM v)
+{
+    SQObjectPtr &inst = stack_get(v,-1);
+    SQObjectPtr &cl = stack_get(v,-2);
+    if(type(inst) != OT_INSTANCE || type(cl) != OT_CLASS)
+        return sq_throwerror(v,_SC("invalid param type"));
+    return _instance(inst)->InstanceOf(_class(cl))?SQTrue:SQFalse;
+}
+
+SQRESULT sq_arrayappend(HSQUIRRELVM v,SQInteger idx)
+{
+    sq_aux_paramscheck(v,2);
+    SQObjectPtr *arr;
+    _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
+    _array(*arr)->Append(v->GetUp(-1));
+    v->Pop();
+    return SQ_OK;
+}
+
+SQRESULT sq_arraypop(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
+{
+    sq_aux_paramscheck(v, 1);
+    SQObjectPtr *arr;
+    _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
+    if(_array(*arr)->Size() > 0) {
+        if(pushval != 0){ v->Push(_array(*arr)->Top()); }
+        _array(*arr)->Pop();
+        return SQ_OK;
+    }
+    return sq_throwerror(v, _SC("empty array"));
+}
+
+SQRESULT sq_arrayresize(HSQUIRRELVM v,SQInteger idx,SQInteger newsize)
+{
+    sq_aux_paramscheck(v,1);
+    SQObjectPtr *arr;
+    _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
+    if(newsize >= 0) {
+        _array(*arr)->Resize(newsize);
+        return SQ_OK;
+    }
+    return sq_throwerror(v,_SC("negative size"));
+}
+
+
+SQRESULT sq_arrayreverse(HSQUIRRELVM v,SQInteger idx)
+{
+    sq_aux_paramscheck(v, 1);
+    SQObjectPtr *o;
+    _GETSAFE_OBJ(v, idx, OT_ARRAY,o);
+    SQArray *arr = _array(*o);
+    if(arr->Size() > 0) {
+        SQObjectPtr t;
+        SQInteger size = arr->Size();
+        SQInteger n = size >> 1; size -= 1;
+        for(SQInteger i = 0; i < n; i++) {
+            t = arr->_values[i];
+            arr->_values[i] = arr->_values[size-i];
+            arr->_values[size-i] = t;
+        }
+        return SQ_OK;
+    }
+    return SQ_OK;
+}
+
+SQRESULT sq_arrayremove(HSQUIRRELVM v,SQInteger idx,SQInteger itemidx)
+{
+    sq_aux_paramscheck(v, 1);
+    SQObjectPtr *arr;
+    _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
+    return _array(*arr)->Remove(itemidx) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));
+}
+
+SQRESULT sq_arrayinsert(HSQUIRRELVM v,SQInteger idx,SQInteger destpos)
+{
+    sq_aux_paramscheck(v, 1);
+    SQObjectPtr *arr;
+    _GETSAFE_OBJ(v, idx, OT_ARRAY,arr);
+    SQRESULT ret = _array(*arr)->Insert(destpos, v->GetUp(-1)) ? SQ_OK : sq_throwerror(v,_SC("index out of range"));
+    v->Pop();
+    return ret;
+}
+
+void sq_newclosure(HSQUIRRELVM v,SQFUNCTION func,SQUnsignedInteger nfreevars)
+{
+    SQNativeClosure *nc = SQNativeClosure::Create(_ss(v), func,nfreevars);
+    nc->_nparamscheck = 0;
+    for(SQUnsignedInteger i = 0; i < nfreevars; i++) {
+        nc->_outervalues[i] = v->Top();
+        v->Pop();
+    }
+    v->Push(SQObjectPtr(nc));
+}
+
+SQRESULT sq_getclosureinfo(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger *nparams,SQUnsignedInteger *nfreevars)
+{
+    SQObject o = stack_get(v, idx);
+    if(type(o) == OT_CLOSURE) {
+        SQClosure *c = _closure(o);
+        SQFunctionProto *proto = c->_function;
+        *nparams = (SQUnsignedInteger)proto->_nparameters;
+        *nfreevars = (SQUnsignedInteger)proto->_noutervalues;
+        return SQ_OK;
+    }
+    else if(type(o) == OT_NATIVECLOSURE)
+    {
+        SQNativeClosure *c = _nativeclosure(o);
+        *nparams = (SQUnsignedInteger)c->_nparamscheck;
+        *nfreevars = c->_noutervalues;
+        return SQ_OK;
+    }
+    return sq_throwerror(v,_SC("the object is not a closure"));
+}
+
+SQRESULT sq_setnativeclosurename(HSQUIRRELVM v,SQInteger idx,const SQChar *name)
+{
+    SQObject o = stack_get(v, idx);
+    if(sq_isnativeclosure(o)) {
+        SQNativeClosure *nc = _nativeclosure(o);
+        nc->_name = SQString::Create(_ss(v),name);
+        return SQ_OK;
+    }
+    return sq_throwerror(v,_SC("the object is not a nativeclosure"));
+}
+
+SQRESULT sq_setparamscheck(HSQUIRRELVM v,SQInteger nparamscheck,const SQChar *typemask)
+{
+    SQObject o = stack_get(v, -1);
+    if(!sq_isnativeclosure(o))
+        return sq_throwerror(v, _SC("native closure expected"));
+    SQNativeClosure *nc = _nativeclosure(o);
+    nc->_nparamscheck = nparamscheck;
+    if(typemask) {
+        SQIntVec res;
+        if(!CompileTypemask(res, typemask))
+            return sq_throwerror(v, _SC("invalid typemask"));
+        nc->_typecheck.copy(res);
+    }
+    else {
+        nc->_typecheck.resize(0);
+    }
+    if(nparamscheck == SQ_MATCHTYPEMASKSTRING) {
+        nc->_nparamscheck = nc->_typecheck.size();
+    }
+    return SQ_OK;
+}
+
+SQRESULT sq_bindenv(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &o = stack_get(v,idx);
+    if(!sq_isnativeclosure(o) &&
+        !sq_isclosure(o))
+        return sq_throwerror(v,_SC("the target is not a closure"));
+    SQObjectPtr &env = stack_get(v,-1);
+    if(!sq_istable(env) &&
+        !sq_isarray(env) &&
+        !sq_isclass(env) &&
+        !sq_isinstance(env))
+        return sq_throwerror(v,_SC("invalid environment"));
+    SQWeakRef *w = _refcounted(env)->GetWeakRef(type(env));
+    SQObjectPtr ret;
+    if(sq_isclosure(o)) {
+        SQClosure *c = _closure(o)->Clone();
+        __ObjRelease(c->_env);
+        c->_env = w;
+        __ObjAddRef(c->_env);
+        if(_closure(o)->_base) {
+            c->_base = _closure(o)->_base;
+            __ObjAddRef(c->_base);
+        }
+        ret = c;
+    }
+    else { //then must be a native closure
+        SQNativeClosure *c = _nativeclosure(o)->Clone();
+        __ObjRelease(c->_env);
+        c->_env = w;
+        __ObjAddRef(c->_env);
+        ret = c;
+    }
+    v->Pop();
+    v->Push(ret);
+    return SQ_OK;
+}
+
+SQRESULT sq_getclosurename(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"));
+    if(sq_isnativeclosure(o))
+    {
+        v->Push(_nativeclosure(o)->_name);
+    }
+    else { //closure
+        v->Push(_closure(o)->_function->_name);
+    }
+    return SQ_OK;
+}
+
+SQRESULT sq_setclosureroot(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &c = stack_get(v,idx);
+    SQObject o = stack_get(v, -1);
+    if(!sq_isclosure(c)) return sq_throwerror(v, _SC("closure expected"));
+    if(sq_istable(o)) {
+        _closure(c)->SetRoot(_table(o)->GetWeakRef(OT_TABLE));
+        v->Pop();
+        return SQ_OK;
+    }
+    return sq_throwerror(v, _SC("ivalid type"));
+}
+
+SQRESULT sq_getclosureroot(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &c = stack_get(v,idx);
+    if(!sq_isclosure(c)) return sq_throwerror(v, _SC("closure expected"));
+    v->Push(_closure(c)->_root->_obj);
+    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_setsharedforeignptr(HSQUIRRELVM v,SQUserPointer p)
+{
+    _ss(v)->_foreignptr = p;
+}
+
+SQUserPointer sq_getsharedforeignptr(HSQUIRRELVM v)
+{
+    return _ss(v)->_foreignptr;
+}
+
+void sq_setvmreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook)
+{
+    v->_releasehook = hook;
+}
+
+SQRELEASEHOOK sq_getvmreleasehook(HSQUIRRELVM v)
+{
+    return v->_releasehook;
+}
+
+void sq_setsharedreleasehook(HSQUIRRELVM v,SQRELEASEHOOK hook)
+{
+    _ss(v)->_releasehook = hook;
+}
+
+SQRELEASEHOOK sq_getsharedreleasehook(HSQUIRRELVM v)
+{
+    return _ss(v)->_releasehook;
+}
+
+void sq_push(HSQUIRRELVM v,SQInteger idx)
+{
+    v->Push(stack_get(v, idx));
+}
+
+SQObjectType sq_gettype(HSQUIRRELVM v,SQInteger idx)
+{
+    return type(stack_get(v, idx));
+}
+
+SQRESULT sq_typeof(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &o = stack_get(v, idx);
+    SQObjectPtr res;
+    if(!v->TypeOf(o,res)) {
+        return SQ_ERROR;
+    }
+    v->Push(res);
+    return SQ_OK;
+}
+
+SQRESULT sq_tostring(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &o = stack_get(v, idx);
+    SQObjectPtr res;
+    if(!v->ToString(o,res)) {
+        return SQ_ERROR;
+    }
+    v->Push(res);
+    return SQ_OK;
+}
+
+void sq_tobool(HSQUIRRELVM v, SQInteger idx, SQBool *b)
+{
+    SQObjectPtr &o = stack_get(v, idx);
+    *b = SQVM::IsFalse(o)?SQFalse:SQTrue;
+}
+
+SQRESULT sq_getinteger(HSQUIRRELVM v,SQInteger idx,SQInteger *i)
+{
+    SQObjectPtr &o = stack_get(v, idx);
+    if(sq_isnumeric(o)) {
+        *i = tointeger(o);
+        return SQ_OK;
+    }
+    return SQ_ERROR;
+}
+
+SQRESULT sq_getfloat(HSQUIRRELVM v,SQInteger idx,SQFloat *f)
+{
+    SQObjectPtr &o = stack_get(v, idx);
+    if(sq_isnumeric(o)) {
+        *f = tofloat(o);
+        return SQ_OK;
+    }
+    return SQ_ERROR;
+}
+
+SQRESULT sq_getbool(HSQUIRRELVM v,SQInteger idx,SQBool *b)
+{
+    SQObjectPtr &o = stack_get(v, idx);
+    if(sq_isbool(o)) {
+        *b = _integer(o);
+        return SQ_OK;
+    }
+    return SQ_ERROR;
+}
+
+SQRESULT sq_getstring(HSQUIRRELVM v,SQInteger idx,const SQChar **c)
+{
+    SQObjectPtr *o = NULL;
+    _GETSAFE_OBJ(v, idx, OT_STRING,o);
+    *c = _stringval(*o);
+    return SQ_OK;
+}
+
+SQRESULT sq_getthread(HSQUIRRELVM v,SQInteger idx,HSQUIRRELVM *thread)
+{
+    SQObjectPtr *o = NULL;
+    _GETSAFE_OBJ(v, idx, OT_THREAD,o);
+    *thread = _thread(*o);
+    return SQ_OK;
+}
+
+SQRESULT sq_clone(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &o = stack_get(v,idx);
+    v->PushNull();
+    if(!v->Clone(o, stack_get(v, -1))){
+        v->Pop();
+        return SQ_ERROR;
+    }
+    return SQ_OK;
+}
+
+SQInteger sq_getsize(HSQUIRRELVM v, SQInteger idx)
+{
+    SQObjectPtr &o = stack_get(v, idx);
+    SQObjectType type = type(o);
+    switch(type) {
+    case OT_STRING:     return _string(o)->_len;
+    case OT_TABLE:      return _table(o)->CountUsed();
+    case OT_ARRAY:      return _array(o)->Size();
+    case OT_USERDATA:   return _userdata(o)->_size;
+    case OT_INSTANCE:   return _instance(o)->_class->_udsize;
+    case OT_CLASS:      return _class(o)->_udsize;
+    default:
+        return sq_aux_invalidtype(v, type);
+    }
+}
+
+SQHash sq_gethash(HSQUIRRELVM v, SQInteger idx)
+{
+    SQObjectPtr &o = stack_get(v, idx);
+    return HashObj(o);
+}
+
+SQRESULT sq_getuserdata(HSQUIRRELVM v,SQInteger idx,SQUserPointer *p,SQUserPointer *typetag)
+{
+    SQObjectPtr *o = NULL;
+    _GETSAFE_OBJ(v, idx, OT_USERDATA,o);
+    (*p) = _userdataval(*o);
+    if(typetag) *typetag = _userdata(*o)->_typetag;
+    return SQ_OK;
+}
+
+SQRESULT sq_settypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer typetag)
+{
+    SQObjectPtr &o = stack_get(v,idx);
+    switch(type(o)) {
+        case OT_USERDATA:   _userdata(o)->_typetag = typetag;   break;
+        case OT_CLASS:      _class(o)->_typetag = typetag;      break;
+        default:            return sq_throwerror(v,_SC("invalid object type"));
+    }
+    return SQ_OK;
+}
+
+SQRESULT sq_getobjtypetag(const HSQOBJECT *o,SQUserPointer * typetag)
+{
+  switch(type(*o)) {
+    case OT_INSTANCE: *typetag = _instance(*o)->_class->_typetag; break;
+    case OT_USERDATA: *typetag = _userdata(*o)->_typetag; break;
+    case OT_CLASS:    *typetag = _class(*o)->_typetag; break;
+    default: return SQ_ERROR;
+  }
+  return SQ_OK;
+}
+
+SQRESULT sq_gettypetag(HSQUIRRELVM v,SQInteger idx,SQUserPointer *typetag)
+{
+    SQObjectPtr &o = stack_get(v,idx);
+    if(SQ_FAILED(sq_getobjtypetag(&o,typetag)))
+        return sq_throwerror(v,_SC("invalid object type"));
+    return SQ_OK;
+}
+
+SQRESULT sq_getuserpointer(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p)
+{
+    SQObjectPtr *o = NULL;
+    _GETSAFE_OBJ(v, idx, OT_USERPOINTER,o);
+    (*p) = _userpointer(*o);
+    return SQ_OK;
+}
+
+SQRESULT sq_setinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer p)
+{
+    SQObjectPtr &o = stack_get(v,idx);
+    if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));
+    _instance(o)->_userpointer = p;
+    return SQ_OK;
+}
+
+SQRESULT sq_setclassudsize(HSQUIRRELVM v, SQInteger idx, SQInteger udsize)
+{
+    SQObjectPtr &o = stack_get(v,idx);
+    if(type(o) != OT_CLASS) return sq_throwerror(v,_SC("the object is not a class"));
+    if(_class(o)->_locked) return sq_throwerror(v,_SC("the class is locked"));
+    _class(o)->_udsize = udsize;
+    return SQ_OK;
+}
+
+
+SQRESULT sq_getinstanceup(HSQUIRRELVM v, SQInteger idx, SQUserPointer *p,SQUserPointer typetag)
+{
+    SQObjectPtr &o = stack_get(v,idx);
+    if(type(o) != OT_INSTANCE) return sq_throwerror(v,_SC("the object is not a class instance"));
+    (*p) = _instance(o)->_userpointer;
+    if(typetag != 0) {
+        SQClass *cl = _instance(o)->_class;
+        do{
+            if(cl->_typetag == typetag)
+                return SQ_OK;
+            cl = cl->_base;
+        }while(cl != NULL);
+        return sq_throwerror(v,_SC("invalid type tag"));
+    }
+    return SQ_OK;
+}
+
+SQInteger sq_gettop(HSQUIRRELVM v)
+{
+    return (v->_top) - v->_stackbase;
+}
+
+void sq_settop(HSQUIRRELVM v, SQInteger newtop)
+{
+    SQInteger top = sq_gettop(v);
+    if(top > newtop)
+        sq_pop(v, top - newtop);
+    else
+        while(top++ < newtop) sq_pushnull(v);
+}
+
+void sq_pop(HSQUIRRELVM v, SQInteger nelemstopop)
+{
+    assert(v->_top >= nelemstopop);
+    v->Pop(nelemstopop);
+}
+
+void sq_poptop(HSQUIRRELVM v)
+{
+    assert(v->_top >= 1);
+    v->Pop();
+}
+
+
+void sq_remove(HSQUIRRELVM v, SQInteger idx)
+{
+    v->Remove(idx);
+}
+
+SQInteger sq_cmp(HSQUIRRELVM v)
+{
+    SQInteger res;
+    v->ObjCmp(stack_get(v, -1), stack_get(v, -2),res);
+    return res;
+}
+
+SQRESULT sq_newslot(HSQUIRRELVM v, SQInteger idx, SQBool bstatic)
+{
+    sq_aux_paramscheck(v, 3);
+    SQObjectPtr &self = stack_get(v, idx);
+    if(type(self) == OT_TABLE || type(self) == OT_CLASS) {
+        SQObjectPtr &key = v->GetUp(-2);
+        if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));
+        v->NewSlot(self, key, v->GetUp(-1),bstatic?true:false);
+        v->Pop(2);
+    }
+    return SQ_OK;
+}
+
+SQRESULT sq_deleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
+{
+    sq_aux_paramscheck(v, 2);
+    SQObjectPtr *self;
+    _GETSAFE_OBJ(v, idx, OT_TABLE,self);
+    SQObjectPtr &key = v->GetUp(-1);
+    if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null is not a valid key"));
+    SQObjectPtr res;
+    if(!v->DeleteSlot(*self, key, res)){
+        v->Pop();
+        return SQ_ERROR;
+    }
+    if(pushval) v->GetUp(-1) = res;
+    else v->Pop();
+    return SQ_OK;
+}
+
+SQRESULT sq_set(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &self = stack_get(v, idx);
+    if(v->Set(self, v->GetUp(-2), v->GetUp(-1),DONT_FALL_BACK)) {
+        v->Pop(2);
+        return SQ_OK;
+    }
+    return SQ_ERROR;
+}
+
+SQRESULT sq_rawset(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &self = stack_get(v, idx);
+    SQObjectPtr &key = v->GetUp(-2);
+    if(type(key) == OT_NULL) {
+        v->Pop(2);
+        return sq_throwerror(v, _SC("null key"));
+    }
+    switch(type(self)) {
+    case OT_TABLE:
+        _table(self)->NewSlot(key, v->GetUp(-1));
+        v->Pop(2);
+        return SQ_OK;
+    break;
+    case OT_CLASS:
+        _class(self)->NewSlot(_ss(v), key, v->GetUp(-1),false);
+        v->Pop(2);
+        return SQ_OK;
+    break;
+    case OT_INSTANCE:
+        if(_instance(self)->Set(key, v->GetUp(-1))) {
+            v->Pop(2);
+            return SQ_OK;
+        }
+    break;
+    case OT_ARRAY:
+        if(v->Set(self, key, 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_newmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)
+{
+    SQObjectPtr &self = stack_get(v, idx);
+    if(type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));
+    SQObjectPtr &key = v->GetUp(-3);
+    if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null key"));
+    if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,false))
+        return SQ_ERROR;
+    return SQ_OK;
+}
+
+SQRESULT sq_rawnewmember(HSQUIRRELVM v,SQInteger idx,SQBool bstatic)
+{
+    SQObjectPtr &self = stack_get(v, idx);
+    if(type(self) != OT_CLASS) return sq_throwerror(v, _SC("new member only works with classes"));
+    SQObjectPtr &key = v->GetUp(-3);
+    if(type(key) == OT_NULL) return sq_throwerror(v, _SC("null key"));
+    if(!v->NewSlotA(self,key,v->GetUp(-2),v->GetUp(-1),bstatic?true:false,true))
+        return SQ_ERROR;
+    return SQ_OK;
+}
+
+SQRESULT sq_setdelegate(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &self = stack_get(v, idx);
+    SQObjectPtr &mt = v->GetUp(-1);
+    SQObjectType type = type(self);
+    switch(type) {
+    case OT_TABLE:
+        if(type(mt) == OT_TABLE) {
+            if(!_table(self)->SetDelegate(_table(mt))) return sq_throwerror(v, _SC("delagate cycle")); v->Pop();}
+        else if(type(mt)==OT_NULL) {
+            _table(self)->SetDelegate(NULL); v->Pop(); }
+        else return sq_aux_invalidtype(v,type);
+        break;
+    case OT_USERDATA:
+        if(type(mt)==OT_TABLE) {
+            _userdata(self)->SetDelegate(_table(mt)); v->Pop(); }
+        else if(type(mt)==OT_NULL) {
+            _userdata(self)->SetDelegate(NULL); v->Pop(); }
+        else return sq_aux_invalidtype(v, type);
+        break;
+    default:
+            return sq_aux_invalidtype(v, type);
+        break;
+    }
+    return SQ_OK;
+}
+
+SQRESULT sq_rawdeleteslot(HSQUIRRELVM v,SQInteger idx,SQBool pushval)
+{
+    sq_aux_paramscheck(v, 2);
+    SQObjectPtr *self;
+    _GETSAFE_OBJ(v, idx, OT_TABLE,self);
+    SQObjectPtr &key = v->GetUp(-1);
+    SQObjectPtr t;
+    if(_table(*self)->Get(key,t)) {
+        _table(*self)->Remove(key);
+    }
+    if(pushval != 0)
+        v->GetUp(-1) = t;
+    else
+        v->Pop();
+    return SQ_OK;
+}
+
+SQRESULT sq_getdelegate(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &self=stack_get(v,idx);
+    switch(type(self)){
+    case OT_TABLE:
+    case OT_USERDATA:
+        if(!_delegable(self)->_delegate){
+            v->PushNull();
+            break;
+        }
+        v->Push(SQObjectPtr(_delegable(self)->_delegate));
+        break;
+    default: return sq_throwerror(v,_SC("wrong type")); break;
+    }
+    return SQ_OK;
+
+}
+
+SQRESULT sq_get(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &self=stack_get(v,idx);
+    SQObjectPtr &obj = v->GetUp(-1);
+    if(v->Get(self,obj,obj,false,DONT_FALL_BACK))
+        return SQ_OK;
+    v->Pop();
+    return SQ_ERROR;
+}
+
+SQRESULT sq_rawget(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &self=stack_get(v,idx);
+    SQObjectPtr &obj = v->GetUp(-1);
+    switch(type(self)) {
+    case OT_TABLE:
+        if(_table(self)->Get(obj,obj))
+            return SQ_OK;
+        break;
+    case OT_CLASS:
+        if(_class(self)->Get(obj,obj))
+            return SQ_OK;
+        break;
+    case OT_INSTANCE:
+        if(_instance(self)->Get(obj,obj))
+            return SQ_OK;
+        break;
+    case OT_ARRAY:{
+        if(sq_isnumeric(obj)){
+            if(_array(self)->Get(tointeger(obj),obj)) {
+                return SQ_OK;
+            }
+        }
+        else {
+            v->Pop();
+            return sq_throwerror(v,_SC("invalid index type for an array"));
+        }
+                  }
+        break;
+    default:
+        v->Pop();
+        return sq_throwerror(v,_SC("rawget works only on array/table/instance and class"));
+    }
+    v->Pop();
+    return sq_throwerror(v,_SC("the index doesn't exist"));
+}
+
+SQRESULT sq_getstackobj(HSQUIRRELVM v,SQInteger idx,HSQOBJECT *po)
+{
+    *po=stack_get(v,idx);
+    return SQ_OK;
+}
+
+const SQChar *sq_getlocal(HSQUIRRELVM v,SQUnsignedInteger level,SQUnsignedInteger idx)
+{
+    SQUnsignedInteger cstksize=v->_callsstacksize;
+    SQUnsignedInteger lvl=(cstksize-level)-1;
+    SQInteger stackbase=v->_stackbase;
+    if(lvl<cstksize){
+        for(SQUnsignedInteger i=0;i<level;i++){
+            SQVM::CallInfo &ci=v->_callsstack[(cstksize-i)-1];
+            stackbase-=ci._prevstkbase;
+        }
+        SQVM::CallInfo &ci=v->_callsstack[lvl];
+        if(type(ci._closure)!=OT_CLOSURE)
+            return NULL;
+        SQClosure *c=_closure(ci._closure);
+        SQFunctionProto *func=c->_function;
+        if(func->_noutervalues > (SQInteger)idx) {
+            v->Push(*_outer(c->_outervalues[idx])->_valptr);
+            return _stringval(func->_outervalues[idx]._name);
+        }
+        idx -= func->_noutervalues;
+        return func->GetLocal(v,stackbase,idx,(SQInteger)(ci._ip-func->_instructions)-1);
+    }
+    return NULL;
+}
+
+void sq_pushobject(HSQUIRRELVM v,HSQOBJECT obj)
+{
+    v->Push(SQObjectPtr(obj));
+}
+
+void sq_resetobject(HSQOBJECT *po)
+{
+    po->_unVal.pUserPointer=NULL;po->_type=OT_NULL;
+}
+
+SQRESULT sq_throwerror(HSQUIRRELVM v,const SQChar *err)
+{
+    v->_lasterror=SQString::Create(_ss(v),err);
+    return SQ_ERROR;
+}
+
+SQRESULT sq_throwobject(HSQUIRRELVM v)
+{
+    v->_lasterror = v->GetUp(-1);
+    v->Pop();
+    return SQ_ERROR;
+}
+
+
+void sq_reseterror(HSQUIRRELVM v)
+{
+    v->_lasterror.Null();
+}
+
+void sq_getlasterror(HSQUIRRELVM v)
+{
+    v->Push(v->_lasterror);
+}
+
+SQRESULT sq_reservestack(HSQUIRRELVM v,SQInteger nsize)
+{
+    if (((SQUnsignedInteger)v->_top + nsize) > v->_stack.size()) {
+        if(v->_nmetamethodscall) {
+            return sq_throwerror(v,_SC("cannot resize stack while in  a metamethod"));
+        }
+        v->_stack.resize(v->_stack.size() + ((v->_top + nsize) - v->_stack.size()));
+    }
+    return SQ_OK;
+}
+
+SQRESULT sq_resume(HSQUIRRELVM v,SQBool retval,SQBool raiseerror)
+{
+    if (type(v->GetUp(-1)) == OT_GENERATOR)
+    {
+        v->PushNull(); //retval
+        if (!v->Execute(v->GetUp(-2), 0, v->_top, v->GetUp(-1), raiseerror, SQVM::ET_RESUME_GENERATOR))
+        {v->Raise_Error(v->_lasterror); return SQ_ERROR;}
+        if(!retval)
+            v->Pop();
+        return SQ_OK;
+    }
+    return sq_throwerror(v,_SC("only generators can be resumed"));
+}
+
+SQRESULT sq_call(HSQUIRRELVM v,SQInteger params,SQBool retval,SQBool raiseerror)
+{
+    SQObjectPtr res;
+    if(v->Call(v->GetUp(-(params+1)),params,v->_top-params,res,raiseerror?true:false)){
+
+        if(!v->_suspended) {
+            v->Pop(params);//pop closure and args
+        }
+        if(retval){
+            v->Push(res); return SQ_OK;
+        }
+        return SQ_OK;
+    }
+    else {
+        v->Pop(params);
+        return SQ_ERROR;
+    }
+    if(!v->_suspended)
+        v->Pop(params);
+    return sq_throwerror(v,_SC("call failed"));
+}
+
+SQRESULT sq_suspendvm(HSQUIRRELVM v)
+{
+    return v->Suspend();
+}
+
+SQRESULT sq_wakeupvm(HSQUIRRELVM v,SQBool wakeupret,SQBool retval,SQBool raiseerror,SQBool throwerror)
+{
+    SQObjectPtr ret;
+    if(!v->_suspended)
+        return sq_throwerror(v,_SC("cannot resume a vm that is not running any code"));
+    SQInteger target = v->_suspended_target;
+    if(wakeupret) {
+        if(target != -1) {
+            v->GetAt(v->_stackbase+v->_suspended_target)=v->GetUp(-1); //retval
+        }
+        v->Pop();
+    } else if(target != -1) { v->GetAt(v->_stackbase+v->_suspended_target).Null(); }
+    SQObjectPtr dummy;
+    if(!v->Execute(dummy,-1,-1,ret,raiseerror,throwerror?SQVM::ET_RESUME_THROW_VM : SQVM::ET_RESUME_VM)) {
+        return SQ_ERROR;
+    }
+    if(retval)
+        v->Push(ret);
+    return SQ_OK;
+}
+
+void sq_setreleasehook(HSQUIRRELVM v,SQInteger idx,SQRELEASEHOOK hook)
+{
+    if(sq_gettop(v) >= 1){
+        SQObjectPtr &ud=stack_get(v,idx);
+        switch( type(ud) ) {
+        case OT_USERDATA:   _userdata(ud)->_hook = hook;    break;
+        case OT_INSTANCE:   _instance(ud)->_hook = hook;    break;
+        case OT_CLASS:      _class(ud)->_hook = hook;       break;
+        default: break; //shutup compiler
+        }
+    }
+}
+
+SQRELEASEHOOK sq_getreleasehook(HSQUIRRELVM v,SQInteger idx)
+{
+    if(sq_gettop(v) >= 1){
+        SQObjectPtr &ud=stack_get(v,idx);
+        switch( type(ud) ) {
+        case OT_USERDATA:   return _userdata(ud)->_hook;    break;
+        case OT_INSTANCE:   return _instance(ud)->_hook;    break;
+        case OT_CLASS:      return _class(ud)->_hook;       break;
+        default: break; //shutup compiler
+        }
+    }
+    return NULL;
+}
+
+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(_closure(*o)->_function->_noutervalues)
+        return sq_throwerror(v,_SC("a closure with free valiables bound it cannot be serialized"));
+    if(w(up,&tag,2) != 2)
+        return sq_throwerror(v,_SC("io error"));
+    if(!_closure(*o)->Save(v,up,w))
+        return SQ_ERROR;
+    return SQ_OK;
+}
+
+SQRESULT sq_readclosure(HSQUIRRELVM v,SQREADFUNC r,SQUserPointer up)
+{
+    SQObjectPtr closure;
+
+    unsigned short tag;
+    if(r(up,&tag,2) != 2)
+        return sq_throwerror(v,_SC("io error"));
+    if(tag != SQ_BYTECODE_STREAM_TAG)
+        return sq_throwerror(v,_SC("invalid stream"));
+    if(!SQClosure::Load(v,up,r,closure))
+        return SQ_ERROR;
+    v->Push(closure);
+    return SQ_OK;
+}
+
+SQChar *sq_getscratchpad(HSQUIRRELVM v,SQInteger minsize)
+{
+    return _ss(v)->GetScratchPad(minsize);
+}
+
+SQRESULT sq_resurrectunreachable(HSQUIRRELVM v)
+{
+#ifndef NO_GARBAGE_COLLECTOR
+    _ss(v)->ResurrectUnreachable(v);
+    return SQ_OK;
+#else
+    return sq_throwerror(v,_SC("sq_resurrectunreachable requires a garbage collector build"));
+#endif
+}
+
+SQInteger sq_collectgarbage(HSQUIRRELVM v)
+{
+#ifndef NO_GARBAGE_COLLECTOR
+    return _ss(v)->CollectGarbage(v);
+#else
+    return -1;
+#endif
+}
+
+SQRESULT sq_getcallee(HSQUIRRELVM v)
+{
+    if(v->_callsstacksize > 1)
+    {
+        v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);
+        return SQ_OK;
+    }
+    return sq_throwerror(v,_SC("no closure in the calls stack"));
+}
+
+const SQChar *sq_getfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
+{
+    SQObjectPtr &self=stack_get(v,idx);
+    const SQChar *name = NULL;
+    switch(type(self))
+    {
+    case OT_CLOSURE:{
+        SQClosure *clo = _closure(self);
+        SQFunctionProto *fp = clo->_function;
+        if(((SQUnsignedInteger)fp->_noutervalues) > nval) {
+            v->Push(*(_outer(clo->_outervalues[nval])->_valptr));
+            SQOuterVar &ov = fp->_outervalues[nval];
+            name = _stringval(ov._name);
+        }
+                    }
+        break;
+    case OT_NATIVECLOSURE:{
+        SQNativeClosure *clo = _nativeclosure(self);
+        if(clo->_noutervalues > nval) {
+            v->Push(clo->_outervalues[nval]);
+            name = _SC("@NATIVE");
+        }
+                          }
+        break;
+    default: break; //shutup compiler
+    }
+    return name;
+}
+
+SQRESULT sq_setfreevariable(HSQUIRRELVM v,SQInteger idx,SQUnsignedInteger nval)
+{
+    SQObjectPtr &self=stack_get(v,idx);
+    switch(type(self))
+    {
+    case OT_CLOSURE:{
+        SQFunctionProto *fp = _closure(self)->_function;
+        if(((SQUnsignedInteger)fp->_noutervalues) > nval){
+            *(_outer(_closure(self)->_outervalues[nval])->_valptr) = stack_get(v,-1);
+        }
+        else return sq_throwerror(v,_SC("invalid free var index"));
+                    }
+        break;
+    case OT_NATIVECLOSURE:
+        if(_nativeclosure(self)->_noutervalues > nval){
+            _nativeclosure(self)->_outervalues[nval] = stack_get(v,-1);
+        }
+        else return sq_throwerror(v,_SC("invalid free var index"));
+        break;
+    default:
+        return sq_aux_invalidtype(v,type(self));
+    }
+    v->Pop();
+    return SQ_OK;
+}
+
+SQRESULT sq_setattributes(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr *o = NULL;
+    _GETSAFE_OBJ(v, idx, OT_CLASS,o);
+    SQObjectPtr &key = stack_get(v,-2);
+    SQObjectPtr &val = stack_get(v,-1);
+    SQObjectPtr attrs;
+    if(type(key) == OT_NULL) {
+        attrs = _class(*o)->_attributes;
+        _class(*o)->_attributes = val;
+        v->Pop(2);
+        v->Push(attrs);
+        return SQ_OK;
+    }else if(_class(*o)->GetAttributes(key,attrs)) {
+        _class(*o)->SetAttributes(key,val);
+        v->Pop(2);
+        v->Push(attrs);
+        return SQ_OK;
+    }
+    return sq_throwerror(v,_SC("wrong index"));
+}
+
+SQRESULT sq_getattributes(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr *o = NULL;
+    _GETSAFE_OBJ(v, idx, OT_CLASS,o);
+    SQObjectPtr &key = stack_get(v,-1);
+    SQObjectPtr attrs;
+    if(type(key) == OT_NULL) {
+        attrs = _class(*o)->_attributes;
+        v->Pop();
+        v->Push(attrs);
+        return SQ_OK;
+    }
+    else if(_class(*o)->GetAttributes(key,attrs)) {
+        v->Pop();
+        v->Push(attrs);
+        return SQ_OK;
+    }
+    return sq_throwerror(v,_SC("wrong index"));
+}
+
+SQRESULT sq_getmemberhandle(HSQUIRRELVM v,SQInteger idx,HSQMEMBERHANDLE *handle)
+{
+    SQObjectPtr *o = NULL;
+    _GETSAFE_OBJ(v, idx, OT_CLASS,o);
+    SQObjectPtr &key = stack_get(v,-1);
+    SQTable *m = _class(*o)->_members;
+    SQObjectPtr val;
+    if(m->Get(key,val)) {
+        handle->_static = _isfield(val) ? SQFalse : SQTrue;
+        handle->_index = _member_idx(val);
+        v->Pop();
+        return SQ_OK;
+    }
+    return sq_throwerror(v,_SC("wrong index"));
+}
+
+SQRESULT _getmemberbyhandle(HSQUIRRELVM v,SQObjectPtr &self,const HSQMEMBERHANDLE *handle,SQObjectPtr *&val)
+{
+    switch(type(self)) {
+        case OT_INSTANCE: {
+                SQInstance *i = _instance(self);
+                if(handle->_static) {
+                    SQClass *c = i->_class;
+                    val = &c->_methods[handle->_index].val;
+                }
+                else {
+                    val = &i->_values[handle->_index];
+
+                }
+            }
+            break;
+        case OT_CLASS: {
+                SQClass *c = _class(self);
+                if(handle->_static) {
+                    val = &c->_methods[handle->_index].val;
+                }
+                else {
+                    val = &c->_defaultvalues[handle->_index].val;
+                }
+            }
+            break;
+        default:
+            return sq_throwerror(v,_SC("wrong type(expected class or instance)"));
+    }
+    return SQ_OK;
+}
+
+SQRESULT sq_getbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle)
+{
+    SQObjectPtr &self = stack_get(v,idx);
+    SQObjectPtr *val = NULL;
+    if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) {
+        return SQ_ERROR;
+    }
+    v->Push(_realval(*val));
+    return SQ_OK;
+}
+
+SQRESULT sq_setbyhandle(HSQUIRRELVM v,SQInteger idx,const HSQMEMBERHANDLE *handle)
+{
+    SQObjectPtr &self = stack_get(v,idx);
+    SQObjectPtr &newval = stack_get(v,-1);
+    SQObjectPtr *val = NULL;
+    if(SQ_FAILED(_getmemberbyhandle(v,self,handle,val))) {
+        return SQ_ERROR;
+    }
+    *val = newval;
+    v->Pop();
+    return SQ_OK;
+}
+
+SQRESULT sq_getbase(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr *o = NULL;
+    _GETSAFE_OBJ(v, idx, OT_CLASS,o);
+    if(_class(*o)->_base)
+        v->Push(SQObjectPtr(_class(*o)->_base));
+    else
+        v->PushNull();
+    return SQ_OK;
+}
+
+SQRESULT sq_getclass(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr *o = NULL;
+    _GETSAFE_OBJ(v, idx, OT_INSTANCE,o);
+    v->Push(SQObjectPtr(_instance(*o)->_class));
+    return SQ_OK;
+}
+
+SQRESULT sq_createinstance(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr *o = NULL;
+    _GETSAFE_OBJ(v, idx, OT_CLASS,o);
+    v->Push(_class(*o)->CreateInstance());
+    return SQ_OK;
+}
+
+void sq_weakref(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObject &o=stack_get(v,idx);
+    if(ISREFCOUNTED(type(o))) {
+        v->Push(_refcounted(o)->GetWeakRef(type(o)));
+        return;
+    }
+    v->Push(o);
+}
+
+SQRESULT sq_getweakrefval(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr &o = stack_get(v,idx);
+    if(type(o) != OT_WEAKREF) {
+        return sq_throwerror(v,_SC("the object must be a weakref"));
+    }
+    v->Push(_weakref(o)->_obj);
+    return SQ_OK;
+}
+
+SQRESULT sq_getdefaultdelegate(HSQUIRRELVM v,SQObjectType t)
+{
+    SQSharedState *ss = _ss(v);
+    switch(t) {
+    case OT_TABLE: v->Push(ss->_table_default_delegate); break;
+    case OT_ARRAY: v->Push(ss->_array_default_delegate); break;
+    case OT_STRING: v->Push(ss->_string_default_delegate); break;
+    case OT_INTEGER: case OT_FLOAT: v->Push(ss->_number_default_delegate); break;
+    case OT_GENERATOR: v->Push(ss->_generator_default_delegate); break;
+    case OT_CLOSURE: case OT_NATIVECLOSURE: v->Push(ss->_closure_default_delegate); break;
+    case OT_THREAD: v->Push(ss->_thread_default_delegate); break;
+    case OT_CLASS: v->Push(ss->_class_default_delegate); break;
+    case OT_INSTANCE: v->Push(ss->_instance_default_delegate); break;
+    case OT_WEAKREF: v->Push(ss->_weakref_default_delegate); break;
+    default: return sq_throwerror(v,_SC("the type doesn't have a default delegate"));
+    }
+    return SQ_OK;
+}
+
+SQRESULT sq_next(HSQUIRRELVM v,SQInteger idx)
+{
+    SQObjectPtr o=stack_get(v,idx),&refpos = stack_get(v,-1),realkey,val;
+    if(type(o) == OT_GENERATOR) {
+        return sq_throwerror(v,_SC("cannot iterate a generator"));
+    }
+    int faketojump;
+    if(!v->FOREACH_OP(o,realkey,val,refpos,0,666,faketojump))
+        return SQ_ERROR;
+    if(faketojump != 666) {
+        v->Push(realkey);
+        v->Push(val);
+        return SQ_OK;
+    }
+    return SQ_ERROR;
+}
+
+struct BufState{
+    const SQChar *buf;
+    SQInteger ptr;
+    SQInteger size;
+};
+
+SQInteger buf_lexfeed(SQUserPointer file)
+{
+    BufState *buf=(BufState*)file;
+    if(buf->size<(buf->ptr+1))
+        return 0;
+    return buf->buf[buf->ptr++];
+}
+
+SQRESULT sq_compilebuffer(HSQUIRRELVM v,const SQChar *s,SQInteger size,const SQChar *sourcename,SQBool raiseerror) {
+    BufState buf;
+    buf.buf = s;
+    buf.size = size;
+    buf.ptr = 0;
+    return sq_compile(v, buf_lexfeed, &buf, sourcename, raiseerror);
+}
+
+void sq_move(HSQUIRRELVM dest,HSQUIRRELVM src,SQInteger idx)
+{
+    dest->Push(stack_get(src,idx));
+}
+
+void sq_setprintfunc(HSQUIRRELVM v, SQPRINTFUNCTION printfunc,SQPRINTFUNCTION errfunc)
+{
+    _ss(v)->_printfunc = printfunc;
+    _ss(v)->_errorfunc = errfunc;
+}
+
+SQPRINTFUNCTION sq_getprintfunc(HSQUIRRELVM v)
+{
+    return _ss(v)->_printfunc;
+}
+
+SQPRINTFUNCTION sq_geterrorfunc(HSQUIRRELVM v)
+{
+    return _ss(v)->_errorfunc;
+}
+
+void *sq_malloc(SQUnsignedInteger size)
+{
+    return SQ_MALLOC(size);
+}
+
+void *sq_realloc(void* p,SQUnsignedInteger oldsize,SQUnsignedInteger newsize)
+{
+    return SQ_REALLOC(p,oldsize,newsize);
+}
+
+void sq_free(void *p,SQUnsignedInteger size)
+{
+    SQ_FREE(p,size);
+}

+ 94 - 94
squirrel/sqarray.h

@@ -1,94 +1,94 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQARRAY_H_
-#define _SQARRAY_H_
-
-struct SQArray : public CHAINABLE_OBJ
-{
-private:
-	SQArray(SQSharedState *ss,SQInteger nsize){_values.resize(nsize); INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}
-	~SQArray()
-	{
-		REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
-	}
-public:
-	static SQArray* Create(SQSharedState *ss,SQInteger nInitialSize){
-		SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray));
-		new (newarray) SQArray(ss,nInitialSize);
-		return newarray;
-	}
-#ifndef NO_GARBAGE_COLLECTOR
-	void Mark(SQCollectable **chain);
-	SQObjectType GetType() {return OT_ARRAY;}
-#endif
-	void Finalize(){
-		_values.resize(0);
-	}
-	bool Get(const SQInteger nidx,SQObjectPtr &val)
-	{
-		if(nidx>=0 && nidx<(SQInteger)_values.size()){
-			SQObjectPtr &o = _values[nidx];
-			val = _realval(o);
-			return true;
-		}
-		else return false;
-	}
-	bool Set(const SQInteger nidx,const SQObjectPtr &val)
-	{
-		if(nidx>=0 && nidx<(SQInteger)_values.size()){
-			_values[nidx]=val;
-			return true;
-		}
-		else return false;
-	}
-	SQInteger Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval)
-	{
-		SQUnsignedInteger idx=TranslateIndex(refpos);
-		while(idx<_values.size()){
-			//first found
-			outkey=(SQInteger)idx;
-			SQObjectPtr &o = _values[idx];
-			outval = _realval(o);
-			//return idx for the next iteration
-			return ++idx;
-		}
-		//nothing to iterate anymore
-		return -1;
-	}
-	SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),0); anew->_values.copy(_values); return anew; }
-	SQInteger Size() const {return _values.size();}
-	void Resize(SQInteger size)
-	{
-		SQObjectPtr _null;
-		Resize(size,_null);
-	}
-	void Resize(SQInteger size,SQObjectPtr &fill) { _values.resize(size,fill); ShrinkIfNeeded(); }
-	void Reserve(SQInteger size) { _values.reserve(size); }
-	void Append(const SQObject &o){_values.push_back(o);}
-	void Extend(const SQArray *a);
-	SQObjectPtr &Top(){return _values.top();}
-	void Pop(){_values.pop_back(); ShrinkIfNeeded(); }
-	bool Insert(SQInteger idx,const SQObject &val){
-		if(idx < 0 || idx > (SQInteger)_values.size())
-			return false;
-		_values.insert(idx,val);
-		return true;
-	}
-	void ShrinkIfNeeded() {
-		if(_values.size() <= _values.capacity()>>2) //shrink the array
-			_values.shrinktofit();
-	}
-	bool Remove(SQInteger idx){
-		if(idx < 0 || idx >= (SQInteger)_values.size())
-			return false;
-		_values.remove(idx);
-		ShrinkIfNeeded();
-		return true;
-	}
-	void Release()
-	{
-		sq_delete(this,SQArray);
-	}
-	
-	SQObjectPtrVec _values;
-};
-#endif //_SQARRAY_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQARRAY_H_
+#define _SQARRAY_H_
+
+struct SQArray : public CHAINABLE_OBJ
+{
+private:
+    SQArray(SQSharedState *ss,SQInteger nsize){_values.resize(nsize); INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}
+    ~SQArray()
+    {
+        REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+    }
+public:
+    static SQArray* Create(SQSharedState *ss,SQInteger nInitialSize){
+        SQArray *newarray=(SQArray*)SQ_MALLOC(sizeof(SQArray));
+        new (newarray) SQArray(ss,nInitialSize);
+        return newarray;
+    }
+#ifndef NO_GARBAGE_COLLECTOR
+    void Mark(SQCollectable **chain);
+    SQObjectType GetType() {return OT_ARRAY;}
+#endif
+    void Finalize(){
+        _values.resize(0);
+    }
+    bool Get(const SQInteger nidx,SQObjectPtr &val)
+    {
+        if(nidx>=0 && nidx<(SQInteger)_values.size()){
+            SQObjectPtr &o = _values[nidx];
+            val = _realval(o);
+            return true;
+        }
+        else return false;
+    }
+    bool Set(const SQInteger nidx,const SQObjectPtr &val)
+    {
+        if(nidx>=0 && nidx<(SQInteger)_values.size()){
+            _values[nidx]=val;
+            return true;
+        }
+        else return false;
+    }
+    SQInteger Next(const SQObjectPtr &refpos,SQObjectPtr &outkey,SQObjectPtr &outval)
+    {
+        SQUnsignedInteger idx=TranslateIndex(refpos);
+        while(idx<_values.size()){
+            //first found
+            outkey=(SQInteger)idx;
+            SQObjectPtr &o = _values[idx];
+            outval = _realval(o);
+            //return idx for the next iteration
+            return ++idx;
+        }
+        //nothing to iterate anymore
+        return -1;
+    }
+    SQArray *Clone(){SQArray *anew=Create(_opt_ss(this),0); anew->_values.copy(_values); return anew; }
+    SQInteger Size() const {return _values.size();}
+    void Resize(SQInteger size)
+    {
+        SQObjectPtr _null;
+        Resize(size,_null);
+    }
+    void Resize(SQInteger size,SQObjectPtr &fill) { _values.resize(size,fill); ShrinkIfNeeded(); }
+    void Reserve(SQInteger size) { _values.reserve(size); }
+    void Append(const SQObject &o){_values.push_back(o);}
+    void Extend(const SQArray *a);
+    SQObjectPtr &Top(){return _values.top();}
+    void Pop(){_values.pop_back(); ShrinkIfNeeded(); }
+    bool Insert(SQInteger idx,const SQObject &val){
+        if(idx < 0 || idx > (SQInteger)_values.size())
+            return false;
+        _values.insert(idx,val);
+        return true;
+    }
+    void ShrinkIfNeeded() {
+        if(_values.size() <= _values.capacity()>>2) //shrink the array
+            _values.shrinktofit();
+    }
+    bool Remove(SQInteger idx){
+        if(idx < 0 || idx >= (SQInteger)_values.size())
+            return false;
+        _values.remove(idx);
+        ShrinkIfNeeded();
+        return true;
+    }
+    void Release()
+    {
+        sq_delete(this,SQArray);
+    }
+
+    SQObjectPtrVec _values;
+};
+#endif //_SQARRAY_H_

+ 1266 - 1266
squirrel/sqbaselib.cpp

@@ -1,1266 +1,1266 @@
-/*
-	see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include "sqvm.h"
-#include "sqstring.h"
-#include "sqtable.h"
-#include "sqarray.h"
-#include "sqfuncproto.h"
-#include "sqclosure.h"
-#include "sqclass.h"
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-
-static bool str2num(const SQChar *s,SQObjectPtr &res,SQInteger base)
-{
-	SQChar *end;
-	const SQChar *e = s;
-	SQBool isfloat = SQFalse;
-	SQChar c;
-	while((c = *e) != _SC('\0'))
-	{
-		if(c == _SC('.') || c == _SC('E')|| c == _SC('e')) { //e and E is for scientific notation
-			isfloat = SQTrue;
-			break;
-		}
-		e++;
-	}
-	if(isfloat){
-		SQFloat r = SQFloat(scstrtod(s,&end));
-		if(s == end) return false;
-		res = r;
-	}
-	else{
-		SQInteger r = SQInteger(scstrtol(s,&end,(int)base));
-		if(s == end) return false;
-		res = r;
-	}
-	return true;
-}
-
-static SQInteger base_dummy(HSQUIRRELVM v)
-{
-	return 0;
-}
-
-#ifndef NO_GARBAGE_COLLECTOR
-static SQInteger base_collectgarbage(HSQUIRRELVM v)
-{
-	sq_pushinteger(v, sq_collectgarbage(v));
-	return 1;
-}
-static SQInteger base_resurectureachable(HSQUIRRELVM v)
-{
-	sq_resurrectunreachable(v);
-	return 1;
-}
-#endif
-
-static SQInteger base_getroottable(HSQUIRRELVM v)
-{
-	v->Push(v->_roottable);
-	return 1;
-}
-
-static SQInteger base_getconsttable(HSQUIRRELVM v)
-{
-	v->Push(_ss(v)->_consts);
-	return 1;
-}
-
-
-static SQInteger base_setroottable(HSQUIRRELVM v)
-{
-	SQObjectPtr o = v->_roottable;
-	if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR;
-	v->Push(o);
-	return 1;
-}
-
-static SQInteger base_setconsttable(HSQUIRRELVM v)
-{
-	SQObjectPtr o = _ss(v)->_consts;
-	if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR;
-	v->Push(o);
-	return 1;
-}
-
-static SQInteger base_seterrorhandler(HSQUIRRELVM v)
-{
-	sq_seterrorhandler(v);
-	return 0;
-}
-
-static SQInteger base_setdebughook(HSQUIRRELVM v)
-{
-	sq_setdebughook(v);
-	return 0;
-}
-
-static SQInteger base_enabledebuginfo(HSQUIRRELVM v)
-{
-	SQObjectPtr &o=stack_get(v,2);
-	
-	sq_enabledebuginfo(v,SQVM::IsFalse(o)?SQFalse:SQTrue);
-	return 0;
-}
-
-static SQInteger __getcallstackinfos(HSQUIRRELVM v,SQInteger level)
-{
-	SQStackInfos si;
-	SQInteger seq = 0;
-	const SQChar *name = NULL;
-	
-	if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))
-	{
-		const SQChar *fn = _SC("unknown");
-		const SQChar *src = _SC("unknown");
-		if(si.funcname)fn = si.funcname;
-		if(si.source)src = si.source;
-		sq_newtable(v);
-		sq_pushstring(v, _SC("func"), -1);
-		sq_pushstring(v, fn, -1);
-		sq_newslot(v, -3, SQFalse);
-		sq_pushstring(v, _SC("src"), -1);
-		sq_pushstring(v, src, -1);
-		sq_newslot(v, -3, SQFalse);
-		sq_pushstring(v, _SC("line"), -1);
-		sq_pushinteger(v, si.line);
-		sq_newslot(v, -3, SQFalse);
-		sq_pushstring(v, _SC("locals"), -1);
-		sq_newtable(v);
-		seq=0;
-		while ((name = sq_getlocal(v, level, seq))) {
-			sq_pushstring(v, name, -1);
-			sq_push(v, -2);
-			sq_newslot(v, -4, SQFalse);
-			sq_pop(v, 1);
-			seq++;
-		}
-		sq_newslot(v, -3, SQFalse);
-		return 1;
-	}
-
-	return 0;
-}
-static SQInteger base_getstackinfos(HSQUIRRELVM v)
-{
-	SQInteger level;
-	sq_getinteger(v, -1, &level);
-	return __getcallstackinfos(v,level);
-}
-
-static SQInteger base_assert(HSQUIRRELVM v)
-{
-	if(SQVM::IsFalse(stack_get(v,2))){
-		return sq_throwerror(v,_SC("assertion failed"));
-	}
-	return 0;
-}
-
-static SQInteger get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,SQObjectPtr &o)
-{
-	SQInteger top = sq_gettop(v);
-	sidx=0;
-	eidx=0;
-	o=stack_get(v,1);
-	if(top>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;
-	if(SQ_SUCCEEDED(sq_tostring(v,2)))
-	{
- 		if(SQ_SUCCEEDED(sq_getstring(v,-1,&str))) {
-			if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str);
-			return 0;
-		}
-	}
-	return SQ_ERROR;
-}
-
-static SQInteger base_error(HSQUIRRELVM v)
-{
-	const SQChar *str;
-	if(SQ_SUCCEEDED(sq_tostring(v,2)))
-	{
- 		if(SQ_SUCCEEDED(sq_getstring(v,-1,&str))) {
-			if(_ss(v)->_errorfunc) _ss(v)->_errorfunc(v,_SC("%s"),str);
-			return 0;
-		}
-	}
-	return SQ_ERROR;
-}
-
-static SQInteger base_compilestring(HSQUIRRELVM v)
-{
-	SQInteger nargs=sq_gettop(v);
-	const SQChar *src=NULL,*name=_SC("unnamedbuffer");
-	SQInteger size;
-	sq_getstring(v,2,&src);
-	size=sq_getsize(v,2);
-	if(nargs>2){
-		sq_getstring(v,3,&name);
-	}
-	if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse)))
-		return 1;
-	else
-		return SQ_ERROR;
-}
-
-static SQInteger base_newthread(HSQUIRRELVM v)
-{
-	SQObjectPtr &func = stack_get(v,2);
-	SQInteger stksize = (_closure(func)->_function->_stacksize << 1) +2;
-	HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize);
-	sq_move(newv,v,-2);
-	return 1;
-}
-
-static SQInteger base_suspend(HSQUIRRELVM v)
-{
-	return sq_suspendvm(v);
-}
-
-static SQInteger base_array(HSQUIRRELVM v)
-{
-	SQArray *a;
-	SQObject &size = stack_get(v,2);
-	if(sq_gettop(v) > 2) {
-		a = SQArray::Create(_ss(v),0);
-		a->Resize(tointeger(size),stack_get(v,3));
-	}
-	else {
-		a = SQArray::Create(_ss(v),tointeger(size));
-	}
-	v->Push(a);
-	return 1;
-}
-
-static SQInteger base_type(HSQUIRRELVM v)
-{
-	SQObjectPtr &o = stack_get(v,2);
-	v->Push(SQString::Create(_ss(v),GetTypeName(o),-1));
-	return 1;
-}
-
-static SQInteger base_callee(HSQUIRRELVM v)
-{
-	if(v->_callsstacksize > 1)
-	{
-		v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);
-		return 1;
-	}
-	return sq_throwerror(v,_SC("no closure in the calls stack"));
-}
-
-static SQRegFunction base_funcs[]={
-	//generic
-	{_SC("seterrorhandler"),base_seterrorhandler,2, NULL},
-	{_SC("setdebughook"),base_setdebughook,2, NULL},
-	{_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL},
-	{_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},
-	{_SC("getroottable"),base_getroottable,1, NULL},
-	{_SC("setroottable"),base_setroottable,2, NULL},
-	{_SC("getconsttable"),base_getconsttable,1, NULL},
-	{_SC("setconsttable"),base_setconsttable,2, NULL},
-	{_SC("assert"),base_assert,2, NULL},
-	{_SC("print"),base_print,2, NULL},
-	{_SC("error"),base_error,2, NULL},
-	{_SC("compilestring"),base_compilestring,-2, _SC(".ss")},
-	{_SC("newthread"),base_newthread,2, _SC(".c")},
-	{_SC("suspend"),base_suspend,-1, NULL},
-	{_SC("array"),base_array,-2, _SC(".n")},
-	{_SC("type"),base_type,2, NULL},
-	{_SC("callee"),base_callee,0,NULL},
-	{_SC("dummy"),base_dummy,0,NULL},
-#ifndef NO_GARBAGE_COLLECTOR
-	{_SC("collectgarbage"),base_collectgarbage,0, NULL},
-	{_SC("resurrectunreachable"),base_resurectureachable,0, NULL},
-#endif
-	{0,0}
-};
-
-void sq_base_register(HSQUIRRELVM v)
-{
-	SQInteger i=0;
-	sq_pushroottable(v);
-	while(base_funcs[i].name!=0) {
-		sq_pushstring(v,base_funcs[i].name,-1);
-		sq_newclosure(v,base_funcs[i].f,0);
-		sq_setnativeclosurename(v,-1,base_funcs[i].name);
-		sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);
-		sq_newslot(v,-3, SQFalse);
-		i++;
-	}
-	
-	sq_pushstring(v,_SC("_versionnumber_"),-1);
-	sq_pushinteger(v,SQUIRREL_VERSION_NUMBER);
-	sq_newslot(v,-3, SQFalse);
-	sq_pushstring(v,_SC("_version_"),-1);
-	sq_pushstring(v,SQUIRREL_VERSION,-1);
-	sq_newslot(v,-3, SQFalse);
-	sq_pushstring(v,_SC("_charsize_"),-1);
-	sq_pushinteger(v,sizeof(SQChar));
-	sq_newslot(v,-3, SQFalse);
-	sq_pushstring(v,_SC("_intsize_"),-1);
-	sq_pushinteger(v,sizeof(SQInteger));
-	sq_newslot(v,-3, SQFalse);
-	sq_pushstring(v,_SC("_floatsize_"),-1);
-	sq_pushinteger(v,sizeof(SQFloat));
-	sq_newslot(v,-3, SQFalse);
-	sq_pop(v,1);
-}
-
-static SQInteger default_delegate_len(HSQUIRRELVM v)
-{
-	v->Push(SQInteger(sq_getsize(v,1)));
-	return 1;
-}
-
-static SQInteger default_delegate_tofloat(HSQUIRRELVM v)
-{
-	SQObjectPtr &o=stack_get(v,1);
-	switch(type(o)){
-	case OT_STRING:{
-		SQObjectPtr res;
-		if(str2num(_stringval(o),res,10)){
-			v->Push(SQObjectPtr(tofloat(res)));
-			break;
-		}}
-		return sq_throwerror(v, _SC("cannot convert the string"));
-		break;
-	case OT_INTEGER:case OT_FLOAT:
-		v->Push(SQObjectPtr(tofloat(o)));
-		break;
-	case OT_BOOL:
-		v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0)));
-		break;
-	default:
-		v->PushNull();
-		break;
-	}
-	return 1;
-}
-
-static SQInteger default_delegate_tointeger(HSQUIRRELVM v)
-{
-	SQObjectPtr &o=stack_get(v,1);
-	SQInteger base = 10;
-	if(sq_gettop(v) > 1) {
-		sq_getinteger(v,2,&base);
-	}
-	switch(type(o)){
-	case OT_STRING:{
-		SQObjectPtr res;
-		if(str2num(_stringval(o),res,base)){
-			v->Push(SQObjectPtr(tointeger(res)));
-			break;
-		}}
-		return sq_throwerror(v, _SC("cannot convert the string"));
-		break;
-	case OT_INTEGER:case OT_FLOAT:
-		v->Push(SQObjectPtr(tointeger(o)));
-		break;
-	case OT_BOOL:
-		v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0));
-		break;
-	default:
-		v->PushNull();
-		break;
-	}
-	return 1;
-}
-
-static SQInteger default_delegate_tostring(HSQUIRRELVM v)
-{
-	if(SQ_FAILED(sq_tostring(v,1)))
-		return SQ_ERROR;
-	return 1;
-}
-
-static SQInteger obj_delegate_weakref(HSQUIRRELVM v)
-{
-	sq_weakref(v,1);
-	return 1;
-}
-
-static SQInteger obj_clear(HSQUIRRELVM v)
-{
-	return sq_clear(v,-1);
-}
-
-
-static SQInteger number_delegate_tochar(HSQUIRRELVM v)
-{
-	SQObject &o=stack_get(v,1);
-	SQChar c = (SQChar)tointeger(o);
-	v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1));
-	return 1;
-}
-
-
-
-/////////////////////////////////////////////////////////////////
-//TABLE DEFAULT DELEGATE
-
-static SQInteger table_rawdelete(HSQUIRRELVM v)
-{
-	if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue)))
-		return SQ_ERROR;
-	return 1;
-}
-
-
-static SQInteger container_rawexists(HSQUIRRELVM v)
-{
-	if(SQ_SUCCEEDED(sq_rawget(v,-2))) {
-		sq_pushbool(v,SQTrue);
-		return 1;
-	}
-	sq_pushbool(v,SQFalse);
-	return 1;
-}
-
-static SQInteger container_rawset(HSQUIRRELVM v)
-{
-	return sq_rawset(v,-3);
-}
-
-
-static SQInteger container_rawget(HSQUIRRELVM v)
-{
-	return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;
-}
-
-static SQInteger table_setdelegate(HSQUIRRELVM v)
-{
-	if(SQ_FAILED(sq_setdelegate(v,-2)))
-		return SQ_ERROR;
-	sq_push(v,-1); // -1 because sq_setdelegate pops 1
-	return 1;
-}
-
-static SQInteger table_getdelegate(HSQUIRRELVM v)
-{
-	return SQ_SUCCEEDED(sq_getdelegate(v,-1))?1:SQ_ERROR;
-}
-
-SQRegFunction SQSharedState::_table_default_delegate_funcz[]={
-	{_SC("len"),default_delegate_len,1, _SC("t")},
-	{_SC("rawget"),container_rawget,2, _SC("t")},
-	{_SC("rawset"),container_rawset,3, _SC("t")},
-	{_SC("rawdelete"),table_rawdelete,2, _SC("t")},
-	{_SC("rawin"),container_rawexists,2, _SC("t")},
-	{_SC("weakref"),obj_delegate_weakref,1, NULL },
-	{_SC("tostring"),default_delegate_tostring,1, _SC(".")},
-	{_SC("clear"),obj_clear,1, _SC(".")},
-	{_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")},
-	{_SC("getdelegate"),table_getdelegate,1, _SC(".")},
-	{0,0}
-};
-
-//ARRAY DEFAULT DELEGATE///////////////////////////////////////
-
-static SQInteger array_append(HSQUIRRELVM v)
-{
-	return sq_arrayappend(v,-2);
-}
-
-static SQInteger array_extend(HSQUIRRELVM v)
-{
-	_array(stack_get(v,1))->Extend(_array(stack_get(v,2)));
-	return 0;
-}
-
-static SQInteger array_reverse(HSQUIRRELVM v)
-{
-	return sq_arrayreverse(v,-1);
-}
-
-static SQInteger array_pop(HSQUIRRELVM v)
-{
-	return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR;
-}
-
-static SQInteger array_top(HSQUIRRELVM v)
-{
-	SQObject &o=stack_get(v,1);
-	if(_array(o)->Size()>0){
-		v->Push(_array(o)->Top());
-		return 1;
-	}
-	else return sq_throwerror(v,_SC("top() on a empty array"));
-}
-
-static SQInteger array_insert(HSQUIRRELVM v)
-{
-	SQObject &o=stack_get(v,1);
-	SQObject &idx=stack_get(v,2);
-	SQObject &val=stack_get(v,3);
-	if(!_array(o)->Insert(tointeger(idx),val))
-		return sq_throwerror(v,_SC("index out of range"));
-	return 0;
-}
-
-static SQInteger array_remove(HSQUIRRELVM v)
-{
-	SQObject &o = stack_get(v, 1);
-	SQObject &idx = stack_get(v, 2);
-	if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type"));
-	SQObjectPtr val;
-	if(_array(o)->Get(tointeger(idx), val)) {
-		_array(o)->Remove(tointeger(idx));
-		v->Push(val);
-		return 1;
-	}
-	return sq_throwerror(v, _SC("idx out of range"));
-}
-
-static SQInteger array_resize(HSQUIRRELVM v)
-{
-	SQObject &o = stack_get(v, 1);
-	SQObject &nsize = stack_get(v, 2);
-	SQObjectPtr fill;
-	if(sq_isnumeric(nsize)) {
-		if(sq_gettop(v) > 2)
-			fill = stack_get(v, 3);
-		_array(o)->Resize(tointeger(nsize),fill);
-		return 0;
-	}
-	return sq_throwerror(v, _SC("size must be a number"));
-}
-
-static SQInteger __map_array(SQArray *dest,SQArray *src,HSQUIRRELVM v) {
-	SQObjectPtr temp;
-	SQInteger size = src->Size();
-	for(SQInteger n = 0; n < size; n++) {
-		src->Get(n,temp);
-		v->Push(src);
-		v->Push(temp);
-		if(SQ_FAILED(sq_call(v,2,SQTrue,SQFalse))) {
-			return SQ_ERROR;
-		}
-		dest->Set(n,v->GetUp(-1));
-		v->Pop();
-	}
-	return 0;
-}
-
-static SQInteger array_map(HSQUIRRELVM v)
-{
-	SQObject &o = stack_get(v,1);
-	SQInteger size = _array(o)->Size();
-	SQObjectPtr ret = SQArray::Create(_ss(v),size);
-	if(SQ_FAILED(__map_array(_array(ret),_array(o),v)))
-		return SQ_ERROR;
-	v->Push(ret);
-	return 1;
-}
-
-static SQInteger array_apply(HSQUIRRELVM v)
-{
-	SQObject &o = stack_get(v,1);
-	if(SQ_FAILED(__map_array(_array(o),_array(o),v)))
-		return SQ_ERROR;
-	return 0;
-}
-
-static SQInteger array_reduce(HSQUIRRELVM v)
-{
-	SQObject &o = stack_get(v,1);
-	SQArray *a = _array(o);
-	SQInteger size = a->Size();
-	if(size == 0) {
-		return 0;
-	}
-	SQObjectPtr res;
-	a->Get(0,res);
-	if(size > 1) {
-		SQObjectPtr other;
-		for(SQInteger n = 1; n < size; n++) {
-			a->Get(n,other);
-			v->Push(o);
-			v->Push(res);
-			v->Push(other);
-			if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {
-				return SQ_ERROR;
-			}
-			res = v->GetUp(-1);
-			v->Pop();
-		}
-	}
-	v->Push(res);
-	return 1;
-}
-
-static SQInteger array_filter(HSQUIRRELVM v)
-{
-	SQObject &o = stack_get(v,1);
-	SQArray *a = _array(o);
-	SQObjectPtr ret = SQArray::Create(_ss(v),0);
-	SQInteger size = a->Size();
-	SQObjectPtr val;
-	for(SQInteger n = 0; n < size; n++) {
-		a->Get(n,val);
-		v->Push(o);
-		v->Push(n);
-		v->Push(val);
-		if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {
-			return SQ_ERROR;
-		}
-		if(!SQVM::IsFalse(v->GetUp(-1))) {
-			_array(ret)->Append(val);
-		}
-		v->Pop();
-	}
-	v->Push(ret);
-	return 1;
-}
-
-static SQInteger array_find(HSQUIRRELVM v)
-{
-	SQObject &o = stack_get(v,1);
-	SQObjectPtr &val = stack_get(v,2);
-	SQArray *a = _array(o);
-	SQInteger size = a->Size();
-	SQObjectPtr temp;
-	for(SQInteger n = 0; n < size; n++) {
-		bool res = false;
-		a->Get(n,temp);
-		if(SQVM::IsEqual(temp,val,res) && res) {
-			v->Push(n);
-			return 1;
-		}
-	}
-	return 0;
-}
-
-
-static bool _sort_compare(HSQUIRRELVM v,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;
-		}
-		if(SQ_FAILED(sq_getinteger(v, -1, &ret))) {
-			v->Raise_Error(_SC("numeric value expected as return value of the compare function"));
-			return false;
-		}
-		sq_settop(v, top);
-		return true;
-	}
-	return true;
-}
-
-static bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, SQInteger root, SQInteger bottom, SQInteger func)
-{
-	SQInteger maxChild;
-	SQInteger done = 0;
-	SQInteger ret;
-	SQInteger root2;
-	while (((root2 = root * 2) <= bottom) && (!done))
-	{
-		if (root2 == bottom) {
-			maxChild = root2;
-		}
-		else {
-			if(!_sort_compare(v,arr->_values[root2],arr->_values[root2 + 1],func,ret))
-				return false;
-			if (ret > 0) {
-				maxChild = root2;
-			}
-			else {
-				maxChild = root2 + 1;
-			}
-		}
-
-		if(!_sort_compare(v,arr->_values[root],arr->_values[maxChild],func,ret))
-			return false;
-		if (ret < 0) {
-			if (root == maxChild) {
-                v->Raise_Error(_SC("inconsistent compare function"));
-                return false; // We'd be swapping ourselve. The compare function is incorrect
-            }
-
-			_Swap(arr->_values[root],arr->_values[maxChild]);
-			root = maxChild;
-		}
-		else {
-			done = 1;
-		}
-	}
-	return true;
-}
-
-static bool _hsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger l, SQInteger r,SQInteger func)
-{
-	SQArray *a = _array(arr);
-	SQInteger i;
-	SQInteger array_size = a->Size();
-	for (i = (array_size / 2); i >= 0; i--) {
-		if(!_hsort_sift_down(v,a, i, array_size - 1,func)) return false;
-	}
-
-	for (i = array_size-1; i >= 1; i--)
-	{
-		_Swap(a->_values[0],a->_values[i]);
-		if(!_hsort_sift_down(v,a, 0, i-1,func)) return false;
-	}
-	return true;
-}
-
-static SQInteger array_sort(HSQUIRRELVM v)
-{
-	SQInteger func = -1;
-	SQObjectPtr &o = stack_get(v,1);
-	if(_array(o)->Size() > 1) {
-		if(sq_gettop(v) == 2) func = 2;
-		if(!_hsort(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 || sidx < 0)return sq_throwerror(v, _SC("slice out of range"));
-	SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);
-	SQObjectPtr t;
-	SQInteger count=0;
-	for(SQInteger i=sidx;i<eidx;i++){
-		_array(o)->Get(i,t);
-		arr->Set(count++,t);
-	}
-	v->Push(arr);
-	return 1;
-	
-}
-
-SQRegFunction SQSharedState::_array_default_delegate_funcz[]={
-	{_SC("len"),default_delegate_len,1, _SC("a")},
-	{_SC("append"),array_append,2, _SC("a")},
-	{_SC("extend"),array_extend,2, _SC("aa")},
-	{_SC("push"),array_append,2, _SC("a")},
-	{_SC("pop"),array_pop,1, _SC("a")},
-	{_SC("top"),array_top,1, _SC("a")},
-	{_SC("insert"),array_insert,3, _SC("an")},
-	{_SC("remove"),array_remove,2, _SC("an")},
-	{_SC("resize"),array_resize,-2, _SC("an")},
-	{_SC("reverse"),array_reverse,1, _SC("a")},
-	{_SC("sort"),array_sort,-1, _SC("ac")},
-	{_SC("slice"),array_slice,-1, _SC("ann")},
-	{_SC("weakref"),obj_delegate_weakref,1, NULL },
-	{_SC("tostring"),default_delegate_tostring,1, _SC(".")},
-	{_SC("clear"),obj_clear,1, _SC(".")},
-	{_SC("map"),array_map,2, _SC("ac")}, 
-	{_SC("apply"),array_apply,2, _SC("ac")}, 
-	{_SC("reduce"),array_reduce,2, _SC("ac")}, 
-	{_SC("filter"),array_filter,2, _SC("ac")},
-	{_SC("find"),array_find,2, _SC("a.")},
-	{0,0}
-};
-
-//STRING DEFAULT DELEGATE//////////////////////////
-static SQInteger string_slice(HSQUIRRELVM v)
-{
-	SQInteger sidx,eidx;
-	SQObjectPtr o;
-	if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;
-	SQInteger slen = _string(o)->_len;
-	if(sidx < 0)sidx = slen + sidx;
-	if(eidx < 0)eidx = slen + eidx;
-	if(eidx < sidx)	return sq_throwerror(v,_SC("wrong indexes"));
-	if(eidx > slen || sidx < 0)	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) \
-{\
-	SQInteger sidx,eidx; \
-	SQObjectPtr str; \
-	if(SQ_FAILED(get_slice_params(v,sidx,eidx,str)))return -1; \
-	SQInteger slen = _string(str)->_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 || sidx < 0)	return sq_throwerror(v,_SC("slice out of range")); \
-	SQInteger len=_string(str)->_len; \
-	const SQChar *sthis=_stringval(str); \
-	SQChar *snew=(_ss(v)->GetScratchPad(sq_rsl(len))); \
-	memcpy(snew,sthis,sq_rsl(len));\
-	for(SQInteger i=sidx;i<eidx;i++) snew[i] = func(sthis[i]); \
-	v->Push(SQString::Create(_ss(v),snew,len)); \
-	return 1; \
-}
-
-
-STRING_TOFUNCZ(tolower)
-STRING_TOFUNCZ(toupper)
-
-SQRegFunction SQSharedState::_string_default_delegate_funcz[]={
-	{_SC("len"),default_delegate_len,1, _SC("s")},
-	{_SC("tointeger"),default_delegate_tointeger,-1, _SC("sn")},
-	{_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 n n")},
-	{_SC("toupper"),string_toupper,-1, _SC("s n n")},
-	{_SC("weakref"),obj_delegate_weakref,1, NULL },
-	{0,0}
-};
-
-//INTEGER DEFAULT DELEGATE//////////////////////////
-SQRegFunction SQSharedState::_number_default_delegate_funcz[]={
-	{_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")},
-	{_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")},
-	{_SC("tostring"),default_delegate_tostring,1, _SC(".")},
-	{_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},
-	{_SC("weakref"),obj_delegate_weakref,1, NULL },
-	{0,0}
-};
-
-//CLOSURE DEFAULT DELEGATE//////////////////////////
-static SQInteger closure_pcall(HSQUIRRELVM v)
-{
-	return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQFalse))?1:SQ_ERROR;
-}
-
-static SQInteger closure_call(HSQUIRRELVM v)
-{
-	return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQTrue))?1:SQ_ERROR;
-}
-
-static SQInteger _closure_acall(HSQUIRRELVM v,SQBool raiseerror)
-{
-	SQArray *aparams=_array(stack_get(v,2));
-	SQInteger nparams=aparams->Size();
-	v->Push(stack_get(v,1));
-	for(SQInteger i=0;i<nparams;i++)v->Push(aparams->_values[i]);
-	return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue,raiseerror))?1:SQ_ERROR;
-}
-
-static SQInteger closure_acall(HSQUIRRELVM v)
-{
-	return _closure_acall(v,SQTrue);
-}
-
-static SQInteger closure_pacall(HSQUIRRELVM v)
-{
-	return _closure_acall(v,SQFalse);
-}
-
-static SQInteger closure_bindenv(HSQUIRRELVM v)
-{
-	if(SQ_FAILED(sq_bindenv(v,1)))
-		return SQ_ERROR;
-	return 1;
-}
-
-static SQInteger closure_getroot(HSQUIRRELVM v)
-{
-	if(SQ_FAILED(sq_getclosureroot(v,-1)))
-		return SQ_ERROR;
-	return 1;
-}
-
-static SQInteger closure_setroot(HSQUIRRELVM v)
-{
-	if(SQ_FAILED(sq_setclosureroot(v,-2)))
-		return SQ_ERROR;
-	return 1;
-}
-
-static SQInteger closure_getinfos(HSQUIRRELVM v) {
-	SQObject o = stack_get(v,1);
-	SQTable *res = SQTable::Create(_ss(v),4);
-	if(type(o) == OT_CLOSURE) {
-		SQFunctionProto *f = _closure(o)->_function;
-		SQInteger nparams = f->_nparameters + (f->_varparams?1:0);
-		SQObjectPtr params = SQArray::Create(_ss(v),nparams);
-    SQObjectPtr defparams = SQArray::Create(_ss(v),f->_ndefaultparams);
-		for(SQInteger n = 0; n<f->_nparameters; n++) {
-			_array(params)->Set((SQInteger)n,f->_parameters[n]);
-		}
-    for(SQInteger j = 0; j<f->_ndefaultparams; j++) {
-			_array(defparams)->Set((SQInteger)j,_closure(o)->_defaultparams[j]);
-		}
-		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);
-    res->NewSlot(SQString::Create(_ss(v),_SC("defparams"),-1),defparams);
-	}
-	else { //OT_NATIVECLOSURE 
-		SQNativeClosure *nc = _nativeclosure(o);
-		res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),true);
-		res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),nc->_name);
-		res->NewSlot(SQString::Create(_ss(v),_SC("paramscheck"),-1),nc->_nparamscheck);
-		SQObjectPtr typecheck;
-		if(nc->_typecheck.size() > 0) {
-			typecheck =
-				SQArray::Create(_ss(v), nc->_typecheck.size());
-			for(SQUnsignedInteger n = 0; n<nc->_typecheck.size(); n++) {
-					_array(typecheck)->Set((SQInteger)n,nc->_typecheck[n]);
-			}
-		}
-		res->NewSlot(SQString::Create(_ss(v),_SC("typecheck"),-1),typecheck);
-	}
-	v->Push(res);
-	return 1;
-}
-
-
-
-SQRegFunction SQSharedState::_closure_default_delegate_funcz[]={
-	{_SC("call"),closure_call,-1, _SC("c")},
-	{_SC("pcall"),closure_pcall,-1, _SC("c")},
-	{_SC("acall"),closure_acall,2, _SC("ca")},
-	{_SC("pacall"),closure_pacall,2, _SC("ca")},
-	{_SC("weakref"),obj_delegate_weakref,1, NULL },
-	{_SC("tostring"),default_delegate_tostring,1, _SC(".")},
-	{_SC("bindenv"),closure_bindenv,2, _SC("c x|y|t")},
-	{_SC("getinfos"),closure_getinfos,1, _SC("c")},
-	{_SC("getroot"),closure_getroot,1, _SC("c")},
-	{_SC("setroot"),closure_setroot,2, _SC("ct")},
-	{0,0}
-};
-
-//GENERATOR DEFAULT DELEGATE
-static SQInteger generator_getstatus(HSQUIRRELVM v)
-{
-	SQObject &o=stack_get(v,1);
-	switch(_generator(o)->_state){
-		case SQGenerator::eSuspended:v->Push(SQString::Create(_ss(v),_SC("suspended")));break;
-		case SQGenerator::eRunning:v->Push(SQString::Create(_ss(v),_SC("running")));break;
-		case SQGenerator::eDead:v->Push(SQString::Create(_ss(v),_SC("dead")));break;
-	}
-	return 1;
-}
-
-SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={
-	{_SC("getstatus"),generator_getstatus,1, _SC("g")},
-	{_SC("weakref"),obj_delegate_weakref,1, NULL },
-	{_SC("tostring"),default_delegate_tostring,1, _SC(".")},
-	{0,0}
-};
-
-//THREAD DEFAULT DELEGATE
-static SQInteger thread_call(HSQUIRRELVM v)
-{
-	SQObjectPtr o = stack_get(v,1);
-	if(type(o) == OT_THREAD) {
-		SQInteger nparams = sq_gettop(v);
-		_thread(o)->Push(_thread(o)->_roottable);
-		for(SQInteger i = 2; i<(nparams+1); i++)
-			sq_move(_thread(o),v,i);
-		if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQTrue))) {
-			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?SQTrue:SQFalse;
-		if(wakeupret) {
-			sq_move(thread,v,2);
-		}
-		if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,SQTrue,SQTrue,SQFalse))) {
-			sq_move(v,thread,-1);
-			sq_pop(thread,1); //pop retval
-			if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {
-				sq_settop(thread,1); //pop roottable
-			}
-			return 1;
-		}
-		sq_settop(thread,1);
-		v->_lasterror = thread->_lasterror;
-		return SQ_ERROR;
-	}
-	return sq_throwerror(v,_SC("wrong parameter"));
-}
-
-static SQInteger thread_wakeupthrow(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;
-			}
-		}
-			
-		sq_move(thread,v,2);
-		sq_throwobject(thread);
-		SQBool rethrow_error = SQTrue;
-		if(sq_gettop(v) > 2) {
-			sq_getbool(v,3,&rethrow_error);
-		}
-		if(SQ_SUCCEEDED(sq_wakeupvm(thread,SQFalse,SQTrue,SQTrue,SQTrue))) {
-			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);
-		if(rethrow_error) {
-			v->_lasterror = thread->_lasterror;
-			return SQ_ERROR;
-		}
-		return SQ_OK;
-	}
-	return sq_throwerror(v,_SC("wrong parameter"));
-}
-
-static SQInteger thread_getstatus(HSQUIRRELVM v)
-{
-	SQObjectPtr &o = stack_get(v,1);
-	switch(sq_getvmstate(_thread(o))) {
-		case SQ_VMSTATE_IDLE:
-			sq_pushstring(v,_SC("idle"),-1);
-		break;
-		case SQ_VMSTATE_RUNNING:
-			sq_pushstring(v,_SC("running"),-1);
-		break;
-		case SQ_VMSTATE_SUSPENDED:
-			sq_pushstring(v,_SC("suspended"),-1);
-		break;
-		default:
-			return sq_throwerror(v,_SC("internal VM error"));
-	}
-	return 1;
-}
-
-static SQInteger thread_getstackinfos(HSQUIRRELVM v)
-{
-	SQObjectPtr o = stack_get(v,1);
-	if(type(o) == OT_THREAD) {
-		SQVM *thread = _thread(o);
-		SQInteger threadtop = sq_gettop(thread);
-		SQInteger level;
-		sq_getinteger(v,-1,&level);
-		SQRESULT res = __getcallstackinfos(thread,level);
-		if(SQ_FAILED(res))
-		{
-			sq_settop(thread,threadtop);
-			if(type(thread->_lasterror) == OT_STRING) {
-				sq_throwerror(v,_stringval(thread->_lasterror));
-			}
-			else {
-				sq_throwerror(v,_SC("unknown error"));
-			}
-		}
-		if(res > 0) {
-			//some result
-			sq_move(v,thread,-1);
-			sq_settop(thread,threadtop);
-			return 1;
-		}
-		//no result
-		sq_settop(thread,threadtop);
-		return 0;
-		
-	}
-	return sq_throwerror(v,_SC("wrong parameter"));
-}
-
-SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {
-	{_SC("call"), thread_call, -1, _SC("v")},
-	{_SC("wakeup"), thread_wakeup, -1, _SC("v")},
-	{_SC("wakeupthrow"), thread_wakeupthrow, -2, _SC("v.b")},
-	{_SC("getstatus"), thread_getstatus, 1, _SC("v")},
-	{_SC("weakref"),obj_delegate_weakref,1, NULL },
-	{_SC("getstackinfos"),thread_getstackinfos,2, _SC("vn")},
-	{_SC("tostring"),default_delegate_tostring,1, _SC(".")},
-	{0,0},
-};
-
-static SQInteger class_getattributes(HSQUIRRELVM v)
-{
-	return SQ_SUCCEEDED(sq_getattributes(v,-2))?1:SQ_ERROR;
-}
-
-static SQInteger class_setattributes(HSQUIRRELVM v)
-{
-	return SQ_SUCCEEDED(sq_setattributes(v,-3))?1:SQ_ERROR;
-}
-
-static SQInteger class_instance(HSQUIRRELVM v)
-{
-	return SQ_SUCCEEDED(sq_createinstance(v,-1))?1:SQ_ERROR;
-}
-
-static SQInteger class_getbase(HSQUIRRELVM v)
-{
-	return SQ_SUCCEEDED(sq_getbase(v,-1))?1:SQ_ERROR;
-}
-
-static SQInteger class_newmember(HSQUIRRELVM v)
-{
-	SQInteger top = sq_gettop(v);
-	SQBool bstatic = SQFalse;
-	if(top == 5)
-	{
-		sq_tobool(v,-1,&bstatic);
-		sq_pop(v,1);
-	}
-
-	if(top < 4) {
-		sq_pushnull(v);
-	}
-	return SQ_SUCCEEDED(sq_newmember(v,-4,bstatic))?1:SQ_ERROR;
-}
-
-static SQInteger class_rawnewmember(HSQUIRRELVM v)
-{
-	SQInteger top = sq_gettop(v);
-	SQBool bstatic = SQFalse;
-	if(top == 5)
-	{
-		sq_tobool(v,-1,&bstatic);
-		sq_pop(v,1);
-	}
-
-	if(top < 4) {
-		sq_pushnull(v);
-	}
-	return SQ_SUCCEEDED(sq_rawnewmember(v,-4,bstatic))?1:SQ_ERROR;
-}
-
-SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {
-	{_SC("getattributes"), class_getattributes, 2, _SC("y.")},
-	{_SC("setattributes"), class_setattributes, 3, _SC("y..")},
-	{_SC("rawget"),container_rawget,2, _SC("y")},
-	{_SC("rawset"),container_rawset,3, _SC("y")},
-	{_SC("rawin"),container_rawexists,2, _SC("y")},
-	{_SC("weakref"),obj_delegate_weakref,1, NULL },
-	{_SC("tostring"),default_delegate_tostring,1, _SC(".")},
-	{_SC("instance"),class_instance,1, _SC("y")},
-	{_SC("getbase"),class_getbase,1, _SC("y")},
-	{_SC("newmember"),class_newmember,-3, _SC("y")},
-	{_SC("rawnewmember"),class_rawnewmember,-3, _SC("y")},
-	{0,0}
-};
-
-
-static SQInteger instance_getclass(HSQUIRRELVM v)
-{
-	if(SQ_SUCCEEDED(sq_getclass(v,1)))
-		return 1;
-	return SQ_ERROR;
-}
-
-SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {
-	{_SC("getclass"), instance_getclass, 1, _SC("x")},
-	{_SC("rawget"),container_rawget,2, _SC("x")},
-	{_SC("rawset"),container_rawset,3, _SC("x")},
-	{_SC("rawin"),container_rawexists,2, _SC("x")},
-	{_SC("weakref"),obj_delegate_weakref,1, NULL },
-	{_SC("tostring"),default_delegate_tostring,1, _SC(".")},
-	{0,0}
-};
-
-static SQInteger weakref_ref(HSQUIRRELVM v)
-{
-	if(SQ_FAILED(sq_getweakrefval(v,1)))
-		return SQ_ERROR;
-	return 1;
-}
-
-SQRegFunction SQSharedState::_weakref_default_delegate_funcz[] = {
-	{_SC("ref"),weakref_ref,1, _SC("r")},
-	{_SC("weakref"),obj_delegate_weakref,1, NULL },
-	{_SC("tostring"),default_delegate_tostring,1, _SC(".")},
-	{0,0}
-};
-
+/*
+    see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqvm.h"
+#include "sqstring.h"
+#include "sqtable.h"
+#include "sqarray.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+#include "sqclass.h"
+#include <stdlib.h>
+#include <stdarg.h>
+#include <ctype.h>
+
+static bool str2num(const SQChar *s,SQObjectPtr &res,SQInteger base)
+{
+    SQChar *end;
+    const SQChar *e = s;
+    SQBool isfloat = SQFalse;
+    SQChar c;
+    while((c = *e) != _SC('\0'))
+    {
+        if(c == _SC('.') || c == _SC('E')|| c == _SC('e')) { //e and E is for scientific notation
+            isfloat = SQTrue;
+            break;
+        }
+        e++;
+    }
+    if(isfloat){
+        SQFloat r = SQFloat(scstrtod(s,&end));
+        if(s == end) return false;
+        res = r;
+    }
+    else{
+        SQInteger r = SQInteger(scstrtol(s,&end,(int)base));
+        if(s == end) return false;
+        res = r;
+    }
+    return true;
+}
+
+static SQInteger base_dummy(HSQUIRRELVM v)
+{
+    return 0;
+}
+
+#ifndef NO_GARBAGE_COLLECTOR
+static SQInteger base_collectgarbage(HSQUIRRELVM v)
+{
+    sq_pushinteger(v, sq_collectgarbage(v));
+    return 1;
+}
+static SQInteger base_resurectureachable(HSQUIRRELVM v)
+{
+    sq_resurrectunreachable(v);
+    return 1;
+}
+#endif
+
+static SQInteger base_getroottable(HSQUIRRELVM v)
+{
+    v->Push(v->_roottable);
+    return 1;
+}
+
+static SQInteger base_getconsttable(HSQUIRRELVM v)
+{
+    v->Push(_ss(v)->_consts);
+    return 1;
+}
+
+
+static SQInteger base_setroottable(HSQUIRRELVM v)
+{
+    SQObjectPtr o = v->_roottable;
+    if(SQ_FAILED(sq_setroottable(v))) return SQ_ERROR;
+    v->Push(o);
+    return 1;
+}
+
+static SQInteger base_setconsttable(HSQUIRRELVM v)
+{
+    SQObjectPtr o = _ss(v)->_consts;
+    if(SQ_FAILED(sq_setconsttable(v))) return SQ_ERROR;
+    v->Push(o);
+    return 1;
+}
+
+static SQInteger base_seterrorhandler(HSQUIRRELVM v)
+{
+    sq_seterrorhandler(v);
+    return 0;
+}
+
+static SQInteger base_setdebughook(HSQUIRRELVM v)
+{
+    sq_setdebughook(v);
+    return 0;
+}
+
+static SQInteger base_enabledebuginfo(HSQUIRRELVM v)
+{
+    SQObjectPtr &o=stack_get(v,2);
+
+    sq_enabledebuginfo(v,SQVM::IsFalse(o)?SQFalse:SQTrue);
+    return 0;
+}
+
+static SQInteger __getcallstackinfos(HSQUIRRELVM v,SQInteger level)
+{
+    SQStackInfos si;
+    SQInteger seq = 0;
+    const SQChar *name = NULL;
+
+    if (SQ_SUCCEEDED(sq_stackinfos(v, level, &si)))
+    {
+        const SQChar *fn = _SC("unknown");
+        const SQChar *src = _SC("unknown");
+        if(si.funcname)fn = si.funcname;
+        if(si.source)src = si.source;
+        sq_newtable(v);
+        sq_pushstring(v, _SC("func"), -1);
+        sq_pushstring(v, fn, -1);
+        sq_newslot(v, -3, SQFalse);
+        sq_pushstring(v, _SC("src"), -1);
+        sq_pushstring(v, src, -1);
+        sq_newslot(v, -3, SQFalse);
+        sq_pushstring(v, _SC("line"), -1);
+        sq_pushinteger(v, si.line);
+        sq_newslot(v, -3, SQFalse);
+        sq_pushstring(v, _SC("locals"), -1);
+        sq_newtable(v);
+        seq=0;
+        while ((name = sq_getlocal(v, level, seq))) {
+            sq_pushstring(v, name, -1);
+            sq_push(v, -2);
+            sq_newslot(v, -4, SQFalse);
+            sq_pop(v, 1);
+            seq++;
+        }
+        sq_newslot(v, -3, SQFalse);
+        return 1;
+    }
+
+    return 0;
+}
+static SQInteger base_getstackinfos(HSQUIRRELVM v)
+{
+    SQInteger level;
+    sq_getinteger(v, -1, &level);
+    return __getcallstackinfos(v,level);
+}
+
+static SQInteger base_assert(HSQUIRRELVM v)
+{
+    if(SQVM::IsFalse(stack_get(v,2))){
+        return sq_throwerror(v,_SC("assertion failed"));
+    }
+    return 0;
+}
+
+static SQInteger get_slice_params(HSQUIRRELVM v,SQInteger &sidx,SQInteger &eidx,SQObjectPtr &o)
+{
+    SQInteger top = sq_gettop(v);
+    sidx=0;
+    eidx=0;
+    o=stack_get(v,1);
+    if(top>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;
+    if(SQ_SUCCEEDED(sq_tostring(v,2)))
+    {
+        if(SQ_SUCCEEDED(sq_getstring(v,-1,&str))) {
+            if(_ss(v)->_printfunc) _ss(v)->_printfunc(v,_SC("%s"),str);
+            return 0;
+        }
+    }
+    return SQ_ERROR;
+}
+
+static SQInteger base_error(HSQUIRRELVM v)
+{
+    const SQChar *str;
+    if(SQ_SUCCEEDED(sq_tostring(v,2)))
+    {
+        if(SQ_SUCCEEDED(sq_getstring(v,-1,&str))) {
+            if(_ss(v)->_errorfunc) _ss(v)->_errorfunc(v,_SC("%s"),str);
+            return 0;
+        }
+    }
+    return SQ_ERROR;
+}
+
+static SQInteger base_compilestring(HSQUIRRELVM v)
+{
+    SQInteger nargs=sq_gettop(v);
+    const SQChar *src=NULL,*name=_SC("unnamedbuffer");
+    SQInteger size;
+    sq_getstring(v,2,&src);
+    size=sq_getsize(v,2);
+    if(nargs>2){
+        sq_getstring(v,3,&name);
+    }
+    if(SQ_SUCCEEDED(sq_compilebuffer(v,src,size,name,SQFalse)))
+        return 1;
+    else
+        return SQ_ERROR;
+}
+
+static SQInteger base_newthread(HSQUIRRELVM v)
+{
+    SQObjectPtr &func = stack_get(v,2);
+    SQInteger stksize = (_closure(func)->_function->_stacksize << 1) +2;
+    HSQUIRRELVM newv = sq_newthread(v, (stksize < MIN_STACK_OVERHEAD + 2)? MIN_STACK_OVERHEAD + 2 : stksize);
+    sq_move(newv,v,-2);
+    return 1;
+}
+
+static SQInteger base_suspend(HSQUIRRELVM v)
+{
+    return sq_suspendvm(v);
+}
+
+static SQInteger base_array(HSQUIRRELVM v)
+{
+    SQArray *a;
+    SQObject &size = stack_get(v,2);
+    if(sq_gettop(v) > 2) {
+        a = SQArray::Create(_ss(v),0);
+        a->Resize(tointeger(size),stack_get(v,3));
+    }
+    else {
+        a = SQArray::Create(_ss(v),tointeger(size));
+    }
+    v->Push(a);
+    return 1;
+}
+
+static SQInteger base_type(HSQUIRRELVM v)
+{
+    SQObjectPtr &o = stack_get(v,2);
+    v->Push(SQString::Create(_ss(v),GetTypeName(o),-1));
+    return 1;
+}
+
+static SQInteger base_callee(HSQUIRRELVM v)
+{
+    if(v->_callsstacksize > 1)
+    {
+        v->Push(v->_callsstack[v->_callsstacksize - 2]._closure);
+        return 1;
+    }
+    return sq_throwerror(v,_SC("no closure in the calls stack"));
+}
+
+static const SQRegFunction base_funcs[]={
+    //generic
+    {_SC("seterrorhandler"),base_seterrorhandler,2, NULL},
+    {_SC("setdebughook"),base_setdebughook,2, NULL},
+    {_SC("enabledebuginfo"),base_enabledebuginfo,2, NULL},
+    {_SC("getstackinfos"),base_getstackinfos,2, _SC(".n")},
+    {_SC("getroottable"),base_getroottable,1, NULL},
+    {_SC("setroottable"),base_setroottable,2, NULL},
+    {_SC("getconsttable"),base_getconsttable,1, NULL},
+    {_SC("setconsttable"),base_setconsttable,2, NULL},
+    {_SC("assert"),base_assert,2, NULL},
+    {_SC("print"),base_print,2, NULL},
+    {_SC("error"),base_error,2, NULL},
+    {_SC("compilestring"),base_compilestring,-2, _SC(".ss")},
+    {_SC("newthread"),base_newthread,2, _SC(".c")},
+    {_SC("suspend"),base_suspend,-1, NULL},
+    {_SC("array"),base_array,-2, _SC(".n")},
+    {_SC("type"),base_type,2, NULL},
+    {_SC("callee"),base_callee,0,NULL},
+    {_SC("dummy"),base_dummy,0,NULL},
+#ifndef NO_GARBAGE_COLLECTOR
+    {_SC("collectgarbage"),base_collectgarbage,0, NULL},
+    {_SC("resurrectunreachable"),base_resurectureachable,0, NULL},
+#endif
+    {0,0}
+};
+
+void sq_base_register(HSQUIRRELVM v)
+{
+    SQInteger i=0;
+    sq_pushroottable(v);
+    while(base_funcs[i].name!=0) {
+        sq_pushstring(v,base_funcs[i].name,-1);
+        sq_newclosure(v,base_funcs[i].f,0);
+        sq_setnativeclosurename(v,-1,base_funcs[i].name);
+        sq_setparamscheck(v,base_funcs[i].nparamscheck,base_funcs[i].typemask);
+        sq_newslot(v,-3, SQFalse);
+        i++;
+    }
+
+    sq_pushstring(v,_SC("_versionnumber_"),-1);
+    sq_pushinteger(v,SQUIRREL_VERSION_NUMBER);
+    sq_newslot(v,-3, SQFalse);
+    sq_pushstring(v,_SC("_version_"),-1);
+    sq_pushstring(v,SQUIRREL_VERSION,-1);
+    sq_newslot(v,-3, SQFalse);
+    sq_pushstring(v,_SC("_charsize_"),-1);
+    sq_pushinteger(v,sizeof(SQChar));
+    sq_newslot(v,-3, SQFalse);
+    sq_pushstring(v,_SC("_intsize_"),-1);
+    sq_pushinteger(v,sizeof(SQInteger));
+    sq_newslot(v,-3, SQFalse);
+    sq_pushstring(v,_SC("_floatsize_"),-1);
+    sq_pushinteger(v,sizeof(SQFloat));
+    sq_newslot(v,-3, SQFalse);
+    sq_pop(v,1);
+}
+
+static SQInteger default_delegate_len(HSQUIRRELVM v)
+{
+    v->Push(SQInteger(sq_getsize(v,1)));
+    return 1;
+}
+
+static SQInteger default_delegate_tofloat(HSQUIRRELVM v)
+{
+    SQObjectPtr &o=stack_get(v,1);
+    switch(type(o)){
+    case OT_STRING:{
+        SQObjectPtr res;
+        if(str2num(_stringval(o),res,10)){
+            v->Push(SQObjectPtr(tofloat(res)));
+            break;
+        }}
+        return sq_throwerror(v, _SC("cannot convert the string"));
+        break;
+    case OT_INTEGER:case OT_FLOAT:
+        v->Push(SQObjectPtr(tofloat(o)));
+        break;
+    case OT_BOOL:
+        v->Push(SQObjectPtr((SQFloat)(_integer(o)?1:0)));
+        break;
+    default:
+        v->PushNull();
+        break;
+    }
+    return 1;
+}
+
+static SQInteger default_delegate_tointeger(HSQUIRRELVM v)
+{
+    SQObjectPtr &o=stack_get(v,1);
+    SQInteger base = 10;
+    if(sq_gettop(v) > 1) {
+        sq_getinteger(v,2,&base);
+    }
+    switch(type(o)){
+    case OT_STRING:{
+        SQObjectPtr res;
+        if(str2num(_stringval(o),res,base)){
+            v->Push(SQObjectPtr(tointeger(res)));
+            break;
+        }}
+        return sq_throwerror(v, _SC("cannot convert the string"));
+        break;
+    case OT_INTEGER:case OT_FLOAT:
+        v->Push(SQObjectPtr(tointeger(o)));
+        break;
+    case OT_BOOL:
+        v->Push(SQObjectPtr(_integer(o)?(SQInteger)1:(SQInteger)0));
+        break;
+    default:
+        v->PushNull();
+        break;
+    }
+    return 1;
+}
+
+static SQInteger default_delegate_tostring(HSQUIRRELVM v)
+{
+    if(SQ_FAILED(sq_tostring(v,1)))
+        return SQ_ERROR;
+    return 1;
+}
+
+static SQInteger obj_delegate_weakref(HSQUIRRELVM v)
+{
+    sq_weakref(v,1);
+    return 1;
+}
+
+static SQInteger obj_clear(HSQUIRRELVM v)
+{
+    return sq_clear(v,-1);
+}
+
+
+static SQInteger number_delegate_tochar(HSQUIRRELVM v)
+{
+    SQObject &o=stack_get(v,1);
+    SQChar c = (SQChar)tointeger(o);
+    v->Push(SQString::Create(_ss(v),(const SQChar *)&c,1));
+    return 1;
+}
+
+
+
+/////////////////////////////////////////////////////////////////
+//TABLE DEFAULT DELEGATE
+
+static SQInteger table_rawdelete(HSQUIRRELVM v)
+{
+    if(SQ_FAILED(sq_rawdeleteslot(v,1,SQTrue)))
+        return SQ_ERROR;
+    return 1;
+}
+
+
+static SQInteger container_rawexists(HSQUIRRELVM v)
+{
+    if(SQ_SUCCEEDED(sq_rawget(v,-2))) {
+        sq_pushbool(v,SQTrue);
+        return 1;
+    }
+    sq_pushbool(v,SQFalse);
+    return 1;
+}
+
+static SQInteger container_rawset(HSQUIRRELVM v)
+{
+    return sq_rawset(v,-3);
+}
+
+
+static SQInteger container_rawget(HSQUIRRELVM v)
+{
+    return SQ_SUCCEEDED(sq_rawget(v,-2))?1:SQ_ERROR;
+}
+
+static SQInteger table_setdelegate(HSQUIRRELVM v)
+{
+    if(SQ_FAILED(sq_setdelegate(v,-2)))
+        return SQ_ERROR;
+    sq_push(v,-1); // -1 because sq_setdelegate pops 1
+    return 1;
+}
+
+static SQInteger table_getdelegate(HSQUIRRELVM v)
+{
+    return SQ_SUCCEEDED(sq_getdelegate(v,-1))?1:SQ_ERROR;
+}
+
+const SQRegFunction SQSharedState::_table_default_delegate_funcz[]={
+    {_SC("len"),default_delegate_len,1, _SC("t")},
+    {_SC("rawget"),container_rawget,2, _SC("t")},
+    {_SC("rawset"),container_rawset,3, _SC("t")},
+    {_SC("rawdelete"),table_rawdelete,2, _SC("t")},
+    {_SC("rawin"),container_rawexists,2, _SC("t")},
+    {_SC("weakref"),obj_delegate_weakref,1, NULL },
+    {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
+    {_SC("clear"),obj_clear,1, _SC(".")},
+    {_SC("setdelegate"),table_setdelegate,2, _SC(".t|o")},
+    {_SC("getdelegate"),table_getdelegate,1, _SC(".")},
+    {0,0}
+};
+
+//ARRAY DEFAULT DELEGATE///////////////////////////////////////
+
+static SQInteger array_append(HSQUIRRELVM v)
+{
+    return sq_arrayappend(v,-2);
+}
+
+static SQInteger array_extend(HSQUIRRELVM v)
+{
+    _array(stack_get(v,1))->Extend(_array(stack_get(v,2)));
+    return 0;
+}
+
+static SQInteger array_reverse(HSQUIRRELVM v)
+{
+    return sq_arrayreverse(v,-1);
+}
+
+static SQInteger array_pop(HSQUIRRELVM v)
+{
+    return SQ_SUCCEEDED(sq_arraypop(v,1,SQTrue))?1:SQ_ERROR;
+}
+
+static SQInteger array_top(HSQUIRRELVM v)
+{
+    SQObject &o=stack_get(v,1);
+    if(_array(o)->Size()>0){
+        v->Push(_array(o)->Top());
+        return 1;
+    }
+    else return sq_throwerror(v,_SC("top() on a empty array"));
+}
+
+static SQInteger array_insert(HSQUIRRELVM v)
+{
+    SQObject &o=stack_get(v,1);
+    SQObject &idx=stack_get(v,2);
+    SQObject &val=stack_get(v,3);
+    if(!_array(o)->Insert(tointeger(idx),val))
+        return sq_throwerror(v,_SC("index out of range"));
+    return 0;
+}
+
+static SQInteger array_remove(HSQUIRRELVM v)
+{
+    SQObject &o = stack_get(v, 1);
+    SQObject &idx = stack_get(v, 2);
+    if(!sq_isnumeric(idx)) return sq_throwerror(v, _SC("wrong type"));
+    SQObjectPtr val;
+    if(_array(o)->Get(tointeger(idx), val)) {
+        _array(o)->Remove(tointeger(idx));
+        v->Push(val);
+        return 1;
+    }
+    return sq_throwerror(v, _SC("idx out of range"));
+}
+
+static SQInteger array_resize(HSQUIRRELVM v)
+{
+    SQObject &o = stack_get(v, 1);
+    SQObject &nsize = stack_get(v, 2);
+    SQObjectPtr fill;
+    if(sq_isnumeric(nsize)) {
+        if(sq_gettop(v) > 2)
+            fill = stack_get(v, 3);
+        _array(o)->Resize(tointeger(nsize),fill);
+        return 0;
+    }
+    return sq_throwerror(v, _SC("size must be a number"));
+}
+
+static SQInteger __map_array(SQArray *dest,SQArray *src,HSQUIRRELVM v) {
+    SQObjectPtr temp;
+    SQInteger size = src->Size();
+    for(SQInteger n = 0; n < size; n++) {
+        src->Get(n,temp);
+        v->Push(src);
+        v->Push(temp);
+        if(SQ_FAILED(sq_call(v,2,SQTrue,SQFalse))) {
+            return SQ_ERROR;
+        }
+        dest->Set(n,v->GetUp(-1));
+        v->Pop();
+    }
+    return 0;
+}
+
+static SQInteger array_map(HSQUIRRELVM v)
+{
+    SQObject &o = stack_get(v,1);
+    SQInteger size = _array(o)->Size();
+    SQObjectPtr ret = SQArray::Create(_ss(v),size);
+    if(SQ_FAILED(__map_array(_array(ret),_array(o),v)))
+        return SQ_ERROR;
+    v->Push(ret);
+    return 1;
+}
+
+static SQInteger array_apply(HSQUIRRELVM v)
+{
+    SQObject &o = stack_get(v,1);
+    if(SQ_FAILED(__map_array(_array(o),_array(o),v)))
+        return SQ_ERROR;
+    return 0;
+}
+
+static SQInteger array_reduce(HSQUIRRELVM v)
+{
+    SQObject &o = stack_get(v,1);
+    SQArray *a = _array(o);
+    SQInteger size = a->Size();
+    if(size == 0) {
+        return 0;
+    }
+    SQObjectPtr res;
+    a->Get(0,res);
+    if(size > 1) {
+        SQObjectPtr other;
+        for(SQInteger n = 1; n < size; n++) {
+            a->Get(n,other);
+            v->Push(o);
+            v->Push(res);
+            v->Push(other);
+            if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {
+                return SQ_ERROR;
+            }
+            res = v->GetUp(-1);
+            v->Pop();
+        }
+    }
+    v->Push(res);
+    return 1;
+}
+
+static SQInteger array_filter(HSQUIRRELVM v)
+{
+    SQObject &o = stack_get(v,1);
+    SQArray *a = _array(o);
+    SQObjectPtr ret = SQArray::Create(_ss(v),0);
+    SQInteger size = a->Size();
+    SQObjectPtr val;
+    for(SQInteger n = 0; n < size; n++) {
+        a->Get(n,val);
+        v->Push(o);
+        v->Push(n);
+        v->Push(val);
+        if(SQ_FAILED(sq_call(v,3,SQTrue,SQFalse))) {
+            return SQ_ERROR;
+        }
+        if(!SQVM::IsFalse(v->GetUp(-1))) {
+            _array(ret)->Append(val);
+        }
+        v->Pop();
+    }
+    v->Push(ret);
+    return 1;
+}
+
+static SQInteger array_find(HSQUIRRELVM v)
+{
+    SQObject &o = stack_get(v,1);
+    SQObjectPtr &val = stack_get(v,2);
+    SQArray *a = _array(o);
+    SQInteger size = a->Size();
+    SQObjectPtr temp;
+    for(SQInteger n = 0; n < size; n++) {
+        bool res = false;
+        a->Get(n,temp);
+        if(SQVM::IsEqual(temp,val,res) && res) {
+            v->Push(n);
+            return 1;
+        }
+    }
+    return 0;
+}
+
+
+static bool _sort_compare(HSQUIRRELVM v,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;
+        }
+        if(SQ_FAILED(sq_getinteger(v, -1, &ret))) {
+            v->Raise_Error(_SC("numeric value expected as return value of the compare function"));
+            return false;
+        }
+        sq_settop(v, top);
+        return true;
+    }
+    return true;
+}
+
+static bool _hsort_sift_down(HSQUIRRELVM v,SQArray *arr, SQInteger root, SQInteger bottom, SQInteger func)
+{
+    SQInteger maxChild;
+    SQInteger done = 0;
+    SQInteger ret;
+    SQInteger root2;
+    while (((root2 = root * 2) <= bottom) && (!done))
+    {
+        if (root2 == bottom) {
+            maxChild = root2;
+        }
+        else {
+            if(!_sort_compare(v,arr->_values[root2],arr->_values[root2 + 1],func,ret))
+                return false;
+            if (ret > 0) {
+                maxChild = root2;
+            }
+            else {
+                maxChild = root2 + 1;
+            }
+        }
+
+        if(!_sort_compare(v,arr->_values[root],arr->_values[maxChild],func,ret))
+            return false;
+        if (ret < 0) {
+            if (root == maxChild) {
+                v->Raise_Error(_SC("inconsistent compare function"));
+                return false; // We'd be swapping ourselve. The compare function is incorrect
+            }
+
+            _Swap(arr->_values[root],arr->_values[maxChild]);
+            root = maxChild;
+        }
+        else {
+            done = 1;
+        }
+    }
+    return true;
+}
+
+static bool _hsort(HSQUIRRELVM v,SQObjectPtr &arr, SQInteger l, SQInteger r,SQInteger func)
+{
+    SQArray *a = _array(arr);
+    SQInteger i;
+    SQInteger array_size = a->Size();
+    for (i = (array_size / 2); i >= 0; i--) {
+        if(!_hsort_sift_down(v,a, i, array_size - 1,func)) return false;
+    }
+
+    for (i = array_size-1; i >= 1; i--)
+    {
+        _Swap(a->_values[0],a->_values[i]);
+        if(!_hsort_sift_down(v,a, 0, i-1,func)) return false;
+    }
+    return true;
+}
+
+static SQInteger array_sort(HSQUIRRELVM v)
+{
+    SQInteger func = -1;
+    SQObjectPtr &o = stack_get(v,1);
+    if(_array(o)->Size() > 1) {
+        if(sq_gettop(v) == 2) func = 2;
+        if(!_hsort(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 || sidx < 0)return sq_throwerror(v, _SC("slice out of range"));
+    SQArray *arr=SQArray::Create(_ss(v),eidx-sidx);
+    SQObjectPtr t;
+    SQInteger count=0;
+    for(SQInteger i=sidx;i<eidx;i++){
+        _array(o)->Get(i,t);
+        arr->Set(count++,t);
+    }
+    v->Push(arr);
+    return 1;
+
+}
+
+const SQRegFunction SQSharedState::_array_default_delegate_funcz[]={
+    {_SC("len"),default_delegate_len,1, _SC("a")},
+    {_SC("append"),array_append,2, _SC("a")},
+    {_SC("extend"),array_extend,2, _SC("aa")},
+    {_SC("push"),array_append,2, _SC("a")},
+    {_SC("pop"),array_pop,1, _SC("a")},
+    {_SC("top"),array_top,1, _SC("a")},
+    {_SC("insert"),array_insert,3, _SC("an")},
+    {_SC("remove"),array_remove,2, _SC("an")},
+    {_SC("resize"),array_resize,-2, _SC("an")},
+    {_SC("reverse"),array_reverse,1, _SC("a")},
+    {_SC("sort"),array_sort,-1, _SC("ac")},
+    {_SC("slice"),array_slice,-1, _SC("ann")},
+    {_SC("weakref"),obj_delegate_weakref,1, NULL },
+    {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
+    {_SC("clear"),obj_clear,1, _SC(".")},
+    {_SC("map"),array_map,2, _SC("ac")},
+    {_SC("apply"),array_apply,2, _SC("ac")},
+    {_SC("reduce"),array_reduce,2, _SC("ac")},
+    {_SC("filter"),array_filter,2, _SC("ac")},
+    {_SC("find"),array_find,2, _SC("a.")},
+    {0,0}
+};
+
+//STRING DEFAULT DELEGATE//////////////////////////
+static SQInteger string_slice(HSQUIRRELVM v)
+{
+    SQInteger sidx,eidx;
+    SQObjectPtr o;
+    if(SQ_FAILED(get_slice_params(v,sidx,eidx,o)))return -1;
+    SQInteger slen = _string(o)->_len;
+    if(sidx < 0)sidx = slen + sidx;
+    if(eidx < 0)eidx = slen + eidx;
+    if(eidx < sidx) return sq_throwerror(v,_SC("wrong indexes"));
+    if(eidx > slen || sidx < 0) 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) \
+{\
+    SQInteger sidx,eidx; \
+    SQObjectPtr str; \
+    if(SQ_FAILED(get_slice_params(v,sidx,eidx,str)))return -1; \
+    SQInteger slen = _string(str)->_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 || sidx < 0) return sq_throwerror(v,_SC("slice out of range")); \
+    SQInteger len=_string(str)->_len; \
+    const SQChar *sthis=_stringval(str); \
+    SQChar *snew=(_ss(v)->GetScratchPad(sq_rsl(len))); \
+    memcpy(snew,sthis,sq_rsl(len));\
+    for(SQInteger i=sidx;i<eidx;i++) snew[i] = func(sthis[i]); \
+    v->Push(SQString::Create(_ss(v),snew,len)); \
+    return 1; \
+}
+
+
+STRING_TOFUNCZ(tolower)
+STRING_TOFUNCZ(toupper)
+
+const SQRegFunction SQSharedState::_string_default_delegate_funcz[]={
+    {_SC("len"),default_delegate_len,1, _SC("s")},
+    {_SC("tointeger"),default_delegate_tointeger,-1, _SC("sn")},
+    {_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 n n")},
+    {_SC("toupper"),string_toupper,-1, _SC("s n n")},
+    {_SC("weakref"),obj_delegate_weakref,1, NULL },
+    {0,0}
+};
+
+//INTEGER DEFAULT DELEGATE//////////////////////////
+const SQRegFunction SQSharedState::_number_default_delegate_funcz[]={
+    {_SC("tointeger"),default_delegate_tointeger,1, _SC("n|b")},
+    {_SC("tofloat"),default_delegate_tofloat,1, _SC("n|b")},
+    {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
+    {_SC("tochar"),number_delegate_tochar,1, _SC("n|b")},
+    {_SC("weakref"),obj_delegate_weakref,1, NULL },
+    {0,0}
+};
+
+//CLOSURE DEFAULT DELEGATE//////////////////////////
+static SQInteger closure_pcall(HSQUIRRELVM v)
+{
+    return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQFalse))?1:SQ_ERROR;
+}
+
+static SQInteger closure_call(HSQUIRRELVM v)
+{
+    return SQ_SUCCEEDED(sq_call(v,sq_gettop(v)-1,SQTrue,SQTrue))?1:SQ_ERROR;
+}
+
+static SQInteger _closure_acall(HSQUIRRELVM v,SQBool raiseerror)
+{
+    SQArray *aparams=_array(stack_get(v,2));
+    SQInteger nparams=aparams->Size();
+    v->Push(stack_get(v,1));
+    for(SQInteger i=0;i<nparams;i++)v->Push(aparams->_values[i]);
+    return SQ_SUCCEEDED(sq_call(v,nparams,SQTrue,raiseerror))?1:SQ_ERROR;
+}
+
+static SQInteger closure_acall(HSQUIRRELVM v)
+{
+    return _closure_acall(v,SQTrue);
+}
+
+static SQInteger closure_pacall(HSQUIRRELVM v)
+{
+    return _closure_acall(v,SQFalse);
+}
+
+static SQInteger closure_bindenv(HSQUIRRELVM v)
+{
+    if(SQ_FAILED(sq_bindenv(v,1)))
+        return SQ_ERROR;
+    return 1;
+}
+
+static SQInteger closure_getroot(HSQUIRRELVM v)
+{
+    if(SQ_FAILED(sq_getclosureroot(v,-1)))
+        return SQ_ERROR;
+    return 1;
+}
+
+static SQInteger closure_setroot(HSQUIRRELVM v)
+{
+    if(SQ_FAILED(sq_setclosureroot(v,-2)))
+        return SQ_ERROR;
+    return 1;
+}
+
+static SQInteger closure_getinfos(HSQUIRRELVM v) {
+    SQObject o = stack_get(v,1);
+    SQTable *res = SQTable::Create(_ss(v),4);
+    if(type(o) == OT_CLOSURE) {
+        SQFunctionProto *f = _closure(o)->_function;
+        SQInteger nparams = f->_nparameters + (f->_varparams?1:0);
+        SQObjectPtr params = SQArray::Create(_ss(v),nparams);
+    SQObjectPtr defparams = SQArray::Create(_ss(v),f->_ndefaultparams);
+        for(SQInteger n = 0; n<f->_nparameters; n++) {
+            _array(params)->Set((SQInteger)n,f->_parameters[n]);
+        }
+    for(SQInteger j = 0; j<f->_ndefaultparams; j++) {
+            _array(defparams)->Set((SQInteger)j,_closure(o)->_defaultparams[j]);
+        }
+        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);
+    res->NewSlot(SQString::Create(_ss(v),_SC("defparams"),-1),defparams);
+    }
+    else { //OT_NATIVECLOSURE
+        SQNativeClosure *nc = _nativeclosure(o);
+        res->NewSlot(SQString::Create(_ss(v),_SC("native"),-1),true);
+        res->NewSlot(SQString::Create(_ss(v),_SC("name"),-1),nc->_name);
+        res->NewSlot(SQString::Create(_ss(v),_SC("paramscheck"),-1),nc->_nparamscheck);
+        SQObjectPtr typecheck;
+        if(nc->_typecheck.size() > 0) {
+            typecheck =
+                SQArray::Create(_ss(v), nc->_typecheck.size());
+            for(SQUnsignedInteger n = 0; n<nc->_typecheck.size(); n++) {
+                    _array(typecheck)->Set((SQInteger)n,nc->_typecheck[n]);
+            }
+        }
+        res->NewSlot(SQString::Create(_ss(v),_SC("typecheck"),-1),typecheck);
+    }
+    v->Push(res);
+    return 1;
+}
+
+
+
+const 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")},
+    {_SC("getroot"),closure_getroot,1, _SC("c")},
+    {_SC("setroot"),closure_setroot,2, _SC("ct")},
+    {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;
+}
+
+const SQRegFunction SQSharedState::_generator_default_delegate_funcz[]={
+    {_SC("getstatus"),generator_getstatus,1, _SC("g")},
+    {_SC("weakref"),obj_delegate_weakref,1, NULL },
+    {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
+    {0,0}
+};
+
+//THREAD DEFAULT DELEGATE
+static SQInteger thread_call(HSQUIRRELVM v)
+{
+    SQObjectPtr o = stack_get(v,1);
+    if(type(o) == OT_THREAD) {
+        SQInteger nparams = sq_gettop(v);
+        _thread(o)->Push(_thread(o)->_roottable);
+        for(SQInteger i = 2; i<(nparams+1); i++)
+            sq_move(_thread(o),v,i);
+        if(SQ_SUCCEEDED(sq_call(_thread(o),nparams,SQTrue,SQTrue))) {
+            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?SQTrue:SQFalse;
+        if(wakeupret) {
+            sq_move(thread,v,2);
+        }
+        if(SQ_SUCCEEDED(sq_wakeupvm(thread,wakeupret,SQTrue,SQTrue,SQFalse))) {
+            sq_move(v,thread,-1);
+            sq_pop(thread,1); //pop retval
+            if(sq_getvmstate(thread) == SQ_VMSTATE_IDLE) {
+                sq_settop(thread,1); //pop roottable
+            }
+            return 1;
+        }
+        sq_settop(thread,1);
+        v->_lasterror = thread->_lasterror;
+        return SQ_ERROR;
+    }
+    return sq_throwerror(v,_SC("wrong parameter"));
+}
+
+static SQInteger thread_wakeupthrow(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;
+            }
+        }
+
+        sq_move(thread,v,2);
+        sq_throwobject(thread);
+        SQBool rethrow_error = SQTrue;
+        if(sq_gettop(v) > 2) {
+            sq_getbool(v,3,&rethrow_error);
+        }
+        if(SQ_SUCCEEDED(sq_wakeupvm(thread,SQFalse,SQTrue,SQTrue,SQTrue))) {
+            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);
+        if(rethrow_error) {
+            v->_lasterror = thread->_lasterror;
+            return SQ_ERROR;
+        }
+        return SQ_OK;
+    }
+    return sq_throwerror(v,_SC("wrong parameter"));
+}
+
+static SQInteger thread_getstatus(HSQUIRRELVM v)
+{
+    SQObjectPtr &o = stack_get(v,1);
+    switch(sq_getvmstate(_thread(o))) {
+        case SQ_VMSTATE_IDLE:
+            sq_pushstring(v,_SC("idle"),-1);
+        break;
+        case SQ_VMSTATE_RUNNING:
+            sq_pushstring(v,_SC("running"),-1);
+        break;
+        case SQ_VMSTATE_SUSPENDED:
+            sq_pushstring(v,_SC("suspended"),-1);
+        break;
+        default:
+            return sq_throwerror(v,_SC("internal VM error"));
+    }
+    return 1;
+}
+
+static SQInteger thread_getstackinfos(HSQUIRRELVM v)
+{
+    SQObjectPtr o = stack_get(v,1);
+    if(type(o) == OT_THREAD) {
+        SQVM *thread = _thread(o);
+        SQInteger threadtop = sq_gettop(thread);
+        SQInteger level;
+        sq_getinteger(v,-1,&level);
+        SQRESULT res = __getcallstackinfos(thread,level);
+        if(SQ_FAILED(res))
+        {
+            sq_settop(thread,threadtop);
+            if(type(thread->_lasterror) == OT_STRING) {
+                sq_throwerror(v,_stringval(thread->_lasterror));
+            }
+            else {
+                sq_throwerror(v,_SC("unknown error"));
+            }
+        }
+        if(res > 0) {
+            //some result
+            sq_move(v,thread,-1);
+            sq_settop(thread,threadtop);
+            return 1;
+        }
+        //no result
+        sq_settop(thread,threadtop);
+        return 0;
+
+    }
+    return sq_throwerror(v,_SC("wrong parameter"));
+}
+
+const SQRegFunction SQSharedState::_thread_default_delegate_funcz[] = {
+    {_SC("call"), thread_call, -1, _SC("v")},
+    {_SC("wakeup"), thread_wakeup, -1, _SC("v")},
+    {_SC("wakeupthrow"), thread_wakeupthrow, -2, _SC("v.b")},
+    {_SC("getstatus"), thread_getstatus, 1, _SC("v")},
+    {_SC("weakref"),obj_delegate_weakref,1, NULL },
+    {_SC("getstackinfos"),thread_getstackinfos,2, _SC("vn")},
+    {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
+    {0,0},
+};
+
+static SQInteger class_getattributes(HSQUIRRELVM v)
+{
+    return SQ_SUCCEEDED(sq_getattributes(v,-2))?1:SQ_ERROR;
+}
+
+static SQInteger class_setattributes(HSQUIRRELVM v)
+{
+    return SQ_SUCCEEDED(sq_setattributes(v,-3))?1:SQ_ERROR;
+}
+
+static SQInteger class_instance(HSQUIRRELVM v)
+{
+    return SQ_SUCCEEDED(sq_createinstance(v,-1))?1:SQ_ERROR;
+}
+
+static SQInteger class_getbase(HSQUIRRELVM v)
+{
+    return SQ_SUCCEEDED(sq_getbase(v,-1))?1:SQ_ERROR;
+}
+
+static SQInteger class_newmember(HSQUIRRELVM v)
+{
+    SQInteger top = sq_gettop(v);
+    SQBool bstatic = SQFalse;
+    if(top == 5)
+    {
+        sq_tobool(v,-1,&bstatic);
+        sq_pop(v,1);
+    }
+
+    if(top < 4) {
+        sq_pushnull(v);
+    }
+    return SQ_SUCCEEDED(sq_newmember(v,-4,bstatic))?1:SQ_ERROR;
+}
+
+static SQInteger class_rawnewmember(HSQUIRRELVM v)
+{
+    SQInteger top = sq_gettop(v);
+    SQBool bstatic = SQFalse;
+    if(top == 5)
+    {
+        sq_tobool(v,-1,&bstatic);
+        sq_pop(v,1);
+    }
+
+    if(top < 4) {
+        sq_pushnull(v);
+    }
+    return SQ_SUCCEEDED(sq_rawnewmember(v,-4,bstatic))?1:SQ_ERROR;
+}
+
+const SQRegFunction SQSharedState::_class_default_delegate_funcz[] = {
+    {_SC("getattributes"), class_getattributes, 2, _SC("y.")},
+    {_SC("setattributes"), class_setattributes, 3, _SC("y..")},
+    {_SC("rawget"),container_rawget,2, _SC("y")},
+    {_SC("rawset"),container_rawset,3, _SC("y")},
+    {_SC("rawin"),container_rawexists,2, _SC("y")},
+    {_SC("weakref"),obj_delegate_weakref,1, NULL },
+    {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
+    {_SC("instance"),class_instance,1, _SC("y")},
+    {_SC("getbase"),class_getbase,1, _SC("y")},
+    {_SC("newmember"),class_newmember,-3, _SC("y")},
+    {_SC("rawnewmember"),class_rawnewmember,-3, _SC("y")},
+    {0,0}
+};
+
+
+static SQInteger instance_getclass(HSQUIRRELVM v)
+{
+    if(SQ_SUCCEEDED(sq_getclass(v,1)))
+        return 1;
+    return SQ_ERROR;
+}
+
+const SQRegFunction SQSharedState::_instance_default_delegate_funcz[] = {
+    {_SC("getclass"), instance_getclass, 1, _SC("x")},
+    {_SC("rawget"),container_rawget,2, _SC("x")},
+    {_SC("rawset"),container_rawset,3, _SC("x")},
+    {_SC("rawin"),container_rawexists,2, _SC("x")},
+    {_SC("weakref"),obj_delegate_weakref,1, NULL },
+    {_SC("tostring"),default_delegate_tostring,1, _SC(".")},
+    {0,0}
+};
+
+static SQInteger weakref_ref(HSQUIRRELVM v)
+{
+    if(SQ_FAILED(sq_getweakrefval(v,1)))
+        return SQ_ERROR;
+    return 1;
+}
+
+const 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}
+};
+

+ 210 - 210
squirrel/sqclass.cpp

@@ -1,210 +1,210 @@
-/*
-	see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include "sqvm.h"
-#include "sqtable.h"
-#include "sqclass.h"
-#include "sqfuncproto.h"
-#include "sqclosure.h"
-
-
-
-SQClass::SQClass(SQSharedState *ss,SQClass *base)
-{
-	_base = base;
-	_typetag = 0;
-	_hook = NULL;
-	_udsize = 0;
-	_locked = false;
-	_constructoridx = -1;
-	if(_base) {
-		_constructoridx = _base->_constructoridx;
-		_udsize = _base->_udsize;
-		_defaultvalues.copy(base->_defaultvalues);
-		_methods.copy(base->_methods);
-		_COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST);
-		__ObjAddRef(_base);
-	}
-	_members = base?base->_members->Clone() : SQTable::Create(ss,0);
-	__ObjAddRef(_members);
-	
-	INIT_CHAIN();
-	ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
-}
-
-void SQClass::Finalize() { 
-	_attributes.Null();
-	_NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size());
-	_methods.resize(0);
-	_NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST);
-	__ObjRelease(_members);
-	if(_base) {
-		__ObjRelease(_base);
-	}
-}
-
-SQClass::~SQClass()
-{
-	REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
-	Finalize();
-}
-
-bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
-{
-	SQObjectPtr temp;
-	bool belongs_to_static_table = type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic;
-	if(_locked && !belongs_to_static_table) 
-		return false; //the class already has an instance so cannot be modified
-	if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value
-	{
-		_defaultvalues[_member_idx(temp)].val = val;
-		return true;
-	}
-	if(belongs_to_static_table) {
-		SQInteger mmidx;
-		if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) && 
-			(mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
-			_metamethods[mmidx] = val;
-		} 
-		else {
-			SQObjectPtr theval = val;
-			if(_base && type(val) == OT_CLOSURE) {
-				theval = _closure(val)->Clone();
-				_closure(theval)->_base = _base;
-				__ObjAddRef(_base); //ref for the closure
-			}
-			if(type(temp) == OT_NULL) {
-				bool isconstructor;
-				SQVM::IsEqual(ss->_constructoridx, key, isconstructor);
-				if(isconstructor) {
-					_constructoridx = (SQInteger)_methods.size();
-				}
-				SQClassMember m;
-				m.val = theval;
-				_members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));
-				_methods.push_back(m);
-			}
-			else {
-				_methods[_member_idx(temp)].val = theval;
-			}
-		}
-		return true;
-	}
-	SQClassMember m;
-	m.val = val;
-	_members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size())));
-	_defaultvalues.push_back(m);
-	return true;
-}
-
-SQInstance *SQClass::CreateInstance()
-{
-	if(!_locked) Lock();
-	return SQInstance::Create(_opt_ss(this),this);
-}
-
-SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
-{
-	SQObjectPtr oval;
-	SQInteger idx = _members->Next(false,refpos,outkey,oval);
-	if(idx != -1) {
-		if(_ismethod(oval)) {
-			outval = _methods[_member_idx(oval)].val;
-		}
-		else {
-			SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
-			outval = _realval(o);
-		}
-	}
-	return idx;
-}
-
-bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)
-{
-	SQObjectPtr idx;
-	if(_members->Get(key,idx)) {
-		if(_isfield(idx))
-			_defaultvalues[_member_idx(idx)].attrs = val;
-		else
-			_methods[_member_idx(idx)].attrs = val;
-		return true;
-	}
-	return false;
-}
-
-bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)
-{
-	SQObjectPtr idx;
-	if(_members->Get(key,idx)) {
-		outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
-		return true;
-	}
-	return false;
-}
-
-///////////////////////////////////////////////////////////////////////
-void SQInstance::Init(SQSharedState *ss)
-{
-	_userpointer = NULL;
-	_hook = NULL;
-	__ObjAddRef(_class);
-	_delegate = _class->_members;
-	INIT_CHAIN();
-	ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
-}
-
-SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)
-{
-	_memsize = memsize;
-	_class = c;
-	SQUnsignedInteger nvalues = _class->_defaultvalues.size();
-	for(SQUnsignedInteger n = 0; n < nvalues; n++) {
-		new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val);
-	}
-	Init(ss);
-}
-
-SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)
-{
-	_memsize = memsize;
-	_class = i->_class;
-	SQUnsignedInteger nvalues = _class->_defaultvalues.size();
-	for(SQUnsignedInteger n = 0; n < nvalues; n++) {
-		new (&_values[n]) SQObjectPtr(i->_values[n]);
-	}
-	Init(ss);
-}
-
-void SQInstance::Finalize() 
-{
-	SQUnsignedInteger nvalues = _class->_defaultvalues.size();
-	__ObjRelease(_class);
-	_NULL_SQOBJECT_VECTOR(_values,nvalues);
-}
-
-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;
-}
+/*
+    see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqvm.h"
+#include "sqtable.h"
+#include "sqclass.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+
+
+
+SQClass::SQClass(SQSharedState *ss,SQClass *base)
+{
+    _base = base;
+    _typetag = 0;
+    _hook = NULL;
+    _udsize = 0;
+    _locked = false;
+    _constructoridx = -1;
+    if(_base) {
+        _constructoridx = _base->_constructoridx;
+        _udsize = _base->_udsize;
+        _defaultvalues.copy(base->_defaultvalues);
+        _methods.copy(base->_methods);
+        _COPY_VECTOR(_metamethods,base->_metamethods,MT_LAST);
+        __ObjAddRef(_base);
+    }
+    _members = base?base->_members->Clone() : SQTable::Create(ss,0);
+    __ObjAddRef(_members);
+
+    INIT_CHAIN();
+    ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
+}
+
+void SQClass::Finalize() {
+    _attributes.Null();
+    _NULL_SQOBJECT_VECTOR(_defaultvalues,_defaultvalues.size());
+    _methods.resize(0);
+    _NULL_SQOBJECT_VECTOR(_metamethods,MT_LAST);
+    __ObjRelease(_members);
+    if(_base) {
+        __ObjRelease(_base);
+    }
+}
+
+SQClass::~SQClass()
+{
+    REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
+    Finalize();
+}
+
+bool SQClass::NewSlot(SQSharedState *ss,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
+{
+    SQObjectPtr temp;
+    bool belongs_to_static_table = type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE || bstatic;
+    if(_locked && !belongs_to_static_table)
+        return false; //the class already has an instance so cannot be modified
+    if(_members->Get(key,temp) && _isfield(temp)) //overrides the default value
+    {
+        _defaultvalues[_member_idx(temp)].val = val;
+        return true;
+    }
+    if(belongs_to_static_table) {
+        SQInteger mmidx;
+        if((type(val) == OT_CLOSURE || type(val) == OT_NATIVECLOSURE) &&
+            (mmidx = ss->GetMetaMethodIdxByName(key)) != -1) {
+            _metamethods[mmidx] = val;
+        }
+        else {
+            SQObjectPtr theval = val;
+            if(_base && type(val) == OT_CLOSURE) {
+                theval = _closure(val)->Clone();
+                _closure(theval)->_base = _base;
+                __ObjAddRef(_base); //ref for the closure
+            }
+            if(type(temp) == OT_NULL) {
+                bool isconstructor;
+                SQVM::IsEqual(ss->_constructoridx, key, isconstructor);
+                if(isconstructor) {
+                    _constructoridx = (SQInteger)_methods.size();
+                }
+                SQClassMember m;
+                m.val = theval;
+                _members->NewSlot(key,SQObjectPtr(_make_method_idx(_methods.size())));
+                _methods.push_back(m);
+            }
+            else {
+                _methods[_member_idx(temp)].val = theval;
+            }
+        }
+        return true;
+    }
+    SQClassMember m;
+    m.val = val;
+    _members->NewSlot(key,SQObjectPtr(_make_field_idx(_defaultvalues.size())));
+    _defaultvalues.push_back(m);
+    return true;
+}
+
+SQInstance *SQClass::CreateInstance()
+{
+    if(!_locked) Lock();
+    return SQInstance::Create(_opt_ss(this),this);
+}
+
+SQInteger SQClass::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
+{
+    SQObjectPtr oval;
+    SQInteger idx = _members->Next(false,refpos,outkey,oval);
+    if(idx != -1) {
+        if(_ismethod(oval)) {
+            outval = _methods[_member_idx(oval)].val;
+        }
+        else {
+            SQObjectPtr &o = _defaultvalues[_member_idx(oval)].val;
+            outval = _realval(o);
+        }
+    }
+    return idx;
+}
+
+bool SQClass::SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val)
+{
+    SQObjectPtr idx;
+    if(_members->Get(key,idx)) {
+        if(_isfield(idx))
+            _defaultvalues[_member_idx(idx)].attrs = val;
+        else
+            _methods[_member_idx(idx)].attrs = val;
+        return true;
+    }
+    return false;
+}
+
+bool SQClass::GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval)
+{
+    SQObjectPtr idx;
+    if(_members->Get(key,idx)) {
+        outval = (_isfield(idx)?_defaultvalues[_member_idx(idx)].attrs:_methods[_member_idx(idx)].attrs);
+        return true;
+    }
+    return false;
+}
+
+///////////////////////////////////////////////////////////////////////
+void SQInstance::Init(SQSharedState *ss)
+{
+    _userpointer = NULL;
+    _hook = NULL;
+    __ObjAddRef(_class);
+    _delegate = _class->_members;
+    INIT_CHAIN();
+    ADD_TO_CHAIN(&_sharedstate->_gc_chain, this);
+}
+
+SQInstance::SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize)
+{
+    _memsize = memsize;
+    _class = c;
+    SQUnsignedInteger nvalues = _class->_defaultvalues.size();
+    for(SQUnsignedInteger n = 0; n < nvalues; n++) {
+        new (&_values[n]) SQObjectPtr(_class->_defaultvalues[n].val);
+    }
+    Init(ss);
+}
+
+SQInstance::SQInstance(SQSharedState *ss, SQInstance *i, SQInteger memsize)
+{
+    _memsize = memsize;
+    _class = i->_class;
+    SQUnsignedInteger nvalues = _class->_defaultvalues.size();
+    for(SQUnsignedInteger n = 0; n < nvalues; n++) {
+        new (&_values[n]) SQObjectPtr(i->_values[n]);
+    }
+    Init(ss);
+}
+
+void SQInstance::Finalize()
+{
+    SQUnsignedInteger nvalues = _class->_defaultvalues.size();
+    __ObjRelease(_class);
+    _NULL_SQOBJECT_VECTOR(_values,nvalues);
+}
+
+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;
+}

+ 162 - 162
squirrel/sqclass.h

@@ -1,162 +1,162 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQCLASS_H_
-#define _SQCLASS_H_
-
-struct SQInstance;
-
-struct SQClassMember {
-	SQObjectPtr val;
-	SQObjectPtr attrs;
-	void Null() {
-		val.Null();
-		attrs.Null();
-	}
-};
-
-typedef sqvector<SQClassMember> SQClassMemberVec;
-
-#define MEMBER_TYPE_METHOD 0x01000000
-#define MEMBER_TYPE_FIELD 0x02000000
-
-#define _ismethod(o) (_integer(o)&MEMBER_TYPE_METHOD)
-#define _isfield(o) (_integer(o)&MEMBER_TYPE_FIELD)
-#define _make_method_idx(i) ((SQInteger)(MEMBER_TYPE_METHOD|i))
-#define _make_field_idx(i) ((SQInteger)(MEMBER_TYPE_FIELD|i))
-#define _member_type(o) (_integer(o)&0xFF000000)
-#define _member_idx(o) (_integer(o)&0x00FFFFFF)
-
-struct SQClass : public CHAINABLE_OBJ
-{
-	SQClass(SQSharedState *ss,SQClass *base);
-public:
-	static SQClass* Create(SQSharedState *ss,SQClass *base) {
-		SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass));
-		new (newclass) SQClass(ss, base);
-		return newclass;
-	}
-	~SQClass();
-	bool NewSlot(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic);
-	bool Get(const SQObjectPtr &key,SQObjectPtr &val) {
-		if(_members->Get(key,val)) {
-			if(_isfield(val)) {
-				SQObjectPtr &o = _defaultvalues[_member_idx(val)].val;
-				val = _realval(o);
-			}
-			else {
-				val = _methods[_member_idx(val)].val;
-			}
-			return true;
-		}
-		return false;
-	}
-	bool GetConstructor(SQObjectPtr &ctor)
-	{
-		if(_constructoridx != -1) {
-			ctor = _methods[_constructoridx].val;
-			return true;
-		}
-		return false;
-	}
-	bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val);
-	bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval);
-	void Lock() { _locked = true; if(_base) _base->Lock(); }
-	void Release() { 
-		if (_hook) { _hook(_typetag,0);}
-		sq_delete(this, SQClass);	
-	}
-	void Finalize();
-#ifndef NO_GARBAGE_COLLECTOR
-	void Mark(SQCollectable ** );
-	SQObjectType GetType() {return OT_CLASS;}
-#endif
-	SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
-	SQInstance *CreateInstance();
-	SQTable *_members;
-	SQClass *_base;
-	SQClassMemberVec _defaultvalues;
-	SQClassMemberVec _methods;
-	SQObjectPtr _metamethods[MT_LAST];
-	SQObjectPtr _attributes;
-	SQUserPointer _typetag;
-	SQRELEASEHOOK _hook;
-	bool _locked;
-	SQInteger _constructoridx;
-	SQInteger _udsize;
-};
-
-#define calcinstancesize(_theclass_) \
-	(_theclass_->_udsize + sq_aligning(sizeof(SQInstance) +  (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))))
-
-struct SQInstance : public SQDelegable 
-{
-	void Init(SQSharedState *ss);
-	SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize);
-	SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize);
-public:
-	static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {
-		
-		SQInteger size = calcinstancesize(theclass);
-		SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
-		new (newinst) SQInstance(ss, theclass,size);
-		if(theclass->_udsize) {
-			newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize);
-		}
-		return newinst;
-	}
-	SQInstance *Clone(SQSharedState *ss)
-	{
-		SQInteger size = calcinstancesize(_class);
-		SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
-		new (newinst) SQInstance(ss, this,size);
-		if(_class->_udsize) {
-			newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize);
-		}
-		return newinst;
-	}
-	~SQInstance();
-	bool Get(const SQObjectPtr &key,SQObjectPtr &val)  {
-		if(_class->_members->Get(key,val)) {
-			if(_isfield(val)) {
-				SQObjectPtr &o = _values[_member_idx(val)];
-				val = _realval(o);
-			}
-			else {
-				val = _class->_methods[_member_idx(val)].val;
-			}
-			return true;
-		}
-		return false;
-	}
-	bool Set(const SQObjectPtr &key,const SQObjectPtr &val) {
-		SQObjectPtr idx;
-		if(_class->_members->Get(key,idx) && _isfield(idx)) {
-            _values[_member_idx(idx)] = val;
-			return true;
-		}
-		return false;
-	}
-	void Release() {
-		_uiRef++;
-		if (_hook) { _hook(_userpointer,0);}
-		_uiRef--;
-		if(_uiRef > 0) return;
-		SQInteger size = _memsize;
-		this->~SQInstance();
-		SQ_FREE(this, size);
-	}
-	void Finalize();
-#ifndef NO_GARBAGE_COLLECTOR 
-	void Mark(SQCollectable ** );
-	SQObjectType GetType() {return OT_INSTANCE;}
-#endif
-	bool InstanceOf(SQClass *trg);
-	bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);
-
-	SQClass *_class;
-	SQUserPointer _userpointer;
-	SQRELEASEHOOK _hook;
-	SQInteger _memsize;
-	SQObjectPtr _values[1];
-};
-
-#endif //_SQCLASS_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQCLASS_H_
+#define _SQCLASS_H_
+
+struct SQInstance;
+
+struct SQClassMember {
+    SQObjectPtr val;
+    SQObjectPtr attrs;
+    void Null() {
+        val.Null();
+        attrs.Null();
+    }
+};
+
+typedef sqvector<SQClassMember> SQClassMemberVec;
+
+#define MEMBER_TYPE_METHOD 0x01000000
+#define MEMBER_TYPE_FIELD 0x02000000
+
+#define _ismethod(o) (_integer(o)&MEMBER_TYPE_METHOD)
+#define _isfield(o) (_integer(o)&MEMBER_TYPE_FIELD)
+#define _make_method_idx(i) ((SQInteger)(MEMBER_TYPE_METHOD|i))
+#define _make_field_idx(i) ((SQInteger)(MEMBER_TYPE_FIELD|i))
+#define _member_type(o) (_integer(o)&0xFF000000)
+#define _member_idx(o) (_integer(o)&0x00FFFFFF)
+
+struct SQClass : public CHAINABLE_OBJ
+{
+    SQClass(SQSharedState *ss,SQClass *base);
+public:
+    static SQClass* Create(SQSharedState *ss,SQClass *base) {
+        SQClass *newclass = (SQClass *)SQ_MALLOC(sizeof(SQClass));
+        new (newclass) SQClass(ss, base);
+        return newclass;
+    }
+    ~SQClass();
+    bool NewSlot(SQSharedState *ss, const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic);
+    bool Get(const SQObjectPtr &key,SQObjectPtr &val) {
+        if(_members->Get(key,val)) {
+            if(_isfield(val)) {
+                SQObjectPtr &o = _defaultvalues[_member_idx(val)].val;
+                val = _realval(o);
+            }
+            else {
+                val = _methods[_member_idx(val)].val;
+            }
+            return true;
+        }
+        return false;
+    }
+    bool GetConstructor(SQObjectPtr &ctor)
+    {
+        if(_constructoridx != -1) {
+            ctor = _methods[_constructoridx].val;
+            return true;
+        }
+        return false;
+    }
+    bool SetAttributes(const SQObjectPtr &key,const SQObjectPtr &val);
+    bool GetAttributes(const SQObjectPtr &key,SQObjectPtr &outval);
+    void Lock() { _locked = true; if(_base) _base->Lock(); }
+    void Release() {
+        if (_hook) { _hook(_typetag,0);}
+        sq_delete(this, SQClass);
+    }
+    void Finalize();
+#ifndef NO_GARBAGE_COLLECTOR
+    void Mark(SQCollectable ** );
+    SQObjectType GetType() {return OT_CLASS;}
+#endif
+    SQInteger Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
+    SQInstance *CreateInstance();
+    SQTable *_members;
+    SQClass *_base;
+    SQClassMemberVec _defaultvalues;
+    SQClassMemberVec _methods;
+    SQObjectPtr _metamethods[MT_LAST];
+    SQObjectPtr _attributes;
+    SQUserPointer _typetag;
+    SQRELEASEHOOK _hook;
+    bool _locked;
+    SQInteger _constructoridx;
+    SQInteger _udsize;
+};
+
+#define calcinstancesize(_theclass_) \
+    (_theclass_->_udsize + sq_aligning(sizeof(SQInstance) +  (sizeof(SQObjectPtr)*(_theclass_->_defaultvalues.size()>0?_theclass_->_defaultvalues.size()-1:0))))
+
+struct SQInstance : public SQDelegable
+{
+    void Init(SQSharedState *ss);
+    SQInstance(SQSharedState *ss, SQClass *c, SQInteger memsize);
+    SQInstance(SQSharedState *ss, SQInstance *c, SQInteger memsize);
+public:
+    static SQInstance* Create(SQSharedState *ss,SQClass *theclass) {
+
+        SQInteger size = calcinstancesize(theclass);
+        SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
+        new (newinst) SQInstance(ss, theclass,size);
+        if(theclass->_udsize) {
+            newinst->_userpointer = ((unsigned char *)newinst) + (size - theclass->_udsize);
+        }
+        return newinst;
+    }
+    SQInstance *Clone(SQSharedState *ss)
+    {
+        SQInteger size = calcinstancesize(_class);
+        SQInstance *newinst = (SQInstance *)SQ_MALLOC(size);
+        new (newinst) SQInstance(ss, this,size);
+        if(_class->_udsize) {
+            newinst->_userpointer = ((unsigned char *)newinst) + (size - _class->_udsize);
+        }
+        return newinst;
+    }
+    ~SQInstance();
+    bool Get(const SQObjectPtr &key,SQObjectPtr &val)  {
+        if(_class->_members->Get(key,val)) {
+            if(_isfield(val)) {
+                SQObjectPtr &o = _values[_member_idx(val)];
+                val = _realval(o);
+            }
+            else {
+                val = _class->_methods[_member_idx(val)].val;
+            }
+            return true;
+        }
+        return false;
+    }
+    bool Set(const SQObjectPtr &key,const SQObjectPtr &val) {
+        SQObjectPtr idx;
+        if(_class->_members->Get(key,idx) && _isfield(idx)) {
+            _values[_member_idx(idx)] = val;
+            return true;
+        }
+        return false;
+    }
+    void Release() {
+        _uiRef++;
+        if (_hook) { _hook(_userpointer,0);}
+        _uiRef--;
+        if(_uiRef > 0) return;
+        SQInteger size = _memsize;
+        this->~SQInstance();
+        SQ_FREE(this, size);
+    }
+    void Finalize();
+#ifndef NO_GARBAGE_COLLECTOR
+    void Mark(SQCollectable ** );
+    SQObjectType GetType() {return OT_INSTANCE;}
+#endif
+    bool InstanceOf(SQClass *trg);
+    bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);
+
+    SQClass *_class;
+    SQUserPointer _userpointer;
+    SQRELEASEHOOK _hook;
+    SQInteger _memsize;
+    SQObjectPtr _values[1];
+};
+
+#endif //_SQCLASS_H_

+ 201 - 201
squirrel/sqclosure.h

@@ -1,201 +1,201 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQCLOSURE_H_
-#define _SQCLOSURE_H_
-
-
-#define _CALC_CLOSURE_SIZE(func) (sizeof(SQClosure) + (func->_noutervalues*sizeof(SQObjectPtr)) + (func->_ndefaultparams*sizeof(SQObjectPtr)))
-
-struct SQFunctionProto;
-struct SQClass;
-struct SQClosure : public CHAINABLE_OBJ
-{
-private:
-	SQClosure(SQSharedState *ss,SQFunctionProto *func){_function = func; __ObjAddRef(_function); _base = NULL; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL; _root=NULL;}
-public:
-	static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func,SQWeakRef *root){
-		SQInteger size = _CALC_CLOSURE_SIZE(func);
-		SQClosure *nc=(SQClosure*)SQ_MALLOC(size);
-		new (nc) SQClosure(ss,func);
-		nc->_outervalues = (SQObjectPtr *)(nc + 1);
-		nc->_defaultparams = &nc->_outervalues[func->_noutervalues];
-		nc->_root = root;
-		 __ObjAddRef(nc->_root);
-		_CONSTRUCT_VECTOR(SQObjectPtr,func->_noutervalues,nc->_outervalues);
-		_CONSTRUCT_VECTOR(SQObjectPtr,func->_ndefaultparams,nc->_defaultparams);
-		return nc;
-	}
-	void Release(){
-		SQFunctionProto *f = _function;
-		SQInteger size = _CALC_CLOSURE_SIZE(f);
-		_DESTRUCT_VECTOR(SQObjectPtr,f->_noutervalues,_outervalues);
-		_DESTRUCT_VECTOR(SQObjectPtr,f->_ndefaultparams,_defaultparams);
-		__ObjRelease(_function);
-		this->~SQClosure();
-		sq_vm_free(this,size);
-	}
-	void SetRoot(SQWeakRef *r)
-	{
-		__ObjRelease(_root);
-		_root = r;
-		__ObjAddRef(_root);
-	}
-	SQClosure *Clone()
-	{
-		SQFunctionProto *f = _function;
-		SQClosure * ret = SQClosure::Create(_opt_ss(this),f,_root);
-		ret->_env = _env;
-		if(ret->_env) __ObjAddRef(ret->_env);
-		_COPY_VECTOR(ret->_outervalues,_outervalues,f->_noutervalues);
-		_COPY_VECTOR(ret->_defaultparams,_defaultparams,f->_ndefaultparams);
-		return ret;
-	}
-	~SQClosure();
-	
-	bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
-	static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
-#ifndef NO_GARBAGE_COLLECTOR
-	void Mark(SQCollectable **chain);
-	void Finalize(){
-		SQFunctionProto *f = _function;
-		_NULL_SQOBJECT_VECTOR(_outervalues,f->_noutervalues);
-		_NULL_SQOBJECT_VECTOR(_defaultparams,f->_ndefaultparams);
-	}
-	SQObjectType GetType() {return OT_CLOSURE;}
-#endif
-	SQWeakRef *_env;
-	SQWeakRef *_root;
-	SQClass *_base;
-	SQFunctionProto *_function;
-	SQObjectPtr *_outervalues;
-	SQObjectPtr *_defaultparams;
-};
-
-//////////////////////////////////////////////
-struct SQOuter : public CHAINABLE_OBJ
-{
-
-private:
-	SQOuter(SQSharedState *ss, SQObjectPtr *outer){_valptr = outer; _next = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); }
-
-public:
-	static SQOuter *Create(SQSharedState *ss, SQObjectPtr *outer)
-	{
-		SQOuter *nc  = (SQOuter*)SQ_MALLOC(sizeof(SQOuter));
-		new (nc) SQOuter(ss, outer);
-		return nc;
-	}
-	~SQOuter() { REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); }
-
-	void Release()
-	{
-		this->~SQOuter();
-		sq_vm_free(this,sizeof(SQOuter));
-	}
-	
-#ifndef NO_GARBAGE_COLLECTOR
-	void Mark(SQCollectable **chain);
-	void Finalize() { _value.Null(); }
-	SQObjectType GetType() {return OT_OUTER;}
-#endif
-
-	SQObjectPtr *_valptr;  /* pointer to value on stack, or _value below */
-	SQInteger    _idx;     /* idx in stack array, for relocation */
-	SQObjectPtr  _value;   /* value of outer after stack frame is closed */
-	SQOuter     *_next;    /* pointer to next outer when frame is open   */
-};
-
-//////////////////////////////////////////////
-struct SQGenerator : public CHAINABLE_OBJ 
-{
-	enum SQGeneratorState{eRunning,eSuspended,eDead};
-private:
-	SQGenerator(SQSharedState *ss,SQClosure *closure){_closure=closure;_state=eRunning;_ci._generator=NULL;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}
-public:
-	static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){
-		SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator));
-		new (nc) SQGenerator(ss,closure);
-		return nc;
-	}
-	~SQGenerator()
-	{
-		REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
-	}
-    void Kill(){
-		_state=eDead;
-		_stack.resize(0);
-		_closure.Null();}
-	void Release(){
-		sq_delete(this,SQGenerator);
-	}
-	
-	bool Yield(SQVM *v,SQInteger target);
-	bool Resume(SQVM *v,SQObjectPtr &dest);
-#ifndef NO_GARBAGE_COLLECTOR
-	void Mark(SQCollectable **chain);
-	void Finalize(){_stack.resize(0);_closure.Null();}
-	SQObjectType GetType() {return OT_GENERATOR;}
-#endif
-	SQObjectPtr _closure;
-	SQObjectPtrVec _stack;
-	SQVM::CallInfo _ci;
-	ExceptionsTraps _etraps;
-	SQGeneratorState _state;
-};
-
-#define _CALC_NATVIVECLOSURE_SIZE(noutervalues) (sizeof(SQNativeClosure) + (noutervalues*sizeof(SQObjectPtr)))
-
-struct SQNativeClosure : public CHAINABLE_OBJ
-{
-private:
-	SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;}
-public:
-	static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func,SQInteger nouters)
-	{
-		SQInteger size = _CALC_NATVIVECLOSURE_SIZE(nouters);
-		SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(size);
-		new (nc) SQNativeClosure(ss,func);
-		nc->_outervalues = (SQObjectPtr *)(nc + 1);
-		nc->_noutervalues = nouters;
-		_CONSTRUCT_VECTOR(SQObjectPtr,nc->_noutervalues,nc->_outervalues);
-		return nc;
-	}
-	SQNativeClosure *Clone()
-	{
-		SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function,_noutervalues);
-		ret->_env = _env;
-		if(ret->_env) __ObjAddRef(ret->_env);
-		ret->_name = _name;
-		_COPY_VECTOR(ret->_outervalues,_outervalues,_noutervalues);
-		ret->_typecheck.copy(_typecheck);
-		ret->_nparamscheck = _nparamscheck;
-		return ret;
-	}
-	~SQNativeClosure()
-	{
-		__ObjRelease(_env);
-		REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
-	}
-	void Release(){
-		SQInteger size = _CALC_NATVIVECLOSURE_SIZE(_noutervalues);
-		_DESTRUCT_VECTOR(SQObjectPtr,_noutervalues,_outervalues);
-		this->~SQNativeClosure();
-		sq_free(this,size);
-	}
-	
-#ifndef NO_GARBAGE_COLLECTOR
-	void Mark(SQCollectable **chain);
-	void Finalize() { _NULL_SQOBJECT_VECTOR(_outervalues,_noutervalues); }
-	SQObjectType GetType() {return OT_NATIVECLOSURE;}
-#endif
-	SQInteger _nparamscheck;
-	SQIntVec _typecheck;
-	SQObjectPtr *_outervalues;
-	SQUnsignedInteger _noutervalues;
-	SQWeakRef *_env;
-	SQFUNCTION _function;
-	SQObjectPtr _name;
-};
-
-
-
-#endif //_SQCLOSURE_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQCLOSURE_H_
+#define _SQCLOSURE_H_
+
+
+#define _CALC_CLOSURE_SIZE(func) (sizeof(SQClosure) + (func->_noutervalues*sizeof(SQObjectPtr)) + (func->_ndefaultparams*sizeof(SQObjectPtr)))
+
+struct SQFunctionProto;
+struct SQClass;
+struct SQClosure : public CHAINABLE_OBJ
+{
+private:
+    SQClosure(SQSharedState *ss,SQFunctionProto *func){_function = func; __ObjAddRef(_function); _base = NULL; INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL; _root=NULL;}
+public:
+    static SQClosure *Create(SQSharedState *ss,SQFunctionProto *func,SQWeakRef *root){
+        SQInteger size = _CALC_CLOSURE_SIZE(func);
+        SQClosure *nc=(SQClosure*)SQ_MALLOC(size);
+        new (nc) SQClosure(ss,func);
+        nc->_outervalues = (SQObjectPtr *)(nc + 1);
+        nc->_defaultparams = &nc->_outervalues[func->_noutervalues];
+        nc->_root = root;
+         __ObjAddRef(nc->_root);
+        _CONSTRUCT_VECTOR(SQObjectPtr,func->_noutervalues,nc->_outervalues);
+        _CONSTRUCT_VECTOR(SQObjectPtr,func->_ndefaultparams,nc->_defaultparams);
+        return nc;
+    }
+    void Release(){
+        SQFunctionProto *f = _function;
+        SQInteger size = _CALC_CLOSURE_SIZE(f);
+        _DESTRUCT_VECTOR(SQObjectPtr,f->_noutervalues,_outervalues);
+        _DESTRUCT_VECTOR(SQObjectPtr,f->_ndefaultparams,_defaultparams);
+        __ObjRelease(_function);
+        this->~SQClosure();
+        sq_vm_free(this,size);
+    }
+    void SetRoot(SQWeakRef *r)
+    {
+        __ObjRelease(_root);
+        _root = r;
+        __ObjAddRef(_root);
+    }
+    SQClosure *Clone()
+    {
+        SQFunctionProto *f = _function;
+        SQClosure * ret = SQClosure::Create(_opt_ss(this),f,_root);
+        ret->_env = _env;
+        if(ret->_env) __ObjAddRef(ret->_env);
+        _COPY_VECTOR(ret->_outervalues,_outervalues,f->_noutervalues);
+        _COPY_VECTOR(ret->_defaultparams,_defaultparams,f->_ndefaultparams);
+        return ret;
+    }
+    ~SQClosure();
+
+    bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
+    static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
+#ifndef NO_GARBAGE_COLLECTOR
+    void Mark(SQCollectable **chain);
+    void Finalize(){
+        SQFunctionProto *f = _function;
+        _NULL_SQOBJECT_VECTOR(_outervalues,f->_noutervalues);
+        _NULL_SQOBJECT_VECTOR(_defaultparams,f->_ndefaultparams);
+    }
+    SQObjectType GetType() {return OT_CLOSURE;}
+#endif
+    SQWeakRef *_env;
+    SQWeakRef *_root;
+    SQClass *_base;
+    SQFunctionProto *_function;
+    SQObjectPtr *_outervalues;
+    SQObjectPtr *_defaultparams;
+};
+
+//////////////////////////////////////////////
+struct SQOuter : public CHAINABLE_OBJ
+{
+
+private:
+    SQOuter(SQSharedState *ss, SQObjectPtr *outer){_valptr = outer; _next = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); }
+
+public:
+    static SQOuter *Create(SQSharedState *ss, SQObjectPtr *outer)
+    {
+        SQOuter *nc  = (SQOuter*)SQ_MALLOC(sizeof(SQOuter));
+        new (nc) SQOuter(ss, outer);
+        return nc;
+    }
+    ~SQOuter() { REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this); }
+
+    void Release()
+    {
+        this->~SQOuter();
+        sq_vm_free(this,sizeof(SQOuter));
+    }
+
+#ifndef NO_GARBAGE_COLLECTOR
+    void Mark(SQCollectable **chain);
+    void Finalize() { _value.Null(); }
+    SQObjectType GetType() {return OT_OUTER;}
+#endif
+
+    SQObjectPtr *_valptr;  /* pointer to value on stack, or _value below */
+    SQInteger    _idx;     /* idx in stack array, for relocation */
+    SQObjectPtr  _value;   /* value of outer after stack frame is closed */
+    SQOuter     *_next;    /* pointer to next outer when frame is open   */
+};
+
+//////////////////////////////////////////////
+struct SQGenerator : public CHAINABLE_OBJ
+{
+    enum SQGeneratorState{eRunning,eSuspended,eDead};
+private:
+    SQGenerator(SQSharedState *ss,SQClosure *closure){_closure=closure;_state=eRunning;_ci._generator=NULL;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);}
+public:
+    static SQGenerator *Create(SQSharedState *ss,SQClosure *closure){
+        SQGenerator *nc=(SQGenerator*)SQ_MALLOC(sizeof(SQGenerator));
+        new (nc) SQGenerator(ss,closure);
+        return nc;
+    }
+    ~SQGenerator()
+    {
+        REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+    }
+    void Kill(){
+        _state=eDead;
+        _stack.resize(0);
+        _closure.Null();}
+    void Release(){
+        sq_delete(this,SQGenerator);
+    }
+
+    bool Yield(SQVM *v,SQInteger target);
+    bool Resume(SQVM *v,SQObjectPtr &dest);
+#ifndef NO_GARBAGE_COLLECTOR
+    void Mark(SQCollectable **chain);
+    void Finalize(){_stack.resize(0);_closure.Null();}
+    SQObjectType GetType() {return OT_GENERATOR;}
+#endif
+    SQObjectPtr _closure;
+    SQObjectPtrVec _stack;
+    SQVM::CallInfo _ci;
+    ExceptionsTraps _etraps;
+    SQGeneratorState _state;
+};
+
+#define _CALC_NATVIVECLOSURE_SIZE(noutervalues) (sizeof(SQNativeClosure) + (noutervalues*sizeof(SQObjectPtr)))
+
+struct SQNativeClosure : public CHAINABLE_OBJ
+{
+private:
+    SQNativeClosure(SQSharedState *ss,SQFUNCTION func){_function=func;INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this); _env = NULL;}
+public:
+    static SQNativeClosure *Create(SQSharedState *ss,SQFUNCTION func,SQInteger nouters)
+    {
+        SQInteger size = _CALC_NATVIVECLOSURE_SIZE(nouters);
+        SQNativeClosure *nc=(SQNativeClosure*)SQ_MALLOC(size);
+        new (nc) SQNativeClosure(ss,func);
+        nc->_outervalues = (SQObjectPtr *)(nc + 1);
+        nc->_noutervalues = nouters;
+        _CONSTRUCT_VECTOR(SQObjectPtr,nc->_noutervalues,nc->_outervalues);
+        return nc;
+    }
+    SQNativeClosure *Clone()
+    {
+        SQNativeClosure * ret = SQNativeClosure::Create(_opt_ss(this),_function,_noutervalues);
+        ret->_env = _env;
+        if(ret->_env) __ObjAddRef(ret->_env);
+        ret->_name = _name;
+        _COPY_VECTOR(ret->_outervalues,_outervalues,_noutervalues);
+        ret->_typecheck.copy(_typecheck);
+        ret->_nparamscheck = _nparamscheck;
+        return ret;
+    }
+    ~SQNativeClosure()
+    {
+        __ObjRelease(_env);
+        REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+    }
+    void Release(){
+        SQInteger size = _CALC_NATVIVECLOSURE_SIZE(_noutervalues);
+        _DESTRUCT_VECTOR(SQObjectPtr,_noutervalues,_outervalues);
+        this->~SQNativeClosure();
+        sq_free(this,size);
+    }
+
+#ifndef NO_GARBAGE_COLLECTOR
+    void Mark(SQCollectable **chain);
+    void Finalize() { _NULL_SQOBJECT_VECTOR(_outervalues,_noutervalues); }
+    SQObjectType GetType() {return OT_NATIVECLOSURE;}
+#endif
+    SQInteger _nparamscheck;
+    SQIntVec _typecheck;
+    SQObjectPtr *_outervalues;
+    SQUnsignedInteger _noutervalues;
+    SQWeakRef *_env;
+    SQFUNCTION _function;
+    SQObjectPtr _name;
+};
+
+
+
+#endif //_SQCLOSURE_H_

+ 1577 - 1577
squirrel/sqcompiler.cpp

@@ -1,1577 +1,1577 @@
-/*
-	see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#ifndef NO_COMPILER
-#include <stdarg.h>
-#include <setjmp.h>
-#include "sqopcodes.h"
-#include "sqstring.h"
-#include "sqfuncproto.h"
-#include "sqcompiler.h"
-#include "sqfuncstate.h"
-#include "sqlexer.h"
-#include "sqvm.h"
-#include "sqtable.h"
-
-#define EXPR   1
-#define OBJECT 2
-#define BASE   3
-#define LOCAL  4
-#define OUTER  5
-
-struct SQExpState {
-  SQInteger  etype;       /* expr. type; one of EXPR, OBJECT, BASE, OUTER or LOCAL */
-  SQInteger  epos;        /* expr. location on stack; -1 for OBJECT and BASE */
-  bool       donot_get;   /* signal not to deref the next value */
-};
-
-#define MAX_COMPILER_ERROR_LEN 256
-
-struct SQScope {
-	SQInteger outers;
-	SQInteger stacksize;
-};
-
-#define BEGIN_SCOPE() SQScope __oldscope__ = _scope; \
-					 _scope.outers = _fs->_outers; \
-					 _scope.stacksize = _fs->GetStackSize();
-
-#define RESOLVE_OUTERS() if(_fs->GetStackSize() != _scope.stacksize) { \
-							if(_fs->CountOuters(_scope.stacksize)) { \
-								_fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \
-							} \
-						}
-
-#define END_SCOPE_NO_CLOSE() {	if(_fs->GetStackSize() != _scope.stacksize) { \
-							_fs->SetStackSize(_scope.stacksize); \
-						} \
-						_scope = __oldscope__; \
-					}
-
-#define END_SCOPE() {	SQInteger oldouters = _fs->_outers;\
-						if(_fs->GetStackSize() != _scope.stacksize) { \
-							_fs->SetStackSize(_scope.stacksize); \
-							if(oldouters != _fs->_outers) { \
-								_fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \
-							} \
-						} \
-						_scope = __oldscope__; \
-					}
-
-#define BEGIN_BREAKBLE_BLOCK()	SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \
-							SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \
-							_fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0);
-
-#define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \
-					__ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \
-					if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \
-					if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \
-					_fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();}
-
-class SQCompiler
-{
-public:
-	SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo)
-	{
-		_vm=v;
-		_lex.Init(_ss(v), rg, up,ThrowError,this);
-		_sourcename = SQString::Create(_ss(v), sourcename);
-		_lineinfo = lineinfo;_raiseerror = raiseerror;
-		_scope.outers = 0;
-		_scope.stacksize = 0;
-		_compilererror[0] = _SC('\0');
-	}
-	static void ThrowError(void *ud, const SQChar *s) {
-		SQCompiler *c = (SQCompiler *)ud;
-		c->Error(s);
-	}
-	void Error(const SQChar *s, ...)
-	{
-		va_list vl;
-		va_start(vl, s);
-		scvsprintf(_compilererror, MAX_COMPILER_ERROR_LEN, s, vl);
-		va_end(vl);
-		longjmp(_errorjmp,1);
-	}
-	void Lex(){	_token = _lex.Lex();}
-	SQObject Expect(SQInteger tok)
-	{
-		
-		if(_token != tok) {
-			if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {
-				//do nothing
-			}
-			else {
-				const SQChar *etypename;
-				if(tok > 255) {
-					switch(tok)
-					{
-					case TK_IDENTIFIER:
-						etypename = _SC("IDENTIFIER");
-						break;
-					case TK_STRING_LITERAL:
-						etypename = _SC("STRING_LITERAL");
-						break;
-					case TK_INTEGER:
-						etypename = _SC("INTEGER");
-						break;
-					case TK_FLOAT:
-						etypename = _SC("FLOAT");
-						break;
-					default:
-						etypename = _lex.Tok2Str(tok);
-					}
-					Error(_SC("expected '%s'"), etypename);
-				}
-				Error(_SC("expected '%c'"), tok);
-			}
-		}
-		SQObjectPtr ret;
-		switch(tok)
-		{
-		case TK_IDENTIFIER:
-			ret = _fs->CreateString(_lex._svalue);
-			break;
-		case TK_STRING_LITERAL:
-			ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
-			break;
-		case TK_INTEGER:
-			ret = SQObjectPtr(_lex._nvalue);
-			break;
-		case TK_FLOAT:
-			ret = SQObjectPtr(_lex._fvalue);
-			break;
-		}
-		Lex();
-		return ret;
-	}
-	bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); }
-	void OptionalSemicolon()
-	{
-		if(_token == _SC(';')) { Lex(); return; }
-		if(!IsEndOfStatement()) {
-			Error(_SC("end of statement expected (; or lf)"));
-		}
-	}
-	void MoveIfCurrentTargetIsLocal() {
-		SQInteger trg = _fs->TopTarget();
-		if(_fs->IsLocal(trg)) {
-			trg = _fs->PopTarget(); //pops the target and moves it
-			_fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg);
-		}
-	}
-	bool Compile(SQObjectPtr &o)
-	{
-		_debugline = 1;
-		_debugop = 0;
-
-		SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this);
-		funcstate._name = SQString::Create(_ss(_vm), _SC("main"));
-		_fs = &funcstate;
-		_fs->AddParameter(_fs->CreateString(_SC("this")));
-		_fs->AddParameter(_fs->CreateString(_SC("vargv")));
-		_fs->_varparams = true;
-		_fs->_sourcename = _sourcename;
-		SQInteger stacksize = _fs->GetStackSize();
-		if(setjmp(_errorjmp) == 0) {
-			Lex();
-			while(_token > 0){
-				Statement();
-				if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
-			}
-			_fs->SetStackSize(stacksize);
-			_fs->AddLineInfos(_lex._currentline, _lineinfo, true);
-			_fs->AddInstruction(_OP_RETURN, 0xFF);
-			_fs->SetStackSize(0);
-			o =_fs->BuildProto();
-#ifdef _DEBUG_DUMP
-			_fs->Dump(_funcproto(o));
-#endif
-		}
-		else {
-			if(_raiseerror && _ss(_vm)->_compilererrorhandler) {
-				_ss(_vm)->_compilererrorhandler(_vm, _compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),
-					_lex._currentline, _lex._currentcolumn);
-			}
-			_vm->_lasterror = SQString::Create(_ss(_vm), _compilererror, -1);
-			return false;
-		}
-		return true;
-	}
-	void Statements()
-	{
-		while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) {
-			Statement();
-			if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
-		}
-	}
-	void Statement(bool closeframe = true)
-	{
-		_fs->AddLineInfos(_lex._currentline, _lineinfo);
-		switch(_token){
-		case _SC(';'):	Lex();					break;
-		case TK_IF:		IfStatement();			break;
-		case TK_WHILE:		WhileStatement();		break;
-		case TK_DO:		DoWhileStatement();		break;
-		case TK_FOR:		ForStatement();			break;
-		case TK_FOREACH:	ForEachStatement();		break;
-		case TK_SWITCH:	SwitchStatement();		break;
-		case TK_LOCAL:		LocalDeclStatement();	break;
-		case TK_RETURN:
-		case TK_YIELD: {
-			SQOpcode op;
-			if(_token == TK_RETURN) {
-				op = _OP_RETURN;
-			}
-			else {
-				op = _OP_YIELD;
-				_fs->_bgenerator = true;
-			}
-			Lex();
-			if(!IsEndOfStatement()) {
-				SQInteger retexp = _fs->GetCurrentPos()+1;
-				CommaExpr();
-				if(op == _OP_RETURN && _fs->_traps > 0)
-					_fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);
-				_fs->_returnexp = retexp;
-				_fs->AddInstruction(op, 1, _fs->PopTarget(),_fs->GetStackSize());
-			}
-			else{ 
-				if(op == _OP_RETURN && _fs->_traps > 0)
-					_fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);
-				_fs->_returnexp = -1;
-				_fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize()); 
-			}
-			break;}
-		case TK_BREAK:
-			if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block"));
-			if(_fs->_breaktargets.top() > 0){
-				_fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);
-			}
-			RESOLVE_OUTERS();
-			_fs->AddInstruction(_OP_JMP, 0, -1234);
-			_fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());
-			Lex();
-			break;
-		case TK_CONTINUE:
-			if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block"));
-			if(_fs->_continuetargets.top() > 0) {
-				_fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);
-			}
-			RESOLVE_OUTERS();
-			_fs->AddInstruction(_OP_JMP, 0, -1234);
-			_fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());
-			Lex();
-			break;
-		case TK_FUNCTION:
-			FunctionStatement();
-			break;
-		case TK_CLASS:
-			ClassStatement();
-			break;
-		case TK_ENUM:
-			EnumStatement();
-			break;
-		case _SC('{'):{
-				BEGIN_SCOPE();
-				Lex();
-				Statements();
-				Expect(_SC('}'));
-				if(closeframe) {
-					END_SCOPE();
-				}
-				else {
-					END_SCOPE_NO_CLOSE();
-				}
-			}
-			break;
-		case TK_TRY:
-			TryCatchStatement();
-			break;
-		case TK_THROW:
-			Lex();
-			CommaExpr();
-			_fs->AddInstruction(_OP_THROW, _fs->PopTarget());
-			break;
-		case TK_CONST:
-			{
-			Lex();
-			SQObject id = Expect(TK_IDENTIFIER);
-			Expect('=');
-			SQObject val = ExpectScalar();
-			OptionalSemicolon();
-			SQTable *enums = _table(_ss(_vm)->_consts);
-			SQObjectPtr strongid = id; 
-			enums->NewSlot(strongid,SQObjectPtr(val));
-			strongid.Null();
-			}
-			break;
-		default:
-			CommaExpr();
-			_fs->DiscardTarget();
-			//_fs->PopTarget();
-			break;
-		}
-		_fs->SnoozeOpt();
-	}
-	void EmitDerefOp(SQOpcode op)
-	{
-		SQInteger val = _fs->PopTarget();
-		SQInteger key = _fs->PopTarget();
-		SQInteger src = _fs->PopTarget();
-        _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);
-	}
-	void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0)
-	{
-		SQInteger p2 = _fs->PopTarget(); //src in OP_GET
-		SQInteger p1 = _fs->PopTarget(); //key in OP_GET
-		_fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);
-	}
-	void EmitCompoundArith(SQInteger tok, SQInteger etype, SQInteger pos)
-	{
-		/* Generate code depending on the expression type */
-		switch(etype) {
-		case LOCAL:{
-			SQInteger p2 = _fs->PopTarget(); //src in OP_GET
-			SQInteger p1 = _fs->PopTarget(); //key in OP_GET
-			_fs->PushTarget(p1);
-			//EmitCompArithLocal(tok, p1, p1, p2);
-			_fs->AddInstruction(ChooseArithOpByToken(tok),p1, p2, p1, 0);
-			_fs->SnoozeOpt();
-				   }
-			break;
-		case OBJECT:
-		case BASE:
-			{
-				SQInteger val = _fs->PopTarget();
-				SQInteger key = _fs->PopTarget();
-				SQInteger src = _fs->PopTarget();
-				/* _OP_COMPARITH mixes dest obj and source val in the arg1 */
-				_fs->AddInstruction(_OP_COMPARITH, _fs->PushTarget(), (src<<16)|val, key, ChooseCompArithCharByToken(tok));
-			}
-			break;
-		case OUTER:
-			{
-				SQInteger val = _fs->TopTarget();
-				SQInteger tmp = _fs->PushTarget();
-				_fs->AddInstruction(_OP_GETOUTER,   tmp, pos);
-				_fs->AddInstruction(ChooseArithOpByToken(tok), tmp, val, tmp, 0);
-				_fs->PopTarget();
-				_fs->PopTarget();
-				_fs->AddInstruction(_OP_SETOUTER, _fs->PushTarget(), pos, tmp);
-			}
-			break;
-		}
-	}
-	void CommaExpr()
-	{
-		for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr());
-	}
-	void Expression()
-	{
-		 SQExpState es = _es;
-		_es.etype     = EXPR;
-		_es.epos      = -1;
-		_es.donot_get = false;
-		LogicalOrExp();
-		switch(_token)  {
-		case _SC('='):
-		case TK_NEWSLOT:
-		case TK_MINUSEQ:
-		case TK_PLUSEQ:
-		case TK_MULEQ:
-		case TK_DIVEQ:
-		case TK_MODEQ:{
-			SQInteger op = _token;
-			SQInteger ds = _es.etype;
-			SQInteger pos = _es.epos;
-			if(ds == EXPR) Error(_SC("can't assign expression"));
-			else if(ds == BASE) Error(_SC("'base' cannot be modified"));
-			Lex(); Expression();
-
-			switch(op){
-			case TK_NEWSLOT:
-				if(ds == OBJECT || ds == BASE)
-					EmitDerefOp(_OP_NEWSLOT);
-				else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
-					Error(_SC("can't 'create' a local slot"));
-				break;
-			case _SC('='): //ASSIGN
-				switch(ds) {
-				case LOCAL:
-					{
-						SQInteger src = _fs->PopTarget();
-						SQInteger dst = _fs->TopTarget();
-						_fs->AddInstruction(_OP_MOVE, dst, src);
-					}
-					break;
-				case OBJECT:
-				case BASE:
-					EmitDerefOp(_OP_SET);
-					break;
-				case OUTER:
-					{
-						SQInteger src = _fs->PopTarget();
-						SQInteger dst = _fs->PushTarget();
-						_fs->AddInstruction(_OP_SETOUTER, dst, pos, src);
-					}
-				}
-				break;
-			case TK_MINUSEQ:
-			case TK_PLUSEQ:
-			case TK_MULEQ:
-			case TK_DIVEQ:
-			case TK_MODEQ:
-				EmitCompoundArith(op, ds, pos);
-				break;
-			}
-			}
-			break;
-		case _SC('?'): {
-			Lex();
-			_fs->AddInstruction(_OP_JZ, _fs->PopTarget());
-			SQInteger jzpos = _fs->GetCurrentPos();
-			SQInteger trg = _fs->PushTarget();
-			Expression();
-			SQInteger first_exp = _fs->PopTarget();
-			if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
-			SQInteger endfirstexp = _fs->GetCurrentPos();
-			_fs->AddInstruction(_OP_JMP, 0, 0);
-			Expect(_SC(':'));
-			SQInteger jmppos = _fs->GetCurrentPos();
-			Expression();
-			SQInteger second_exp = _fs->PopTarget();
-			if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
-			_fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
-			_fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1);
-			_fs->SnoozeOpt();
-			}
-			break;
-		}
-		_es = es;
-	}
-	template<typename T> void INVOKE_EXP(T f)
-	{
-		SQExpState es = _es;
-		_es.etype     = EXPR;
-		_es.epos      = -1;
-		_es.donot_get = false;
-		(this->*f)();
-		_es = es;
-	}
-	template<typename T> void BIN_EXP(SQOpcode op, T f,SQInteger op3 = 0)
-	{
-		Lex(); 
-		INVOKE_EXP(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(); INVOKE_EXP(&SQCompiler::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(); INVOKE_EXP(&SQCompiler::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;
-			}
-		
-		default:
-			return;
-		}
-	}
-	void BitwiseOrExp()
-	{
-		BitwiseXorExp();
-		for(;;) if(_token == _SC('|'))
-		{BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR);
-		}else return;
-	}
-	void BitwiseXorExp()
-	{
-		BitwiseAndExp();
-		for(;;) if(_token == _SC('^'))
-		{BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR);
-		}else return;
-	}
-	void BitwiseAndExp()
-	{
-		EqExp();
-		for(;;) if(_token == _SC('&'))
-		{BIN_EXP(_OP_BITW, &SQCompiler::EqExp,BW_AND);
-		}else return;
-	}
-	void EqExp()
-	{
-		CompExp();
-		for(;;) switch(_token) {
-		case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::CompExp); break;
-		case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::CompExp); break;
-		case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQCompiler::CompExp,CMP_3W); break;
-		default: return;	
-		}
-	}
-	void CompExp()
-	{
-		ShiftExp();
-		for(;;) switch(_token) {
-		case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break;
-		case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break;
-		case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;
-		case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;
-		case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::ShiftExp); break;
-		case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &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;	
-		}
-	}
-	SQOpcode ChooseArithOpByToken(SQInteger tok)
-	{
-		switch(tok) {
-			case TK_PLUSEQ: case '+': return _OP_ADD;
-			case TK_MINUSEQ: case '-': return _OP_SUB;
-			case TK_MULEQ: case '*': return _OP_MUL;
-			case TK_DIVEQ: case '/': return _OP_DIV;
-			case TK_MODEQ: case '%': return _OP_MOD;
-			default: assert(0);
-		}
-		return _OP_ADD;
-	}
-	SQInteger ChooseCompArithCharByToken(SQInteger tok)
-	{
-		SQInteger oper;
-		switch(tok){
-		case TK_MINUSEQ: oper = '-'; break;
-		case TK_PLUSEQ: oper = '+'; break;
-		case TK_MULEQ: oper = '*'; break;
-		case TK_DIVEQ: oper = '/'; break;
-		case TK_MODEQ: oper = '%'; break;
-		default: oper = 0; //shut up compiler
-			assert(0); break;
-		};
-		return oper;
-	}
-	void PlusExp()
-	{
-		MultExp();
-		for(;;) switch(_token) {
-		case _SC('+'): case _SC('-'):
-			BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::MultExp); break;
-		default: return;
-		}
-	}
-	
-	void MultExp()
-	{
-		PrefixedExpr();
-		for(;;) switch(_token) {
-		case _SC('*'): case _SC('/'): case _SC('%'):
-			BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::PrefixedExpr); break;
-		default: return;
-		}
-	}
-	//if 'pos' != -1 the previous variable is a local variable
-	void PrefixedExpr()
-	{
-		SQInteger pos = Factor();
-		for(;;) {
-			switch(_token) {
-			case _SC('.'):
-				pos = -1;
-				Lex(); 
-
-				_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
-				if(_es.etype==BASE) {
-					Emit2ArgsOP(_OP_GET);
-					pos = _fs->TopTarget();
-					_es.etype = EXPR;
-					_es.epos   = pos;
-				}
-				else {
-					if(NeedGet()) {
-						Emit2ArgsOP(_OP_GET);
-					}
-					_es.etype = OBJECT;
-				}
-				break;
-			case _SC('['):
-				if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));
-				Lex(); Expression(); Expect(_SC(']')); 
-				pos = -1;
-				if(_es.etype==BASE) {
-					Emit2ArgsOP(_OP_GET);
-					pos = _fs->TopTarget();
-					_es.etype = EXPR;
-					_es.epos   = pos;
-				}
-				else {
-					if(NeedGet()) {
-						Emit2ArgsOP(_OP_GET);
-					}
-					_es.etype = OBJECT;
-				}
-				break;
-			case TK_MINUSMINUS:
-			case TK_PLUSPLUS:
-				{
-					if(IsEndOfStatement()) return;
-					SQInteger diff = (_token==TK_MINUSMINUS) ? -1 : 1;
-					Lex();
-					switch(_es.etype)
-					{
-						case EXPR: Error(_SC("can't '++' or '--' an expression")); break;
-						case OBJECT:
-						case BASE:
-							if(_es.donot_get == true)  { Error(_SC("can't '++' or '--' an expression")); break; } //mmh dor this make sense?
-							Emit2ArgsOP(_OP_PINC, diff);
-							break;
-						case LOCAL: {
-							SQInteger src = _fs->PopTarget();
-							_fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, diff);
-									}
-							break;
-						case OUTER: {
-							SQInteger tmp1 = _fs->PushTarget();
-							SQInteger tmp2 = _fs->PushTarget();
-							_fs->AddInstruction(_OP_GETOUTER, tmp2, _es.epos);
-							_fs->AddInstruction(_OP_PINCL,    tmp1, tmp2, 0, diff);
-							_fs->AddInstruction(_OP_SETOUTER, tmp2, _es.epos, tmp2);
-							_fs->PopTarget();
-						}
-					}
-				}
-				return;
-				break;	
-			case _SC('('): 
-				switch(_es.etype) {
-					case OBJECT: {
-						SQInteger key     = _fs->PopTarget();  /* location of the key */
-						SQInteger table   = _fs->PopTarget();  /* location of the object */
-						SQInteger closure = _fs->PushTarget(); /* location for the closure */
-						SQInteger ttarget = _fs->PushTarget(); /* location for 'this' pointer */
-						_fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);
-						}
-						break;
-					case BASE:
-						//Emit2ArgsOP(_OP_GET);
-						_fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
-						break;
-					case OUTER:
-						_fs->AddInstruction(_OP_GETOUTER, _fs->PushTarget(), _es.epos);
-						_fs->AddInstruction(_OP_MOVE,     _fs->PushTarget(), 0);
-						break;
-					default:
-						_fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
-				}
-				_es.etype = EXPR;
-				Lex();
-				FunctionCallArgs();
-				break;
-			default: return;
-			}
-		}
-	}
-	SQInteger Factor()
-	{
-		//_es.etype = EXPR;
-		switch(_token)
-		{
-		case TK_STRING_LITERAL:
-			_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
-			Lex(); 
-			break;
-		case TK_BASE:
-			Lex();
-			_fs->AddInstruction(_OP_GETBASE, _fs->PushTarget());
-			_es.etype  = BASE;
-			_es.epos   = _fs->TopTarget();
-			return (_es.epos);
-			break;
-		case TK_IDENTIFIER:
-		case TK_CONSTRUCTOR:
-		case TK_THIS:{
-				SQObject id;
-				SQObject constant;
-
-				switch(_token) {
-					case TK_IDENTIFIER:  id = _fs->CreateString(_lex._svalue);       break;
-					case TK_THIS:        id = _fs->CreateString(_SC("this"),4);        break;
-					case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor"),11); break;
-				}
-
-				SQInteger pos = -1;
-				Lex();
-				if((pos = _fs->GetLocalVariable(id)) != -1) {
-					/* Handle a local variable (includes 'this') */
-					_fs->PushTarget(pos);
-					_es.etype  = LOCAL;
-					_es.epos   = pos;
-				}
-
-				else if((pos = _fs->GetOuterVariable(id)) != -1) {
-					/* Handle a free var */
-					if(NeedGet()) {
-						_es.epos  = _fs->PushTarget();
-						_fs->AddInstruction(_OP_GETOUTER, _es.epos, pos);	
-						/* _es.etype = EXPR; already default value */
-					}
-					else {
-						_es.etype = OUTER;
-						_es.epos  = pos;
-					}
-				}
-
-				else if(_fs->IsConstant(id, constant)) {
-					/* Handle named constant */
-					SQObjectPtr constval;
-					SQObject    constid;
-					if(type(constant) == OT_TABLE) {
-						Expect('.');
-						constid = Expect(TK_IDENTIFIER);
-						if(!_table(constant)->Get(constid, constval)) {
-							constval.Null();
-							Error(_SC("invalid constant [%s.%s]"), _stringval(id), _stringval(constid));
-						}
-					}
-					else {
-						constval = constant;
-					}
-					_es.epos = _fs->PushTarget();
-
-					/* generate direct or literal function depending on size */
-					SQObjectType ctype = type(constval);
-					switch(ctype) {
-						case OT_INTEGER: EmitLoadConstInt(_integer(constval),_es.epos); break;
-						case OT_FLOAT: EmitLoadConstFloat(_float(constval),_es.epos); break;
-						case OT_BOOL: _fs->AddInstruction(_OP_LOADBOOL, _es.epos, _integer(constval)); break;
-						default: _fs->AddInstruction(_OP_LOAD,_es.epos,_fs->GetConstant(constval)); break;
-					}
-					_es.etype = EXPR;
-				}
-				else {
-					/* Handle a non-local variable, aka a field. Push the 'this' pointer on
-					* the virtual stack (always found in offset 0, so no instruction needs to
-					* be generated), and push the key next. Generate an _OP_LOAD instruction
-					* for the latter. If we are not using the variable as a dref expr, generate
-					* the _OP_GET instruction.
-					*/
-					_fs->PushTarget(0);
-					_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
-					if(NeedGet()) {
-						Emit2ArgsOP(_OP_GET);
-					}
-					_es.etype = OBJECT;
-				}
-				return _es.epos;
-			}
-			break;
-		case TK_DOUBLE_COLON:  // "::"
-			_fs->AddInstruction(_OP_LOADROOT, _fs->PushTarget());
-			_es.etype = OBJECT;
-			_token = _SC('.'); /* hack: drop into PrefixExpr, case '.'*/
-			_es.epos = -1;
-			return _es.epos;
-			break;
-		case TK_NULL: 
-			_fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
-			Lex();
-			break;
-		case TK_INTEGER: EmitLoadConstInt(_lex._nvalue,-1); Lex();	break;
-		case TK_FLOAT: EmitLoadConstFloat(_lex._fvalue,-1); Lex(); break;
-		case TK_TRUE: case TK_FALSE:
-			_fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);
-			Lex();
-			break;
-		case _SC('['): {
-				_fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,0,NOT_ARRAY);
-				SQInteger apos = _fs->GetCurrentPos(),key = 0;
-				Lex();
-				while(_token != _SC(']')) {
-                    Expression(); 
-					if(_token == _SC(',')) Lex();
-					SQInteger val = _fs->PopTarget();
-					SQInteger array = _fs->TopTarget();
-					_fs->AddInstruction(_OP_APPENDARRAY, array, val, AAT_STACK);
-					key++;
-				}
-				_fs->SetIntructionParam(apos, 1, key);
-				Lex();
-			}
-			break;
-		case _SC('{'):
-			_fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
-			Lex();ParseTableOrClass(_SC(','),_SC('}'));
-			break;
-		case TK_FUNCTION: FunctionExp(_token);break;
-		case _SC('@'): FunctionExp(_token,true);break;
-		case TK_CLASS: Lex(); ClassExp();break;
-		case _SC('-'): 
-			Lex(); 
-			switch(_token) {
-			case TK_INTEGER: EmitLoadConstInt(-_lex._nvalue,-1); Lex(); break;
-			case TK_FLOAT: EmitLoadConstFloat(-_lex._fvalue,-1); Lex(); break;
-			default: UnaryOP(_OP_NEG);
-			}
-			break;
-		case _SC('!'): Lex(); UnaryOP(_OP_NOT); break;
-		case _SC('~'): 
-			Lex(); 
-			if(_token == TK_INTEGER)  { EmitLoadConstInt(~_lex._nvalue,-1); Lex(); break; }
-			UnaryOP(_OP_BWNOT); 
-			break;
-		case TK_TYPEOF : Lex() ;UnaryOP(_OP_TYPEOF); break;
-		case TK_RESUME : Lex(); UnaryOP(_OP_RESUME); break;
-		case TK_CLONE : Lex(); UnaryOP(_OP_CLONE); break;
-		case TK_MINUSMINUS : 
-		case TK_PLUSPLUS :PrefixIncDec(_token); break;
-		case TK_DELETE : DeleteExpr(); break;
-		case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));
-			break;
-		case TK___LINE__: EmitLoadConstInt(_lex._currentline,-1); Lex(); break;
-        case TK___FILE__: _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_sourcename)); Lex(); break;
-		default: Error(_SC("expression expected"));
-		}
-		_es.etype = EXPR;
-		return -1;
-	}
-	void EmitLoadConstInt(SQInteger value,SQInteger target)
-	{
-		if(target < 0) {
-			target = _fs->PushTarget();
-		}
-		if(value <= INT_MAX && value > INT_MIN) { //does it fit in 32 bits?
-			_fs->AddInstruction(_OP_LOADINT, target,value);
-		}
-		else {
-			_fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));
-		}
-	}
-	void EmitLoadConstFloat(SQFloat value,SQInteger target)
-	{
-		if(target < 0) {
-			target = _fs->PushTarget();
-		}
-		if(sizeof(SQFloat) == sizeof(SQInt32)) {
-			_fs->AddInstruction(_OP_LOADFLOAT, target,*((SQInt32 *)&value));
-		}
-		else {
-			_fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));
-		}
-	}
-	void UnaryOP(SQOpcode op)
-	{
-		PrefixedExpr();
-		SQInteger src = _fs->PopTarget();
-		_fs->AddInstruction(op, _fs->PushTarget(), src);
-	}
-	bool NeedGet()
-	{
-		switch(_token) {
-		case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_MODEQ: case TK_MULEQ:
-	    case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ:
-			return false;
-		case TK_PLUSPLUS: case TK_MINUSMINUS:
-			if (!IsEndOfStatement()) {
-				return false;
-			}
-		break;
-		}
-		return (!_es.donot_get || ( _es.donot_get && (_token == _SC('.') || _token == _SC('['))));
-	}
-	void FunctionCallArgs()
-	{
-		SQInteger nargs = 1;//this
-		 while(_token != _SC(')')) {
-			 Expression();
-			 MoveIfCurrentTargetIsLocal();
-			 nargs++; 
-			 if(_token == _SC(',')){ 
-				 Lex(); 
-				 if(_token == ')') Error(_SC("expression expected, found ')'"));
-			 }
-		 }
-		 Lex();
-		 for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget();
-		 SQInteger stackbase = _fs->PopTarget();
-		 SQInteger closure = _fs->PopTarget();
-         _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);
-	}
-	void ParseTableOrClass(SQInteger separator,SQInteger terminator)
-	{
-		SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;
-		while(_token != terminator) {
-			bool hasattrs = false;
-			bool isstatic = false;
-			//check if is an attribute
-			if(separator == ';') {
-				if(_token == TK_ATTR_OPEN) {
-					_fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); Lex();
-					ParseTableOrClass(',',TK_ATTR_CLOSE);
-					hasattrs = true;
-				}
-				if(_token == TK_STATIC) {
-					isstatic = true;
-					Lex();
-				}
-			}
-			switch(_token) {
-			case TK_FUNCTION:
-			case TK_CONSTRUCTOR:{
-				SQInteger tk = _token;
-				Lex();
-				SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor"));
-				Expect(_SC('('));
-				_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
-				CreateFunction(id);
-				_fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
-								}
-								break;
-			case _SC('['):
-				Lex(); CommaExpr(); Expect(_SC(']'));
-				Expect(_SC('=')); Expression();
-				break;
-			case TK_STRING_LITERAL: //JSON
-				if(separator == ',') { //only works for tables
-					_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_STRING_LITERAL)));
-					Expect(_SC(':')); Expression();
-					break;
-				}
-			default :
-				_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
-				Expect(_SC('=')); Expression();
-			}
-			if(_token == separator) Lex();//optional comma/semicolon
-			nkeys++;
-			SQInteger val = _fs->PopTarget();
-			SQInteger key = _fs->PopTarget();
-			SQInteger attrs = hasattrs ? _fs->PopTarget():-1;
-			assert((hasattrs && (attrs == key-1)) || !hasattrs);
-			unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);
-			SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
-			if(separator == _SC(',')) { //hack recognizes a table from the separator
-				_fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val);
-			}
-			else {
-				_fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val); //this for classes only as it invokes _newmember
-			}
-		}
-		if(separator == _SC(',')) //hack recognizes a table from the separator
-			_fs->SetIntructionParam(tpos, 1, nkeys);
-		Lex();
-	}
-	void LocalDeclStatement()
-	{
-		SQObject varname;
-		Lex();
-		if( _token == TK_FUNCTION) {
-			Lex();
-			varname = Expect(TK_IDENTIFIER);
-			Expect(_SC('('));
-			CreateFunction(varname,false);
-			_fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
-			_fs->PopTarget();
-			_fs->PushLocalVariable(varname);
-			return;
-		}
-
-		do {
-			varname = Expect(TK_IDENTIFIER);
-			if(_token == _SC('=')) {
-				Lex(); Expression();
-				SQInteger src = _fs->PopTarget();
-				SQInteger dest = _fs->PushTarget();
-				if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);
-			}
-			else{
-				_fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
-			}
-			_fs->PopTarget();
-			_fs->PushLocalVariable(varname);
-			if(_token == _SC(',')) Lex(); else break;
-		} while(1);
-	}
-	void IfBlock()
-	{
-		if (_token == _SC('{'))
-		{
-			BEGIN_SCOPE();
-			Lex();
-			Statements();
-			Expect(_SC('}'));
-			if (true) {
-				END_SCOPE();
-			}
-			else {
-				END_SCOPE_NO_CLOSE();
-			}
-		}
-		else {
-			//BEGIN_SCOPE();
-			Statement();
-			if (_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
-			//END_SCOPE();
-		}
-	}
-	void IfStatement()
-	{
-		SQInteger jmppos;
-		bool haselse = false;
-		Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
-		_fs->AddInstruction(_OP_JZ, _fs->PopTarget());
-		SQInteger jnepos = _fs->GetCurrentPos();
-		
-		
-		
-		IfBlock();
-		//
-		/*static int n = 0;
-		if (_token != _SC('}') && _token != TK_ELSE) {
-			printf("IF %d-----------------------!!!!!!!!!\n", n);
-			if (n == 5)
-			{
-				printf("asd");
-			}
-			n++;
-			//OptionalSemicolon();
-		}*/
-		
-		
-		SQInteger endifblock = _fs->GetCurrentPos();
-		if(_token == TK_ELSE){
-			haselse = true;
-			//BEGIN_SCOPE();
-			_fs->AddInstruction(_OP_JMP);
-			jmppos = _fs->GetCurrentPos();
-			Lex();
-			//Statement(); if(_lex._prevtoken != _SC('}')) OptionalSemicolon();
-			IfBlock();
-			//END_SCOPE();
-			_fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
-		}
-		_fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));
-	}
-	void WhileStatement()
-	{
-		SQInteger jzpos, jmppos;
-		jmppos = _fs->GetCurrentPos();
-		Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
-		
-		BEGIN_BREAKBLE_BLOCK();
-		_fs->AddInstruction(_OP_JZ, _fs->PopTarget());
-		jzpos = _fs->GetCurrentPos();
-		BEGIN_SCOPE();
-		
-		Statement();
-		
-		END_SCOPE();
-		_fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
-		_fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
-		
-		END_BREAKBLE_BLOCK(jmppos);
-	}
-	void DoWhileStatement()
-	{
-		Lex();
-		SQInteger jmptrg = _fs->GetCurrentPos();
-		BEGIN_BREAKBLE_BLOCK()
-		BEGIN_SCOPE();
-		Statement();
-		END_SCOPE();
-		Expect(TK_WHILE);
-		SQInteger continuetrg = _fs->GetCurrentPos();
-		Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
-		_fs->AddInstruction(_OP_JZ, _fs->PopTarget(), 1);
-		_fs->AddInstruction(_OP_JMP, 0, jmptrg - _fs->GetCurrentPos() - 1);
-		END_BREAKBLE_BLOCK(continuetrg);
-	}
-	void ForStatement()
-	{
-		Lex();
-		BEGIN_SCOPE();
-		Expect(_SC('('));
-		if(_token == TK_LOCAL) LocalDeclStatement();
-		else if(_token != _SC(';')){
-			CommaExpr();
-			_fs->PopTarget();
-		}
-		Expect(_SC(';'));
-		_fs->SnoozeOpt();
-		SQInteger jmppos = _fs->GetCurrentPos();
-		SQInteger jzpos = -1;
-		if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }
-		Expect(_SC(';'));
-		_fs->SnoozeOpt();
-		SQInteger expstart = _fs->GetCurrentPos() + 1;
-		if(_token != _SC(')')) {
-			CommaExpr();
-			_fs->PopTarget();
-		}
-		Expect(_SC(')'));
-		_fs->SnoozeOpt();
-		SQInteger expend = _fs->GetCurrentPos();
-		SQInteger expsize = (expend - expstart) + 1;
-		SQInstructionVec exp;
-		if(expsize > 0) {
-			for(SQInteger i = 0; i < expsize; i++)
-				exp.push_back(_fs->GetInstruction(expstart + i));
-			_fs->PopInstructions(expsize);
-		}
-		BEGIN_BREAKBLE_BLOCK()
-		Statement();
-		SQInteger continuetrg = _fs->GetCurrentPos();
-		if(expsize > 0) {
-			for(SQInteger i = 0; i < expsize; i++)
-				_fs->AddInstruction(exp[i]);
-		}
-		_fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
-		if(jzpos>  0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
-		END_SCOPE();
-		
-		END_BREAKBLE_BLOCK(continuetrg);
-	}
-	void ForEachStatement()
-	{
-		SQObject idxname, valname;
-		Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);
-		if(_token == _SC(',')) {
-			idxname = valname;
-			Lex(); valname = Expect(TK_IDENTIFIER);
-		}
-		else{
-			idxname = _fs->CreateString(_SC("@INDEX@"));
-		}
-		Expect(TK_IN);
-		
-		//save the stack size
-		BEGIN_SCOPE();
-		//put the table in the stack(evaluate the table expression)
-		Expression(); Expect(_SC(')'));
-		SQInteger container = _fs->TopTarget();
-		//push the index local var
-		SQInteger indexpos = _fs->PushLocalVariable(idxname);
-		_fs->AddInstruction(_OP_LOADNULLS, indexpos,1);
-		//push the value local var
-		SQInteger valuepos = _fs->PushLocalVariable(valname);
-		_fs->AddInstruction(_OP_LOADNULLS, valuepos,1);
-		//push reference index
-		SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible
-		_fs->AddInstruction(_OP_LOADNULLS, itrpos,1);
-		SQInteger jmppos = _fs->GetCurrentPos();
-		_fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);
-		SQInteger foreachpos = _fs->GetCurrentPos();
-		_fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos);
-		//generate the statement code
-		BEGIN_BREAKBLE_BLOCK()
-		Statement();
-		_fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
-		_fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);
-		_fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos);
-		END_BREAKBLE_BLOCK(foreachpos - 1);
-		//restore the local variable stack(remove index,val and ref idx)
-		_fs->PopTarget();
-		END_SCOPE();
-	}
-	void SwitchStatement()
-	{
-		Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
-		Expect(_SC('{'));
-		SQInteger expr = _fs->TopTarget();
-		bool bfirst = true;
-		SQInteger tonextcondjmp = -1;
-		SQInteger skipcondjmp = -1;
-		SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size();
-		_fs->_breaktargets.push_back(0);
-		while(_token == TK_CASE) {
-			if(!bfirst) {
-				_fs->AddInstruction(_OP_JMP, 0, 0);
-				skipcondjmp = _fs->GetCurrentPos();
-				_fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
-			}
-			//condition
-			Lex(); Expression(); Expect(_SC(':'));
-			SQInteger trg = _fs->PopTarget();
-			SQInteger eqtarget = trg;
-			bool local = _fs->IsLocal(trg);
-			if(local) {
-				eqtarget = _fs->PushTarget(); //we need to allocate a extra reg
-			}
-			_fs->AddInstruction(_OP_EQ, eqtarget, trg, expr);
-			_fs->AddInstruction(_OP_JZ, eqtarget, 0);
-			if(local) {
-				_fs->PopTarget();
-			}
-			
-			//end condition
-			if(skipcondjmp != -1) {
-				_fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));
-			}
-			tonextcondjmp = _fs->GetCurrentPos();
-			BEGIN_SCOPE();
-			Statements();
-			END_SCOPE();
-			bfirst = false;
-		}
-		if(tonextcondjmp != -1)
-			_fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
-		if(_token == TK_DEFAULT) {
-			Lex(); Expect(_SC(':'));
-			BEGIN_SCOPE();
-			Statements();
-			END_SCOPE();
-		}
-		Expect(_SC('}'));
-		_fs->PopTarget();
-		__nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;
-		if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);
-		_fs->_breaktargets.pop_back();
-	}
-	void FunctionStatement()
-	{
-		SQObject id;
-		Lex(); id = Expect(TK_IDENTIFIER);
-		_fs->PushTarget(0);
-		_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
-		if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
-		
-		while(_token == TK_DOUBLE_COLON) {
-			Lex();
-			id = Expect(TK_IDENTIFIER);
-			_fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
-			if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
-		}
-		Expect(_SC('('));
-		CreateFunction(id);
-		_fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
-		EmitDerefOp(_OP_NEWSLOT);
-		_fs->PopTarget();
-	}
-	void ClassStatement()
-	{
-		SQExpState es;
-		Lex();
-		es = _es;
-		_es.donot_get = true;
-		PrefixedExpr();
-		if(_es.etype == EXPR) {
-			Error(_SC("invalid class name"));
-		}
-		else if(_es.etype == OBJECT || _es.etype == BASE) {
-			ClassExp();
-			EmitDerefOp(_OP_NEWSLOT);
-			_fs->PopTarget();
-		}
-		else {
-			Error(_SC("cannot create a class in a local with the syntax(class <local>)"));
-		}
-		_es = es;
-	}
-	SQObject ExpectScalar()
-	{
-		SQObject val;
-		val._type = OT_NULL; val._unVal.nInteger = 0; //shut up GCC 4.x
-		switch(_token) {
-			case TK_INTEGER:
-				val._type = OT_INTEGER;
-				val._unVal.nInteger = _lex._nvalue;
-				break;
-			case TK_FLOAT:
-				val._type = OT_FLOAT;
-				val._unVal.fFloat = _lex._fvalue;
-				break;
-			case TK_STRING_LITERAL:
-				val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
-				break;
-			case TK_TRUE:
-			case TK_FALSE:
-				val._type = OT_BOOL;
-				val._unVal.nInteger = _token == TK_TRUE ? 1 : 0;
-				break;
-			case '-':
-				Lex();
-				switch(_token)
-				{
-				case TK_INTEGER:
-					val._type = OT_INTEGER;
-					val._unVal.nInteger = -_lex._nvalue;
-				break;
-				case TK_FLOAT:
-					val._type = OT_FLOAT;
-					val._unVal.fFloat = -_lex._fvalue;
-				break;
-				default:
-					Error(_SC("scalar expected : integer,float"));
-				}
-				break;
-			default:
-				Error(_SC("scalar expected : integer,float or string"));
-		}
-		Lex();
-		return val;
-	}
-	void EnumStatement()
-	{
-		Lex(); 
-		SQObject id = Expect(TK_IDENTIFIER);
-		Expect(_SC('{'));
-		
-		SQObject table = _fs->CreateTable();
-		SQInteger nval = 0;
-		while(_token != _SC('}')) {
-			SQObject key = Expect(TK_IDENTIFIER);
-			SQObject val;
-			if(_token == _SC('=')) {
-				Lex();
-				val = ExpectScalar();
-			}
-			else {
-				val._type = OT_INTEGER;
-				val._unVal.nInteger = nval++;
-			}
-			_table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val));
-			if(_token == ',') Lex();
-		}
-		SQTable *enums = _table(_ss(_vm)->_consts);
-		SQObjectPtr strongid = id; 
-		enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table));
-		strongid.Null();
-		Lex();
-	}
-	void TryCatchStatement()
-	{
-		SQObject exid;
-		Lex();
-		_fs->AddInstruction(_OP_PUSHTRAP,0,0);
-		_fs->_traps++;
-		if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;
-		if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;
-		SQInteger trappos = _fs->GetCurrentPos();
-		{
-			BEGIN_SCOPE();
-			Statement();
-			END_SCOPE();
-		}
-		_fs->_traps--;
-		_fs->AddInstruction(_OP_POPTRAP, 1, 0);
-		if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;
-		if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--;
-		_fs->AddInstruction(_OP_JMP, 0, 0);
-		SQInteger jmppos = _fs->GetCurrentPos();
-		_fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));
-		Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));
-		{
-			BEGIN_SCOPE();
-			SQInteger ex_target = _fs->PushLocalVariable(exid);
-			_fs->SetIntructionParam(trappos, 0, ex_target);
-			Statement();
-			_fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);
-			END_SCOPE();
-		}
-	}
-	void FunctionExp(SQInteger ftype,bool lambda = false)
-	{
-		Lex(); Expect(_SC('('));
-		SQObjectPtr dummy;
-		CreateFunction(dummy,lambda);
-		_fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);
-	}
-	void ClassExp()
-	{
-		SQInteger base = -1;
-		SQInteger attrs = -1;
-		if(_token == TK_EXTENDS) {
-			Lex(); Expression();
-			base = _fs->TopTarget();
-		}
-		if(_token == TK_ATTR_OPEN) {
-			Lex();
-			_fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
-			ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);
-			attrs = _fs->TopTarget();
-		}
-		Expect(_SC('{'));
-		if(attrs != -1) _fs->PopTarget();
-		if(base != -1) _fs->PopTarget();
-		_fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS);
-		ParseTableOrClass(_SC(';'),_SC('}'));
-	}
-	void DeleteExpr()
-	{
-		SQExpState es;
-		Lex();
-		es = _es;
-		_es.donot_get = true;
-		PrefixedExpr();
-		if(_es.etype==EXPR) Error(_SC("can't delete an expression"));
-		if(_es.etype==OBJECT || _es.etype==BASE) {
-			Emit2ArgsOP(_OP_DELETE);
-		}
-		else {
-			Error(_SC("cannot delete an (outer) local"));
-		}
-		_es = es;
-	}
-	void PrefixIncDec(SQInteger token)
-	{
-		SQExpState  es;
-		SQInteger diff = (token==TK_MINUSMINUS) ? -1 : 1;
-		Lex();
-		es = _es;
-		_es.donot_get = true;
-		PrefixedExpr();
-		if(_es.etype==EXPR) {
-			Error(_SC("can't '++' or '--' an expression"));
-		}
-		else if(_es.etype==OBJECT || _es.etype==BASE) {
-			Emit2ArgsOP(_OP_INC, diff);
-		}
-		else if(_es.etype==LOCAL) {
-			SQInteger src = _fs->TopTarget();
-			_fs->AddInstruction(_OP_INCL, src, src, 0, diff);
-			
-		}
-		else if(_es.etype==OUTER) {
-			SQInteger tmp = _fs->PushTarget();
-			_fs->AddInstruction(_OP_GETOUTER, tmp, _es.epos);
-			_fs->AddInstruction(_OP_INCL,     tmp, tmp, 0, diff);
-			_fs->AddInstruction(_OP_SETOUTER, tmp, _es.epos, tmp);
-		}
-		_es = es;
-	}
-	void CreateFunction(SQObject &name,bool lambda = false)
-	{
-		SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));
-		funcstate->_name = name;
-		SQObject paramname;
-		funcstate->AddParameter(_fs->CreateString(_SC("this")));
-		funcstate->_sourcename = _sourcename;
-		SQInteger defparams = 0;
-		while(_token!=_SC(')')) {
-			if(_token == TK_VARPARAMS) {
-				if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters"));
-				funcstate->AddParameter(_fs->CreateString(_SC("vargv")));
-				funcstate->_varparams = true;
-				Lex();
-				if(_token != _SC(')')) Error(_SC("expected ')'"));
-				break;
-			}
-			else {
-				paramname = Expect(TK_IDENTIFIER);
-				funcstate->AddParameter(paramname);
-				if(_token == _SC('=')) { 
-					Lex();
-					Expression();
-					funcstate->AddDefaultParam(_fs->TopTarget());
-					defparams++;
-				}
-				else {
-					if(defparams > 0) Error(_SC("expected '='"));
-				}
-				if(_token == _SC(',')) Lex();
-				else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
-			}
-		}
-		Expect(_SC(')'));
-		for(SQInteger n = 0; n < defparams; n++) {
-			_fs->PopTarget();
-		}
-				
-		SQFuncState *currchunk = _fs;
-		_fs = funcstate;
-		if(lambda) { 
-			Expression(); 
-			_fs->AddInstruction(_OP_RETURN, 1, _fs->PopTarget());}
-		else { 
-			Statement(false); 
-		}
-		funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);
-        funcstate->AddInstruction(_OP_RETURN, -1);
-		funcstate->SetStackSize(0);
-
-		SQFunctionProto *func = funcstate->BuildProto();
-#ifdef _DEBUG_DUMP
-		funcstate->Dump(func);
-#endif
-		_fs = currchunk;
-		_fs->_functions.push_back(func);
-		_fs->PopChildState();
-	}
-	void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
-	{
-		while(ntoresolve > 0) {
-			SQInteger pos = funcstate->_unresolvedbreaks.back();
-			funcstate->_unresolvedbreaks.pop_back();
-			//set the jmp instruction
-			funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0);
-			ntoresolve--;
-		}
-	}
-	void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos)
-	{
-		while(ntoresolve > 0) {
-			SQInteger pos = funcstate->_unresolvedcontinues.back();
-			funcstate->_unresolvedcontinues.pop_back();
-			//set the jmp instruction
-			funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);
-			ntoresolve--;
-		}
-	}
-private:
-	SQInteger _token;
-	SQFuncState *_fs;
-	SQObjectPtr _sourcename;
-	SQLexer _lex;
-	bool _lineinfo;
-	bool _raiseerror;
-	SQInteger _debugline;
-	SQInteger _debugop;
-	SQExpState   _es;
-	SQScope _scope;
-	SQChar _compilererror[MAX_COMPILER_ERROR_LEN];
-	jmp_buf _errorjmp;
-	SQVM *_vm;
-};
-
-bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)
-{
-	SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);
-	return p.Compile(out);
-}
-
-#endif
+/*
+    see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#ifndef NO_COMPILER
+#include <stdarg.h>
+#include <setjmp.h>
+#include "sqopcodes.h"
+#include "sqstring.h"
+#include "sqfuncproto.h"
+#include "sqcompiler.h"
+#include "sqfuncstate.h"
+#include "sqlexer.h"
+#include "sqvm.h"
+#include "sqtable.h"
+
+#define EXPR   1
+#define OBJECT 2
+#define BASE   3
+#define LOCAL  4
+#define OUTER  5
+
+struct SQExpState {
+  SQInteger  etype;       /* expr. type; one of EXPR, OBJECT, BASE, OUTER or LOCAL */
+  SQInteger  epos;        /* expr. location on stack; -1 for OBJECT and BASE */
+  bool       donot_get;   /* signal not to deref the next value */
+};
+
+#define MAX_COMPILER_ERROR_LEN 256
+
+struct SQScope {
+    SQInteger outers;
+    SQInteger stacksize;
+};
+
+#define BEGIN_SCOPE() SQScope __oldscope__ = _scope; \
+                     _scope.outers = _fs->_outers; \
+                     _scope.stacksize = _fs->GetStackSize();
+
+#define RESOLVE_OUTERS() if(_fs->GetStackSize() != _scope.stacksize) { \
+                            if(_fs->CountOuters(_scope.stacksize)) { \
+                                _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \
+                            } \
+                        }
+
+#define END_SCOPE_NO_CLOSE() {  if(_fs->GetStackSize() != _scope.stacksize) { \
+                            _fs->SetStackSize(_scope.stacksize); \
+                        } \
+                        _scope = __oldscope__; \
+                    }
+
+#define END_SCOPE() {   SQInteger oldouters = _fs->_outers;\
+                        if(_fs->GetStackSize() != _scope.stacksize) { \
+                            _fs->SetStackSize(_scope.stacksize); \
+                            if(oldouters != _fs->_outers) { \
+                                _fs->AddInstruction(_OP_CLOSE,0,_scope.stacksize); \
+                            } \
+                        } \
+                        _scope = __oldscope__; \
+                    }
+
+#define BEGIN_BREAKBLE_BLOCK()  SQInteger __nbreaks__=_fs->_unresolvedbreaks.size(); \
+                            SQInteger __ncontinues__=_fs->_unresolvedcontinues.size(); \
+                            _fs->_breaktargets.push_back(0);_fs->_continuetargets.push_back(0);
+
+#define END_BREAKBLE_BLOCK(continue_target) {__nbreaks__=_fs->_unresolvedbreaks.size()-__nbreaks__; \
+                    __ncontinues__=_fs->_unresolvedcontinues.size()-__ncontinues__; \
+                    if(__ncontinues__>0)ResolveContinues(_fs,__ncontinues__,continue_target); \
+                    if(__nbreaks__>0)ResolveBreaks(_fs,__nbreaks__); \
+                    _fs->_breaktargets.pop_back();_fs->_continuetargets.pop_back();}
+
+class SQCompiler
+{
+public:
+    SQCompiler(SQVM *v, SQLEXREADFUNC rg, SQUserPointer up, const SQChar* sourcename, bool raiseerror, bool lineinfo)
+    {
+        _vm=v;
+        _lex.Init(_ss(v), rg, up,ThrowError,this);
+        _sourcename = SQString::Create(_ss(v), sourcename);
+        _lineinfo = lineinfo;_raiseerror = raiseerror;
+        _scope.outers = 0;
+        _scope.stacksize = 0;
+        _compilererror[0] = _SC('\0');
+    }
+    static void ThrowError(void *ud, const SQChar *s) {
+        SQCompiler *c = (SQCompiler *)ud;
+        c->Error(s);
+    }
+    void Error(const SQChar *s, ...)
+    {
+        va_list vl;
+        va_start(vl, s);
+        scvsprintf(_compilererror, MAX_COMPILER_ERROR_LEN, s, vl);
+        va_end(vl);
+        longjmp(_errorjmp,1);
+    }
+    void Lex(){ _token = _lex.Lex();}
+    SQObject Expect(SQInteger tok)
+    {
+
+        if(_token != tok) {
+            if(_token == TK_CONSTRUCTOR && tok == TK_IDENTIFIER) {
+                //do nothing
+            }
+            else {
+                const SQChar *etypename;
+                if(tok > 255) {
+                    switch(tok)
+                    {
+                    case TK_IDENTIFIER:
+                        etypename = _SC("IDENTIFIER");
+                        break;
+                    case TK_STRING_LITERAL:
+                        etypename = _SC("STRING_LITERAL");
+                        break;
+                    case TK_INTEGER:
+                        etypename = _SC("INTEGER");
+                        break;
+                    case TK_FLOAT:
+                        etypename = _SC("FLOAT");
+                        break;
+                    default:
+                        etypename = _lex.Tok2Str(tok);
+                    }
+                    Error(_SC("expected '%s'"), etypename);
+                }
+                Error(_SC("expected '%c'"), tok);
+            }
+        }
+        SQObjectPtr ret;
+        switch(tok)
+        {
+        case TK_IDENTIFIER:
+            ret = _fs->CreateString(_lex._svalue);
+            break;
+        case TK_STRING_LITERAL:
+            ret = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
+            break;
+        case TK_INTEGER:
+            ret = SQObjectPtr(_lex._nvalue);
+            break;
+        case TK_FLOAT:
+            ret = SQObjectPtr(_lex._fvalue);
+            break;
+        }
+        Lex();
+        return ret;
+    }
+    bool IsEndOfStatement() { return ((_lex._prevtoken == _SC('\n')) || (_token == SQUIRREL_EOB) || (_token == _SC('}')) || (_token == _SC(';'))); }
+    void OptionalSemicolon()
+    {
+        if(_token == _SC(';')) { Lex(); return; }
+        if(!IsEndOfStatement()) {
+            Error(_SC("end of statement expected (; or lf)"));
+        }
+    }
+    void MoveIfCurrentTargetIsLocal() {
+        SQInteger trg = _fs->TopTarget();
+        if(_fs->IsLocal(trg)) {
+            trg = _fs->PopTarget(); //pops the target and moves it
+            _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), trg);
+        }
+    }
+    bool Compile(SQObjectPtr &o)
+    {
+        _debugline = 1;
+        _debugop = 0;
+
+        SQFuncState funcstate(_ss(_vm), NULL,ThrowError,this);
+        funcstate._name = SQString::Create(_ss(_vm), _SC("main"));
+        _fs = &funcstate;
+        _fs->AddParameter(_fs->CreateString(_SC("this")));
+        _fs->AddParameter(_fs->CreateString(_SC("vargv")));
+        _fs->_varparams = true;
+        _fs->_sourcename = _sourcename;
+        SQInteger stacksize = _fs->GetStackSize();
+        if(setjmp(_errorjmp) == 0) {
+            Lex();
+            while(_token > 0){
+                Statement();
+                if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
+            }
+            _fs->SetStackSize(stacksize);
+            _fs->AddLineInfos(_lex._currentline, _lineinfo, true);
+            _fs->AddInstruction(_OP_RETURN, 0xFF);
+            _fs->SetStackSize(0);
+            o =_fs->BuildProto();
+#ifdef _DEBUG_DUMP
+            _fs->Dump(_funcproto(o));
+#endif
+        }
+        else {
+            if(_raiseerror && _ss(_vm)->_compilererrorhandler) {
+                _ss(_vm)->_compilererrorhandler(_vm, _compilererror, type(_sourcename) == OT_STRING?_stringval(_sourcename):_SC("unknown"),
+                    _lex._currentline, _lex._currentcolumn);
+            }
+            _vm->_lasterror = SQString::Create(_ss(_vm), _compilererror, -1);
+            return false;
+        }
+        return true;
+    }
+    void Statements()
+    {
+        while(_token != _SC('}') && _token != TK_DEFAULT && _token != TK_CASE) {
+            Statement();
+            if(_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
+        }
+    }
+    void Statement(bool closeframe = true)
+    {
+        _fs->AddLineInfos(_lex._currentline, _lineinfo);
+        switch(_token){
+        case _SC(';'):  Lex();                  break;
+        case TK_IF:     IfStatement();          break;
+        case TK_WHILE:      WhileStatement();       break;
+        case TK_DO:     DoWhileStatement();     break;
+        case TK_FOR:        ForStatement();         break;
+        case TK_FOREACH:    ForEachStatement();     break;
+        case TK_SWITCH: SwitchStatement();      break;
+        case TK_LOCAL:      LocalDeclStatement();   break;
+        case TK_RETURN:
+        case TK_YIELD: {
+            SQOpcode op;
+            if(_token == TK_RETURN) {
+                op = _OP_RETURN;
+            }
+            else {
+                op = _OP_YIELD;
+                _fs->_bgenerator = true;
+            }
+            Lex();
+            if(!IsEndOfStatement()) {
+                SQInteger retexp = _fs->GetCurrentPos()+1;
+                CommaExpr();
+                if(op == _OP_RETURN && _fs->_traps > 0)
+                    _fs->AddInstruction(_OP_POPTRAP, _fs->_traps, 0);
+                _fs->_returnexp = retexp;
+                _fs->AddInstruction(op, 1, _fs->PopTarget(),_fs->GetStackSize());
+            }
+            else{
+                if(op == _OP_RETURN && _fs->_traps > 0)
+                    _fs->AddInstruction(_OP_POPTRAP, _fs->_traps ,0);
+                _fs->_returnexp = -1;
+                _fs->AddInstruction(op, 0xFF,0,_fs->GetStackSize());
+            }
+            break;}
+        case TK_BREAK:
+            if(_fs->_breaktargets.size() <= 0)Error(_SC("'break' has to be in a loop block"));
+            if(_fs->_breaktargets.top() > 0){
+                _fs->AddInstruction(_OP_POPTRAP, _fs->_breaktargets.top(), 0);
+            }
+            RESOLVE_OUTERS();
+            _fs->AddInstruction(_OP_JMP, 0, -1234);
+            _fs->_unresolvedbreaks.push_back(_fs->GetCurrentPos());
+            Lex();
+            break;
+        case TK_CONTINUE:
+            if(_fs->_continuetargets.size() <= 0)Error(_SC("'continue' has to be in a loop block"));
+            if(_fs->_continuetargets.top() > 0) {
+                _fs->AddInstruction(_OP_POPTRAP, _fs->_continuetargets.top(), 0);
+            }
+            RESOLVE_OUTERS();
+            _fs->AddInstruction(_OP_JMP, 0, -1234);
+            _fs->_unresolvedcontinues.push_back(_fs->GetCurrentPos());
+            Lex();
+            break;
+        case TK_FUNCTION:
+            FunctionStatement();
+            break;
+        case TK_CLASS:
+            ClassStatement();
+            break;
+        case TK_ENUM:
+            EnumStatement();
+            break;
+        case _SC('{'):{
+                BEGIN_SCOPE();
+                Lex();
+                Statements();
+                Expect(_SC('}'));
+                if(closeframe) {
+                    END_SCOPE();
+                }
+                else {
+                    END_SCOPE_NO_CLOSE();
+                }
+            }
+            break;
+        case TK_TRY:
+            TryCatchStatement();
+            break;
+        case TK_THROW:
+            Lex();
+            CommaExpr();
+            _fs->AddInstruction(_OP_THROW, _fs->PopTarget());
+            break;
+        case TK_CONST:
+            {
+            Lex();
+            SQObject id = Expect(TK_IDENTIFIER);
+            Expect('=');
+            SQObject val = ExpectScalar();
+            OptionalSemicolon();
+            SQTable *enums = _table(_ss(_vm)->_consts);
+            SQObjectPtr strongid = id;
+            enums->NewSlot(strongid,SQObjectPtr(val));
+            strongid.Null();
+            }
+            break;
+        default:
+            CommaExpr();
+            _fs->DiscardTarget();
+            //_fs->PopTarget();
+            break;
+        }
+        _fs->SnoozeOpt();
+    }
+    void EmitDerefOp(SQOpcode op)
+    {
+        SQInteger val = _fs->PopTarget();
+        SQInteger key = _fs->PopTarget();
+        SQInteger src = _fs->PopTarget();
+        _fs->AddInstruction(op,_fs->PushTarget(),src,key,val);
+    }
+    void Emit2ArgsOP(SQOpcode op, SQInteger p3 = 0)
+    {
+        SQInteger p2 = _fs->PopTarget(); //src in OP_GET
+        SQInteger p1 = _fs->PopTarget(); //key in OP_GET
+        _fs->AddInstruction(op,_fs->PushTarget(), p1, p2, p3);
+    }
+    void EmitCompoundArith(SQInteger tok, SQInteger etype, SQInteger pos)
+    {
+        /* Generate code depending on the expression type */
+        switch(etype) {
+        case LOCAL:{
+            SQInteger p2 = _fs->PopTarget(); //src in OP_GET
+            SQInteger p1 = _fs->PopTarget(); //key in OP_GET
+            _fs->PushTarget(p1);
+            //EmitCompArithLocal(tok, p1, p1, p2);
+            _fs->AddInstruction(ChooseArithOpByToken(tok),p1, p2, p1, 0);
+            _fs->SnoozeOpt();
+                   }
+            break;
+        case OBJECT:
+        case BASE:
+            {
+                SQInteger val = _fs->PopTarget();
+                SQInteger key = _fs->PopTarget();
+                SQInteger src = _fs->PopTarget();
+                /* _OP_COMPARITH mixes dest obj and source val in the arg1 */
+                _fs->AddInstruction(_OP_COMPARITH, _fs->PushTarget(), (src<<16)|val, key, ChooseCompArithCharByToken(tok));
+            }
+            break;
+        case OUTER:
+            {
+                SQInteger val = _fs->TopTarget();
+                SQInteger tmp = _fs->PushTarget();
+                _fs->AddInstruction(_OP_GETOUTER,   tmp, pos);
+                _fs->AddInstruction(ChooseArithOpByToken(tok), tmp, val, tmp, 0);
+                _fs->PopTarget();
+                _fs->PopTarget();
+                _fs->AddInstruction(_OP_SETOUTER, _fs->PushTarget(), pos, tmp);
+            }
+            break;
+        }
+    }
+    void CommaExpr()
+    {
+        for(Expression();_token == ',';_fs->PopTarget(), Lex(), CommaExpr());
+    }
+    void Expression()
+    {
+         SQExpState es = _es;
+        _es.etype     = EXPR;
+        _es.epos      = -1;
+        _es.donot_get = false;
+        LogicalOrExp();
+        switch(_token)  {
+        case _SC('='):
+        case TK_NEWSLOT:
+        case TK_MINUSEQ:
+        case TK_PLUSEQ:
+        case TK_MULEQ:
+        case TK_DIVEQ:
+        case TK_MODEQ:{
+            SQInteger op = _token;
+            SQInteger ds = _es.etype;
+            SQInteger pos = _es.epos;
+            if(ds == EXPR) Error(_SC("can't assign expression"));
+            else if(ds == BASE) Error(_SC("'base' cannot be modified"));
+            Lex(); Expression();
+
+            switch(op){
+            case TK_NEWSLOT:
+                if(ds == OBJECT || ds == BASE)
+                    EmitDerefOp(_OP_NEWSLOT);
+                else //if _derefstate != DEREF_NO_DEREF && DEREF_FIELD so is the index of a local
+                    Error(_SC("can't 'create' a local slot"));
+                break;
+            case _SC('='): //ASSIGN
+                switch(ds) {
+                case LOCAL:
+                    {
+                        SQInteger src = _fs->PopTarget();
+                        SQInteger dst = _fs->TopTarget();
+                        _fs->AddInstruction(_OP_MOVE, dst, src);
+                    }
+                    break;
+                case OBJECT:
+                case BASE:
+                    EmitDerefOp(_OP_SET);
+                    break;
+                case OUTER:
+                    {
+                        SQInteger src = _fs->PopTarget();
+                        SQInteger dst = _fs->PushTarget();
+                        _fs->AddInstruction(_OP_SETOUTER, dst, pos, src);
+                    }
+                }
+                break;
+            case TK_MINUSEQ:
+            case TK_PLUSEQ:
+            case TK_MULEQ:
+            case TK_DIVEQ:
+            case TK_MODEQ:
+                EmitCompoundArith(op, ds, pos);
+                break;
+            }
+            }
+            break;
+        case _SC('?'): {
+            Lex();
+            _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
+            SQInteger jzpos = _fs->GetCurrentPos();
+            SQInteger trg = _fs->PushTarget();
+            Expression();
+            SQInteger first_exp = _fs->PopTarget();
+            if(trg != first_exp) _fs->AddInstruction(_OP_MOVE, trg, first_exp);
+            SQInteger endfirstexp = _fs->GetCurrentPos();
+            _fs->AddInstruction(_OP_JMP, 0, 0);
+            Expect(_SC(':'));
+            SQInteger jmppos = _fs->GetCurrentPos();
+            Expression();
+            SQInteger second_exp = _fs->PopTarget();
+            if(trg != second_exp) _fs->AddInstruction(_OP_MOVE, trg, second_exp);
+            _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
+            _fs->SetIntructionParam(jzpos, 1, endfirstexp - jzpos + 1);
+            _fs->SnoozeOpt();
+            }
+            break;
+        }
+        _es = es;
+    }
+    template<typename T> void INVOKE_EXP(T f)
+    {
+        SQExpState es = _es;
+        _es.etype     = EXPR;
+        _es.epos      = -1;
+        _es.donot_get = false;
+        (this->*f)();
+        _es = es;
+    }
+    template<typename T> void BIN_EXP(SQOpcode op, T f,SQInteger op3 = 0)
+    {
+        Lex();
+        INVOKE_EXP(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(); INVOKE_EXP(&SQCompiler::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(); INVOKE_EXP(&SQCompiler::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;
+            }
+
+        default:
+            return;
+        }
+    }
+    void BitwiseOrExp()
+    {
+        BitwiseXorExp();
+        for(;;) if(_token == _SC('|'))
+        {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseXorExp,BW_OR);
+        }else return;
+    }
+    void BitwiseXorExp()
+    {
+        BitwiseAndExp();
+        for(;;) if(_token == _SC('^'))
+        {BIN_EXP(_OP_BITW, &SQCompiler::BitwiseAndExp,BW_XOR);
+        }else return;
+    }
+    void BitwiseAndExp()
+    {
+        EqExp();
+        for(;;) if(_token == _SC('&'))
+        {BIN_EXP(_OP_BITW, &SQCompiler::EqExp,BW_AND);
+        }else return;
+    }
+    void EqExp()
+    {
+        CompExp();
+        for(;;) switch(_token) {
+        case TK_EQ: BIN_EXP(_OP_EQ, &SQCompiler::CompExp); break;
+        case TK_NE: BIN_EXP(_OP_NE, &SQCompiler::CompExp); break;
+        case TK_3WAYSCMP: BIN_EXP(_OP_CMP, &SQCompiler::CompExp,CMP_3W); break;
+        default: return;
+        }
+    }
+    void CompExp()
+    {
+        ShiftExp();
+        for(;;) switch(_token) {
+        case _SC('>'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_G); break;
+        case _SC('<'): BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_L); break;
+        case TK_GE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_GE); break;
+        case TK_LE: BIN_EXP(_OP_CMP, &SQCompiler::ShiftExp,CMP_LE); break;
+        case TK_IN: BIN_EXP(_OP_EXISTS, &SQCompiler::ShiftExp); break;
+        case TK_INSTANCEOF: BIN_EXP(_OP_INSTANCEOF, &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;
+        }
+    }
+    SQOpcode ChooseArithOpByToken(SQInteger tok)
+    {
+        switch(tok) {
+            case TK_PLUSEQ: case '+': return _OP_ADD;
+            case TK_MINUSEQ: case '-': return _OP_SUB;
+            case TK_MULEQ: case '*': return _OP_MUL;
+            case TK_DIVEQ: case '/': return _OP_DIV;
+            case TK_MODEQ: case '%': return _OP_MOD;
+            default: assert(0);
+        }
+        return _OP_ADD;
+    }
+    SQInteger ChooseCompArithCharByToken(SQInteger tok)
+    {
+        SQInteger oper;
+        switch(tok){
+        case TK_MINUSEQ: oper = '-'; break;
+        case TK_PLUSEQ: oper = '+'; break;
+        case TK_MULEQ: oper = '*'; break;
+        case TK_DIVEQ: oper = '/'; break;
+        case TK_MODEQ: oper = '%'; break;
+        default: oper = 0; //shut up compiler
+            assert(0); break;
+        };
+        return oper;
+    }
+    void PlusExp()
+    {
+        MultExp();
+        for(;;) switch(_token) {
+        case _SC('+'): case _SC('-'):
+            BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::MultExp); break;
+        default: return;
+        }
+    }
+
+    void MultExp()
+    {
+        PrefixedExpr();
+        for(;;) switch(_token) {
+        case _SC('*'): case _SC('/'): case _SC('%'):
+            BIN_EXP(ChooseArithOpByToken(_token), &SQCompiler::PrefixedExpr); break;
+        default: return;
+        }
+    }
+    //if 'pos' != -1 the previous variable is a local variable
+    void PrefixedExpr()
+    {
+        SQInteger pos = Factor();
+        for(;;) {
+            switch(_token) {
+            case _SC('.'):
+                pos = -1;
+                Lex();
+
+                _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
+                if(_es.etype==BASE) {
+                    Emit2ArgsOP(_OP_GET);
+                    pos = _fs->TopTarget();
+                    _es.etype = EXPR;
+                    _es.epos   = pos;
+                }
+                else {
+                    if(NeedGet()) {
+                        Emit2ArgsOP(_OP_GET);
+                    }
+                    _es.etype = OBJECT;
+                }
+                break;
+            case _SC('['):
+                if(_lex._prevtoken == _SC('\n')) Error(_SC("cannot brake deref/or comma needed after [exp]=exp slot declaration"));
+                Lex(); Expression(); Expect(_SC(']'));
+                pos = -1;
+                if(_es.etype==BASE) {
+                    Emit2ArgsOP(_OP_GET);
+                    pos = _fs->TopTarget();
+                    _es.etype = EXPR;
+                    _es.epos   = pos;
+                }
+                else {
+                    if(NeedGet()) {
+                        Emit2ArgsOP(_OP_GET);
+                    }
+                    _es.etype = OBJECT;
+                }
+                break;
+            case TK_MINUSMINUS:
+            case TK_PLUSPLUS:
+                {
+                    if(IsEndOfStatement()) return;
+                    SQInteger diff = (_token==TK_MINUSMINUS) ? -1 : 1;
+                    Lex();
+                    switch(_es.etype)
+                    {
+                        case EXPR: Error(_SC("can't '++' or '--' an expression")); break;
+                        case OBJECT:
+                        case BASE:
+                            if(_es.donot_get == true)  { Error(_SC("can't '++' or '--' an expression")); break; } //mmh dor this make sense?
+                            Emit2ArgsOP(_OP_PINC, diff);
+                            break;
+                        case LOCAL: {
+                            SQInteger src = _fs->PopTarget();
+                            _fs->AddInstruction(_OP_PINCL, _fs->PushTarget(), src, 0, diff);
+                                    }
+                            break;
+                        case OUTER: {
+                            SQInteger tmp1 = _fs->PushTarget();
+                            SQInteger tmp2 = _fs->PushTarget();
+                            _fs->AddInstruction(_OP_GETOUTER, tmp2, _es.epos);
+                            _fs->AddInstruction(_OP_PINCL,    tmp1, tmp2, 0, diff);
+                            _fs->AddInstruction(_OP_SETOUTER, tmp2, _es.epos, tmp2);
+                            _fs->PopTarget();
+                        }
+                    }
+                }
+                return;
+                break;
+            case _SC('('):
+                switch(_es.etype) {
+                    case OBJECT: {
+                        SQInteger key     = _fs->PopTarget();  /* location of the key */
+                        SQInteger table   = _fs->PopTarget();  /* location of the object */
+                        SQInteger closure = _fs->PushTarget(); /* location for the closure */
+                        SQInteger ttarget = _fs->PushTarget(); /* location for 'this' pointer */
+                        _fs->AddInstruction(_OP_PREPCALL, closure, key, table, ttarget);
+                        }
+                        break;
+                    case BASE:
+                        //Emit2ArgsOP(_OP_GET);
+                        _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
+                        break;
+                    case OUTER:
+                        _fs->AddInstruction(_OP_GETOUTER, _fs->PushTarget(), _es.epos);
+                        _fs->AddInstruction(_OP_MOVE,     _fs->PushTarget(), 0);
+                        break;
+                    default:
+                        _fs->AddInstruction(_OP_MOVE, _fs->PushTarget(), 0);
+                }
+                _es.etype = EXPR;
+                Lex();
+                FunctionCallArgs();
+                break;
+            default: return;
+            }
+        }
+    }
+    SQInteger Factor()
+    {
+        //_es.etype = EXPR;
+        switch(_token)
+        {
+        case TK_STRING_LITERAL:
+            _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_fs->CreateString(_lex._svalue,_lex._longstr.size()-1)));
+            Lex();
+            break;
+        case TK_BASE:
+            Lex();
+            _fs->AddInstruction(_OP_GETBASE, _fs->PushTarget());
+            _es.etype  = BASE;
+            _es.epos   = _fs->TopTarget();
+            return (_es.epos);
+            break;
+        case TK_IDENTIFIER:
+        case TK_CONSTRUCTOR:
+        case TK_THIS:{
+                SQObject id;
+                SQObject constant;
+
+                switch(_token) {
+                    case TK_IDENTIFIER:  id = _fs->CreateString(_lex._svalue);       break;
+                    case TK_THIS:        id = _fs->CreateString(_SC("this"),4);        break;
+                    case TK_CONSTRUCTOR: id = _fs->CreateString(_SC("constructor"),11); break;
+                }
+
+                SQInteger pos = -1;
+                Lex();
+                if((pos = _fs->GetLocalVariable(id)) != -1) {
+                    /* Handle a local variable (includes 'this') */
+                    _fs->PushTarget(pos);
+                    _es.etype  = LOCAL;
+                    _es.epos   = pos;
+                }
+
+                else if((pos = _fs->GetOuterVariable(id)) != -1) {
+                    /* Handle a free var */
+                    if(NeedGet()) {
+                        _es.epos  = _fs->PushTarget();
+                        _fs->AddInstruction(_OP_GETOUTER, _es.epos, pos);
+                        /* _es.etype = EXPR; already default value */
+                    }
+                    else {
+                        _es.etype = OUTER;
+                        _es.epos  = pos;
+                    }
+                }
+
+                else if(_fs->IsConstant(id, constant)) {
+                    /* Handle named constant */
+                    SQObjectPtr constval;
+                    SQObject    constid;
+                    if(type(constant) == OT_TABLE) {
+                        Expect('.');
+                        constid = Expect(TK_IDENTIFIER);
+                        if(!_table(constant)->Get(constid, constval)) {
+                            constval.Null();
+                            Error(_SC("invalid constant [%s.%s]"), _stringval(id), _stringval(constid));
+                        }
+                    }
+                    else {
+                        constval = constant;
+                    }
+                    _es.epos = _fs->PushTarget();
+
+                    /* generate direct or literal function depending on size */
+                    SQObjectType ctype = type(constval);
+                    switch(ctype) {
+                        case OT_INTEGER: EmitLoadConstInt(_integer(constval),_es.epos); break;
+                        case OT_FLOAT: EmitLoadConstFloat(_float(constval),_es.epos); break;
+                        case OT_BOOL: _fs->AddInstruction(_OP_LOADBOOL, _es.epos, _integer(constval)); break;
+                        default: _fs->AddInstruction(_OP_LOAD,_es.epos,_fs->GetConstant(constval)); break;
+                    }
+                    _es.etype = EXPR;
+                }
+                else {
+                    /* Handle a non-local variable, aka a field. Push the 'this' pointer on
+                    * the virtual stack (always found in offset 0, so no instruction needs to
+                    * be generated), and push the key next. Generate an _OP_LOAD instruction
+                    * for the latter. If we are not using the variable as a dref expr, generate
+                    * the _OP_GET instruction.
+                    */
+                    _fs->PushTarget(0);
+                    _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
+                    if(NeedGet()) {
+                        Emit2ArgsOP(_OP_GET);
+                    }
+                    _es.etype = OBJECT;
+                }
+                return _es.epos;
+            }
+            break;
+        case TK_DOUBLE_COLON:  // "::"
+            _fs->AddInstruction(_OP_LOADROOT, _fs->PushTarget());
+            _es.etype = OBJECT;
+            _token = _SC('.'); /* hack: drop into PrefixExpr, case '.'*/
+            _es.epos = -1;
+            return _es.epos;
+            break;
+        case TK_NULL:
+            _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
+            Lex();
+            break;
+        case TK_INTEGER: EmitLoadConstInt(_lex._nvalue,-1); Lex();  break;
+        case TK_FLOAT: EmitLoadConstFloat(_lex._fvalue,-1); Lex(); break;
+        case TK_TRUE: case TK_FALSE:
+            _fs->AddInstruction(_OP_LOADBOOL, _fs->PushTarget(),_token == TK_TRUE?1:0);
+            Lex();
+            break;
+        case _SC('['): {
+                _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,0,NOT_ARRAY);
+                SQInteger apos = _fs->GetCurrentPos(),key = 0;
+                Lex();
+                while(_token != _SC(']')) {
+                    Expression();
+                    if(_token == _SC(',')) Lex();
+                    SQInteger val = _fs->PopTarget();
+                    SQInteger array = _fs->TopTarget();
+                    _fs->AddInstruction(_OP_APPENDARRAY, array, val, AAT_STACK);
+                    key++;
+                }
+                _fs->SetIntructionParam(apos, 1, key);
+                Lex();
+            }
+            break;
+        case _SC('{'):
+            _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
+            Lex();ParseTableOrClass(_SC(','),_SC('}'));
+            break;
+        case TK_FUNCTION: FunctionExp(_token);break;
+        case _SC('@'): FunctionExp(_token,true);break;
+        case TK_CLASS: Lex(); ClassExp();break;
+        case _SC('-'):
+            Lex();
+            switch(_token) {
+            case TK_INTEGER: EmitLoadConstInt(-_lex._nvalue,-1); Lex(); break;
+            case TK_FLOAT: EmitLoadConstFloat(-_lex._fvalue,-1); Lex(); break;
+            default: UnaryOP(_OP_NEG);
+            }
+            break;
+        case _SC('!'): Lex(); UnaryOP(_OP_NOT); break;
+        case _SC('~'):
+            Lex();
+            if(_token == TK_INTEGER)  { EmitLoadConstInt(~_lex._nvalue,-1); Lex(); break; }
+            UnaryOP(_OP_BWNOT);
+            break;
+        case TK_TYPEOF : Lex() ;UnaryOP(_OP_TYPEOF); break;
+        case TK_RESUME : Lex(); UnaryOP(_OP_RESUME); break;
+        case TK_CLONE : Lex(); UnaryOP(_OP_CLONE); break;
+        case TK_MINUSMINUS :
+        case TK_PLUSPLUS :PrefixIncDec(_token); break;
+        case TK_DELETE : DeleteExpr(); break;
+        case _SC('('): Lex(); CommaExpr(); Expect(_SC(')'));
+            break;
+        case TK___LINE__: EmitLoadConstInt(_lex._currentline,-1); Lex(); break;
+        case TK___FILE__: _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(_sourcename)); Lex(); break;
+        default: Error(_SC("expression expected"));
+        }
+        _es.etype = EXPR;
+        return -1;
+    }
+    void EmitLoadConstInt(SQInteger value,SQInteger target)
+    {
+        if(target < 0) {
+            target = _fs->PushTarget();
+        }
+        if(value <= INT_MAX && value > INT_MIN) { //does it fit in 32 bits?
+            _fs->AddInstruction(_OP_LOADINT, target,value);
+        }
+        else {
+            _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));
+        }
+    }
+    void EmitLoadConstFloat(SQFloat value,SQInteger target)
+    {
+        if(target < 0) {
+            target = _fs->PushTarget();
+        }
+        if(sizeof(SQFloat) == sizeof(SQInt32)) {
+            _fs->AddInstruction(_OP_LOADFLOAT, target,*((SQInt32 *)&value));
+        }
+        else {
+            _fs->AddInstruction(_OP_LOAD, target, _fs->GetNumericConstant(value));
+        }
+    }
+    void UnaryOP(SQOpcode op)
+    {
+        PrefixedExpr();
+        SQInteger src = _fs->PopTarget();
+        _fs->AddInstruction(op, _fs->PushTarget(), src);
+    }
+    bool NeedGet()
+    {
+        switch(_token) {
+        case _SC('='): case _SC('('): case TK_NEWSLOT: case TK_MODEQ: case TK_MULEQ:
+        case TK_DIVEQ: case TK_MINUSEQ: case TK_PLUSEQ:
+            return false;
+        case TK_PLUSPLUS: case TK_MINUSMINUS:
+            if (!IsEndOfStatement()) {
+                return false;
+            }
+        break;
+        }
+        return (!_es.donot_get || ( _es.donot_get && (_token == _SC('.') || _token == _SC('['))));
+    }
+    void FunctionCallArgs()
+    {
+        SQInteger nargs = 1;//this
+         while(_token != _SC(')')) {
+             Expression();
+             MoveIfCurrentTargetIsLocal();
+             nargs++;
+             if(_token == _SC(',')){
+                 Lex();
+                 if(_token == ')') Error(_SC("expression expected, found ')'"));
+             }
+         }
+         Lex();
+         for(SQInteger i = 0; i < (nargs - 1); i++) _fs->PopTarget();
+         SQInteger stackbase = _fs->PopTarget();
+         SQInteger closure = _fs->PopTarget();
+         _fs->AddInstruction(_OP_CALL, _fs->PushTarget(), closure, stackbase, nargs);
+    }
+    void ParseTableOrClass(SQInteger separator,SQInteger terminator)
+    {
+        SQInteger tpos = _fs->GetCurrentPos(),nkeys = 0;
+        while(_token != terminator) {
+            bool hasattrs = false;
+            bool isstatic = false;
+            //check if is an attribute
+            if(separator == ';') {
+                if(_token == TK_ATTR_OPEN) {
+                    _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE); Lex();
+                    ParseTableOrClass(',',TK_ATTR_CLOSE);
+                    hasattrs = true;
+                }
+                if(_token == TK_STATIC) {
+                    isstatic = true;
+                    Lex();
+                }
+            }
+            switch(_token) {
+            case TK_FUNCTION:
+            case TK_CONSTRUCTOR:{
+                SQInteger tk = _token;
+                Lex();
+                SQObject id = tk == TK_FUNCTION ? Expect(TK_IDENTIFIER) : _fs->CreateString(_SC("constructor"));
+                Expect(_SC('('));
+                _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
+                CreateFunction(id);
+                _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
+                                }
+                                break;
+            case _SC('['):
+                Lex(); CommaExpr(); Expect(_SC(']'));
+                Expect(_SC('=')); Expression();
+                break;
+            case TK_STRING_LITERAL: //JSON
+                if(separator == ',') { //only works for tables
+                    _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_STRING_LITERAL)));
+                    Expect(_SC(':')); Expression();
+                    break;
+                }
+            default :
+                _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(Expect(TK_IDENTIFIER)));
+                Expect(_SC('=')); Expression();
+            }
+            if(_token == separator) Lex();//optional comma/semicolon
+            nkeys++;
+            SQInteger val = _fs->PopTarget();
+            SQInteger key = _fs->PopTarget();
+            SQInteger attrs = hasattrs ? _fs->PopTarget():-1;
+            assert((hasattrs && (attrs == key-1)) || !hasattrs);
+            unsigned char flags = (hasattrs?NEW_SLOT_ATTRIBUTES_FLAG:0)|(isstatic?NEW_SLOT_STATIC_FLAG:0);
+            SQInteger table = _fs->TopTarget(); //<<BECAUSE OF THIS NO COMMON EMIT FUNC IS POSSIBLE
+            if(separator == _SC(',')) { //hack recognizes a table from the separator
+                _fs->AddInstruction(_OP_NEWSLOT, 0xFF, table, key, val);
+            }
+            else {
+                _fs->AddInstruction(_OP_NEWSLOTA, flags, table, key, val); //this for classes only as it invokes _newmember
+            }
+        }
+        if(separator == _SC(',')) //hack recognizes a table from the separator
+            _fs->SetIntructionParam(tpos, 1, nkeys);
+        Lex();
+    }
+    void LocalDeclStatement()
+    {
+        SQObject varname;
+        Lex();
+        if( _token == TK_FUNCTION) {
+            Lex();
+            varname = Expect(TK_IDENTIFIER);
+            Expect(_SC('('));
+            CreateFunction(varname,false);
+            _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
+            _fs->PopTarget();
+            _fs->PushLocalVariable(varname);
+            return;
+        }
+
+        do {
+            varname = Expect(TK_IDENTIFIER);
+            if(_token == _SC('=')) {
+                Lex(); Expression();
+                SQInteger src = _fs->PopTarget();
+                SQInteger dest = _fs->PushTarget();
+                if(dest != src) _fs->AddInstruction(_OP_MOVE, dest, src);
+            }
+            else{
+                _fs->AddInstruction(_OP_LOADNULLS, _fs->PushTarget(),1);
+            }
+            _fs->PopTarget();
+            _fs->PushLocalVariable(varname);
+            if(_token == _SC(',')) Lex(); else break;
+        } while(1);
+    }
+    void IfBlock()
+    {
+        if (_token == _SC('{'))
+        {
+            BEGIN_SCOPE();
+            Lex();
+            Statements();
+            Expect(_SC('}'));
+            if (true) {
+                END_SCOPE();
+            }
+            else {
+                END_SCOPE_NO_CLOSE();
+            }
+        }
+        else {
+            //BEGIN_SCOPE();
+            Statement();
+            if (_lex._prevtoken != _SC('}') && _lex._prevtoken != _SC(';')) OptionalSemicolon();
+            //END_SCOPE();
+        }
+    }
+    void IfStatement()
+    {
+        SQInteger jmppos;
+        bool haselse = false;
+        Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+        _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
+        SQInteger jnepos = _fs->GetCurrentPos();
+
+
+
+        IfBlock();
+        //
+        /*static int n = 0;
+        if (_token != _SC('}') && _token != TK_ELSE) {
+            printf("IF %d-----------------------!!!!!!!!!\n", n);
+            if (n == 5)
+            {
+                printf("asd");
+            }
+            n++;
+            //OptionalSemicolon();
+        }*/
+
+
+        SQInteger endifblock = _fs->GetCurrentPos();
+        if(_token == TK_ELSE){
+            haselse = true;
+            //BEGIN_SCOPE();
+            _fs->AddInstruction(_OP_JMP);
+            jmppos = _fs->GetCurrentPos();
+            Lex();
+            //Statement(); if(_lex._prevtoken != _SC('}')) OptionalSemicolon();
+            IfBlock();
+            //END_SCOPE();
+            _fs->SetIntructionParam(jmppos, 1, _fs->GetCurrentPos() - jmppos);
+        }
+        _fs->SetIntructionParam(jnepos, 1, endifblock - jnepos + (haselse?1:0));
+    }
+    void WhileStatement()
+    {
+        SQInteger jzpos, jmppos;
+        jmppos = _fs->GetCurrentPos();
+        Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+
+        BEGIN_BREAKBLE_BLOCK();
+        _fs->AddInstruction(_OP_JZ, _fs->PopTarget());
+        jzpos = _fs->GetCurrentPos();
+        BEGIN_SCOPE();
+
+        Statement();
+
+        END_SCOPE();
+        _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
+        _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
+
+        END_BREAKBLE_BLOCK(jmppos);
+    }
+    void DoWhileStatement()
+    {
+        Lex();
+        SQInteger jmptrg = _fs->GetCurrentPos();
+        BEGIN_BREAKBLE_BLOCK()
+        BEGIN_SCOPE();
+        Statement();
+        END_SCOPE();
+        Expect(TK_WHILE);
+        SQInteger continuetrg = _fs->GetCurrentPos();
+        Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+        _fs->AddInstruction(_OP_JZ, _fs->PopTarget(), 1);
+        _fs->AddInstruction(_OP_JMP, 0, jmptrg - _fs->GetCurrentPos() - 1);
+        END_BREAKBLE_BLOCK(continuetrg);
+    }
+    void ForStatement()
+    {
+        Lex();
+        BEGIN_SCOPE();
+        Expect(_SC('('));
+        if(_token == TK_LOCAL) LocalDeclStatement();
+        else if(_token != _SC(';')){
+            CommaExpr();
+            _fs->PopTarget();
+        }
+        Expect(_SC(';'));
+        _fs->SnoozeOpt();
+        SQInteger jmppos = _fs->GetCurrentPos();
+        SQInteger jzpos = -1;
+        if(_token != _SC(';')) { CommaExpr(); _fs->AddInstruction(_OP_JZ, _fs->PopTarget()); jzpos = _fs->GetCurrentPos(); }
+        Expect(_SC(';'));
+        _fs->SnoozeOpt();
+        SQInteger expstart = _fs->GetCurrentPos() + 1;
+        if(_token != _SC(')')) {
+            CommaExpr();
+            _fs->PopTarget();
+        }
+        Expect(_SC(')'));
+        _fs->SnoozeOpt();
+        SQInteger expend = _fs->GetCurrentPos();
+        SQInteger expsize = (expend - expstart) + 1;
+        SQInstructionVec exp;
+        if(expsize > 0) {
+            for(SQInteger i = 0; i < expsize; i++)
+                exp.push_back(_fs->GetInstruction(expstart + i));
+            _fs->PopInstructions(expsize);
+        }
+        BEGIN_BREAKBLE_BLOCK()
+        Statement();
+        SQInteger continuetrg = _fs->GetCurrentPos();
+        if(expsize > 0) {
+            for(SQInteger i = 0; i < expsize; i++)
+                _fs->AddInstruction(exp[i]);
+        }
+        _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1, 0);
+        if(jzpos>  0) _fs->SetIntructionParam(jzpos, 1, _fs->GetCurrentPos() - jzpos);
+        END_SCOPE();
+
+        END_BREAKBLE_BLOCK(continuetrg);
+    }
+    void ForEachStatement()
+    {
+        SQObject idxname, valname;
+        Lex(); Expect(_SC('(')); valname = Expect(TK_IDENTIFIER);
+        if(_token == _SC(',')) {
+            idxname = valname;
+            Lex(); valname = Expect(TK_IDENTIFIER);
+        }
+        else{
+            idxname = _fs->CreateString(_SC("@INDEX@"));
+        }
+        Expect(TK_IN);
+
+        //save the stack size
+        BEGIN_SCOPE();
+        //put the table in the stack(evaluate the table expression)
+        Expression(); Expect(_SC(')'));
+        SQInteger container = _fs->TopTarget();
+        //push the index local var
+        SQInteger indexpos = _fs->PushLocalVariable(idxname);
+        _fs->AddInstruction(_OP_LOADNULLS, indexpos,1);
+        //push the value local var
+        SQInteger valuepos = _fs->PushLocalVariable(valname);
+        _fs->AddInstruction(_OP_LOADNULLS, valuepos,1);
+        //push reference index
+        SQInteger itrpos = _fs->PushLocalVariable(_fs->CreateString(_SC("@ITERATOR@"))); //use invalid id to make it inaccessible
+        _fs->AddInstruction(_OP_LOADNULLS, itrpos,1);
+        SQInteger jmppos = _fs->GetCurrentPos();
+        _fs->AddInstruction(_OP_FOREACH, container, 0, indexpos);
+        SQInteger foreachpos = _fs->GetCurrentPos();
+        _fs->AddInstruction(_OP_POSTFOREACH, container, 0, indexpos);
+        //generate the statement code
+        BEGIN_BREAKBLE_BLOCK()
+        Statement();
+        _fs->AddInstruction(_OP_JMP, 0, jmppos - _fs->GetCurrentPos() - 1);
+        _fs->SetIntructionParam(foreachpos, 1, _fs->GetCurrentPos() - foreachpos);
+        _fs->SetIntructionParam(foreachpos + 1, 1, _fs->GetCurrentPos() - foreachpos);
+        END_BREAKBLE_BLOCK(foreachpos - 1);
+        //restore the local variable stack(remove index,val and ref idx)
+        _fs->PopTarget();
+        END_SCOPE();
+    }
+    void SwitchStatement()
+    {
+        Lex(); Expect(_SC('(')); CommaExpr(); Expect(_SC(')'));
+        Expect(_SC('{'));
+        SQInteger expr = _fs->TopTarget();
+        bool bfirst = true;
+        SQInteger tonextcondjmp = -1;
+        SQInteger skipcondjmp = -1;
+        SQInteger __nbreaks__ = _fs->_unresolvedbreaks.size();
+        _fs->_breaktargets.push_back(0);
+        while(_token == TK_CASE) {
+            if(!bfirst) {
+                _fs->AddInstruction(_OP_JMP, 0, 0);
+                skipcondjmp = _fs->GetCurrentPos();
+                _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
+            }
+            //condition
+            Lex(); Expression(); Expect(_SC(':'));
+            SQInteger trg = _fs->PopTarget();
+            SQInteger eqtarget = trg;
+            bool local = _fs->IsLocal(trg);
+            if(local) {
+                eqtarget = _fs->PushTarget(); //we need to allocate a extra reg
+            }
+            _fs->AddInstruction(_OP_EQ, eqtarget, trg, expr);
+            _fs->AddInstruction(_OP_JZ, eqtarget, 0);
+            if(local) {
+                _fs->PopTarget();
+            }
+
+            //end condition
+            if(skipcondjmp != -1) {
+                _fs->SetIntructionParam(skipcondjmp, 1, (_fs->GetCurrentPos() - skipcondjmp));
+            }
+            tonextcondjmp = _fs->GetCurrentPos();
+            BEGIN_SCOPE();
+            Statements();
+            END_SCOPE();
+            bfirst = false;
+        }
+        if(tonextcondjmp != -1)
+            _fs->SetIntructionParam(tonextcondjmp, 1, _fs->GetCurrentPos() - tonextcondjmp);
+        if(_token == TK_DEFAULT) {
+            Lex(); Expect(_SC(':'));
+            BEGIN_SCOPE();
+            Statements();
+            END_SCOPE();
+        }
+        Expect(_SC('}'));
+        _fs->PopTarget();
+        __nbreaks__ = _fs->_unresolvedbreaks.size() - __nbreaks__;
+        if(__nbreaks__ > 0)ResolveBreaks(_fs, __nbreaks__);
+        _fs->_breaktargets.pop_back();
+    }
+    void FunctionStatement()
+    {
+        SQObject id;
+        Lex(); id = Expect(TK_IDENTIFIER);
+        _fs->PushTarget(0);
+        _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
+        if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
+
+        while(_token == TK_DOUBLE_COLON) {
+            Lex();
+            id = Expect(TK_IDENTIFIER);
+            _fs->AddInstruction(_OP_LOAD, _fs->PushTarget(), _fs->GetConstant(id));
+            if(_token == TK_DOUBLE_COLON) Emit2ArgsOP(_OP_GET);
+        }
+        Expect(_SC('('));
+        CreateFunction(id);
+        _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, 0);
+        EmitDerefOp(_OP_NEWSLOT);
+        _fs->PopTarget();
+    }
+    void ClassStatement()
+    {
+        SQExpState es;
+        Lex();
+        es = _es;
+        _es.donot_get = true;
+        PrefixedExpr();
+        if(_es.etype == EXPR) {
+            Error(_SC("invalid class name"));
+        }
+        else if(_es.etype == OBJECT || _es.etype == BASE) {
+            ClassExp();
+            EmitDerefOp(_OP_NEWSLOT);
+            _fs->PopTarget();
+        }
+        else {
+            Error(_SC("cannot create a class in a local with the syntax(class <local>)"));
+        }
+        _es = es;
+    }
+    SQObject ExpectScalar()
+    {
+        SQObject val;
+        val._type = OT_NULL; val._unVal.nInteger = 0; //shut up GCC 4.x
+        switch(_token) {
+            case TK_INTEGER:
+                val._type = OT_INTEGER;
+                val._unVal.nInteger = _lex._nvalue;
+                break;
+            case TK_FLOAT:
+                val._type = OT_FLOAT;
+                val._unVal.fFloat = _lex._fvalue;
+                break;
+            case TK_STRING_LITERAL:
+                val = _fs->CreateString(_lex._svalue,_lex._longstr.size()-1);
+                break;
+            case TK_TRUE:
+            case TK_FALSE:
+                val._type = OT_BOOL;
+                val._unVal.nInteger = _token == TK_TRUE ? 1 : 0;
+                break;
+            case '-':
+                Lex();
+                switch(_token)
+                {
+                case TK_INTEGER:
+                    val._type = OT_INTEGER;
+                    val._unVal.nInteger = -_lex._nvalue;
+                break;
+                case TK_FLOAT:
+                    val._type = OT_FLOAT;
+                    val._unVal.fFloat = -_lex._fvalue;
+                break;
+                default:
+                    Error(_SC("scalar expected : integer,float"));
+                }
+                break;
+            default:
+                Error(_SC("scalar expected : integer,float or string"));
+        }
+        Lex();
+        return val;
+    }
+    void EnumStatement()
+    {
+        Lex();
+        SQObject id = Expect(TK_IDENTIFIER);
+        Expect(_SC('{'));
+
+        SQObject table = _fs->CreateTable();
+        SQInteger nval = 0;
+        while(_token != _SC('}')) {
+            SQObject key = Expect(TK_IDENTIFIER);
+            SQObject val;
+            if(_token == _SC('=')) {
+                Lex();
+                val = ExpectScalar();
+            }
+            else {
+                val._type = OT_INTEGER;
+                val._unVal.nInteger = nval++;
+            }
+            _table(table)->NewSlot(SQObjectPtr(key),SQObjectPtr(val));
+            if(_token == ',') Lex();
+        }
+        SQTable *enums = _table(_ss(_vm)->_consts);
+        SQObjectPtr strongid = id;
+        enums->NewSlot(SQObjectPtr(strongid),SQObjectPtr(table));
+        strongid.Null();
+        Lex();
+    }
+    void TryCatchStatement()
+    {
+        SQObject exid;
+        Lex();
+        _fs->AddInstruction(_OP_PUSHTRAP,0,0);
+        _fs->_traps++;
+        if(_fs->_breaktargets.size()) _fs->_breaktargets.top()++;
+        if(_fs->_continuetargets.size()) _fs->_continuetargets.top()++;
+        SQInteger trappos = _fs->GetCurrentPos();
+        {
+            BEGIN_SCOPE();
+            Statement();
+            END_SCOPE();
+        }
+        _fs->_traps--;
+        _fs->AddInstruction(_OP_POPTRAP, 1, 0);
+        if(_fs->_breaktargets.size()) _fs->_breaktargets.top()--;
+        if(_fs->_continuetargets.size()) _fs->_continuetargets.top()--;
+        _fs->AddInstruction(_OP_JMP, 0, 0);
+        SQInteger jmppos = _fs->GetCurrentPos();
+        _fs->SetIntructionParam(trappos, 1, (_fs->GetCurrentPos() - trappos));
+        Expect(TK_CATCH); Expect(_SC('(')); exid = Expect(TK_IDENTIFIER); Expect(_SC(')'));
+        {
+            BEGIN_SCOPE();
+            SQInteger ex_target = _fs->PushLocalVariable(exid);
+            _fs->SetIntructionParam(trappos, 0, ex_target);
+            Statement();
+            _fs->SetIntructionParams(jmppos, 0, (_fs->GetCurrentPos() - jmppos), 0);
+            END_SCOPE();
+        }
+    }
+    void FunctionExp(SQInteger ftype,bool lambda = false)
+    {
+        Lex(); Expect(_SC('('));
+        SQObjectPtr dummy;
+        CreateFunction(dummy,lambda);
+        _fs->AddInstruction(_OP_CLOSURE, _fs->PushTarget(), _fs->_functions.size() - 1, ftype == TK_FUNCTION?0:1);
+    }
+    void ClassExp()
+    {
+        SQInteger base = -1;
+        SQInteger attrs = -1;
+        if(_token == TK_EXTENDS) {
+            Lex(); Expression();
+            base = _fs->TopTarget();
+        }
+        if(_token == TK_ATTR_OPEN) {
+            Lex();
+            _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(),0,NOT_TABLE);
+            ParseTableOrClass(_SC(','),TK_ATTR_CLOSE);
+            attrs = _fs->TopTarget();
+        }
+        Expect(_SC('{'));
+        if(attrs != -1) _fs->PopTarget();
+        if(base != -1) _fs->PopTarget();
+        _fs->AddInstruction(_OP_NEWOBJ, _fs->PushTarget(), base, attrs,NOT_CLASS);
+        ParseTableOrClass(_SC(';'),_SC('}'));
+    }
+    void DeleteExpr()
+    {
+        SQExpState es;
+        Lex();
+        es = _es;
+        _es.donot_get = true;
+        PrefixedExpr();
+        if(_es.etype==EXPR) Error(_SC("can't delete an expression"));
+        if(_es.etype==OBJECT || _es.etype==BASE) {
+            Emit2ArgsOP(_OP_DELETE);
+        }
+        else {
+            Error(_SC("cannot delete an (outer) local"));
+        }
+        _es = es;
+    }
+    void PrefixIncDec(SQInteger token)
+    {
+        SQExpState  es;
+        SQInteger diff = (token==TK_MINUSMINUS) ? -1 : 1;
+        Lex();
+        es = _es;
+        _es.donot_get = true;
+        PrefixedExpr();
+        if(_es.etype==EXPR) {
+            Error(_SC("can't '++' or '--' an expression"));
+        }
+        else if(_es.etype==OBJECT || _es.etype==BASE) {
+            Emit2ArgsOP(_OP_INC, diff);
+        }
+        else if(_es.etype==LOCAL) {
+            SQInteger src = _fs->TopTarget();
+            _fs->AddInstruction(_OP_INCL, src, src, 0, diff);
+
+        }
+        else if(_es.etype==OUTER) {
+            SQInteger tmp = _fs->PushTarget();
+            _fs->AddInstruction(_OP_GETOUTER, tmp, _es.epos);
+            _fs->AddInstruction(_OP_INCL,     tmp, tmp, 0, diff);
+            _fs->AddInstruction(_OP_SETOUTER, tmp, _es.epos, tmp);
+        }
+        _es = es;
+    }
+    void CreateFunction(SQObject &name,bool lambda = false)
+    {
+        SQFuncState *funcstate = _fs->PushChildState(_ss(_vm));
+        funcstate->_name = name;
+        SQObject paramname;
+        funcstate->AddParameter(_fs->CreateString(_SC("this")));
+        funcstate->_sourcename = _sourcename;
+        SQInteger defparams = 0;
+        while(_token!=_SC(')')) {
+            if(_token == TK_VARPARAMS) {
+                if(defparams > 0) Error(_SC("function with default parameters cannot have variable number of parameters"));
+                funcstate->AddParameter(_fs->CreateString(_SC("vargv")));
+                funcstate->_varparams = true;
+                Lex();
+                if(_token != _SC(')')) Error(_SC("expected ')'"));
+                break;
+            }
+            else {
+                paramname = Expect(TK_IDENTIFIER);
+                funcstate->AddParameter(paramname);
+                if(_token == _SC('=')) {
+                    Lex();
+                    Expression();
+                    funcstate->AddDefaultParam(_fs->TopTarget());
+                    defparams++;
+                }
+                else {
+                    if(defparams > 0) Error(_SC("expected '='"));
+                }
+                if(_token == _SC(',')) Lex();
+                else if(_token != _SC(')')) Error(_SC("expected ')' or ','"));
+            }
+        }
+        Expect(_SC(')'));
+        for(SQInteger n = 0; n < defparams; n++) {
+            _fs->PopTarget();
+        }
+
+        SQFuncState *currchunk = _fs;
+        _fs = funcstate;
+        if(lambda) {
+            Expression();
+            _fs->AddInstruction(_OP_RETURN, 1, _fs->PopTarget());}
+        else {
+            Statement(false);
+        }
+        funcstate->AddLineInfos(_lex._prevtoken == _SC('\n')?_lex._lasttokenline:_lex._currentline, _lineinfo, true);
+        funcstate->AddInstruction(_OP_RETURN, -1);
+        funcstate->SetStackSize(0);
+
+        SQFunctionProto *func = funcstate->BuildProto();
+#ifdef _DEBUG_DUMP
+        funcstate->Dump(func);
+#endif
+        _fs = currchunk;
+        _fs->_functions.push_back(func);
+        _fs->PopChildState();
+    }
+    void ResolveBreaks(SQFuncState *funcstate, SQInteger ntoresolve)
+    {
+        while(ntoresolve > 0) {
+            SQInteger pos = funcstate->_unresolvedbreaks.back();
+            funcstate->_unresolvedbreaks.pop_back();
+            //set the jmp instruction
+            funcstate->SetIntructionParams(pos, 0, funcstate->GetCurrentPos() - pos, 0);
+            ntoresolve--;
+        }
+    }
+    void ResolveContinues(SQFuncState *funcstate, SQInteger ntoresolve, SQInteger targetpos)
+    {
+        while(ntoresolve > 0) {
+            SQInteger pos = funcstate->_unresolvedcontinues.back();
+            funcstate->_unresolvedcontinues.pop_back();
+            //set the jmp instruction
+            funcstate->SetIntructionParams(pos, 0, targetpos - pos, 0);
+            ntoresolve--;
+        }
+    }
+private:
+    SQInteger _token;
+    SQFuncState *_fs;
+    SQObjectPtr _sourcename;
+    SQLexer _lex;
+    bool _lineinfo;
+    bool _raiseerror;
+    SQInteger _debugline;
+    SQInteger _debugop;
+    SQExpState   _es;
+    SQScope _scope;
+    SQChar _compilererror[MAX_COMPILER_ERROR_LEN];
+    jmp_buf _errorjmp;
+    SQVM *_vm;
+};
+
+bool Compile(SQVM *vm,SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo)
+{
+    SQCompiler p(vm, rg, up, sourcename, raiseerror, lineinfo);
+    return p.Compile(out);
+}
+
+#endif

+ 78 - 78
squirrel/sqcompiler.h

@@ -1,78 +1,78 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQCOMPILER_H_
-#define _SQCOMPILER_H_
-
-struct SQVM;
-
-#define	TK_IDENTIFIER	258
-#define	TK_STRING_LITERAL	259
-#define	TK_INTEGER	260
-#define	TK_FLOAT	261
-#define	TK_BASE	262
-#define	TK_DELETE	263
-#define	TK_EQ	264
-#define	TK_NE	265
-#define	TK_LE	266
-#define	TK_GE	267
-#define	TK_SWITCH	268
-#define	TK_ARROW	269
-#define	TK_AND	270
-#define	TK_OR	271
-#define	TK_IF	272
-#define	TK_ELSE	273
-#define	TK_WHILE	274
-#define	TK_BREAK	275
-#define	TK_FOR	276
-#define	TK_DO	277
-#define	TK_NULL	278
-#define	TK_FOREACH	279
-#define	TK_IN	280
-#define	TK_NEWSLOT	281
-#define	TK_MODULO	282
-#define	TK_LOCAL	283
-#define	TK_CLONE	284
-#define	TK_FUNCTION	285
-#define	TK_RETURN	286
-#define	TK_TYPEOF	287
-#define	TK_UMINUS	288
-#define	TK_PLUSEQ	289
-#define	TK_MINUSEQ	290
-#define	TK_CONTINUE	291
-#define TK_YIELD 292
-#define TK_TRY 293
-#define TK_CATCH 294
-#define TK_THROW 295
-#define TK_SHIFTL 296
-#define TK_SHIFTR 297
-#define TK_RESUME 298
-#define TK_DOUBLE_COLON 299
-#define TK_CASE 300
-#define TK_DEFAULT 301
-#define TK_THIS 302
-#define TK_PLUSPLUS 303
-#define TK_MINUSMINUS 304
-#define TK_3WAYSCMP 305
-#define TK_USHIFTR 306
-#define TK_CLASS 307
-#define TK_EXTENDS 308
-#define TK_CONSTRUCTOR 310
-#define TK_INSTANCEOF 311
-#define TK_VARPARAMS 312
-#define TK___LINE__ 313
-#define TK___FILE__ 314
-#define TK_TRUE 315
-#define TK_FALSE 316
-#define TK_MULEQ 317
-#define TK_DIVEQ 318
-#define TK_MODEQ 319
-#define TK_ATTR_OPEN 320
-#define TK_ATTR_CLOSE 321
-#define TK_STATIC 322
-#define TK_ENUM 323
-#define TK_CONST 324
-
-
-
-typedef void(*CompilerErrorFunc)(void *ud, const SQChar *s);
-bool Compile(SQVM *vm, SQLEXREADFUNC rg, SQUserPointer up, const SQChar *sourcename, SQObjectPtr &out, bool raiseerror, bool lineinfo);
-#endif //_SQCOMPILER_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQCOMPILER_H_
+#define _SQCOMPILER_H_
+
+struct SQVM;
+
+#define TK_IDENTIFIER   258
+#define TK_STRING_LITERAL   259
+#define TK_INTEGER  260
+#define TK_FLOAT    261
+#define TK_BASE 262
+#define TK_DELETE   263
+#define TK_EQ   264
+#define TK_NE   265
+#define TK_LE   266
+#define TK_GE   267
+#define TK_SWITCH   268
+#define TK_ARROW    269
+#define TK_AND  270
+#define TK_OR   271
+#define TK_IF   272
+#define TK_ELSE 273
+#define TK_WHILE    274
+#define TK_BREAK    275
+#define TK_FOR  276
+#define TK_DO   277
+#define TK_NULL 278
+#define TK_FOREACH  279
+#define TK_IN   280
+#define TK_NEWSLOT  281
+#define TK_MODULO   282
+#define TK_LOCAL    283
+#define TK_CLONE    284
+#define TK_FUNCTION 285
+#define TK_RETURN   286
+#define TK_TYPEOF   287
+#define TK_UMINUS   288
+#define TK_PLUSEQ   289
+#define TK_MINUSEQ  290
+#define TK_CONTINUE 291
+#define TK_YIELD 292
+#define TK_TRY 293
+#define TK_CATCH 294
+#define TK_THROW 295
+#define TK_SHIFTL 296
+#define TK_SHIFTR 297
+#define TK_RESUME 298
+#define TK_DOUBLE_COLON 299
+#define TK_CASE 300
+#define TK_DEFAULT 301
+#define TK_THIS 302
+#define TK_PLUSPLUS 303
+#define TK_MINUSMINUS 304
+#define TK_3WAYSCMP 305
+#define TK_USHIFTR 306
+#define TK_CLASS 307
+#define TK_EXTENDS 308
+#define TK_CONSTRUCTOR 310
+#define TK_INSTANCEOF 311
+#define TK_VARPARAMS 312
+#define TK___LINE__ 313
+#define TK___FILE__ 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_

+ 118 - 118
squirrel/sqdebug.cpp

@@ -1,118 +1,118 @@
-/*
-	see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include <stdarg.h>
-#include "sqvm.h"
-#include "sqfuncproto.h"
-#include "sqclosure.h"
-#include "sqstring.h"
-
-SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi)
-{
-	SQInteger cssize = v->_callsstacksize;
-	if (cssize > level) {
-		SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];
-		if(sq_isclosure(ci._closure)) {
-			SQClosure *c = _closure(ci._closure);
-			SQFunctionProto *proto = c->_function;
-			fi->funcid = proto;
-			fi->name = type(proto->_name) == OT_STRING?_stringval(proto->_name):_SC("unknown");
-			fi->source = type(proto->_sourcename) == OT_STRING?_stringval(proto->_sourcename):_SC("unknown");
-			fi->line = proto->_lineinfos[0]._line;
-			return SQ_OK;
-		}
-	}
-	return sq_throwerror(v,_SC("the object is not a closure"));
-}
-
-SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si)
-{
-	SQInteger cssize = v->_callsstacksize;
-	if (cssize > level) {
-		memset(si, 0, sizeof(SQStackInfos));
-		SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];
-		switch (type(ci._closure)) {
-		case OT_CLOSURE:{
-			SQFunctionProto *func = _closure(ci._closure)->_function;
-			if (type(func->_name) == OT_STRING)
-				si->funcname = _stringval(func->_name);
-			if (type(func->_sourcename) == OT_STRING)
-				si->source = _stringval(func->_sourcename);
-			si->line = func->GetLine(ci._ip);
-						}
-			break;
-		case OT_NATIVECLOSURE:
-			si->source = _SC("NATIVE");
-			si->funcname = _SC("unknown");
-			if(type(_nativeclosure(ci._closure)->_name) == OT_STRING)
-				si->funcname = _stringval(_nativeclosure(ci._closure)->_name);
-			si->line = -1;
-			break;
-		default: break; //shutup compiler
-		}
-		return SQ_OK;
-	}
-	return SQ_ERROR;
-}
-
-void SQVM::Raise_Error(const SQChar *s, ...)
-{
-	va_list vl;
-	va_start(vl, s);
-	SQInteger buffersize = (SQInteger)scstrlen(s)+(NUMBER_MAX_CHAR*2);
-	scvsprintf(_sp(sq_rsl(buffersize)),buffersize, s, vl);
-	va_end(vl);
-	_lasterror = SQString::Create(_ss(this),_spval,-1);
-}
-
-void SQVM::Raise_Error(const SQObjectPtr &desc)
-{
-	_lasterror = desc;
-}
-
-SQString *SQVM::PrintObjVal(const SQObjectPtr &o)
-{
-	switch(type(o)) {
-	case OT_STRING: return _string(o);
-	case OT_INTEGER:
-		scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR), _PRINT_INT_FMT, _integer(o));
-		return SQString::Create(_ss(this), _spval);
-		break;
-	case OT_FLOAT:
-		scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)), sq_rsl(NUMBER_MAX_CHAR), _SC("%.14g"), _float(o));
-		return SQString::Create(_ss(this), _spval);
-		break;
-	default:
-		return SQString::Create(_ss(this), GetTypeName(o));
-	}
-}
-
-void SQVM::Raise_IdxError(const SQObjectPtr &o)
-{
-	SQObjectPtr oval = PrintObjVal(o);
-	Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval));
-}
-
-void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2)
-{
-	SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2);
-	Raise_Error(_SC("comparison 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));
-}
+/*
+    see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include <stdarg.h>
+#include "sqvm.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+#include "sqstring.h"
+
+SQRESULT sq_getfunctioninfo(HSQUIRRELVM v,SQInteger level,SQFunctionInfo *fi)
+{
+    SQInteger cssize = v->_callsstacksize;
+    if (cssize > level) {
+        SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];
+        if(sq_isclosure(ci._closure)) {
+            SQClosure *c = _closure(ci._closure);
+            SQFunctionProto *proto = c->_function;
+            fi->funcid = proto;
+            fi->name = type(proto->_name) == OT_STRING?_stringval(proto->_name):_SC("unknown");
+            fi->source = type(proto->_sourcename) == OT_STRING?_stringval(proto->_sourcename):_SC("unknown");
+            fi->line = proto->_lineinfos[0]._line;
+            return SQ_OK;
+        }
+    }
+    return sq_throwerror(v,_SC("the object is not a closure"));
+}
+
+SQRESULT sq_stackinfos(HSQUIRRELVM v, SQInteger level, SQStackInfos *si)
+{
+    SQInteger cssize = v->_callsstacksize;
+    if (cssize > level) {
+        memset(si, 0, sizeof(SQStackInfos));
+        SQVM::CallInfo &ci = v->_callsstack[cssize-level-1];
+        switch (type(ci._closure)) {
+        case OT_CLOSURE:{
+            SQFunctionProto *func = _closure(ci._closure)->_function;
+            if (type(func->_name) == OT_STRING)
+                si->funcname = _stringval(func->_name);
+            if (type(func->_sourcename) == OT_STRING)
+                si->source = _stringval(func->_sourcename);
+            si->line = func->GetLine(ci._ip);
+                        }
+            break;
+        case OT_NATIVECLOSURE:
+            si->source = _SC("NATIVE");
+            si->funcname = _SC("unknown");
+            if(type(_nativeclosure(ci._closure)->_name) == OT_STRING)
+                si->funcname = _stringval(_nativeclosure(ci._closure)->_name);
+            si->line = -1;
+            break;
+        default: break; //shutup compiler
+        }
+        return SQ_OK;
+    }
+    return SQ_ERROR;
+}
+
+void SQVM::Raise_Error(const SQChar *s, ...)
+{
+    va_list vl;
+    va_start(vl, s);
+    SQInteger buffersize = (SQInteger)scstrlen(s)+(NUMBER_MAX_CHAR*2);
+    scvsprintf(_sp(sq_rsl(buffersize)),buffersize, s, vl);
+    va_end(vl);
+    _lasterror = SQString::Create(_ss(this),_spval,-1);
+}
+
+void SQVM::Raise_Error(const SQObjectPtr &desc)
+{
+    _lasterror = desc;
+}
+
+SQString *SQVM::PrintObjVal(const SQObjectPtr &o)
+{
+    switch(type(o)) {
+    case OT_STRING: return _string(o);
+    case OT_INTEGER:
+        scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR), _PRINT_INT_FMT, _integer(o));
+        return SQString::Create(_ss(this), _spval);
+        break;
+    case OT_FLOAT:
+        scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)), sq_rsl(NUMBER_MAX_CHAR), _SC("%.14g"), _float(o));
+        return SQString::Create(_ss(this), _spval);
+        break;
+    default:
+        return SQString::Create(_ss(this), GetTypeName(o));
+    }
+}
+
+void SQVM::Raise_IdxError(const SQObjectPtr &o)
+{
+    SQObjectPtr oval = PrintObjVal(o);
+    Raise_Error(_SC("the index '%.50s' does not exist"), _stringval(oval));
+}
+
+void SQVM::Raise_CompareError(const SQObject &o1, const SQObject &o2)
+{
+    SQObjectPtr oval1 = PrintObjVal(o1), oval2 = PrintObjVal(o2);
+    Raise_Error(_SC("comparison 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));
+}

+ 154 - 154
squirrel/sqfuncproto.h

@@ -1,154 +1,154 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQFUNCTION_H_
-#define _SQFUNCTION_H_
-
-#include "sqopcodes.h"
-
-enum SQOuterType {
-	otLOCAL = 0,
-	otOUTER = 1
-};
-
-struct SQOuterVar
-{
-	
-	SQOuterVar(){}
-	SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t)
-	{
-		_name = name;
-		_src=src;
-		_type=t;
-	}
-	SQOuterVar(const SQOuterVar &ov)
-	{
-		_type=ov._type;
-		_src=ov._src;
-		_name=ov._name;
-	}
-	SQOuterType _type;
-	SQObjectPtr _name;
-	SQObjectPtr _src;
-};
-
-struct SQLocalVarInfo
-{
-	SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0){}
-	SQLocalVarInfo(const SQLocalVarInfo &lvi)
-	{
-		_name=lvi._name;
-		_start_op=lvi._start_op;
-		_end_op=lvi._end_op;
-		_pos=lvi._pos;
-	}
-	SQObjectPtr _name;
-	SQUnsignedInteger _start_op;
-	SQUnsignedInteger _end_op;
-	SQUnsignedInteger _pos;
-};
-
-struct SQLineInfo { SQInteger _line;SQInteger _op; };
-
-typedef sqvector<SQOuterVar> SQOuterVarVec;
-typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;
-typedef sqvector<SQLineInfo> SQLineInfoVec;
-
-#define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf,defparams) (sizeof(SQFunctionProto) \
-		+((ni-1)*sizeof(SQInstruction))+(nl*sizeof(SQObjectPtr)) \
-		+(nparams*sizeof(SQObjectPtr))+(nfuncs*sizeof(SQObjectPtr)) \
-		+(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \
-		+(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger)))
-
-
-struct SQFunctionProto : public CHAINABLE_OBJ
-{
-private:
-	SQFunctionProto(SQSharedState *ss);
-	~SQFunctionProto();
-	
-public:
-	static SQFunctionProto *Create(SQSharedState *ss,SQInteger ninstructions,
-		SQInteger nliterals,SQInteger nparameters,
-		SQInteger nfunctions,SQInteger noutervalues,
-		SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams)
-	{
-		SQFunctionProto *f;
-		//I compact the whole class and members in a single memory allocation
-		f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams));
-		new (f) SQFunctionProto(ss);
-		f->_ninstructions = ninstructions;
-		f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions];
-		f->_nliterals = nliterals;
-		f->_parameters = (SQObjectPtr*)&f->_literals[nliterals];
-		f->_nparameters = nparameters;
-		f->_functions = (SQObjectPtr*)&f->_parameters[nparameters];
-		f->_nfunctions = nfunctions;
-		f->_outervalues = (SQOuterVar*)&f->_functions[nfunctions];
-		f->_noutervalues = noutervalues;
-		f->_lineinfos = (SQLineInfo *)&f->_outervalues[noutervalues];
-		f->_nlineinfos = nlineinfos;
-		f->_localvarinfos = (SQLocalVarInfo *)&f->_lineinfos[nlineinfos];
-		f->_nlocalvarinfos = nlocalvarinfos;
-		f->_defaultparams = (SQInteger *)&f->_localvarinfos[nlocalvarinfos];
-		f->_ndefaultparams = ndefaultparams;
-
-		_CONSTRUCT_VECTOR(SQObjectPtr,f->_nliterals,f->_literals);
-		_CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters);
-		_CONSTRUCT_VECTOR(SQObjectPtr,f->_nfunctions,f->_functions);
-		_CONSTRUCT_VECTOR(SQOuterVar,f->_noutervalues,f->_outervalues);
-		//_CONSTRUCT_VECTOR(SQLineInfo,f->_nlineinfos,f->_lineinfos); //not required are 2 integers
-		_CONSTRUCT_VECTOR(SQLocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos);
-		return f;
-	}
-	void Release(){ 
-		_DESTRUCT_VECTOR(SQObjectPtr,_nliterals,_literals);
-		_DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters);
-		_DESTRUCT_VECTOR(SQObjectPtr,_nfunctions,_functions);
-		_DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues);
-		//_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers
-		_DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos);
-		SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams);
-		this->~SQFunctionProto();
-		sq_vm_free(this,size);
-	}
-	
-	const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);
-	SQInteger GetLine(SQInstruction *curr);
-	bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
-	static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
-#ifndef NO_GARBAGE_COLLECTOR
-	void Mark(SQCollectable **chain);
-	void Finalize(){ _NULL_SQOBJECT_VECTOR(_literals,_nliterals); }
-	SQObjectType GetType() {return OT_FUNCPROTO;}
-#endif
-	SQObjectPtr _sourcename;
-	SQObjectPtr _name;
-    SQInteger _stacksize;
-	bool _bgenerator;
-	SQInteger _varparams;
-
-	SQInteger _nlocalvarinfos;
-	SQLocalVarInfo *_localvarinfos;
-
-	SQInteger _nlineinfos;
-	SQLineInfo *_lineinfos;
-
-	SQInteger _nliterals;
-	SQObjectPtr *_literals;
-
-	SQInteger _nparameters;
-	SQObjectPtr *_parameters;
-	
-	SQInteger _nfunctions;
-	SQObjectPtr *_functions;
-
-	SQInteger _noutervalues;
-	SQOuterVar *_outervalues;
-
-	SQInteger _ndefaultparams;
-	SQInteger *_defaultparams;
-	
-	SQInteger _ninstructions;
-	SQInstruction _instructions[1];
-};
-
-#endif //_SQFUNCTION_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQFUNCTION_H_
+#define _SQFUNCTION_H_
+
+#include "sqopcodes.h"
+
+enum SQOuterType {
+    otLOCAL = 0,
+    otOUTER = 1
+};
+
+struct SQOuterVar
+{
+
+    SQOuterVar(){}
+    SQOuterVar(const SQObjectPtr &name,const SQObjectPtr &src,SQOuterType t)
+    {
+        _name = name;
+        _src=src;
+        _type=t;
+    }
+    SQOuterVar(const SQOuterVar &ov)
+    {
+        _type=ov._type;
+        _src=ov._src;
+        _name=ov._name;
+    }
+    SQOuterType _type;
+    SQObjectPtr _name;
+    SQObjectPtr _src;
+};
+
+struct SQLocalVarInfo
+{
+    SQLocalVarInfo():_start_op(0),_end_op(0),_pos(0){}
+    SQLocalVarInfo(const SQLocalVarInfo &lvi)
+    {
+        _name=lvi._name;
+        _start_op=lvi._start_op;
+        _end_op=lvi._end_op;
+        _pos=lvi._pos;
+    }
+    SQObjectPtr _name;
+    SQUnsignedInteger _start_op;
+    SQUnsignedInteger _end_op;
+    SQUnsignedInteger _pos;
+};
+
+struct SQLineInfo { SQInteger _line;SQInteger _op; };
+
+typedef sqvector<SQOuterVar> SQOuterVarVec;
+typedef sqvector<SQLocalVarInfo> SQLocalVarInfoVec;
+typedef sqvector<SQLineInfo> SQLineInfoVec;
+
+#define _FUNC_SIZE(ni,nl,nparams,nfuncs,nouters,nlineinf,localinf,defparams) (sizeof(SQFunctionProto) \
+        +((ni-1)*sizeof(SQInstruction))+(nl*sizeof(SQObjectPtr)) \
+        +(nparams*sizeof(SQObjectPtr))+(nfuncs*sizeof(SQObjectPtr)) \
+        +(nouters*sizeof(SQOuterVar))+(nlineinf*sizeof(SQLineInfo)) \
+        +(localinf*sizeof(SQLocalVarInfo))+(defparams*sizeof(SQInteger)))
+
+
+struct SQFunctionProto : public CHAINABLE_OBJ
+{
+private:
+    SQFunctionProto(SQSharedState *ss);
+    ~SQFunctionProto();
+
+public:
+    static SQFunctionProto *Create(SQSharedState *ss,SQInteger ninstructions,
+        SQInteger nliterals,SQInteger nparameters,
+        SQInteger nfunctions,SQInteger noutervalues,
+        SQInteger nlineinfos,SQInteger nlocalvarinfos,SQInteger ndefaultparams)
+    {
+        SQFunctionProto *f;
+        //I compact the whole class and members in a single memory allocation
+        f = (SQFunctionProto *)sq_vm_malloc(_FUNC_SIZE(ninstructions,nliterals,nparameters,nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams));
+        new (f) SQFunctionProto(ss);
+        f->_ninstructions = ninstructions;
+        f->_literals = (SQObjectPtr*)&f->_instructions[ninstructions];
+        f->_nliterals = nliterals;
+        f->_parameters = (SQObjectPtr*)&f->_literals[nliterals];
+        f->_nparameters = nparameters;
+        f->_functions = (SQObjectPtr*)&f->_parameters[nparameters];
+        f->_nfunctions = nfunctions;
+        f->_outervalues = (SQOuterVar*)&f->_functions[nfunctions];
+        f->_noutervalues = noutervalues;
+        f->_lineinfos = (SQLineInfo *)&f->_outervalues[noutervalues];
+        f->_nlineinfos = nlineinfos;
+        f->_localvarinfos = (SQLocalVarInfo *)&f->_lineinfos[nlineinfos];
+        f->_nlocalvarinfos = nlocalvarinfos;
+        f->_defaultparams = (SQInteger *)&f->_localvarinfos[nlocalvarinfos];
+        f->_ndefaultparams = ndefaultparams;
+
+        _CONSTRUCT_VECTOR(SQObjectPtr,f->_nliterals,f->_literals);
+        _CONSTRUCT_VECTOR(SQObjectPtr,f->_nparameters,f->_parameters);
+        _CONSTRUCT_VECTOR(SQObjectPtr,f->_nfunctions,f->_functions);
+        _CONSTRUCT_VECTOR(SQOuterVar,f->_noutervalues,f->_outervalues);
+        //_CONSTRUCT_VECTOR(SQLineInfo,f->_nlineinfos,f->_lineinfos); //not required are 2 integers
+        _CONSTRUCT_VECTOR(SQLocalVarInfo,f->_nlocalvarinfos,f->_localvarinfos);
+        return f;
+    }
+    void Release(){
+        _DESTRUCT_VECTOR(SQObjectPtr,_nliterals,_literals);
+        _DESTRUCT_VECTOR(SQObjectPtr,_nparameters,_parameters);
+        _DESTRUCT_VECTOR(SQObjectPtr,_nfunctions,_functions);
+        _DESTRUCT_VECTOR(SQOuterVar,_noutervalues,_outervalues);
+        //_DESTRUCT_VECTOR(SQLineInfo,_nlineinfos,_lineinfos); //not required are 2 integers
+        _DESTRUCT_VECTOR(SQLocalVarInfo,_nlocalvarinfos,_localvarinfos);
+        SQInteger size = _FUNC_SIZE(_ninstructions,_nliterals,_nparameters,_nfunctions,_noutervalues,_nlineinfos,_nlocalvarinfos,_ndefaultparams);
+        this->~SQFunctionProto();
+        sq_vm_free(this,size);
+    }
+
+    const SQChar* GetLocal(SQVM *v,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop);
+    SQInteger GetLine(SQInstruction *curr);
+    bool Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write);
+    static bool Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret);
+#ifndef NO_GARBAGE_COLLECTOR
+    void Mark(SQCollectable **chain);
+    void Finalize(){ _NULL_SQOBJECT_VECTOR(_literals,_nliterals); }
+    SQObjectType GetType() {return OT_FUNCPROTO;}
+#endif
+    SQObjectPtr _sourcename;
+    SQObjectPtr _name;
+    SQInteger _stacksize;
+    bool _bgenerator;
+    SQInteger _varparams;
+
+    SQInteger _nlocalvarinfos;
+    SQLocalVarInfo *_localvarinfos;
+
+    SQInteger _nlineinfos;
+    SQLineInfo *_lineinfos;
+
+    SQInteger _nliterals;
+    SQObjectPtr *_literals;
+
+    SQInteger _nparameters;
+    SQObjectPtr *_parameters;
+
+    SQInteger _nfunctions;
+    SQObjectPtr *_functions;
+
+    SQInteger _noutervalues;
+    SQOuterVar *_outervalues;
+
+    SQInteger _ndefaultparams;
+    SQInteger *_defaultparams;
+
+    SQInteger _ninstructions;
+    SQInstruction _instructions[1];
+};
+
+#endif //_SQFUNCTION_H_

+ 653 - 653
squirrel/sqfuncstate.cpp

@@ -1,653 +1,653 @@
-/*
-	see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#ifndef NO_COMPILER
-#include "sqcompiler.h"
-#include "sqstring.h"
-#include "sqfuncproto.h"
-#include "sqtable.h"
-#include "sqopcodes.h"
-#include "sqfuncstate.h"
-
-#ifdef _DEBUG_DUMP
-SQInstructionDesc g_InstrDesc[]={
-	{_SC("_OP_LINE")},
-	{_SC("_OP_LOAD")},
-	{_SC("_OP_LOADINT")},
-	{_SC("_OP_LOADFLOAT")},
-	{_SC("_OP_DLOAD")},
-	{_SC("_OP_TAILCALL")},
-	{_SC("_OP_CALL")},
-	{_SC("_OP_PREPCALL")},
-	{_SC("_OP_PREPCALLK")},
-	{_SC("_OP_GETK")},
-	{_SC("_OP_MOVE")},
-	{_SC("_OP_NEWSLOT")},
-	{_SC("_OP_DELETE")},
-	{_SC("_OP_SET")},
-	{_SC("_OP_GET")},
-	{_SC("_OP_EQ")},
-	{_SC("_OP_NE")},
-	{_SC("_OP_ADD")},
-	{_SC("_OP_SUB")},
-	{_SC("_OP_MUL")},
-	{_SC("_OP_DIV")},
-	{_SC("_OP_MOD")},
-	{_SC("_OP_BITW")},
-	{_SC("_OP_RETURN")},
-	{_SC("_OP_LOADNULLS")},
-	{_SC("_OP_LOADROOT")},
-	{_SC("_OP_LOADBOOL")},
-	{_SC("_OP_DMOVE")},
-	{_SC("_OP_JMP")},
-	{_SC("_OP_JCMP")},
-	{_SC("_OP_JZ")},
-	{_SC("_OP_SETOUTER")},
-	{_SC("_OP_GETOUTER")},
-	{_SC("_OP_NEWOBJ")},
-	{_SC("_OP_APPENDARRAY")},
-	{_SC("_OP_COMPARITH")},
-	{_SC("_OP_INC")},
-	{_SC("_OP_INCL")},
-	{_SC("_OP_PINC")},
-	{_SC("_OP_PINCL")},
-	{_SC("_OP_CMP")},
-	{_SC("_OP_EXISTS")},
-	{_SC("_OP_INSTANCEOF")},
-	{_SC("_OP_AND")},
-	{_SC("_OP_OR")},
-	{_SC("_OP_NEG")},
-	{_SC("_OP_NOT")},
-	{_SC("_OP_BWNOT")},
-	{_SC("_OP_CLOSURE")},
-	{_SC("_OP_YIELD")},
-	{_SC("_OP_RESUME")},
-	{_SC("_OP_FOREACH")},
-	{_SC("_OP_POSTFOREACH")},
-	{_SC("_OP_CLONE")},
-	{_SC("_OP_TYPEOF")},
-	{_SC("_OP_PUSHTRAP")},
-	{_SC("_OP_POPTRAP")},
-	{_SC("_OP_THROW")},
-	{_SC("_OP_NEWSLOTA")},
-	{_SC("_OP_GETBASE")},
-	{_SC("_OP_CLOSE")},
-};
-#endif
-void DumpLiteral(SQObjectPtr &o)
-{
-	switch(type(o)){
-		case OT_STRING:	scprintf(_SC("\"%s\""),_stringval(o));break;
-		case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
-		case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break;
-		case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
-		default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler
-	}
-}
-
-SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
-{
-		_nliterals = 0;
-		_literals = SQTable::Create(ss,0);
-		_strings =  SQTable::Create(ss,0);
-		_sharedstate = ss;
-		_lastline = 0;
-		_optimization = true;
-		_parent = parent;
-		_stacksize = 0;
-		_traps = 0;
-		_returnexp = 0;
-		_varparams = false;
-		_errfunc = efunc;
-		_errtarget = ed;
-		_bgenerator = false;
-		_outers = 0;
-		_ss = ss;
-
-}
-
-void SQFuncState::Error(const SQChar *err)
-{
-	_errfunc(_errtarget,err);
-}
-
-#ifdef _DEBUG_DUMP
-void SQFuncState::Dump(SQFunctionProto *func)
-{
-	SQUnsignedInteger n=0,i;
-	SQInteger si;
-	scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
-	scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
-	scprintf(_SC("--------------------------------------------------------------------\n"));
-	scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
-	scprintf(_SC("-----LITERALS\n"));
-	SQObjectPtr refidx,key,val;
-	SQInteger idx;
-	SQObjectPtrVec templiterals;
-	templiterals.resize(_nliterals);
-	while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
-		refidx=idx;
-		templiterals[_integer(val)]=key;
-	}
-	for(i=0;i<templiterals.size();i++){
-		scprintf(_SC("[%d] "),n);
-		DumpLiteral(templiterals[i]);
-		scprintf(_SC("\n"));
-		n++;
-	}
-	scprintf(_SC("-----PARAMS\n"));
-	if(_varparams)
-		scprintf(_SC("<<VARPARAMS>>\n"));
-	n=0;
-	for(i=0;i<_parameters.size();i++){
-		scprintf(_SC("[%d] "),n);
-		DumpLiteral(_parameters[i]);
-		scprintf(_SC("\n"));
-		n++;
-	}
-	scprintf(_SC("-----LOCALS\n"));
-	for(si=0;si<func->_nlocalvarinfos;si++){
-		SQLocalVarInfo lvi=func->_localvarinfos[si];
-		scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
-		n++;
-	}
-	scprintf(_SC("-----LINE INFO\n"));
-	for(i=0;i<_lineinfos.size();i++){
-		SQLineInfo li=_lineinfos[i];
-		scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
-		n++;
-	}
-	scprintf(_SC("-----dump\n"));
-	n=0;
-	for(i=0;i<_instructions.size();i++){
-		SQInstruction &inst=_instructions[i];
-		if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
-			
-			SQInteger lidx = inst._arg1;
-			scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
-			if(lidx >= 0xFFFFFFFF)
-				scprintf(_SC("null"));
-			else {
-				SQInteger refidx;
-				SQObjectPtr val,key,refo;
-				while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
-					refo = refidx;	
-				}
-				DumpLiteral(key);
-			}
-			if(inst.op != _OP_DLOAD) {
-				scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
-			}
-			else {
-				scprintf(_SC(" %d "),inst._arg2);
-				lidx = inst._arg3;
-				if(lidx >= 0xFFFFFFFF)
-					scprintf(_SC("null"));
-				else {
-					SQInteger refidx;
-					SQObjectPtr val,key,refo;
-					while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
-						refo = refidx;	
-				}
-				DumpLiteral(key);
-				scprintf(_SC("\n"));
-			}
-			}
-		}
-		else if(inst.op==_OP_LOADFLOAT) {
-			scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3);
-		}
-	/*	else if(inst.op==_OP_ARITH){
-			scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
-		}*/
-		else {
-			scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
-		}
-		n++;
-	}
-	scprintf(_SC("-----\n"));
-	scprintf(_SC("stack size[%d]\n"),func->_stacksize);
-	scprintf(_SC("--------------------------------------------------------------------\n\n"));
-}
-#endif
-
-SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
-{
-	return GetConstant(SQObjectPtr(cons));
-}
-
-SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
-{
-	return GetConstant(SQObjectPtr(cons));
-}
-
-SQInteger SQFuncState::GetConstant(const SQObject &cons)
-{
-	SQObjectPtr val;
-	if(!_table(_literals)->Get(cons,val))
-	{
-		val = _nliterals;
-		_table(_literals)->NewSlot(cons,val);
-		_nliterals++;
-		if(_nliterals > MAX_LITERALS) {
-			val.Null();
-			Error(_SC("internal compiler error: too many literals"));
-		}
-	}
-	return _integer(val);
-}
-
-void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
-{
-	_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
-	_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
-	_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
-	_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
-}
-
-void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
-{
-	switch(arg){
-		case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
-		case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
-		case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
-		case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
-	};
-}
-
-SQInteger SQFuncState::AllocStackPos()
-{
-	SQInteger npos=_vlocals.size();
-	_vlocals.push_back(SQLocalVarInfo());
-	if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
-		if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
-		_stacksize=_vlocals.size();
-	}
-	return npos;
-}
-
-SQInteger SQFuncState::PushTarget(SQInteger n)
-{
-	if(n!=-1){
-		_targetstack.push_back(n);
-		return n;
-	}
-	n=AllocStackPos();
-	_targetstack.push_back(n);
-	return n;
-}
-
-SQInteger SQFuncState::GetUpTarget(SQInteger n){
-	return _targetstack[((_targetstack.size()-1)-n)];
-}
-
-SQInteger SQFuncState::TopTarget(){
-	return _targetstack.back();
-}
-SQInteger SQFuncState::PopTarget()
-{
-	SQUnsignedInteger npos=_targetstack.back();
-	assert(npos < _vlocals.size());
-	SQLocalVarInfo &t = _vlocals[npos];
-	if(type(t._name)==OT_NULL){
-		_vlocals.pop_back();
-	}
-	_targetstack.pop_back();
-	return npos;
-}
-
-SQInteger SQFuncState::GetStackSize()
-{
-	return _vlocals.size();
-}
-
-SQInteger SQFuncState::CountOuters(SQInteger stacksize)
-{
-	SQInteger outers = 0;
-	SQInteger k = _vlocals.size() - 1;
-	while(k >= stacksize) {
-		SQLocalVarInfo &lvi = _vlocals[k];
-		k--;
-		if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
-			outers++;
-		}
-	}
-	return outers;
-}
-
-void SQFuncState::SetStackSize(SQInteger n)
-{
-	SQInteger size=_vlocals.size();
-	while(size>n){
-		size--;
-		SQLocalVarInfo lvi = _vlocals.back();
-		if(type(lvi._name)!=OT_NULL){
-			if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
-				_outers--;
-			}
-			lvi._end_op = GetCurrentPos();
-			_localvarinfos.push_back(lvi);
-		}
-		_vlocals.pop_back();
-	}
-}
-
-bool SQFuncState::IsConstant(const SQObject &name,SQObject &e)
-{
-	SQObjectPtr val;
-	if(_table(_sharedstate->_consts)->Get(name,val)) {
-		e = val;
-		return true;
-	}
-	return false;
-}
-
-bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
-{
-	if(stkpos>=_vlocals.size())return false;
-	else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
-	return false;
-}
-
-SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
-{
-	SQInteger pos=_vlocals.size();
-	SQLocalVarInfo lvi;
-	lvi._name=name;
-	lvi._start_op=GetCurrentPos()+1;
-	lvi._pos=_vlocals.size();
-	_vlocals.push_back(lvi);
-	if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
-	return pos;
-}
-
-
-
-SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
-{
-	SQInteger locals=_vlocals.size();
-	while(locals>=1){
-		SQLocalVarInfo &lvi = _vlocals[locals-1];
-		if(type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){
-			return locals-1;
-		}
-		locals--;
-	}
-	return -1;
-}
-
-void SQFuncState::MarkLocalAsOuter(SQInteger pos)
-{
-	SQLocalVarInfo &lvi = _vlocals[pos];
-	lvi._end_op = UINT_MINUS_ONE;
-	_outers++;
-}
-
-SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
-{
-	SQInteger outers = _outervalues.size();
-	for(SQInteger i = 0; i<outers; i++) {
-		if(_string(_outervalues[i]._name) == _string(name))
-			return i;
-	}
-	SQInteger pos=-1;
-	if(_parent) { 
-		pos = _parent->GetLocalVariable(name);
-		if(pos == -1) {
-			pos = _parent->GetOuterVariable(name);
-			if(pos != -1) {
-				_outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
-				return _outervalues.size() - 1;	
-			}
-		}
-		else {
-			_parent->MarkLocalAsOuter(pos);
-			_outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
-			return _outervalues.size() - 1;
-			
-			
-		}
-	}
-	return -1;
-}
-
-void SQFuncState::AddParameter(const SQObject &name)
-{
-	PushLocalVariable(name);
-	_parameters.push_back(name);
-}
-
-void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
-{
-	if(_lastline!=line || force){
-		SQLineInfo li;
-		li._line=line;li._op=(GetCurrentPos()+1);
-		if(lineop)AddInstruction(_OP_LINE,0,line);
-		if(_lastline!=line) {
-			_lineinfos.push_back(li);
-		}
-		_lastline=line;
-	}
-}
-
-void SQFuncState::DiscardTarget()
-{
-	SQInteger discardedtarget = PopTarget();
-	SQInteger size = _instructions.size();
-	if(size > 0 && _optimization){
-		SQInstruction &pi = _instructions[size-1];//previous instruction
-		switch(pi.op) {
-		case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL:
-			if(pi._arg0 == discardedtarget) {
-				pi._arg0 = 0xFF;
-			}
-		}
-	}
-}
-
-void SQFuncState::AddInstruction(SQInstruction &i)
-{
-	SQInteger size = _instructions.size();
-	if(size > 0 && _optimization){ //simple optimizer
-		SQInstruction &pi = _instructions[size-1];//previous instruction
-		switch(i.op) {
-		case _OP_JZ:
-			if( pi.op == _OP_CMP && pi._arg1 < 0xFF) {
-				pi.op = _OP_JCMP;
-				pi._arg0 = (unsigned char)pi._arg1;
-				pi._arg1 = i._arg1;
-				return;
-			}
-			break;
-		case _OP_SET:
-		case _OP_NEWSLOT:
-			if(i._arg0 == i._arg3) {
-				i._arg0 = 0xFF;
-			}
-			break;
-		case _OP_SETOUTER:
-			if(i._arg0 == i._arg2) {
-				i._arg0 = 0xFF;
-			}
-			break;
-		case _OP_RETURN:
-			if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
-				pi.op = _OP_TAILCALL;
-			} else if(pi.op == _OP_CLOSE){
-				pi = i;
-				return;
-			}
-		break;
-		case _OP_GET:
-			if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
-				pi._arg1 = pi._arg1;
-				pi._arg2 = (unsigned char)i._arg1;
-				pi.op = _OP_GETK;
-				pi._arg0 = i._arg0;
-				
-				return;
-			}
-		break;
-		case _OP_PREPCALL:
-			if( pi.op == _OP_LOAD  && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
-				pi.op = _OP_PREPCALLK;
-				pi._arg0 = i._arg0;
-				pi._arg1 = pi._arg1;
-				pi._arg2 = i._arg2;
-				pi._arg3 = i._arg3;
-				return;
-			}
-			break;
-		case _OP_APPENDARRAY: {
-			SQInteger aat = -1;
-			switch(pi.op) {
-			case _OP_LOAD: aat = AAT_LITERAL; break;
-			case _OP_LOADINT: aat = AAT_INT; break;
-			case _OP_LOADBOOL: aat = AAT_BOOL; break;
-			case _OP_LOADFLOAT: aat = AAT_FLOAT; break;
-			default: break;
-			}
-			if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
-				pi.op = _OP_APPENDARRAY;
-				pi._arg0 = i._arg0;
-				pi._arg1 = pi._arg1;
-				pi._arg2 = (unsigned char)aat;
-				pi._arg3 = MAX_FUNC_STACKSIZE;
-				return;
-			}
-							  }
-			break;
-		case _OP_MOVE:
-			switch(pi.op) {
-			case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW:
-			case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD:
-
-				if(pi._arg0 == i._arg1)
-				{
-					pi._arg0 = i._arg0;
-					_optimization = false;
-					//_result_elimination = false;
-					return;
-				}
-			}
-
-			if(pi.op == _OP_MOVE)
-			{
-				pi.op = _OP_DMOVE;
-				pi._arg2 = i._arg0;
-				pi._arg3 = (unsigned char)i._arg1;
-				return;
-			}
-			break;
-		case _OP_LOAD:
-			if(pi.op == _OP_LOAD && i._arg1 < 256) {
-				pi.op = _OP_DLOAD;
-				pi._arg2 = i._arg0;
-				pi._arg3 = (unsigned char)i._arg1;
-				return;
-			}
-			break;
-		case _OP_EQ:case _OP_NE:
-			if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
-			{
-				pi.op = i.op;
-				pi._arg0 = i._arg0;
-				pi._arg1 = pi._arg1;
-				pi._arg2 = i._arg2;
-				pi._arg3 = MAX_FUNC_STACKSIZE;
-				return;
-			}
-			break;
-		case _OP_LOADNULLS:
-			if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
-				
-				pi._arg1 = pi._arg1 + 1;
-				pi.op = _OP_LOADNULLS;
-				return;
-			}
-            break;
-		case _OP_LINE:
-			if(pi.op == _OP_LINE) {
-				_instructions.pop_back();
-				_lineinfos.pop_back();
-			}
-			break;
-		}
-	}
-	_optimization = true;
-	_instructions.push_back(i);
-}
-
-SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
-{
-	SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
-	_table(_strings)->NewSlot(ns,(SQInteger)1);
-	return ns;
-}
-
-SQObject SQFuncState::CreateTable()
-{
-	SQObjectPtr nt(SQTable::Create(_sharedstate,0));
-	_table(_strings)->NewSlot(nt,(SQInteger)1);
-	return nt;
-}
-
-SQFunctionProto *SQFuncState::BuildProto()
-{
-	
-	SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(),
-		_nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
-		_lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
-
-	SQObjectPtr refidx,key,val;
-	SQInteger idx;
-
-	f->_stacksize = _stacksize;
-	f->_sourcename = _sourcename;
-	f->_bgenerator = _bgenerator;
-	f->_name = _name;
-
-	while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
-		f->_literals[_integer(val)]=key;
-		refidx=idx;
-	}
-
-	for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];
-	for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];
-	for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];
-	for(SQUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl];
-	for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni];
-	for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd];
-
-	memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
-
-	f->_varparams = _varparams;
-
-	return f;
-}
-
-SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
-{
-	SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
-	new (child) SQFuncState(ss,this,_errfunc,_errtarget);
-	_childstates.push_back(child);
-	return child;
-}
-
-void SQFuncState::PopChildState()
-{
-	SQFuncState *child = _childstates.back();
-	sq_delete(child,SQFuncState);
-	_childstates.pop_back();
-}
-
-SQFuncState::~SQFuncState()
-{
-	while(_childstates.size() > 0)
-	{
-		PopChildState();
-	}
-}
-
-#endif
+/*
+    see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#ifndef NO_COMPILER
+#include "sqcompiler.h"
+#include "sqstring.h"
+#include "sqfuncproto.h"
+#include "sqtable.h"
+#include "sqopcodes.h"
+#include "sqfuncstate.h"
+
+#ifdef _DEBUG_DUMP
+SQInstructionDesc g_InstrDesc[]={
+    {_SC("_OP_LINE")},
+    {_SC("_OP_LOAD")},
+    {_SC("_OP_LOADINT")},
+    {_SC("_OP_LOADFLOAT")},
+    {_SC("_OP_DLOAD")},
+    {_SC("_OP_TAILCALL")},
+    {_SC("_OP_CALL")},
+    {_SC("_OP_PREPCALL")},
+    {_SC("_OP_PREPCALLK")},
+    {_SC("_OP_GETK")},
+    {_SC("_OP_MOVE")},
+    {_SC("_OP_NEWSLOT")},
+    {_SC("_OP_DELETE")},
+    {_SC("_OP_SET")},
+    {_SC("_OP_GET")},
+    {_SC("_OP_EQ")},
+    {_SC("_OP_NE")},
+    {_SC("_OP_ADD")},
+    {_SC("_OP_SUB")},
+    {_SC("_OP_MUL")},
+    {_SC("_OP_DIV")},
+    {_SC("_OP_MOD")},
+    {_SC("_OP_BITW")},
+    {_SC("_OP_RETURN")},
+    {_SC("_OP_LOADNULLS")},
+    {_SC("_OP_LOADROOT")},
+    {_SC("_OP_LOADBOOL")},
+    {_SC("_OP_DMOVE")},
+    {_SC("_OP_JMP")},
+    {_SC("_OP_JCMP")},
+    {_SC("_OP_JZ")},
+    {_SC("_OP_SETOUTER")},
+    {_SC("_OP_GETOUTER")},
+    {_SC("_OP_NEWOBJ")},
+    {_SC("_OP_APPENDARRAY")},
+    {_SC("_OP_COMPARITH")},
+    {_SC("_OP_INC")},
+    {_SC("_OP_INCL")},
+    {_SC("_OP_PINC")},
+    {_SC("_OP_PINCL")},
+    {_SC("_OP_CMP")},
+    {_SC("_OP_EXISTS")},
+    {_SC("_OP_INSTANCEOF")},
+    {_SC("_OP_AND")},
+    {_SC("_OP_OR")},
+    {_SC("_OP_NEG")},
+    {_SC("_OP_NOT")},
+    {_SC("_OP_BWNOT")},
+    {_SC("_OP_CLOSURE")},
+    {_SC("_OP_YIELD")},
+    {_SC("_OP_RESUME")},
+    {_SC("_OP_FOREACH")},
+    {_SC("_OP_POSTFOREACH")},
+    {_SC("_OP_CLONE")},
+    {_SC("_OP_TYPEOF")},
+    {_SC("_OP_PUSHTRAP")},
+    {_SC("_OP_POPTRAP")},
+    {_SC("_OP_THROW")},
+    {_SC("_OP_NEWSLOTA")},
+    {_SC("_OP_GETBASE")},
+    {_SC("_OP_CLOSE")},
+};
+#endif
+void DumpLiteral(SQObjectPtr &o)
+{
+    switch(type(o)){
+        case OT_STRING: scprintf(_SC("\"%s\""),_stringval(o));break;
+        case OT_FLOAT: scprintf(_SC("{%f}"),_float(o));break;
+        case OT_INTEGER: scprintf(_SC("{") _PRINT_INT_FMT _SC("}"),_integer(o));break;
+        case OT_BOOL: scprintf(_SC("%s"),_integer(o)?_SC("true"):_SC("false"));break;
+        default: scprintf(_SC("(%s %p)"),GetTypeName(o),(void*)_rawval(o));break; break; //shut up compiler
+    }
+}
+
+SQFuncState::SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed)
+{
+        _nliterals = 0;
+        _literals = SQTable::Create(ss,0);
+        _strings =  SQTable::Create(ss,0);
+        _sharedstate = ss;
+        _lastline = 0;
+        _optimization = true;
+        _parent = parent;
+        _stacksize = 0;
+        _traps = 0;
+        _returnexp = 0;
+        _varparams = false;
+        _errfunc = efunc;
+        _errtarget = ed;
+        _bgenerator = false;
+        _outers = 0;
+        _ss = ss;
+
+}
+
+void SQFuncState::Error(const SQChar *err)
+{
+    _errfunc(_errtarget,err);
+}
+
+#ifdef _DEBUG_DUMP
+void SQFuncState::Dump(SQFunctionProto *func)
+{
+    SQUnsignedInteger n=0,i;
+    SQInteger si;
+    scprintf(_SC("SQInstruction sizeof %d\n"),sizeof(SQInstruction));
+    scprintf(_SC("SQObject sizeof %d\n"),sizeof(SQObject));
+    scprintf(_SC("--------------------------------------------------------------------\n"));
+    scprintf(_SC("*****FUNCTION [%s]\n"),type(func->_name)==OT_STRING?_stringval(func->_name):_SC("unknown"));
+    scprintf(_SC("-----LITERALS\n"));
+    SQObjectPtr refidx,key,val;
+    SQInteger idx;
+    SQObjectPtrVec templiterals;
+    templiterals.resize(_nliterals);
+    while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
+        refidx=idx;
+        templiterals[_integer(val)]=key;
+    }
+    for(i=0;i<templiterals.size();i++){
+        scprintf(_SC("[%d] "),n);
+        DumpLiteral(templiterals[i]);
+        scprintf(_SC("\n"));
+        n++;
+    }
+    scprintf(_SC("-----PARAMS\n"));
+    if(_varparams)
+        scprintf(_SC("<<VARPARAMS>>\n"));
+    n=0;
+    for(i=0;i<_parameters.size();i++){
+        scprintf(_SC("[%d] "),n);
+        DumpLiteral(_parameters[i]);
+        scprintf(_SC("\n"));
+        n++;
+    }
+    scprintf(_SC("-----LOCALS\n"));
+    for(si=0;si<func->_nlocalvarinfos;si++){
+        SQLocalVarInfo lvi=func->_localvarinfos[si];
+        scprintf(_SC("[%d] %s \t%d %d\n"),lvi._pos,_stringval(lvi._name),lvi._start_op,lvi._end_op);
+        n++;
+    }
+    scprintf(_SC("-----LINE INFO\n"));
+    for(i=0;i<_lineinfos.size();i++){
+        SQLineInfo li=_lineinfos[i];
+        scprintf(_SC("op [%d] line [%d] \n"),li._op,li._line);
+        n++;
+    }
+    scprintf(_SC("-----dump\n"));
+    n=0;
+    for(i=0;i<_instructions.size();i++){
+        SQInstruction &inst=_instructions[i];
+        if(inst.op==_OP_LOAD || inst.op==_OP_DLOAD || inst.op==_OP_PREPCALLK || inst.op==_OP_GETK ){
+
+            SQInteger lidx = inst._arg1;
+            scprintf(_SC("[%03d] %15s %d "),n,g_InstrDesc[inst.op].name,inst._arg0);
+            if(lidx >= 0xFFFFFFFF)
+                scprintf(_SC("null"));
+            else {
+                SQInteger refidx;
+                SQObjectPtr val,key,refo;
+                while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
+                    refo = refidx;
+                }
+                DumpLiteral(key);
+            }
+            if(inst.op != _OP_DLOAD) {
+                scprintf(_SC(" %d %d \n"),inst._arg2,inst._arg3);
+            }
+            else {
+                scprintf(_SC(" %d "),inst._arg2);
+                lidx = inst._arg3;
+                if(lidx >= 0xFFFFFFFF)
+                    scprintf(_SC("null"));
+                else {
+                    SQInteger refidx;
+                    SQObjectPtr val,key,refo;
+                    while(((refidx=_table(_literals)->Next(false,refo,key,val))!= -1) && (_integer(val) != lidx)) {
+                        refo = refidx;
+                }
+                DumpLiteral(key);
+                scprintf(_SC("\n"));
+            }
+            }
+        }
+        else if(inst.op==_OP_LOADFLOAT) {
+            scprintf(_SC("[%03d] %15s %d %f %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,*((SQFloat*)&inst._arg1),inst._arg2,inst._arg3);
+        }
+    /*  else if(inst.op==_OP_ARITH){
+            scprintf(_SC("[%03d] %15s %d %d %d %c\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
+        }*/
+        else {
+            scprintf(_SC("[%03d] %15s %d %d %d %d\n"),n,g_InstrDesc[inst.op].name,inst._arg0,inst._arg1,inst._arg2,inst._arg3);
+        }
+        n++;
+    }
+    scprintf(_SC("-----\n"));
+    scprintf(_SC("stack size[%d]\n"),func->_stacksize);
+    scprintf(_SC("--------------------------------------------------------------------\n\n"));
+}
+#endif
+
+SQInteger SQFuncState::GetNumericConstant(const SQInteger cons)
+{
+    return GetConstant(SQObjectPtr(cons));
+}
+
+SQInteger SQFuncState::GetNumericConstant(const SQFloat cons)
+{
+    return GetConstant(SQObjectPtr(cons));
+}
+
+SQInteger SQFuncState::GetConstant(const SQObject &cons)
+{
+    SQObjectPtr val;
+    if(!_table(_literals)->Get(cons,val))
+    {
+        val = _nliterals;
+        _table(_literals)->NewSlot(cons,val);
+        _nliterals++;
+        if(_nliterals > MAX_LITERALS) {
+            val.Null();
+            Error(_SC("internal compiler error: too many literals"));
+        }
+    }
+    return _integer(val);
+}
+
+void SQFuncState::SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2,SQInteger arg3)
+{
+    _instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&arg0);
+    _instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&arg1);
+    _instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&arg2);
+    _instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&arg3);
+}
+
+void SQFuncState::SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val)
+{
+    switch(arg){
+        case 0:_instructions[pos]._arg0=(unsigned char)*((SQUnsignedInteger *)&val);break;
+        case 1:case 4:_instructions[pos]._arg1=(SQInt32)*((SQUnsignedInteger *)&val);break;
+        case 2:_instructions[pos]._arg2=(unsigned char)*((SQUnsignedInteger *)&val);break;
+        case 3:_instructions[pos]._arg3=(unsigned char)*((SQUnsignedInteger *)&val);break;
+    };
+}
+
+SQInteger SQFuncState::AllocStackPos()
+{
+    SQInteger npos=_vlocals.size();
+    _vlocals.push_back(SQLocalVarInfo());
+    if(_vlocals.size()>((SQUnsignedInteger)_stacksize)) {
+        if(_stacksize>MAX_FUNC_STACKSIZE) Error(_SC("internal compiler error: too many locals"));
+        _stacksize=_vlocals.size();
+    }
+    return npos;
+}
+
+SQInteger SQFuncState::PushTarget(SQInteger n)
+{
+    if(n!=-1){
+        _targetstack.push_back(n);
+        return n;
+    }
+    n=AllocStackPos();
+    _targetstack.push_back(n);
+    return n;
+}
+
+SQInteger SQFuncState::GetUpTarget(SQInteger n){
+    return _targetstack[((_targetstack.size()-1)-n)];
+}
+
+SQInteger SQFuncState::TopTarget(){
+    return _targetstack.back();
+}
+SQInteger SQFuncState::PopTarget()
+{
+    SQUnsignedInteger npos=_targetstack.back();
+    assert(npos < _vlocals.size());
+    SQLocalVarInfo &t = _vlocals[npos];
+    if(type(t._name)==OT_NULL){
+        _vlocals.pop_back();
+    }
+    _targetstack.pop_back();
+    return npos;
+}
+
+SQInteger SQFuncState::GetStackSize()
+{
+    return _vlocals.size();
+}
+
+SQInteger SQFuncState::CountOuters(SQInteger stacksize)
+{
+    SQInteger outers = 0;
+    SQInteger k = _vlocals.size() - 1;
+    while(k >= stacksize) {
+        SQLocalVarInfo &lvi = _vlocals[k];
+        k--;
+        if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
+            outers++;
+        }
+    }
+    return outers;
+}
+
+void SQFuncState::SetStackSize(SQInteger n)
+{
+    SQInteger size=_vlocals.size();
+    while(size>n){
+        size--;
+        SQLocalVarInfo lvi = _vlocals.back();
+        if(type(lvi._name)!=OT_NULL){
+            if(lvi._end_op == UINT_MINUS_ONE) { //this means is an outer
+                _outers--;
+            }
+            lvi._end_op = GetCurrentPos();
+            _localvarinfos.push_back(lvi);
+        }
+        _vlocals.pop_back();
+    }
+}
+
+bool SQFuncState::IsConstant(const SQObject &name,SQObject &e)
+{
+    SQObjectPtr val;
+    if(_table(_sharedstate->_consts)->Get(name,val)) {
+        e = val;
+        return true;
+    }
+    return false;
+}
+
+bool SQFuncState::IsLocal(SQUnsignedInteger stkpos)
+{
+    if(stkpos>=_vlocals.size())return false;
+    else if(type(_vlocals[stkpos]._name)!=OT_NULL)return true;
+    return false;
+}
+
+SQInteger SQFuncState::PushLocalVariable(const SQObject &name)
+{
+    SQInteger pos=_vlocals.size();
+    SQLocalVarInfo lvi;
+    lvi._name=name;
+    lvi._start_op=GetCurrentPos()+1;
+    lvi._pos=_vlocals.size();
+    _vlocals.push_back(lvi);
+    if(_vlocals.size()>((SQUnsignedInteger)_stacksize))_stacksize=_vlocals.size();
+    return pos;
+}
+
+
+
+SQInteger SQFuncState::GetLocalVariable(const SQObject &name)
+{
+    SQInteger locals=_vlocals.size();
+    while(locals>=1){
+        SQLocalVarInfo &lvi = _vlocals[locals-1];
+        if(type(lvi._name)==OT_STRING && _string(lvi._name)==_string(name)){
+            return locals-1;
+        }
+        locals--;
+    }
+    return -1;
+}
+
+void SQFuncState::MarkLocalAsOuter(SQInteger pos)
+{
+    SQLocalVarInfo &lvi = _vlocals[pos];
+    lvi._end_op = UINT_MINUS_ONE;
+    _outers++;
+}
+
+SQInteger SQFuncState::GetOuterVariable(const SQObject &name)
+{
+    SQInteger outers = _outervalues.size();
+    for(SQInteger i = 0; i<outers; i++) {
+        if(_string(_outervalues[i]._name) == _string(name))
+            return i;
+    }
+    SQInteger pos=-1;
+    if(_parent) {
+        pos = _parent->GetLocalVariable(name);
+        if(pos == -1) {
+            pos = _parent->GetOuterVariable(name);
+            if(pos != -1) {
+                _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otOUTER)); //local
+                return _outervalues.size() - 1;
+            }
+        }
+        else {
+            _parent->MarkLocalAsOuter(pos);
+            _outervalues.push_back(SQOuterVar(name,SQObjectPtr(SQInteger(pos)),otLOCAL)); //local
+            return _outervalues.size() - 1;
+
+
+        }
+    }
+    return -1;
+}
+
+void SQFuncState::AddParameter(const SQObject &name)
+{
+    PushLocalVariable(name);
+    _parameters.push_back(name);
+}
+
+void SQFuncState::AddLineInfos(SQInteger line,bool lineop,bool force)
+{
+    if(_lastline!=line || force){
+        SQLineInfo li;
+        li._line=line;li._op=(GetCurrentPos()+1);
+        if(lineop)AddInstruction(_OP_LINE,0,line);
+        if(_lastline!=line) {
+            _lineinfos.push_back(li);
+        }
+        _lastline=line;
+    }
+}
+
+void SQFuncState::DiscardTarget()
+{
+    SQInteger discardedtarget = PopTarget();
+    SQInteger size = _instructions.size();
+    if(size > 0 && _optimization){
+        SQInstruction &pi = _instructions[size-1];//previous instruction
+        switch(pi.op) {
+        case _OP_SET:case _OP_NEWSLOT:case _OP_SETOUTER:case _OP_CALL:
+            if(pi._arg0 == discardedtarget) {
+                pi._arg0 = 0xFF;
+            }
+        }
+    }
+}
+
+void SQFuncState::AddInstruction(SQInstruction &i)
+{
+    SQInteger size = _instructions.size();
+    if(size > 0 && _optimization){ //simple optimizer
+        SQInstruction &pi = _instructions[size-1];//previous instruction
+        switch(i.op) {
+        case _OP_JZ:
+            if( pi.op == _OP_CMP && pi._arg1 < 0xFF) {
+                pi.op = _OP_JCMP;
+                pi._arg0 = (unsigned char)pi._arg1;
+                pi._arg1 = i._arg1;
+                return;
+            }
+            break;
+        case _OP_SET:
+        case _OP_NEWSLOT:
+            if(i._arg0 == i._arg3) {
+                i._arg0 = 0xFF;
+            }
+            break;
+        case _OP_SETOUTER:
+            if(i._arg0 == i._arg2) {
+                i._arg0 = 0xFF;
+            }
+            break;
+        case _OP_RETURN:
+            if( _parent && i._arg0 != MAX_FUNC_STACKSIZE && pi.op == _OP_CALL && _returnexp < size-1) {
+                pi.op = _OP_TAILCALL;
+            } else if(pi.op == _OP_CLOSE){
+                pi = i;
+                return;
+            }
+        break;
+        case _OP_GET:
+            if( pi.op == _OP_LOAD && pi._arg0 == i._arg2 && (!IsLocal(pi._arg0))){
+                pi._arg1 = pi._arg1;
+                pi._arg2 = (unsigned char)i._arg1;
+                pi.op = _OP_GETK;
+                pi._arg0 = i._arg0;
+
+                return;
+            }
+        break;
+        case _OP_PREPCALL:
+            if( pi.op == _OP_LOAD  && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
+                pi.op = _OP_PREPCALLK;
+                pi._arg0 = i._arg0;
+                pi._arg1 = pi._arg1;
+                pi._arg2 = i._arg2;
+                pi._arg3 = i._arg3;
+                return;
+            }
+            break;
+        case _OP_APPENDARRAY: {
+            SQInteger aat = -1;
+            switch(pi.op) {
+            case _OP_LOAD: aat = AAT_LITERAL; break;
+            case _OP_LOADINT: aat = AAT_INT; break;
+            case _OP_LOADBOOL: aat = AAT_BOOL; break;
+            case _OP_LOADFLOAT: aat = AAT_FLOAT; break;
+            default: break;
+            }
+            if(aat != -1 && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0))){
+                pi.op = _OP_APPENDARRAY;
+                pi._arg0 = i._arg0;
+                pi._arg1 = pi._arg1;
+                pi._arg2 = (unsigned char)aat;
+                pi._arg3 = MAX_FUNC_STACKSIZE;
+                return;
+            }
+                              }
+            break;
+        case _OP_MOVE:
+            switch(pi.op) {
+            case _OP_GET: case _OP_ADD: case _OP_SUB: case _OP_MUL: case _OP_DIV: case _OP_MOD: case _OP_BITW:
+            case _OP_LOADINT: case _OP_LOADFLOAT: case _OP_LOADBOOL: case _OP_LOAD:
+
+                if(pi._arg0 == i._arg1)
+                {
+                    pi._arg0 = i._arg0;
+                    _optimization = false;
+                    //_result_elimination = false;
+                    return;
+                }
+            }
+
+            if(pi.op == _OP_MOVE)
+            {
+                pi.op = _OP_DMOVE;
+                pi._arg2 = i._arg0;
+                pi._arg3 = (unsigned char)i._arg1;
+                return;
+            }
+            break;
+        case _OP_LOAD:
+            if(pi.op == _OP_LOAD && i._arg1 < 256) {
+                pi.op = _OP_DLOAD;
+                pi._arg2 = i._arg0;
+                pi._arg3 = (unsigned char)i._arg1;
+                return;
+            }
+            break;
+        case _OP_EQ:case _OP_NE:
+            if(pi.op == _OP_LOAD && pi._arg0 == i._arg1 && (!IsLocal(pi._arg0) ))
+            {
+                pi.op = i.op;
+                pi._arg0 = i._arg0;
+                pi._arg1 = pi._arg1;
+                pi._arg2 = i._arg2;
+                pi._arg3 = MAX_FUNC_STACKSIZE;
+                return;
+            }
+            break;
+        case _OP_LOADNULLS:
+            if((pi.op == _OP_LOADNULLS && pi._arg0+pi._arg1 == i._arg0)) {
+
+                pi._arg1 = pi._arg1 + 1;
+                pi.op = _OP_LOADNULLS;
+                return;
+            }
+            break;
+        case _OP_LINE:
+            if(pi.op == _OP_LINE) {
+                _instructions.pop_back();
+                _lineinfos.pop_back();
+            }
+            break;
+        }
+    }
+    _optimization = true;
+    _instructions.push_back(i);
+}
+
+SQObject SQFuncState::CreateString(const SQChar *s,SQInteger len)
+{
+    SQObjectPtr ns(SQString::Create(_sharedstate,s,len));
+    _table(_strings)->NewSlot(ns,(SQInteger)1);
+    return ns;
+}
+
+SQObject SQFuncState::CreateTable()
+{
+    SQObjectPtr nt(SQTable::Create(_sharedstate,0));
+    _table(_strings)->NewSlot(nt,(SQInteger)1);
+    return nt;
+}
+
+SQFunctionProto *SQFuncState::BuildProto()
+{
+
+    SQFunctionProto *f=SQFunctionProto::Create(_ss,_instructions.size(),
+        _nliterals,_parameters.size(),_functions.size(),_outervalues.size(),
+        _lineinfos.size(),_localvarinfos.size(),_defaultparams.size());
+
+    SQObjectPtr refidx,key,val;
+    SQInteger idx;
+
+    f->_stacksize = _stacksize;
+    f->_sourcename = _sourcename;
+    f->_bgenerator = _bgenerator;
+    f->_name = _name;
+
+    while((idx=_table(_literals)->Next(false,refidx,key,val))!=-1) {
+        f->_literals[_integer(val)]=key;
+        refidx=idx;
+    }
+
+    for(SQUnsignedInteger nf = 0; nf < _functions.size(); nf++) f->_functions[nf] = _functions[nf];
+    for(SQUnsignedInteger np = 0; np < _parameters.size(); np++) f->_parameters[np] = _parameters[np];
+    for(SQUnsignedInteger no = 0; no < _outervalues.size(); no++) f->_outervalues[no] = _outervalues[no];
+    for(SQUnsignedInteger nl = 0; nl < _localvarinfos.size(); nl++) f->_localvarinfos[nl] = _localvarinfos[nl];
+    for(SQUnsignedInteger ni = 0; ni < _lineinfos.size(); ni++) f->_lineinfos[ni] = _lineinfos[ni];
+    for(SQUnsignedInteger nd = 0; nd < _defaultparams.size(); nd++) f->_defaultparams[nd] = _defaultparams[nd];
+
+    memcpy(f->_instructions,&_instructions[0],_instructions.size()*sizeof(SQInstruction));
+
+    f->_varparams = _varparams;
+
+    return f;
+}
+
+SQFuncState *SQFuncState::PushChildState(SQSharedState *ss)
+{
+    SQFuncState *child = (SQFuncState *)sq_malloc(sizeof(SQFuncState));
+    new (child) SQFuncState(ss,this,_errfunc,_errtarget);
+    _childstates.push_back(child);
+    return child;
+}
+
+void SQFuncState::PopChildState()
+{
+    SQFuncState *child = _childstates.back();
+    sq_delete(child,SQFuncState);
+    _childstates.pop_back();
+}
+
+SQFuncState::~SQFuncState()
+{
+    while(_childstates.size() > 0)
+    {
+        PopChildState();
+    }
+}
+
+#endif

+ 91 - 91
squirrel/sqfuncstate.h

@@ -1,91 +1,91 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQFUNCSTATE_H_
-#define _SQFUNCSTATE_H_
-///////////////////////////////////
-#include "squtils.h"
-
-struct SQFuncState
-{
-	SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed);
-	~SQFuncState();
-#ifdef _DEBUG_DUMP
-	void Dump(SQFunctionProto *func);
-#endif
-	void Error(const SQChar *err);
-	SQFuncState *PushChildState(SQSharedState *ss);
-	void PopChildState();
-	void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}
-	void AddInstruction(SQInstruction &i);
-	void SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2=0,SQInteger arg3=0);
-	void SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val);
-	SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];}
-	void PopInstructions(SQInteger size){for(SQInteger i=0;i<size;i++)_instructions.pop_back();}
-	void SetStackSize(SQInteger n);
-	SQInteger CountOuters(SQInteger stacksize);
-	void SnoozeOpt(){_optimization=false;}
-	void AddDefaultParam(SQInteger trg) { _defaultparams.push_back(trg); }
-	SQInteger GetDefaultParamCount() { return _defaultparams.size(); }
-	SQInteger GetCurrentPos(){return _instructions.size()-1;}
-	SQInteger GetNumericConstant(const SQInteger cons);
-	SQInteger GetNumericConstant(const SQFloat cons);
-	SQInteger PushLocalVariable(const SQObject &name);
-	void AddParameter(const SQObject &name);
-	//void AddOuterValue(const SQObject &name);
-	SQInteger GetLocalVariable(const SQObject &name);
-	void MarkLocalAsOuter(SQInteger pos);
-	SQInteger GetOuterVariable(const SQObject &name);
-	SQInteger GenerateCode();
-	SQInteger GetStackSize();
-	SQInteger CalcStackFrameSize();
-	void AddLineInfos(SQInteger line,bool lineop,bool force=false);
-	SQFunctionProto *BuildProto();
-	SQInteger AllocStackPos();
-	SQInteger PushTarget(SQInteger n=-1);
-	SQInteger PopTarget();
-	SQInteger TopTarget();
-	SQInteger GetUpTarget(SQInteger n);
-	void DiscardTarget();
-	bool IsLocal(SQUnsignedInteger stkpos);
-	SQObject CreateString(const SQChar *s,SQInteger len = -1);
-	SQObject CreateTable();
-	bool IsConstant(const SQObject &name,SQObject &e);
-	SQInteger _returnexp;
-	SQLocalVarInfoVec _vlocals;
-	SQIntVec _targetstack;
-	SQInteger _stacksize;
-	bool _varparams;
-	bool _bgenerator;
-	SQIntVec _unresolvedbreaks;
-	SQIntVec _unresolvedcontinues;
-	SQObjectPtrVec _functions;
-	SQObjectPtrVec _parameters;
-	SQOuterVarVec _outervalues;
-	SQInstructionVec _instructions;
-	SQLocalVarInfoVec _localvarinfos;
-	SQObjectPtr _literals;
-	SQObjectPtr _strings;
-	SQObjectPtr _name;
-	SQObjectPtr _sourcename;
-	SQInteger _nliterals;
-	SQLineInfoVec _lineinfos;
-	SQFuncState *_parent;
-	SQIntVec _scope_blocks;
-	SQIntVec _breaktargets;
-	SQIntVec _continuetargets;
-	SQIntVec _defaultparams;
-	SQInteger _lastline;
-	SQInteger _traps; //contains number of nested exception traps
-	SQInteger _outers;
-	bool _optimization;
-	SQSharedState *_sharedstate;
-	sqvector<SQFuncState*> _childstates;
-	SQInteger GetConstant(const SQObject &cons);
-private:
-	CompilerErrorFunc _errfunc;
-	void *_errtarget;
-	SQSharedState *_ss;
-};
-
-
-#endif //_SQFUNCSTATE_H_
-
+/*  see copyright notice in squirrel.h */
+#ifndef _SQFUNCSTATE_H_
+#define _SQFUNCSTATE_H_
+///////////////////////////////////
+#include "squtils.h"
+
+struct SQFuncState
+{
+    SQFuncState(SQSharedState *ss,SQFuncState *parent,CompilerErrorFunc efunc,void *ed);
+    ~SQFuncState();
+#ifdef _DEBUG_DUMP
+    void Dump(SQFunctionProto *func);
+#endif
+    void Error(const SQChar *err);
+    SQFuncState *PushChildState(SQSharedState *ss);
+    void PopChildState();
+    void AddInstruction(SQOpcode _op,SQInteger arg0=0,SQInteger arg1=0,SQInteger arg2=0,SQInteger arg3=0){SQInstruction i(_op,arg0,arg1,arg2,arg3);AddInstruction(i);}
+    void AddInstruction(SQInstruction &i);
+    void SetIntructionParams(SQInteger pos,SQInteger arg0,SQInteger arg1,SQInteger arg2=0,SQInteger arg3=0);
+    void SetIntructionParam(SQInteger pos,SQInteger arg,SQInteger val);
+    SQInstruction &GetInstruction(SQInteger pos){return _instructions[pos];}
+    void PopInstructions(SQInteger size){for(SQInteger i=0;i<size;i++)_instructions.pop_back();}
+    void SetStackSize(SQInteger n);
+    SQInteger CountOuters(SQInteger stacksize);
+    void SnoozeOpt(){_optimization=false;}
+    void AddDefaultParam(SQInteger trg) { _defaultparams.push_back(trg); }
+    SQInteger GetDefaultParamCount() { return _defaultparams.size(); }
+    SQInteger GetCurrentPos(){return _instructions.size()-1;}
+    SQInteger GetNumericConstant(const SQInteger cons);
+    SQInteger GetNumericConstant(const SQFloat cons);
+    SQInteger PushLocalVariable(const SQObject &name);
+    void AddParameter(const SQObject &name);
+    //void AddOuterValue(const SQObject &name);
+    SQInteger GetLocalVariable(const SQObject &name);
+    void MarkLocalAsOuter(SQInteger pos);
+    SQInteger GetOuterVariable(const SQObject &name);
+    SQInteger GenerateCode();
+    SQInteger GetStackSize();
+    SQInteger CalcStackFrameSize();
+    void AddLineInfos(SQInteger line,bool lineop,bool force=false);
+    SQFunctionProto *BuildProto();
+    SQInteger AllocStackPos();
+    SQInteger PushTarget(SQInteger n=-1);
+    SQInteger PopTarget();
+    SQInteger TopTarget();
+    SQInteger GetUpTarget(SQInteger n);
+    void DiscardTarget();
+    bool IsLocal(SQUnsignedInteger stkpos);
+    SQObject CreateString(const SQChar *s,SQInteger len = -1);
+    SQObject CreateTable();
+    bool IsConstant(const SQObject &name,SQObject &e);
+    SQInteger _returnexp;
+    SQLocalVarInfoVec _vlocals;
+    SQIntVec _targetstack;
+    SQInteger _stacksize;
+    bool _varparams;
+    bool _bgenerator;
+    SQIntVec _unresolvedbreaks;
+    SQIntVec _unresolvedcontinues;
+    SQObjectPtrVec _functions;
+    SQObjectPtrVec _parameters;
+    SQOuterVarVec _outervalues;
+    SQInstructionVec _instructions;
+    SQLocalVarInfoVec _localvarinfos;
+    SQObjectPtr _literals;
+    SQObjectPtr _strings;
+    SQObjectPtr _name;
+    SQObjectPtr _sourcename;
+    SQInteger _nliterals;
+    SQLineInfoVec _lineinfos;
+    SQFuncState *_parent;
+    SQIntVec _scope_blocks;
+    SQIntVec _breaktargets;
+    SQIntVec _continuetargets;
+    SQIntVec _defaultparams;
+    SQInteger _lastline;
+    SQInteger _traps; //contains number of nested exception traps
+    SQInteger _outers;
+    bool _optimization;
+    SQSharedState *_sharedstate;
+    sqvector<SQFuncState*> _childstates;
+    SQInteger GetConstant(const SQObject &cons);
+private:
+    CompilerErrorFunc _errfunc;
+    void *_errtarget;
+    SQSharedState *_ss;
+};
+
+
+#endif //_SQFUNCSTATE_H_
+

+ 491 - 491
squirrel/sqlexer.cpp

@@ -1,491 +1,491 @@
-/*
-	see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include <ctype.h>
-#include <stdlib.h>
-#include "sqtable.h"
-#include "sqstring.h"
-#include "sqcompiler.h"
-#include "sqlexer.h"
-
-#define CUR_CHAR (_currdata)
-#define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;}
-#define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB)
-#define NEXT() {Next();_currentcolumn++;}
-#define INIT_TEMP_STRING() { _longstr.resize(0);}
-#define APPEND_CHAR(c) { _longstr.push_back(c);}
-#define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));}
-#define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id))
-
-SQLexer::SQLexer(){}
-SQLexer::~SQLexer()
-{
-	_keywords->Release();
-}
-
-void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerErrorFunc efunc,void *ed)
-{
-	_errfunc = efunc;
-	_errtarget = ed;
-	_sharedstate = ss;
-	_keywords = SQTable::Create(ss, 37);
-	ADD_KEYWORD(while, TK_WHILE);
-	ADD_KEYWORD(do, TK_DO);
-	ADD_KEYWORD(if, TK_IF);
-	ADD_KEYWORD(else, TK_ELSE);
-	ADD_KEYWORD(break, TK_BREAK);
-	ADD_KEYWORD(continue, TK_CONTINUE);
-	ADD_KEYWORD(return, TK_RETURN);
-	ADD_KEYWORD(null, TK_NULL);
-	ADD_KEYWORD(function, TK_FUNCTION);
-	ADD_KEYWORD(local, TK_LOCAL);
-	ADD_KEYWORD(for, TK_FOR);
-	ADD_KEYWORD(foreach, TK_FOREACH);
-	ADD_KEYWORD(in, TK_IN);
-	ADD_KEYWORD(typeof, TK_TYPEOF);
-	ADD_KEYWORD(base, TK_BASE);
-	ADD_KEYWORD(delete, TK_DELETE);
-	ADD_KEYWORD(try, TK_TRY);
-	ADD_KEYWORD(catch, TK_CATCH);
-	ADD_KEYWORD(throw, TK_THROW);
-	ADD_KEYWORD(clone, TK_CLONE);
-	ADD_KEYWORD(yield, TK_YIELD);
-	ADD_KEYWORD(resume, TK_RESUME);
-	ADD_KEYWORD(switch, TK_SWITCH);
-	ADD_KEYWORD(case, TK_CASE);
-	ADD_KEYWORD(default, TK_DEFAULT);
-	ADD_KEYWORD(this, TK_THIS);
-	ADD_KEYWORD(class,TK_CLASS);
-	ADD_KEYWORD(extends,TK_EXTENDS);
-	ADD_KEYWORD(constructor,TK_CONSTRUCTOR);
-	ADD_KEYWORD(instanceof,TK_INSTANCEOF);
-	ADD_KEYWORD(true,TK_TRUE);
-	ADD_KEYWORD(false,TK_FALSE);
-	ADD_KEYWORD(static,TK_STATIC);
-	ADD_KEYWORD(enum,TK_ENUM);
-	ADD_KEYWORD(const,TK_CONST);
-	ADD_KEYWORD(__LINE__,TK___LINE__);
-    ADD_KEYWORD(__FILE__,TK___FILE__);
-
-	_readf = rg;
-	_up = up;
-	_lasttokenline = _currentline = 1;
-	_currentcolumn = 0;
-	_prevtoken = -1;
-	_reached_eof = SQFalse;
-	Next();
-}
-
-void SQLexer::Error(const SQChar *err)
-{
-	_errfunc(_errtarget,err);
-}
-
-void SQLexer::Next()
-{
-	SQInteger t = _readf(_up);
-	if(t > MAX_CHAR) Error(_SC("Invalid character"));
-	if(t != 0) {
-		_currdata = (LexChar)t;
-		return;
-	}
-	_currdata = SQUIRREL_EOB;
-	_reached_eof = SQTrue;
-}
-
-const SQChar *SQLexer::Tok2Str(SQInteger tok)
-{
-	SQObjectPtr itr, key, val;
-	SQInteger nitr;
-	while((nitr = _keywords->Next(false,itr, key, val)) != -1) {
-		itr = (SQInteger)nitr;
-		if(((SQInteger)_integer(val)) == tok)
-			return _stringval(key);
-	}
-	return NULL;
-}
-
-void SQLexer::LexBlockComment()
-{
-	bool done = false;
-	while(!done) {
-		switch(CUR_CHAR) {
-			case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;
-			case _SC('\n'): _currentline++; NEXT(); continue;
-			case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment"));
-			default: NEXT();
-		}
-	}
-}
-void SQLexer::LexLineComment()
-{
-	do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));
-}
-
-SQInteger SQLexer::Lex()
-{
-	_lasttokenline = _currentline;
-	while(CUR_CHAR != SQUIRREL_EOB) {
-		switch(CUR_CHAR){
-		case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue;
-		case _SC('\n'):
-			_currentline++;
-			_prevtoken=_curtoken;
-			_curtoken=_SC('\n');
-			NEXT();
-			_currentcolumn=1;
-			continue;
-		case _SC('#'): LexLineComment(); continue;
-		case _SC('/'):
-			NEXT();
-			switch(CUR_CHAR){
-			case _SC('*'):
-				NEXT();
-				LexBlockComment();
-				continue;	
-			case _SC('/'):
-				LexLineComment();
-				continue;
-			case _SC('='):
-				NEXT();
-				RETURN_TOKEN(TK_DIVEQ);
-				continue;
-			case _SC('>'):
-				NEXT();
-				RETURN_TOKEN(TK_ATTR_CLOSE);
-				continue;
-			default:
-				RETURN_TOKEN('/');
-			}
-		case _SC('='):
-			NEXT();
-			if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') }
-			else { NEXT(); RETURN_TOKEN(TK_EQ); }
-		case _SC('<'):
-			NEXT();
-			switch(CUR_CHAR) {
-			case _SC('='):
-				NEXT(); 
-				if(CUR_CHAR == _SC('>')) {
-					NEXT();
-					RETURN_TOKEN(TK_3WAYSCMP); 
-				}
-				RETURN_TOKEN(TK_LE) 
-				break;
-			case _SC('-'): NEXT(); RETURN_TOKEN(TK_NEWSLOT); break;
-			case _SC('<'): NEXT(); RETURN_TOKEN(TK_SHIFTL); break;
-			case _SC('/'): NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); break;
-			}
-			RETURN_TOKEN('<');
-		case _SC('>'):
-			NEXT();
-			if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);}
-			else if(CUR_CHAR == _SC('>')){ 
-				NEXT(); 
-				if(CUR_CHAR == _SC('>')){
-					NEXT();
-					RETURN_TOKEN(TK_USHIFTR);
-				}
-				RETURN_TOKEN(TK_SHIFTR);
-			}
-			else { RETURN_TOKEN('>') }
-		case _SC('!'):
-			NEXT();
-			if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')}
-			else { NEXT(); RETURN_TOKEN(TK_NE); }
-		case _SC('@'): {
-			SQInteger stype;
-			NEXT();
-			if(CUR_CHAR != _SC('"')) {
-				RETURN_TOKEN('@');
-			}
-			if((stype=ReadString('"',true))!=-1) {
-				RETURN_TOKEN(stype);
-			}
-			Error(_SC("error parsing the string"));
-					   }
-		case _SC('"'):
-		case _SC('\''): {
-			SQInteger stype;
-			if((stype=ReadString(CUR_CHAR,false))!=-1){
-				RETURN_TOKEN(stype);
-			}
-			Error(_SC("error parsing the string"));
-			}
-		case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'):
-		case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'):
-			{SQInteger ret = CUR_CHAR;
-			NEXT(); RETURN_TOKEN(ret); }
-		case _SC('.'):
-			NEXT();
-			if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') }
-			NEXT();
-			if (CUR_CHAR != _SC('.')){ Error(_SC("invalid token '..'")); }
-			NEXT();
-			RETURN_TOKEN(TK_VARPARAMS);
-		case _SC('&'):
-			NEXT();
-			if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') }
-			else { NEXT(); RETURN_TOKEN(TK_AND); }
-		case _SC('|'):
-			NEXT();
-			if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') }
-			else { NEXT(); RETURN_TOKEN(TK_OR); }
-		case _SC(':'):
-			NEXT();
-			if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') }
-			else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); }
-		case _SC('*'):
-			NEXT();
-			if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);}
-			else RETURN_TOKEN('*');
-		case _SC('%'):
-			NEXT();
-			if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);}
-			else RETURN_TOKEN('%');
-		case _SC('-'):
-			NEXT();
-			if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);}
-			else if  (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);}
-			else RETURN_TOKEN('-');
-		case _SC('+'):
-			NEXT();
-			if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);}
-			else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);}
-			else RETURN_TOKEN('+');
-		case SQUIRREL_EOB:
-			return 0;
-		default:{
-				if (scisdigit(CUR_CHAR)) {
-					SQInteger ret = ReadNumber();
-					RETURN_TOKEN(ret);
-				}
-				else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {
-					SQInteger t = ReadID();
-					RETURN_TOKEN(t);
-				}
-				else {
-					SQInteger c = CUR_CHAR;
-					if (sciscntrl((int)c)) Error(_SC("unexpected character(control)"));
-					NEXT();
-					RETURN_TOKEN(c);  
-				}
-				RETURN_TOKEN(0);
-			}
-		}
-	}
-	return 0;    
-}
-	
-SQInteger SQLexer::GetIDType(const SQChar *s,SQInteger len)
-{
-	SQObjectPtr t;
-	if(_keywords->GetStr(s,len, t)) {
-		return SQInteger(_integer(t));
-	}
-	return TK_IDENTIFIER;
-}
-
-
-SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim)
-{
-	INIT_TEMP_STRING();
-	NEXT();
-	if(IS_EOB()) return -1;
-	for(;;) {
-		while(CUR_CHAR != ndelim) {
-			switch(CUR_CHAR) {
-			case SQUIRREL_EOB:
-				Error(_SC("unfinished string"));
-				return -1;
-			case _SC('\n'): 
-				if(!verbatim) Error(_SC("newline in a constant")); 
-				APPEND_CHAR(CUR_CHAR); NEXT(); 
-				_currentline++;
-				break;
-			case _SC('\\'):
-				if(verbatim) {
-					APPEND_CHAR('\\'); NEXT(); 
-				}
-				else {
-					NEXT();
-					switch(CUR_CHAR) {
-					case _SC('x'): NEXT(); {
-						if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected")); 
-						const SQInteger maxdigits = 4;
-						SQChar temp[maxdigits+1];
-						SQInteger n = 0;
-						while(isxdigit(CUR_CHAR) && n < maxdigits) {
-							temp[n] = CUR_CHAR;
-							n++;
-							NEXT();
-						}
-						temp[n] = 0;
-						SQChar *sTemp;
-						APPEND_CHAR((SQChar)scstrtoul(temp,&sTemp,16));
-					}
-				    break;
-					case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break;
-					case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break;
-					case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break;
-					case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break;
-					case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break;
-					case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break;
-					case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break;
-					case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break;
-					case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break;
-					case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break;
-					case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break;
-					default:
-						Error(_SC("unrecognised escaper char"));
-					break;
-					}
-				}
-				break;
-			default:
-				APPEND_CHAR(CUR_CHAR);
-				NEXT();
-			}
-		}
-		NEXT();
-		if(verbatim && CUR_CHAR == '"') { //double quotation
-			APPEND_CHAR(CUR_CHAR);
-			NEXT();
-		}
-		else {
-			break;
-		}
-	}
-	TERMINATE_BUFFER();
-	SQInteger len = _longstr.size()-1;
-	if(ndelim == _SC('\'')) {
-		if(len == 0) Error(_SC("empty constant"));
-		if(len > 1) Error(_SC("constant too long"));
-		_nvalue = _longstr[0];
-		return TK_INTEGER;
-	}
-	_svalue = &_longstr[0];
-	return TK_STRING_LITERAL;
-}
-
-void LexHexadecimal(const SQChar *s,SQUnsignedInteger *res)
-{
-	*res = 0;
-	while(*s != 0)
-	{
-		if(scisdigit(*s)) *res = (*res)*16+((*s++)-'0');
-		else if(scisxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10);
-		else { assert(0); }
-	}
-}
-
-void LexInteger(const SQChar *s,SQUnsignedInteger *res)
-{
-	*res = 0;
-	while(*s != 0)
-	{
-		*res = (*res)*10+((*s++)-'0');
-	}
-}
-
-SQInteger scisodigit(SQInteger c) { return c >= _SC('0') && c <= _SC('7'); }
-
-void LexOctal(const SQChar *s,SQUnsignedInteger *res)
-{
-	*res = 0;
-	while(*s != 0)
-	{
-		if(scisodigit(*s)) *res = (*res)*8+((*s++)-'0');
-		else { assert(0); }
-	}
-}
-
-SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; }
-
-
-#define MAX_HEX_DIGITS (sizeof(SQInteger)*2)
-SQInteger SQLexer::ReadNumber()
-{
-#define TINT 1
-#define TFLOAT 2
-#define THEX 3
-#define TSCIENTIFIC 4
-#define TOCTAL 5
-	SQInteger type = TINT, firstchar = CUR_CHAR;
-	SQChar *sTemp;
-	INIT_TEMP_STRING();
-	NEXT();
-	if(firstchar == _SC('0') && (toupper(CUR_CHAR) == _SC('X') || scisodigit(CUR_CHAR)) ) {
-		if(scisodigit(CUR_CHAR)) {
-			type = TOCTAL;
-			while(scisodigit(CUR_CHAR)) {
-				APPEND_CHAR(CUR_CHAR);
-				NEXT();
-			}
-			if(scisdigit(CUR_CHAR)) Error(_SC("invalid octal number"));
-		}
-		else {
-			NEXT();
-			type = THEX;
-			while(isxdigit(CUR_CHAR)) {
-				APPEND_CHAR(CUR_CHAR);
-				NEXT();
-			}
-			if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number"));
-		}
-	}
-	else {
-		APPEND_CHAR((int)firstchar);
-		while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) {
-            if(CUR_CHAR == _SC('.') || isexponent(CUR_CHAR)) 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],_longstr.size() - 1);
-	if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) {
-		_svalue = &_longstr[0];
-	}
-	return res;
-}
+/*
+    see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include <ctype.h>
+#include <stdlib.h>
+#include "sqtable.h"
+#include "sqstring.h"
+#include "sqcompiler.h"
+#include "sqlexer.h"
+
+#define CUR_CHAR (_currdata)
+#define RETURN_TOKEN(t) { _prevtoken = _curtoken; _curtoken = t; return t;}
+#define IS_EOB() (CUR_CHAR <= SQUIRREL_EOB)
+#define NEXT() {Next();_currentcolumn++;}
+#define INIT_TEMP_STRING() { _longstr.resize(0);}
+#define APPEND_CHAR(c) { _longstr.push_back(c);}
+#define TERMINATE_BUFFER() {_longstr.push_back(_SC('\0'));}
+#define ADD_KEYWORD(key,id) _keywords->NewSlot( SQString::Create(ss, _SC(#key)) ,SQInteger(id))
+
+SQLexer::SQLexer(){}
+SQLexer::~SQLexer()
+{
+    _keywords->Release();
+}
+
+void SQLexer::Init(SQSharedState *ss, SQLEXREADFUNC rg, SQUserPointer up,CompilerErrorFunc efunc,void *ed)
+{
+    _errfunc = efunc;
+    _errtarget = ed;
+    _sharedstate = ss;
+    _keywords = SQTable::Create(ss, 37);
+    ADD_KEYWORD(while, TK_WHILE);
+    ADD_KEYWORD(do, TK_DO);
+    ADD_KEYWORD(if, TK_IF);
+    ADD_KEYWORD(else, TK_ELSE);
+    ADD_KEYWORD(break, TK_BREAK);
+    ADD_KEYWORD(continue, TK_CONTINUE);
+    ADD_KEYWORD(return, TK_RETURN);
+    ADD_KEYWORD(null, TK_NULL);
+    ADD_KEYWORD(function, TK_FUNCTION);
+    ADD_KEYWORD(local, TK_LOCAL);
+    ADD_KEYWORD(for, TK_FOR);
+    ADD_KEYWORD(foreach, TK_FOREACH);
+    ADD_KEYWORD(in, TK_IN);
+    ADD_KEYWORD(typeof, TK_TYPEOF);
+    ADD_KEYWORD(base, TK_BASE);
+    ADD_KEYWORD(delete, TK_DELETE);
+    ADD_KEYWORD(try, TK_TRY);
+    ADD_KEYWORD(catch, TK_CATCH);
+    ADD_KEYWORD(throw, TK_THROW);
+    ADD_KEYWORD(clone, TK_CLONE);
+    ADD_KEYWORD(yield, TK_YIELD);
+    ADD_KEYWORD(resume, TK_RESUME);
+    ADD_KEYWORD(switch, TK_SWITCH);
+    ADD_KEYWORD(case, TK_CASE);
+    ADD_KEYWORD(default, TK_DEFAULT);
+    ADD_KEYWORD(this, TK_THIS);
+    ADD_KEYWORD(class,TK_CLASS);
+    ADD_KEYWORD(extends,TK_EXTENDS);
+    ADD_KEYWORD(constructor,TK_CONSTRUCTOR);
+    ADD_KEYWORD(instanceof,TK_INSTANCEOF);
+    ADD_KEYWORD(true,TK_TRUE);
+    ADD_KEYWORD(false,TK_FALSE);
+    ADD_KEYWORD(static,TK_STATIC);
+    ADD_KEYWORD(enum,TK_ENUM);
+    ADD_KEYWORD(const,TK_CONST);
+    ADD_KEYWORD(__LINE__,TK___LINE__);
+    ADD_KEYWORD(__FILE__,TK___FILE__);
+
+    _readf = rg;
+    _up = up;
+    _lasttokenline = _currentline = 1;
+    _currentcolumn = 0;
+    _prevtoken = -1;
+    _reached_eof = SQFalse;
+    Next();
+}
+
+void SQLexer::Error(const SQChar *err)
+{
+    _errfunc(_errtarget,err);
+}
+
+void SQLexer::Next()
+{
+    SQInteger t = _readf(_up);
+    if(t > MAX_CHAR) Error(_SC("Invalid character"));
+    if(t != 0) {
+        _currdata = (LexChar)t;
+        return;
+    }
+    _currdata = SQUIRREL_EOB;
+    _reached_eof = SQTrue;
+}
+
+const SQChar *SQLexer::Tok2Str(SQInteger tok)
+{
+    SQObjectPtr itr, key, val;
+    SQInteger nitr;
+    while((nitr = _keywords->Next(false,itr, key, val)) != -1) {
+        itr = (SQInteger)nitr;
+        if(((SQInteger)_integer(val)) == tok)
+            return _stringval(key);
+    }
+    return NULL;
+}
+
+void SQLexer::LexBlockComment()
+{
+    bool done = false;
+    while(!done) {
+        switch(CUR_CHAR) {
+            case _SC('*'): { NEXT(); if(CUR_CHAR == _SC('/')) { done = true; NEXT(); }}; continue;
+            case _SC('\n'): _currentline++; NEXT(); continue;
+            case SQUIRREL_EOB: Error(_SC("missing \"*/\" in comment"));
+            default: NEXT();
+        }
+    }
+}
+void SQLexer::LexLineComment()
+{
+    do { NEXT(); } while (CUR_CHAR != _SC('\n') && (!IS_EOB()));
+}
+
+SQInteger SQLexer::Lex()
+{
+    _lasttokenline = _currentline;
+    while(CUR_CHAR != SQUIRREL_EOB) {
+        switch(CUR_CHAR){
+        case _SC('\t'): case _SC('\r'): case _SC(' '): NEXT(); continue;
+        case _SC('\n'):
+            _currentline++;
+            _prevtoken=_curtoken;
+            _curtoken=_SC('\n');
+            NEXT();
+            _currentcolumn=1;
+            continue;
+        case _SC('#'): LexLineComment(); continue;
+        case _SC('/'):
+            NEXT();
+            switch(CUR_CHAR){
+            case _SC('*'):
+                NEXT();
+                LexBlockComment();
+                continue;
+            case _SC('/'):
+                LexLineComment();
+                continue;
+            case _SC('='):
+                NEXT();
+                RETURN_TOKEN(TK_DIVEQ);
+                continue;
+            case _SC('>'):
+                NEXT();
+                RETURN_TOKEN(TK_ATTR_CLOSE);
+                continue;
+            default:
+                RETURN_TOKEN('/');
+            }
+        case _SC('='):
+            NEXT();
+            if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('=') }
+            else { NEXT(); RETURN_TOKEN(TK_EQ); }
+        case _SC('<'):
+            NEXT();
+            switch(CUR_CHAR) {
+            case _SC('='):
+                NEXT();
+                if(CUR_CHAR == _SC('>')) {
+                    NEXT();
+                    RETURN_TOKEN(TK_3WAYSCMP);
+                }
+                RETURN_TOKEN(TK_LE)
+                break;
+            case _SC('-'): NEXT(); RETURN_TOKEN(TK_NEWSLOT); break;
+            case _SC('<'): NEXT(); RETURN_TOKEN(TK_SHIFTL); break;
+            case _SC('/'): NEXT(); RETURN_TOKEN(TK_ATTR_OPEN); break;
+            }
+            RETURN_TOKEN('<');
+        case _SC('>'):
+            NEXT();
+            if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_GE);}
+            else if(CUR_CHAR == _SC('>')){
+                NEXT();
+                if(CUR_CHAR == _SC('>')){
+                    NEXT();
+                    RETURN_TOKEN(TK_USHIFTR);
+                }
+                RETURN_TOKEN(TK_SHIFTR);
+            }
+            else { RETURN_TOKEN('>') }
+        case _SC('!'):
+            NEXT();
+            if (CUR_CHAR != _SC('=')){ RETURN_TOKEN('!')}
+            else { NEXT(); RETURN_TOKEN(TK_NE); }
+        case _SC('@'): {
+            SQInteger stype;
+            NEXT();
+            if(CUR_CHAR != _SC('"')) {
+                RETURN_TOKEN('@');
+            }
+            if((stype=ReadString('"',true))!=-1) {
+                RETURN_TOKEN(stype);
+            }
+            Error(_SC("error parsing the string"));
+                       }
+        case _SC('"'):
+        case _SC('\''): {
+            SQInteger stype;
+            if((stype=ReadString(CUR_CHAR,false))!=-1){
+                RETURN_TOKEN(stype);
+            }
+            Error(_SC("error parsing the string"));
+            }
+        case _SC('{'): case _SC('}'): case _SC('('): case _SC(')'): case _SC('['): case _SC(']'):
+        case _SC(';'): case _SC(','): case _SC('?'): case _SC('^'): case _SC('~'):
+            {SQInteger ret = CUR_CHAR;
+            NEXT(); RETURN_TOKEN(ret); }
+        case _SC('.'):
+            NEXT();
+            if (CUR_CHAR != _SC('.')){ RETURN_TOKEN('.') }
+            NEXT();
+            if (CUR_CHAR != _SC('.')){ Error(_SC("invalid token '..'")); }
+            NEXT();
+            RETURN_TOKEN(TK_VARPARAMS);
+        case _SC('&'):
+            NEXT();
+            if (CUR_CHAR != _SC('&')){ RETURN_TOKEN('&') }
+            else { NEXT(); RETURN_TOKEN(TK_AND); }
+        case _SC('|'):
+            NEXT();
+            if (CUR_CHAR != _SC('|')){ RETURN_TOKEN('|') }
+            else { NEXT(); RETURN_TOKEN(TK_OR); }
+        case _SC(':'):
+            NEXT();
+            if (CUR_CHAR != _SC(':')){ RETURN_TOKEN(':') }
+            else { NEXT(); RETURN_TOKEN(TK_DOUBLE_COLON); }
+        case _SC('*'):
+            NEXT();
+            if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MULEQ);}
+            else RETURN_TOKEN('*');
+        case _SC('%'):
+            NEXT();
+            if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MODEQ);}
+            else RETURN_TOKEN('%');
+        case _SC('-'):
+            NEXT();
+            if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_MINUSEQ);}
+            else if  (CUR_CHAR == _SC('-')){ NEXT(); RETURN_TOKEN(TK_MINUSMINUS);}
+            else RETURN_TOKEN('-');
+        case _SC('+'):
+            NEXT();
+            if (CUR_CHAR == _SC('=')){ NEXT(); RETURN_TOKEN(TK_PLUSEQ);}
+            else if (CUR_CHAR == _SC('+')){ NEXT(); RETURN_TOKEN(TK_PLUSPLUS);}
+            else RETURN_TOKEN('+');
+        case SQUIRREL_EOB:
+            return 0;
+        default:{
+                if (scisdigit(CUR_CHAR)) {
+                    SQInteger ret = ReadNumber();
+                    RETURN_TOKEN(ret);
+                }
+                else if (scisalpha(CUR_CHAR) || CUR_CHAR == _SC('_')) {
+                    SQInteger t = ReadID();
+                    RETURN_TOKEN(t);
+                }
+                else {
+                    SQInteger c = CUR_CHAR;
+                    if (sciscntrl((int)c)) Error(_SC("unexpected character(control)"));
+                    NEXT();
+                    RETURN_TOKEN(c);
+                }
+                RETURN_TOKEN(0);
+            }
+        }
+    }
+    return 0;
+}
+
+SQInteger SQLexer::GetIDType(const SQChar *s,SQInteger len)
+{
+    SQObjectPtr t;
+    if(_keywords->GetStr(s,len, t)) {
+        return SQInteger(_integer(t));
+    }
+    return TK_IDENTIFIER;
+}
+
+
+SQInteger SQLexer::ReadString(SQInteger ndelim,bool verbatim)
+{
+    INIT_TEMP_STRING();
+    NEXT();
+    if(IS_EOB()) return -1;
+    for(;;) {
+        while(CUR_CHAR != ndelim) {
+            switch(CUR_CHAR) {
+            case SQUIRREL_EOB:
+                Error(_SC("unfinished string"));
+                return -1;
+            case _SC('\n'):
+                if(!verbatim) Error(_SC("newline in a constant"));
+                APPEND_CHAR(CUR_CHAR); NEXT();
+                _currentline++;
+                break;
+            case _SC('\\'):
+                if(verbatim) {
+                    APPEND_CHAR('\\'); NEXT();
+                }
+                else {
+                    NEXT();
+                    switch(CUR_CHAR) {
+                    case _SC('x'): NEXT(); {
+                        if(!isxdigit(CUR_CHAR)) Error(_SC("hexadecimal number expected"));
+                        const SQInteger maxdigits = 4;
+                        SQChar temp[maxdigits+1];
+                        SQInteger n = 0;
+                        while(isxdigit(CUR_CHAR) && n < maxdigits) {
+                            temp[n] = CUR_CHAR;
+                            n++;
+                            NEXT();
+                        }
+                        temp[n] = 0;
+                        SQChar *sTemp;
+                        APPEND_CHAR((SQChar)scstrtoul(temp,&sTemp,16));
+                    }
+                    break;
+                    case _SC('t'): APPEND_CHAR(_SC('\t')); NEXT(); break;
+                    case _SC('a'): APPEND_CHAR(_SC('\a')); NEXT(); break;
+                    case _SC('b'): APPEND_CHAR(_SC('\b')); NEXT(); break;
+                    case _SC('n'): APPEND_CHAR(_SC('\n')); NEXT(); break;
+                    case _SC('r'): APPEND_CHAR(_SC('\r')); NEXT(); break;
+                    case _SC('v'): APPEND_CHAR(_SC('\v')); NEXT(); break;
+                    case _SC('f'): APPEND_CHAR(_SC('\f')); NEXT(); break;
+                    case _SC('0'): APPEND_CHAR(_SC('\0')); NEXT(); break;
+                    case _SC('\\'): APPEND_CHAR(_SC('\\')); NEXT(); break;
+                    case _SC('"'): APPEND_CHAR(_SC('"')); NEXT(); break;
+                    case _SC('\''): APPEND_CHAR(_SC('\'')); NEXT(); break;
+                    default:
+                        Error(_SC("unrecognised escaper char"));
+                    break;
+                    }
+                }
+                break;
+            default:
+                APPEND_CHAR(CUR_CHAR);
+                NEXT();
+            }
+        }
+        NEXT();
+        if(verbatim && CUR_CHAR == '"') { //double quotation
+            APPEND_CHAR(CUR_CHAR);
+            NEXT();
+        }
+        else {
+            break;
+        }
+    }
+    TERMINATE_BUFFER();
+    SQInteger len = _longstr.size()-1;
+    if(ndelim == _SC('\'')) {
+        if(len == 0) Error(_SC("empty constant"));
+        if(len > 1) Error(_SC("constant too long"));
+        _nvalue = _longstr[0];
+        return TK_INTEGER;
+    }
+    _svalue = &_longstr[0];
+    return TK_STRING_LITERAL;
+}
+
+void LexHexadecimal(const SQChar *s,SQUnsignedInteger *res)
+{
+    *res = 0;
+    while(*s != 0)
+    {
+        if(scisdigit(*s)) *res = (*res)*16+((*s++)-'0');
+        else if(scisxdigit(*s)) *res = (*res)*16+(toupper(*s++)-'A'+10);
+        else { assert(0); }
+    }
+}
+
+void LexInteger(const SQChar *s,SQUnsignedInteger *res)
+{
+    *res = 0;
+    while(*s != 0)
+    {
+        *res = (*res)*10+((*s++)-'0');
+    }
+}
+
+SQInteger scisodigit(SQInteger c) { return c >= _SC('0') && c <= _SC('7'); }
+
+void LexOctal(const SQChar *s,SQUnsignedInteger *res)
+{
+    *res = 0;
+    while(*s != 0)
+    {
+        if(scisodigit(*s)) *res = (*res)*8+((*s++)-'0');
+        else { assert(0); }
+    }
+}
+
+SQInteger isexponent(SQInteger c) { return c == 'e' || c=='E'; }
+
+
+#define MAX_HEX_DIGITS (sizeof(SQInteger)*2)
+SQInteger SQLexer::ReadNumber()
+{
+#define TINT 1
+#define TFLOAT 2
+#define THEX 3
+#define TSCIENTIFIC 4
+#define TOCTAL 5
+    SQInteger type = TINT, firstchar = CUR_CHAR;
+    SQChar *sTemp;
+    INIT_TEMP_STRING();
+    NEXT();
+    if(firstchar == _SC('0') && (toupper(CUR_CHAR) == _SC('X') || scisodigit(CUR_CHAR)) ) {
+        if(scisodigit(CUR_CHAR)) {
+            type = TOCTAL;
+            while(scisodigit(CUR_CHAR)) {
+                APPEND_CHAR(CUR_CHAR);
+                NEXT();
+            }
+            if(scisdigit(CUR_CHAR)) Error(_SC("invalid octal number"));
+        }
+        else {
+            NEXT();
+            type = THEX;
+            while(isxdigit(CUR_CHAR)) {
+                APPEND_CHAR(CUR_CHAR);
+                NEXT();
+            }
+            if(_longstr.size() > MAX_HEX_DIGITS) Error(_SC("too many digits for an Hex number"));
+        }
+    }
+    else {
+        APPEND_CHAR((int)firstchar);
+        while (CUR_CHAR == _SC('.') || scisdigit(CUR_CHAR) || isexponent(CUR_CHAR)) {
+            if(CUR_CHAR == _SC('.') || isexponent(CUR_CHAR)) 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],_longstr.size() - 1);
+    if(res == TK_IDENTIFIER || res == TK_CONSTRUCTOR) {
+        _svalue = &_longstr[0];
+    }
+    return res;
+}

+ 47 - 47
squirrel/sqlexer.h

@@ -1,47 +1,47 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQLEXER_H_
-#define _SQLEXER_H_
-
-#ifdef SQUNICODE
-typedef SQChar LexChar;
-#else
-typedef	unsigned char LexChar;
-#endif
-
-struct SQLexer
-{
-	SQLexer();
-	~SQLexer();
-	void Init(SQSharedState *ss,SQLEXREADFUNC rg,SQUserPointer up,CompilerErrorFunc efunc,void *ed);
-	void Error(const SQChar *err);
-	SQInteger Lex();
-	const SQChar *Tok2Str(SQInteger tok);
-private:
-	SQInteger GetIDType(const SQChar *s,SQInteger len);
-	SQInteger ReadString(SQInteger ndelim,bool verbatim);
-	SQInteger ReadNumber();
-	void LexBlockComment();
-	void LexLineComment();
-	SQInteger ReadID();
-	void Next();
-	SQInteger _curtoken;
-	SQTable *_keywords;
-	SQBool _reached_eof;
-public:
-	SQInteger _prevtoken;
-	SQInteger _currentline;
-	SQInteger _lasttokenline;
-	SQInteger _currentcolumn;
-	const SQChar *_svalue;
-	SQInteger _nvalue;
-	SQFloat _fvalue;
-	SQLEXREADFUNC _readf;
-	SQUserPointer _up;
-	LexChar _currdata;
-	SQSharedState *_sharedstate;
-	sqvector<SQChar> _longstr;
-	CompilerErrorFunc _errfunc;
-	void *_errtarget;
-};
-
-#endif
+/*  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(const SQChar *s,SQInteger len);
+    SQInteger ReadString(SQInteger ndelim,bool verbatim);
+    SQInteger ReadNumber();
+    void LexBlockComment();
+    void LexLineComment();
+    SQInteger ReadID();
+    void Next();
+    SQInteger _curtoken;
+    SQTable *_keywords;
+    SQBool _reached_eof;
+public:
+    SQInteger _prevtoken;
+    SQInteger _currentline;
+    SQInteger _lasttokenline;
+    SQInteger _currentcolumn;
+    const SQChar *_svalue;
+    SQInteger _nvalue;
+    SQFloat _fvalue;
+    SQLEXREADFUNC _readf;
+    SQUserPointer _up;
+    LexChar _currdata;
+    SQSharedState *_sharedstate;
+    sqvector<SQChar> _longstr;
+    CompilerErrorFunc _errfunc;
+    void *_errtarget;
+};
+
+#endif

+ 11 - 11
squirrel/sqmem.cpp

@@ -1,11 +1,11 @@
-/*
-	see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#ifndef SQ_EXCLUDE_DEFAULT_MEMFUNCTIONS
-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); }
-#endif
+/*
+    see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#ifndef SQ_EXCLUDE_DEFAULT_MEMFUNCTIONS
+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); }
+#endif

+ 677 - 677
squirrel/sqobject.cpp

@@ -1,677 +1,677 @@
-/*
-	see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include "sqvm.h"
-#include "sqstring.h"
-#include "sqarray.h"
-#include "sqtable.h"
-#include "squserdata.h"
-#include "sqfuncproto.h"
-#include "sqclass.h"
-#include "sqclosure.h"
-
-
-const SQChar *IdType2Name(SQObjectType type)
-{
-	switch(_RAW_TYPE(type))
-	{
-	case _RT_NULL:return _SC("null");
-	case _RT_INTEGER:return _SC("integer");
-	case _RT_FLOAT:return _SC("float");
-	case _RT_BOOL:return _SC("bool");
-	case _RT_STRING:return _SC("string");
-	case _RT_TABLE:return _SC("table");
-	case _RT_ARRAY:return _SC("array");
-	case _RT_GENERATOR:return _SC("generator");
-	case _RT_CLOSURE:
-	case _RT_NATIVECLOSURE:
-		return _SC("function");
-	case _RT_USERDATA:
-	case _RT_USERPOINTER:
-		return _SC("userdata");
-	case _RT_THREAD: return _SC("thread");
-	case _RT_FUNCPROTO: return _SC("function");
-	case _RT_CLASS: return _SC("class");
-	case _RT_INSTANCE: return _SC("instance");
-	case _RT_WEAKREF: return _SC("weakref");
-	case _RT_OUTER: return _SC("outer");
-	default:
-		return NULL;
-	}
-}
-
-const SQChar *GetTypeName(const SQObjectPtr &obj1)
-{
-	return IdType2Name(type(obj1));	
-}
-
-SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)
-{
-	SQString *str=ADD_STRING(ss,s,len);
-	return str;
-}
-
-void SQString::Release()
-{
-	REMOVE_STRING(_sharedstate,this);
-}
-
-SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
-{
-	SQInteger idx = (SQInteger)TranslateIndex(refpos);
-	while(idx < _len){
-		outkey = (SQInteger)idx;
-		outval = (SQInteger)((SQUnsignedInteger)_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);
-#if defined(SQUSEDOUBLE) && !defined(_SQ64)
-        _weakref->_obj._unVal.raw = 0; //clean the whole union on 32 bits with double
-#endif
-		_weakref->_obj._type = type;
-		_weakref->_obj._unVal.pRefCounted = this;
-	}
-	return _weakref;
-}
-
-SQRefCounted::~SQRefCounted()
-{
-	if(_weakref) {
-		_weakref->_obj._type = OT_NULL;
-		_weakref->_obj._unVal.pRefCounted = NULL;
-	}
-}
-
-void SQWeakRef::Release() { 
-	if(ISREFCOUNTED(_obj._type)) { 
-		_obj._unVal.pRefCounted->_weakref = NULL;
-	} 
-	sq_delete(this,SQWeakRef);
-}
-
-bool SQDelegable::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) {
-	if(_delegate) {
-		return _delegate->Get((*_ss(v)->_metamethods)[mm],res);
-	}
-	return false;
-}
-
-bool SQDelegable::SetDelegate(SQTable *mt)
-{
-	SQTable *temp = mt;
-	if(temp == this) return false;
-	while (temp) {
-		if (temp->_delegate == this) return false; //cycle detected
-		temp = temp->_delegate;
-	}
-	if (mt)	__ObjAddRef(mt);
-	__ObjRelease(_delegate);
-	_delegate = mt;
-	return true;
-}
-
-bool SQGenerator::Yield(SQVM *v,SQInteger target)
-{
-	if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator"));  return false;}
-	if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }
-	SQInteger size = v->_top-v->_stackbase;
-	
-	_stack.resize(size);
-	SQObject _this = v->_stack[v->_stackbase];
-	_stack._vals[0] = ISREFCOUNTED(type(_this)) ? SQObjectPtr(_refcounted(_this)->GetWeakRef(type(_this))) : _this;
-	for(SQInteger n =1; n<target; n++) {
-		_stack._vals[n] = v->_stack[v->_stackbase+n];
-	}
-	for(SQInteger j =0; j < size; j++)
-	{
-		v->_stack[v->_stackbase+j].Null();
-	}
-
-	_ci = *v->ci;
-	_ci._generator=NULL;
-	for(SQInteger i=0;i<_ci._etraps;i++) {
-		_etraps.push_back(v->_etraps.top());
-		v->_etraps.pop_back();
-		// store relative stack base and size in case of resume to other _top
-		SQExceptionTrap &et = _etraps.back();
-		et._stackbase -= v->_stackbase;
-		et._stacksize -= v->_stackbase;
-	}
-	_state=eSuspended;
-	return true;
-}
-
-bool SQGenerator::Resume(SQVM *v,SQObjectPtr &dest)
-{
-	if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }
-	if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }
-	SQInteger size = _stack.size();
-	SQInteger target = &dest - &(v->_stack._vals[v->_stackbase]);
-	assert(target>=0 && target<=255);
-	SQInteger newbase = v->_top;
-	if(!v->EnterFrame(v->_top, v->_top + size, false)) 
-		return false;
-	v->ci->_generator   = this;
-	v->ci->_target      = (SQInt32)target;
-	v->ci->_closure     = _ci._closure;
-	v->ci->_ip          = _ci._ip;
-	v->ci->_literals    = _ci._literals;
-	v->ci->_ncalls      = _ci._ncalls;
-	v->ci->_etraps      = _ci._etraps;
-	v->ci->_root        = _ci._root;
-
-
-	for(SQInteger i=0;i<_ci._etraps;i++) {
-		v->_etraps.push_back(_etraps.top());
-		_etraps.pop_back();
-		SQExceptionTrap &et = v->_etraps.back();
-		// restore absolute stack base and size
-		et._stackbase += newbase;
-		et._stacksize += newbase;
-	}
-	SQObject _this = _stack._vals[0];
-	v->_stack[v->_stackbase] = type(_this) == OT_WEAKREF ? _weakref(_this)->_obj : _this;
-
-	for(SQInteger n = 1; n<size; n++) {
-		v->_stack[v->_stackbase+n] = _stack._vals[n];
-		_stack._vals[n].Null();
-	}
-
-	_state=eRunning;
-	if (v->_debughook)
-		v->CallDebugHook(_SC('c'));
-
-	return true;
-}
-
-void SQArray::Extend(const SQArray *a){
-	SQInteger xlen;
-	if((xlen=a->Size()))
-		for(SQInteger i=0;i<xlen;i++)
-			Append(a->_values[i]);
-}
-
-const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop)
-{
-	SQUnsignedInteger nvars=_nlocalvarinfos;
-	const SQChar *res=NULL; 
-	if(nvars>=nseq){
- 		for(SQUnsignedInteger i=0;i<nvars;i++){
-			if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)
-			{
-				if(nseq==0){
-					vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]);
-					res=_stringval(_localvarinfos[i]._name);
-					break;
-				}
-				nseq--;
-			}
-		}
-	}
-	return res;
-}
-
-
-SQInteger SQFunctionProto::GetLine(SQInstruction *curr)
-{
-	SQInteger op = (SQInteger)(curr-_instructions);
-	SQInteger line=_lineinfos[0]._line;
-	SQInteger low = 0;
-	SQInteger high = _nlineinfos - 1;
-	SQInteger mid = 0;
-	while(low <= high)
-	{
-		mid = low + ((high - low) >> 1);
-		SQInteger curop = _lineinfos[mid]._op;
-		if(curop > op)
-		{
-			high = mid - 1;
-		}
-		else if(curop < op) {
-			if(mid < (_nlineinfos - 1) 
-				&& _lineinfos[mid + 1]._op >= op) {
-				break;
-			}
-			low = mid + 1;
-		}
-		else { //equal
-			break;
-		}
-	}
-	
-	while(mid > 0 && _lineinfos[mid]._op >= op) mid--;
-	
-	line = _lineinfos[mid]._line;
-
-	return line;
-}
-
-SQClosure::~SQClosure()
-{
-	__ObjRelease(_root);
-	__ObjRelease(_env);
-	__ObjRelease(_base);
-	REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
-}
-
-#define _CHECK_IO(exp)  { if(!exp)return false; }
-bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size)
-{
-	if(write(up,dest,size) != size) {
-		v->Raise_Error(_SC("io error (write function failure)"));
-		return false;
-	}
-	return true;
-}
-
-bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,SQInteger size)
-{
-	if(size && read(up,dest,size) != size) {
-		v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));
-		return false;
-	}
-	return true;
-}
-
-bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUnsignedInteger32 tag)
-{
-	return SafeWrite(v,write,up,&tag,sizeof(tag));
-}
-
-bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUnsignedInteger32 tag)
-{
-	SQUnsignedInteger32 t;
-	_CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));
-	if(t != tag){
-		v->Raise_Error(_SC("invalid or corrupted closure stream"));
-		return false;
-	}
-	return true;
-}
-
-bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)
-{
-	SQUnsignedInteger32 _type = (SQUnsignedInteger32)type(o);
-	_CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type)));
-	switch(type(o)){
-	case OT_STRING:
-		_CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));
-		_CHECK_IO(SafeWrite(v,write,up,_stringval(o),sq_rsl(_string(o)->_len)));
-		break;
-	case OT_BOOL:
-	case OT_INTEGER:
-		_CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;
-	case OT_FLOAT:
-		_CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break;
-	case OT_NULL:
-		break;
-	default:
-		v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o));
-		return false;
-	}
-	return true;
-}
-
-bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
-{
-	SQUnsignedInteger32 _type;
-	_CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type)));
-	SQObjectType t = (SQObjectType)_type;
-	switch(t){
-	case OT_STRING:{
-		SQInteger len;
-		_CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger)));
-		_CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(sq_rsl(len)),sq_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_BOOL:{
-		SQInteger i;
-		_CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o._type = OT_BOOL; o._unVal.nInteger = i; break;
-					}
-	case OT_FLOAT:{
-		SQFloat f;
-		_CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;
-				  }
-	case OT_NULL:
-		o.Null();
-		break;
-	default:
-		v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));
-		return false;
-	}
-	return true;
-}
-
-bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
-{
-	_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));
-	_CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));
-	_CHECK_IO(WriteTag(v,write,up,sizeof(SQInteger)));
-	_CHECK_IO(WriteTag(v,write,up,sizeof(SQFloat)));
-	_CHECK_IO(_function->Save(v,up,write));
-	_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));
-	return true;
-}
-
-bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
-{
-	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));
-	_CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));
-	_CHECK_IO(CheckTag(v,read,up,sizeof(SQInteger)));
-	_CHECK_IO(CheckTag(v,read,up,sizeof(SQFloat)));
-	SQObjectPtr func;
-	_CHECK_IO(SQFunctionProto::Load(v,up,read,func));
-	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));
-	ret = SQClosure::Create(_ss(v),_funcproto(func),_table(v->_roottable)->GetWeakRef(OT_TABLE));
-	//FIXME: load an root for this closure
-	return true;
-}
-
-SQFunctionProto::SQFunctionProto(SQSharedState *ss)
-{
-	_stacksize=0;
-	_bgenerator=false;
-	INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);
-}
-
-SQFunctionProto::~SQFunctionProto()
-{
-	REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
-}
-
-bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
-{
-	SQInteger i,nliterals = _nliterals,nparameters = _nparameters;
-	SQInteger noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos;
-	SQInteger nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions;
-	SQInteger ndefaultparams = _ndefaultparams;
-	_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
-	_CHECK_IO(WriteObject(v,up,write,_sourcename));
-	_CHECK_IO(WriteObject(v,up,write,_name));
-	_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
-	_CHECK_IO(SafeWrite(v,write,up,&nliterals,sizeof(nliterals)));
-	_CHECK_IO(SafeWrite(v,write,up,&nparameters,sizeof(nparameters)));
-	_CHECK_IO(SafeWrite(v,write,up,&noutervalues,sizeof(noutervalues)));
-	_CHECK_IO(SafeWrite(v,write,up,&nlocalvarinfos,sizeof(nlocalvarinfos)));
-	_CHECK_IO(SafeWrite(v,write,up,&nlineinfos,sizeof(nlineinfos)));
-	_CHECK_IO(SafeWrite(v,write,up,&ndefaultparams,sizeof(ndefaultparams)));
-	_CHECK_IO(SafeWrite(v,write,up,&ninstructions,sizeof(ninstructions)));
-	_CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions)));
-	_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
-	for(i=0;i<nliterals;i++){
-		_CHECK_IO(WriteObject(v,up,write,_literals[i]));
-	}
-
-	_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
-	for(i=0;i<nparameters;i++){
-		_CHECK_IO(WriteObject(v,up,write,_parameters[i]));
-	}
-
-	_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
-	for(i=0;i<noutervalues;i++){
-		_CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(SQUnsignedInteger)));
-		_CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));
-		_CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));
-	}
-
-	_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
-	for(i=0;i<nlocalvarinfos;i++){
-		SQLocalVarInfo &lvi=_localvarinfos[i];
-		_CHECK_IO(WriteObject(v,up,write,lvi._name));
-		_CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(SQUnsignedInteger)));
-		_CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(SQUnsignedInteger)));
-		_CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(SQUnsignedInteger)));
-	}
-
-	_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
-	_CHECK_IO(SafeWrite(v,write,up,_lineinfos,sizeof(SQLineInfo)*nlineinfos));
-
-	_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
-	_CHECK_IO(SafeWrite(v,write,up,_defaultparams,sizeof(SQInteger)*ndefaultparams));
-
-	_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
-	_CHECK_IO(SafeWrite(v,write,up,_instructions,sizeof(SQInstruction)*ninstructions));
-
-	_CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
-	for(i=0;i<nfunctions;i++){
-		_CHECK_IO(_funcproto(_functions[i])->Save(v,up,write));
-	}
-	_CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));
-	_CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));
-	_CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));
-	return true;
-}
-
-bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
-{
-	SQInteger i, nliterals,nparameters;
-	SQInteger noutervalues ,nlocalvarinfos ;
-	SQInteger nlineinfos,ninstructions ,nfunctions,ndefaultparams ;
-	SQObjectPtr sourcename, name;
-	SQObjectPtr o;
-	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-	_CHECK_IO(ReadObject(v, up, read, sourcename));
-	_CHECK_IO(ReadObject(v, up, read, name));
-	
-	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-	_CHECK_IO(SafeRead(v,read,up, &nliterals, sizeof(nliterals)));
-	_CHECK_IO(SafeRead(v,read,up, &nparameters, sizeof(nparameters)));
-	_CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues)));
-	_CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos)));
-	_CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos)));
-	_CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams)));
-	_CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions)));
-	_CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));
-	
-
-	SQFunctionProto *f = SQFunctionProto::Create(_opt_ss(v),ninstructions,nliterals,nparameters,
-			nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);
-	SQObjectPtr proto = f; //gets a ref in case of failure
-	f->_sourcename = sourcename;
-	f->_name = name;
-
-	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-
-	for(i = 0;i < nliterals; i++){
-		_CHECK_IO(ReadObject(v, up, read, o));
-		f->_literals[i] = o;
-	}
-	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-
-	for(i = 0; i < nparameters; i++){
-		_CHECK_IO(ReadObject(v, up, read, o));
-		f->_parameters[i] = o;
-	}
-	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-
-	for(i = 0; i < noutervalues; i++){
-		SQUnsignedInteger type;
-		SQObjectPtr name;
-		_CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger)));
-		_CHECK_IO(ReadObject(v, up, read, o));
-		_CHECK_IO(ReadObject(v, up, read, name));
-		f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type);
-	}
-	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-
-	for(i = 0; i < nlocalvarinfos; i++){
-		SQLocalVarInfo lvi;
-		_CHECK_IO(ReadObject(v, up, read, lvi._name));
-		_CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(SQUnsignedInteger)));
-		_CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(SQUnsignedInteger)));
-		_CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(SQUnsignedInteger)));
-		f->_localvarinfos[i] = lvi;
-	}
-	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-	_CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(SQLineInfo)*nlineinfos));
-
-	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-	_CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(SQInteger)*ndefaultparams));
-
-	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-	_CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(SQInstruction)*ninstructions));
-
-	_CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
-	for(i = 0; i < nfunctions; i++){
-		_CHECK_IO(_funcproto(o)->Load(v, up, read, o));
-		f->_functions[i] = o;
-	}
-	_CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize)));
-	_CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator)));
-	_CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams)));
-	
-	ret = f;
-	return true;
-}
-
-#ifndef NO_GARBAGE_COLLECTOR
-
-#define START_MARK() 	if(!(_uiRef&MARK_FLAG)){ \
-		_uiRef|=MARK_FLAG;
-
-#define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \
-		AddToChain(chain, this); }
-
-void SQVM::Mark(SQCollectable **chain)
-{
-	START_MARK()
-		SQSharedState::MarkObject(_lasterror,chain);
-		SQSharedState::MarkObject(_errorhandler,chain);
-		SQSharedState::MarkObject(_debughook_closure,chain);
-		SQSharedState::MarkObject(_roottable, chain);
-		SQSharedState::MarkObject(temp_reg, chain);
-		for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
-		for(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain);
-	END_MARK()
-}
-
-void SQArray::Mark(SQCollectable **chain)
-{
-	START_MARK()
-		SQInteger len = _values.size();
-		for(SQInteger i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain);
-	END_MARK()
-}
-void SQTable::Mark(SQCollectable **chain)
-{
-	START_MARK()
-		if(_delegate) _delegate->Mark(chain);
-		SQInteger len = _numofnodes;
-		for(SQInteger i = 0; i < len; i++){
-			SQSharedState::MarkObject(_nodes[i].key, chain);
-			SQSharedState::MarkObject(_nodes[i].val, chain);
-		}
-	END_MARK()
-}
-
-void SQClass::Mark(SQCollectable **chain)
-{
-	START_MARK()
-		_members->Mark(chain);
-		if(_base) _base->Mark(chain);
-		SQSharedState::MarkObject(_attributes, chain);
-		for(SQUnsignedInteger i =0; i< _defaultvalues.size(); i++) {
-			SQSharedState::MarkObject(_defaultvalues[i].val, chain);
-			SQSharedState::MarkObject(_defaultvalues[i].attrs, chain);
-		}
-		for(SQUnsignedInteger j =0; j< _methods.size(); j++) {
-			SQSharedState::MarkObject(_methods[j].val, chain);
-			SQSharedState::MarkObject(_methods[j].attrs, chain);
-		}
-		for(SQUnsignedInteger k =0; k< MT_LAST; k++) {
-			SQSharedState::MarkObject(_metamethods[k], chain);
-		}
-	END_MARK()
-}
-
-void SQInstance::Mark(SQCollectable **chain)
-{
-	START_MARK()
-		_class->Mark(chain);
-		SQUnsignedInteger nvalues = _class->_defaultvalues.size();
-		for(SQUnsignedInteger i =0; i< nvalues; i++) {
-			SQSharedState::MarkObject(_values[i], chain);
-		}
-	END_MARK()
-}
-
-void SQGenerator::Mark(SQCollectable **chain)
-{
-	START_MARK()
-		for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
-		SQSharedState::MarkObject(_closure, chain);
-	END_MARK()
-}
-
-void SQFunctionProto::Mark(SQCollectable **chain)
-{
-	START_MARK()
-		for(SQInteger i = 0; i < _nliterals; i++) SQSharedState::MarkObject(_literals[i], chain);
-		for(SQInteger k = 0; k < _nfunctions; k++) SQSharedState::MarkObject(_functions[k], chain);
-	END_MARK()
-}
-
-void SQClosure::Mark(SQCollectable **chain)
-{
-	START_MARK()
-		if(_base) _base->Mark(chain);
-		SQFunctionProto *fp = _function;
-		fp->Mark(chain);
-		for(SQInteger i = 0; i < fp->_noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain);
-		for(SQInteger k = 0; k < fp->_ndefaultparams; k++) SQSharedState::MarkObject(_defaultparams[k], chain);
-	END_MARK()
-}
-
-void SQNativeClosure::Mark(SQCollectable **chain)
-{
-	START_MARK()
-		for(SQUnsignedInteger i = 0; i < _noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain);
-	END_MARK()
-}
-
-void SQOuter::Mark(SQCollectable **chain)
-{
-	START_MARK()
-    /* If the valptr points to a closed value, that value is alive */
-    if(_valptr == &_value) {
-      SQSharedState::MarkObject(_value, chain);
-    }
-	END_MARK()
-}
-
-void SQUserData::Mark(SQCollectable **chain){
-	START_MARK()
-		if(_delegate) _delegate->Mark(chain);
-	END_MARK()
-}
-
-void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; }
-
-#endif
-
+/*
+    see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqvm.h"
+#include "sqstring.h"
+#include "sqarray.h"
+#include "sqtable.h"
+#include "squserdata.h"
+#include "sqfuncproto.h"
+#include "sqclass.h"
+#include "sqclosure.h"
+
+
+const SQChar *IdType2Name(SQObjectType type)
+{
+    switch(_RAW_TYPE(type))
+    {
+    case _RT_NULL:return _SC("null");
+    case _RT_INTEGER:return _SC("integer");
+    case _RT_FLOAT:return _SC("float");
+    case _RT_BOOL:return _SC("bool");
+    case _RT_STRING:return _SC("string");
+    case _RT_TABLE:return _SC("table");
+    case _RT_ARRAY:return _SC("array");
+    case _RT_GENERATOR:return _SC("generator");
+    case _RT_CLOSURE:
+    case _RT_NATIVECLOSURE:
+        return _SC("function");
+    case _RT_USERDATA:
+    case _RT_USERPOINTER:
+        return _SC("userdata");
+    case _RT_THREAD: return _SC("thread");
+    case _RT_FUNCPROTO: return _SC("function");
+    case _RT_CLASS: return _SC("class");
+    case _RT_INSTANCE: return _SC("instance");
+    case _RT_WEAKREF: return _SC("weakref");
+    case _RT_OUTER: return _SC("outer");
+    default:
+        return NULL;
+    }
+}
+
+const SQChar *GetTypeName(const SQObjectPtr &obj1)
+{
+    return IdType2Name(type(obj1));
+}
+
+SQString *SQString::Create(SQSharedState *ss,const SQChar *s,SQInteger len)
+{
+    SQString *str=ADD_STRING(ss,s,len);
+    return str;
+}
+
+void SQString::Release()
+{
+    REMOVE_STRING(_sharedstate,this);
+}
+
+SQInteger SQString::Next(const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
+{
+    SQInteger idx = (SQInteger)TranslateIndex(refpos);
+    while(idx < _len){
+        outkey = (SQInteger)idx;
+        outval = (SQInteger)((SQUnsignedInteger)_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);
+#if defined(SQUSEDOUBLE) && !defined(_SQ64)
+        _weakref->_obj._unVal.raw = 0; //clean the whole union on 32 bits with double
+#endif
+        _weakref->_obj._type = type;
+        _weakref->_obj._unVal.pRefCounted = this;
+    }
+    return _weakref;
+}
+
+SQRefCounted::~SQRefCounted()
+{
+    if(_weakref) {
+        _weakref->_obj._type = OT_NULL;
+        _weakref->_obj._unVal.pRefCounted = NULL;
+    }
+}
+
+void SQWeakRef::Release() {
+    if(ISREFCOUNTED(_obj._type)) {
+        _obj._unVal.pRefCounted->_weakref = NULL;
+    }
+    sq_delete(this,SQWeakRef);
+}
+
+bool SQDelegable::GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res) {
+    if(_delegate) {
+        return _delegate->Get((*_ss(v)->_metamethods)[mm],res);
+    }
+    return false;
+}
+
+bool SQDelegable::SetDelegate(SQTable *mt)
+{
+    SQTable *temp = mt;
+    if(temp == this) return false;
+    while (temp) {
+        if (temp->_delegate == this) return false; //cycle detected
+        temp = temp->_delegate;
+    }
+    if (mt) __ObjAddRef(mt);
+    __ObjRelease(_delegate);
+    _delegate = mt;
+    return true;
+}
+
+bool SQGenerator::Yield(SQVM *v,SQInteger target)
+{
+    if(_state==eSuspended) { v->Raise_Error(_SC("internal vm error, yielding dead generator"));  return false;}
+    if(_state==eDead) { v->Raise_Error(_SC("internal vm error, yielding a dead generator")); return false; }
+    SQInteger size = v->_top-v->_stackbase;
+
+    _stack.resize(size);
+    SQObject _this = v->_stack[v->_stackbase];
+    _stack._vals[0] = ISREFCOUNTED(type(_this)) ? SQObjectPtr(_refcounted(_this)->GetWeakRef(type(_this))) : _this;
+    for(SQInteger n =1; n<target; n++) {
+        _stack._vals[n] = v->_stack[v->_stackbase+n];
+    }
+    for(SQInteger j =0; j < size; j++)
+    {
+        v->_stack[v->_stackbase+j].Null();
+    }
+
+    _ci = *v->ci;
+    _ci._generator=NULL;
+    for(SQInteger i=0;i<_ci._etraps;i++) {
+        _etraps.push_back(v->_etraps.top());
+        v->_etraps.pop_back();
+        // store relative stack base and size in case of resume to other _top
+        SQExceptionTrap &et = _etraps.back();
+        et._stackbase -= v->_stackbase;
+        et._stacksize -= v->_stackbase;
+    }
+    _state=eSuspended;
+    return true;
+}
+
+bool SQGenerator::Resume(SQVM *v,SQObjectPtr &dest)
+{
+    if(_state==eDead){ v->Raise_Error(_SC("resuming dead generator")); return false; }
+    if(_state==eRunning){ v->Raise_Error(_SC("resuming active generator")); return false; }
+    SQInteger size = _stack.size();
+    SQInteger target = &dest - &(v->_stack._vals[v->_stackbase]);
+    assert(target>=0 && target<=255);
+    SQInteger newbase = v->_top;
+    if(!v->EnterFrame(v->_top, v->_top + size, false))
+        return false;
+    v->ci->_generator   = this;
+    v->ci->_target      = (SQInt32)target;
+    v->ci->_closure     = _ci._closure;
+    v->ci->_ip          = _ci._ip;
+    v->ci->_literals    = _ci._literals;
+    v->ci->_ncalls      = _ci._ncalls;
+    v->ci->_etraps      = _ci._etraps;
+    v->ci->_root        = _ci._root;
+
+
+    for(SQInteger i=0;i<_ci._etraps;i++) {
+        v->_etraps.push_back(_etraps.top());
+        _etraps.pop_back();
+        SQExceptionTrap &et = v->_etraps.back();
+        // restore absolute stack base and size
+        et._stackbase += newbase;
+        et._stacksize += newbase;
+    }
+    SQObject _this = _stack._vals[0];
+    v->_stack[v->_stackbase] = type(_this) == OT_WEAKREF ? _weakref(_this)->_obj : _this;
+
+    for(SQInteger n = 1; n<size; n++) {
+        v->_stack[v->_stackbase+n] = _stack._vals[n];
+        _stack._vals[n].Null();
+    }
+
+    _state=eRunning;
+    if (v->_debughook)
+        v->CallDebugHook(_SC('c'));
+
+    return true;
+}
+
+void SQArray::Extend(const SQArray *a){
+    SQInteger xlen;
+    if((xlen=a->Size()))
+        for(SQInteger i=0;i<xlen;i++)
+            Append(a->_values[i]);
+}
+
+const SQChar* SQFunctionProto::GetLocal(SQVM *vm,SQUnsignedInteger stackbase,SQUnsignedInteger nseq,SQUnsignedInteger nop)
+{
+    SQUnsignedInteger nvars=_nlocalvarinfos;
+    const SQChar *res=NULL;
+    if(nvars>=nseq){
+        for(SQUnsignedInteger i=0;i<nvars;i++){
+            if(_localvarinfos[i]._start_op<=nop && _localvarinfos[i]._end_op>=nop)
+            {
+                if(nseq==0){
+                    vm->Push(vm->_stack[stackbase+_localvarinfos[i]._pos]);
+                    res=_stringval(_localvarinfos[i]._name);
+                    break;
+                }
+                nseq--;
+            }
+        }
+    }
+    return res;
+}
+
+
+SQInteger SQFunctionProto::GetLine(SQInstruction *curr)
+{
+    SQInteger op = (SQInteger)(curr-_instructions);
+    SQInteger line=_lineinfos[0]._line;
+    SQInteger low = 0;
+    SQInteger high = _nlineinfos - 1;
+    SQInteger mid = 0;
+    while(low <= high)
+    {
+        mid = low + ((high - low) >> 1);
+        SQInteger curop = _lineinfos[mid]._op;
+        if(curop > op)
+        {
+            high = mid - 1;
+        }
+        else if(curop < op) {
+            if(mid < (_nlineinfos - 1)
+                && _lineinfos[mid + 1]._op >= op) {
+                break;
+            }
+            low = mid + 1;
+        }
+        else { //equal
+            break;
+        }
+    }
+
+    while(mid > 0 && _lineinfos[mid]._op >= op) mid--;
+
+    line = _lineinfos[mid]._line;
+
+    return line;
+}
+
+SQClosure::~SQClosure()
+{
+    __ObjRelease(_root);
+    __ObjRelease(_env);
+    __ObjRelease(_base);
+    REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+}
+
+#define _CHECK_IO(exp)  { if(!exp)return false; }
+bool SafeWrite(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUserPointer dest,SQInteger size)
+{
+    if(write(up,dest,size) != size) {
+        v->Raise_Error(_SC("io error (write function failure)"));
+        return false;
+    }
+    return true;
+}
+
+bool SafeRead(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUserPointer dest,SQInteger size)
+{
+    if(size && read(up,dest,size) != size) {
+        v->Raise_Error(_SC("io error, read function failure, the origin stream could be corrupted/trucated"));
+        return false;
+    }
+    return true;
+}
+
+bool WriteTag(HSQUIRRELVM v,SQWRITEFUNC write,SQUserPointer up,SQUnsignedInteger32 tag)
+{
+    return SafeWrite(v,write,up,&tag,sizeof(tag));
+}
+
+bool CheckTag(HSQUIRRELVM v,SQWRITEFUNC read,SQUserPointer up,SQUnsignedInteger32 tag)
+{
+    SQUnsignedInteger32 t;
+    _CHECK_IO(SafeRead(v,read,up,&t,sizeof(t)));
+    if(t != tag){
+        v->Raise_Error(_SC("invalid or corrupted closure stream"));
+        return false;
+    }
+    return true;
+}
+
+bool WriteObject(HSQUIRRELVM v,SQUserPointer up,SQWRITEFUNC write,SQObjectPtr &o)
+{
+    SQUnsignedInteger32 _type = (SQUnsignedInteger32)type(o);
+    _CHECK_IO(SafeWrite(v,write,up,&_type,sizeof(_type)));
+    switch(type(o)){
+    case OT_STRING:
+        _CHECK_IO(SafeWrite(v,write,up,&_string(o)->_len,sizeof(SQInteger)));
+        _CHECK_IO(SafeWrite(v,write,up,_stringval(o),sq_rsl(_string(o)->_len)));
+        break;
+    case OT_BOOL:
+    case OT_INTEGER:
+        _CHECK_IO(SafeWrite(v,write,up,&_integer(o),sizeof(SQInteger)));break;
+    case OT_FLOAT:
+        _CHECK_IO(SafeWrite(v,write,up,&_float(o),sizeof(SQFloat)));break;
+    case OT_NULL:
+        break;
+    default:
+        v->Raise_Error(_SC("cannot serialize a %s"),GetTypeName(o));
+        return false;
+    }
+    return true;
+}
+
+bool ReadObject(HSQUIRRELVM v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &o)
+{
+    SQUnsignedInteger32 _type;
+    _CHECK_IO(SafeRead(v,read,up,&_type,sizeof(_type)));
+    SQObjectType t = (SQObjectType)_type;
+    switch(t){
+    case OT_STRING:{
+        SQInteger len;
+        _CHECK_IO(SafeRead(v,read,up,&len,sizeof(SQInteger)));
+        _CHECK_IO(SafeRead(v,read,up,_ss(v)->GetScratchPad(sq_rsl(len)),sq_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_BOOL:{
+        SQInteger i;
+        _CHECK_IO(SafeRead(v,read,up,&i,sizeof(SQInteger))); o._type = OT_BOOL; o._unVal.nInteger = i; break;
+                    }
+    case OT_FLOAT:{
+        SQFloat f;
+        _CHECK_IO(SafeRead(v,read,up,&f,sizeof(SQFloat))); o = f; break;
+                  }
+    case OT_NULL:
+        o.Null();
+        break;
+    default:
+        v->Raise_Error(_SC("cannot serialize a %s"),IdType2Name(t));
+        return false;
+    }
+    return true;
+}
+
+bool SQClosure::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
+{
+    _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_HEAD));
+    _CHECK_IO(WriteTag(v,write,up,sizeof(SQChar)));
+    _CHECK_IO(WriteTag(v,write,up,sizeof(SQInteger)));
+    _CHECK_IO(WriteTag(v,write,up,sizeof(SQFloat)));
+    _CHECK_IO(_function->Save(v,up,write));
+    _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_TAIL));
+    return true;
+}
+
+bool SQClosure::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
+{
+    _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_HEAD));
+    _CHECK_IO(CheckTag(v,read,up,sizeof(SQChar)));
+    _CHECK_IO(CheckTag(v,read,up,sizeof(SQInteger)));
+    _CHECK_IO(CheckTag(v,read,up,sizeof(SQFloat)));
+    SQObjectPtr func;
+    _CHECK_IO(SQFunctionProto::Load(v,up,read,func));
+    _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_TAIL));
+    ret = SQClosure::Create(_ss(v),_funcproto(func),_table(v->_roottable)->GetWeakRef(OT_TABLE));
+    //FIXME: load an root for this closure
+    return true;
+}
+
+SQFunctionProto::SQFunctionProto(SQSharedState *ss)
+{
+    _stacksize=0;
+    _bgenerator=false;
+    INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);
+}
+
+SQFunctionProto::~SQFunctionProto()
+{
+    REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+}
+
+bool SQFunctionProto::Save(SQVM *v,SQUserPointer up,SQWRITEFUNC write)
+{
+    SQInteger i,nliterals = _nliterals,nparameters = _nparameters;
+    SQInteger noutervalues = _noutervalues,nlocalvarinfos = _nlocalvarinfos;
+    SQInteger nlineinfos=_nlineinfos,ninstructions = _ninstructions,nfunctions=_nfunctions;
+    SQInteger ndefaultparams = _ndefaultparams;
+    _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+    _CHECK_IO(WriteObject(v,up,write,_sourcename));
+    _CHECK_IO(WriteObject(v,up,write,_name));
+    _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+    _CHECK_IO(SafeWrite(v,write,up,&nliterals,sizeof(nliterals)));
+    _CHECK_IO(SafeWrite(v,write,up,&nparameters,sizeof(nparameters)));
+    _CHECK_IO(SafeWrite(v,write,up,&noutervalues,sizeof(noutervalues)));
+    _CHECK_IO(SafeWrite(v,write,up,&nlocalvarinfos,sizeof(nlocalvarinfos)));
+    _CHECK_IO(SafeWrite(v,write,up,&nlineinfos,sizeof(nlineinfos)));
+    _CHECK_IO(SafeWrite(v,write,up,&ndefaultparams,sizeof(ndefaultparams)));
+    _CHECK_IO(SafeWrite(v,write,up,&ninstructions,sizeof(ninstructions)));
+    _CHECK_IO(SafeWrite(v,write,up,&nfunctions,sizeof(nfunctions)));
+    _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+    for(i=0;i<nliterals;i++){
+        _CHECK_IO(WriteObject(v,up,write,_literals[i]));
+    }
+
+    _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+    for(i=0;i<nparameters;i++){
+        _CHECK_IO(WriteObject(v,up,write,_parameters[i]));
+    }
+
+    _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+    for(i=0;i<noutervalues;i++){
+        _CHECK_IO(SafeWrite(v,write,up,&_outervalues[i]._type,sizeof(SQUnsignedInteger)));
+        _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._src));
+        _CHECK_IO(WriteObject(v,up,write,_outervalues[i]._name));
+    }
+
+    _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+    for(i=0;i<nlocalvarinfos;i++){
+        SQLocalVarInfo &lvi=_localvarinfos[i];
+        _CHECK_IO(WriteObject(v,up,write,lvi._name));
+        _CHECK_IO(SafeWrite(v,write,up,&lvi._pos,sizeof(SQUnsignedInteger)));
+        _CHECK_IO(SafeWrite(v,write,up,&lvi._start_op,sizeof(SQUnsignedInteger)));
+        _CHECK_IO(SafeWrite(v,write,up,&lvi._end_op,sizeof(SQUnsignedInteger)));
+    }
+
+    _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+    _CHECK_IO(SafeWrite(v,write,up,_lineinfos,sizeof(SQLineInfo)*nlineinfos));
+
+    _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+    _CHECK_IO(SafeWrite(v,write,up,_defaultparams,sizeof(SQInteger)*ndefaultparams));
+
+    _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+    _CHECK_IO(SafeWrite(v,write,up,_instructions,sizeof(SQInstruction)*ninstructions));
+
+    _CHECK_IO(WriteTag(v,write,up,SQ_CLOSURESTREAM_PART));
+    for(i=0;i<nfunctions;i++){
+        _CHECK_IO(_funcproto(_functions[i])->Save(v,up,write));
+    }
+    _CHECK_IO(SafeWrite(v,write,up,&_stacksize,sizeof(_stacksize)));
+    _CHECK_IO(SafeWrite(v,write,up,&_bgenerator,sizeof(_bgenerator)));
+    _CHECK_IO(SafeWrite(v,write,up,&_varparams,sizeof(_varparams)));
+    return true;
+}
+
+bool SQFunctionProto::Load(SQVM *v,SQUserPointer up,SQREADFUNC read,SQObjectPtr &ret)
+{
+    SQInteger i, nliterals,nparameters;
+    SQInteger noutervalues ,nlocalvarinfos ;
+    SQInteger nlineinfos,ninstructions ,nfunctions,ndefaultparams ;
+    SQObjectPtr sourcename, name;
+    SQObjectPtr o;
+    _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+    _CHECK_IO(ReadObject(v, up, read, sourcename));
+    _CHECK_IO(ReadObject(v, up, read, name));
+
+    _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+    _CHECK_IO(SafeRead(v,read,up, &nliterals, sizeof(nliterals)));
+    _CHECK_IO(SafeRead(v,read,up, &nparameters, sizeof(nparameters)));
+    _CHECK_IO(SafeRead(v,read,up, &noutervalues, sizeof(noutervalues)));
+    _CHECK_IO(SafeRead(v,read,up, &nlocalvarinfos, sizeof(nlocalvarinfos)));
+    _CHECK_IO(SafeRead(v,read,up, &nlineinfos, sizeof(nlineinfos)));
+    _CHECK_IO(SafeRead(v,read,up, &ndefaultparams, sizeof(ndefaultparams)));
+    _CHECK_IO(SafeRead(v,read,up, &ninstructions, sizeof(ninstructions)));
+    _CHECK_IO(SafeRead(v,read,up, &nfunctions, sizeof(nfunctions)));
+
+
+    SQFunctionProto *f = SQFunctionProto::Create(_opt_ss(v),ninstructions,nliterals,nparameters,
+            nfunctions,noutervalues,nlineinfos,nlocalvarinfos,ndefaultparams);
+    SQObjectPtr proto = f; //gets a ref in case of failure
+    f->_sourcename = sourcename;
+    f->_name = name;
+
+    _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+
+    for(i = 0;i < nliterals; i++){
+        _CHECK_IO(ReadObject(v, up, read, o));
+        f->_literals[i] = o;
+    }
+    _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+
+    for(i = 0; i < nparameters; i++){
+        _CHECK_IO(ReadObject(v, up, read, o));
+        f->_parameters[i] = o;
+    }
+    _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+
+    for(i = 0; i < noutervalues; i++){
+        SQUnsignedInteger type;
+        SQObjectPtr name;
+        _CHECK_IO(SafeRead(v,read,up, &type, sizeof(SQUnsignedInteger)));
+        _CHECK_IO(ReadObject(v, up, read, o));
+        _CHECK_IO(ReadObject(v, up, read, name));
+        f->_outervalues[i] = SQOuterVar(name,o, (SQOuterType)type);
+    }
+    _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+
+    for(i = 0; i < nlocalvarinfos; i++){
+        SQLocalVarInfo lvi;
+        _CHECK_IO(ReadObject(v, up, read, lvi._name));
+        _CHECK_IO(SafeRead(v,read,up, &lvi._pos, sizeof(SQUnsignedInteger)));
+        _CHECK_IO(SafeRead(v,read,up, &lvi._start_op, sizeof(SQUnsignedInteger)));
+        _CHECK_IO(SafeRead(v,read,up, &lvi._end_op, sizeof(SQUnsignedInteger)));
+        f->_localvarinfos[i] = lvi;
+    }
+    _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+    _CHECK_IO(SafeRead(v,read,up, f->_lineinfos, sizeof(SQLineInfo)*nlineinfos));
+
+    _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+    _CHECK_IO(SafeRead(v,read,up, f->_defaultparams, sizeof(SQInteger)*ndefaultparams));
+
+    _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+    _CHECK_IO(SafeRead(v,read,up, f->_instructions, sizeof(SQInstruction)*ninstructions));
+
+    _CHECK_IO(CheckTag(v,read,up,SQ_CLOSURESTREAM_PART));
+    for(i = 0; i < nfunctions; i++){
+        _CHECK_IO(_funcproto(o)->Load(v, up, read, o));
+        f->_functions[i] = o;
+    }
+    _CHECK_IO(SafeRead(v,read,up, &f->_stacksize, sizeof(f->_stacksize)));
+    _CHECK_IO(SafeRead(v,read,up, &f->_bgenerator, sizeof(f->_bgenerator)));
+    _CHECK_IO(SafeRead(v,read,up, &f->_varparams, sizeof(f->_varparams)));
+
+    ret = f;
+    return true;
+}
+
+#ifndef NO_GARBAGE_COLLECTOR
+
+#define START_MARK()    if(!(_uiRef&MARK_FLAG)){ \
+        _uiRef|=MARK_FLAG;
+
+#define END_MARK() RemoveFromChain(&_sharedstate->_gc_chain, this); \
+        AddToChain(chain, this); }
+
+void SQVM::Mark(SQCollectable **chain)
+{
+    START_MARK()
+        SQSharedState::MarkObject(_lasterror,chain);
+        SQSharedState::MarkObject(_errorhandler,chain);
+        SQSharedState::MarkObject(_debughook_closure,chain);
+        SQSharedState::MarkObject(_roottable, chain);
+        SQSharedState::MarkObject(temp_reg, chain);
+        for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
+        for(SQInteger k = 0; k < _callsstacksize; k++) SQSharedState::MarkObject(_callsstack[k]._closure, chain);
+    END_MARK()
+}
+
+void SQArray::Mark(SQCollectable **chain)
+{
+    START_MARK()
+        SQInteger len = _values.size();
+        for(SQInteger i = 0;i < len; i++) SQSharedState::MarkObject(_values[i], chain);
+    END_MARK()
+}
+void SQTable::Mark(SQCollectable **chain)
+{
+    START_MARK()
+        if(_delegate) _delegate->Mark(chain);
+        SQInteger len = _numofnodes;
+        for(SQInteger i = 0; i < len; i++){
+            SQSharedState::MarkObject(_nodes[i].key, chain);
+            SQSharedState::MarkObject(_nodes[i].val, chain);
+        }
+    END_MARK()
+}
+
+void SQClass::Mark(SQCollectable **chain)
+{
+    START_MARK()
+        _members->Mark(chain);
+        if(_base) _base->Mark(chain);
+        SQSharedState::MarkObject(_attributes, chain);
+        for(SQUnsignedInteger i =0; i< _defaultvalues.size(); i++) {
+            SQSharedState::MarkObject(_defaultvalues[i].val, chain);
+            SQSharedState::MarkObject(_defaultvalues[i].attrs, chain);
+        }
+        for(SQUnsignedInteger j =0; j< _methods.size(); j++) {
+            SQSharedState::MarkObject(_methods[j].val, chain);
+            SQSharedState::MarkObject(_methods[j].attrs, chain);
+        }
+        for(SQUnsignedInteger k =0; k< MT_LAST; k++) {
+            SQSharedState::MarkObject(_metamethods[k], chain);
+        }
+    END_MARK()
+}
+
+void SQInstance::Mark(SQCollectable **chain)
+{
+    START_MARK()
+        _class->Mark(chain);
+        SQUnsignedInteger nvalues = _class->_defaultvalues.size();
+        for(SQUnsignedInteger i =0; i< nvalues; i++) {
+            SQSharedState::MarkObject(_values[i], chain);
+        }
+    END_MARK()
+}
+
+void SQGenerator::Mark(SQCollectable **chain)
+{
+    START_MARK()
+        for(SQUnsignedInteger i = 0; i < _stack.size(); i++) SQSharedState::MarkObject(_stack[i], chain);
+        SQSharedState::MarkObject(_closure, chain);
+    END_MARK()
+}
+
+void SQFunctionProto::Mark(SQCollectable **chain)
+{
+    START_MARK()
+        for(SQInteger i = 0; i < _nliterals; i++) SQSharedState::MarkObject(_literals[i], chain);
+        for(SQInteger k = 0; k < _nfunctions; k++) SQSharedState::MarkObject(_functions[k], chain);
+    END_MARK()
+}
+
+void SQClosure::Mark(SQCollectable **chain)
+{
+    START_MARK()
+        if(_base) _base->Mark(chain);
+        SQFunctionProto *fp = _function;
+        fp->Mark(chain);
+        for(SQInteger i = 0; i < fp->_noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain);
+        for(SQInteger k = 0; k < fp->_ndefaultparams; k++) SQSharedState::MarkObject(_defaultparams[k], chain);
+    END_MARK()
+}
+
+void SQNativeClosure::Mark(SQCollectable **chain)
+{
+    START_MARK()
+        for(SQUnsignedInteger i = 0; i < _noutervalues; i++) SQSharedState::MarkObject(_outervalues[i], chain);
+    END_MARK()
+}
+
+void SQOuter::Mark(SQCollectable **chain)
+{
+    START_MARK()
+    /* If the valptr points to a closed value, that value is alive */
+    if(_valptr == &_value) {
+      SQSharedState::MarkObject(_value, chain);
+    }
+    END_MARK()
+}
+
+void SQUserData::Mark(SQCollectable **chain){
+    START_MARK()
+        if(_delegate) _delegate->Mark(chain);
+    END_MARK()
+}
+
+void SQCollectable::UnMark() { _uiRef&=~MARK_FLAG; }
+
+#endif
+

+ 354 - 354
squirrel/sqobject.h

@@ -1,354 +1,354 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQOBJECT_H_
-#define _SQOBJECT_H_
-
-#include "squtils.h"
-
-#ifdef _SQ64
-#define UINT_MINUS_ONE (0xFFFFFFFFFFFFFFFF)
-#else
-#define UINT_MINUS_ONE (0xFFFFFFFF)
-#endif
-
-#define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R'))
-#define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T'))
-#define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L'))
-
-struct SQSharedState;
-
-enum SQMetaMethod{
-	MT_ADD=0,
-	MT_SUB=1,
-	MT_MUL=2,
-	MT_DIV=3,
-	MT_UNM=4,
-	MT_MODULO=5,
-	MT_SET=6,
-	MT_GET=7,
-	MT_TYPEOF=8,
-	MT_NEXTI=9,
-	MT_CMP=10,
-	MT_CALL=11,
-	MT_CLONED=12,
-	MT_NEWSLOT=13,
-	MT_DELSLOT=14,
-	MT_TOSTRING=15,
-	MT_NEWMEMBER=16,
-	MT_INHERITED=17,
-	MT_LAST = 18
-};
-
-#define MM_ADD		_SC("_add")
-#define MM_SUB		_SC("_sub")
-#define MM_MUL		_SC("_mul")
-#define MM_DIV		_SC("_div")
-#define MM_UNM		_SC("_unm")
-#define MM_MODULO	_SC("_modulo")
-#define MM_SET		_SC("_set")
-#define MM_GET		_SC("_get")
-#define MM_TYPEOF	_SC("_typeof")
-#define MM_NEXTI	_SC("_nexti")
-#define MM_CMP		_SC("_cmp")
-#define MM_CALL		_SC("_call")
-#define MM_CLONED	_SC("_cloned")
-#define MM_NEWSLOT	_SC("_newslot")
-#define MM_DELSLOT	_SC("_delslot")
-#define MM_TOSTRING	_SC("_tostring")
-#define MM_NEWMEMBER _SC("_newmember")
-#define MM_INHERITED _SC("_inherited")
-
-
-#define _CONSTRUCT_VECTOR(type,size,ptr) { \
-	for(SQInteger n = 0; n < ((SQInteger)size); n++) { \
-			new (&ptr[n]) type(); \
-		} \
-}
-
-#define _DESTRUCT_VECTOR(type,size,ptr) { \
-	for(SQInteger nl = 0; nl < ((SQInteger)size); nl++) { \
-			ptr[nl].~type(); \
-	} \
-}
-
-#define _COPY_VECTOR(dest,src,size) { \
-	for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \
-		dest[_n_] = src[_n_]; \
-	} \
-}
-
-#define _NULL_SQOBJECT_VECTOR(vec,size) { \
-	for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \
-		vec[_n_].Null(); \
-	} \
-}
-
-#define MINPOWER2 4
-
-struct SQRefCounted
-{
-	SQUnsignedInteger _uiRef;
-	struct SQWeakRef *_weakref;
-	SQRefCounted() { _uiRef = 0; _weakref = NULL; }
-	virtual ~SQRefCounted();
-	SQWeakRef *GetWeakRef(SQObjectType type);
-	virtual void Release()=0;
-	
-};
-
-struct SQWeakRef : SQRefCounted
-{
-	void Release();
-	SQObject _obj;
-};
-
-#define _realval(o) (type((o)) != OT_WEAKREF?(SQObject)o:_weakref(o)->_obj)
-
-struct SQObjectPtr;
-
-#define __AddRef(type,unval) if(ISREFCOUNTED(type))	\
-		{ \
-			unval.pRefCounted->_uiRef++; \
-		}  
-
-#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)==0))	\
-		{	\
-			unval.pRefCounted->Release();	\
-		}
-
-#define __ObjRelease(obj) { \
-	if((obj)) {	\
-		(obj)->_uiRef--; \
-		if((obj)->_uiRef == 0) \
-			(obj)->Release(); \
-		(obj) = NULL;	\
-	} \
-}
-
-#define __ObjAddRef(obj) { \
-	(obj)->_uiRef++; \
-}
-
-#define type(obj) ((obj)._type)
-#define is_delegable(t) (type(t)&SQOBJECT_DELEGABLE)
-#define raw_type(obj) _RAW_TYPE((obj)._type)
-
-#define _integer(obj) ((obj)._unVal.nInteger)
-#define _float(obj) ((obj)._unVal.fFloat)
-#define _string(obj) ((obj)._unVal.pString)
-#define _table(obj) ((obj)._unVal.pTable)
-#define _array(obj) ((obj)._unVal.pArray)
-#define _closure(obj) ((obj)._unVal.pClosure)
-#define _generator(obj) ((obj)._unVal.pGenerator)
-#define _nativeclosure(obj) ((obj)._unVal.pNativeClosure)
-#define _userdata(obj) ((obj)._unVal.pUserData)
-#define _userpointer(obj) ((obj)._unVal.pUserPointer)
-#define _thread(obj) ((obj)._unVal.pThread)
-#define _funcproto(obj) ((obj)._unVal.pFunctionProto)
-#define _class(obj) ((obj)._unVal.pClass)
-#define _instance(obj) ((obj)._unVal.pInstance)
-#define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable)
-#define _weakref(obj) ((obj)._unVal.pWeakRef)
-#define _outer(obj) ((obj)._unVal.pOuter)
-#define _refcounted(obj) ((obj)._unVal.pRefCounted)
-#define _rawval(obj) ((obj)._unVal.raw)
-
-#define _stringval(obj) (obj)._unVal.pString->_val
-#define _userdataval(obj) ((SQUserPointer)sq_aligning((obj)._unVal.pUserData + 1))
-
-#define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num))
-#define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num))
-/////////////////////////////////////////////////////////////////////////////////////
-/////////////////////////////////////////////////////////////////////////////////////
-#if defined(SQUSEDOUBLE) && !defined(_SQ64) || !defined(SQUSEDOUBLE) && defined(_SQ64)
-#define SQ_REFOBJECT_INIT()	SQ_OBJECT_RAWINIT()
-#else
-#define SQ_REFOBJECT_INIT()
-#endif
-
-#define _REF_TYPE_DECL(type,_class,sym) \
-	SQObjectPtr(_class * x) \
-	{ \
-		SQ_OBJECT_RAWINIT() \
-		_type=type; \
-		_unVal.sym = x; \
-		assert(_unVal.pTable); \
-		_unVal.pRefCounted->_uiRef++; \
-	} \
-	inline SQObjectPtr& operator=(_class *x) \
-	{  \
-		SQObjectType tOldType; \
-		SQObjectValue unOldVal; \
-		tOldType=_type; \
-		unOldVal=_unVal; \
-		_type = type; \
-		SQ_REFOBJECT_INIT() \
-		_unVal.sym = x; \
-		_unVal.pRefCounted->_uiRef++; \
-		__Release(tOldType,unOldVal); \
-		return *this; \
-	}
-
-#define _SCALAR_TYPE_DECL(type,_class,sym) \
-	SQObjectPtr(_class x) \
-	{ \
-		SQ_OBJECT_RAWINIT() \
-		_type=type; \
-		_unVal.sym = x; \
-	} \
-	inline SQObjectPtr& operator=(_class x) \
-	{  \
-		__Release(_type,_unVal); \
-		_type = type; \
-		SQ_OBJECT_RAWINIT() \
-		_unVal.sym = x; \
-		return *this; \
-	}
-struct SQObjectPtr : public SQObject
-{
-	SQObjectPtr()
-	{
-		SQ_OBJECT_RAWINIT()
-		_type=OT_NULL;
-		_unVal.pUserPointer=NULL;
-	}
-	SQObjectPtr(const SQObjectPtr &o)
-	{
-		_type = o._type;
-		_unVal = o._unVal;
-		__AddRef(_type,_unVal);
-	}
-	SQObjectPtr(const SQObject &o)
-	{
-		_type = o._type;
-		_unVal = o._unVal;
-		__AddRef(_type,_unVal);
-	}
-	_REF_TYPE_DECL(OT_TABLE,SQTable,pTable)
-	_REF_TYPE_DECL(OT_CLASS,SQClass,pClass)
-	_REF_TYPE_DECL(OT_INSTANCE,SQInstance,pInstance)
-	_REF_TYPE_DECL(OT_ARRAY,SQArray,pArray)
-	_REF_TYPE_DECL(OT_CLOSURE,SQClosure,pClosure)
-	_REF_TYPE_DECL(OT_NATIVECLOSURE,SQNativeClosure,pNativeClosure)
-	_REF_TYPE_DECL(OT_OUTER,SQOuter,pOuter)
-	_REF_TYPE_DECL(OT_GENERATOR,SQGenerator,pGenerator)
-	_REF_TYPE_DECL(OT_STRING,SQString,pString)
-	_REF_TYPE_DECL(OT_USERDATA,SQUserData,pUserData)
-	_REF_TYPE_DECL(OT_WEAKREF,SQWeakRef,pWeakRef)
-	_REF_TYPE_DECL(OT_THREAD,SQVM,pThread)
-	_REF_TYPE_DECL(OT_FUNCPROTO,SQFunctionProto,pFunctionProto)
-	
-	_SCALAR_TYPE_DECL(OT_INTEGER,SQInteger,nInteger)
-	_SCALAR_TYPE_DECL(OT_FLOAT,SQFloat,fFloat)
-	_SCALAR_TYPE_DECL(OT_USERPOINTER,SQUserPointer,pUserPointer)
-
-	SQObjectPtr(bool bBool)
-	{
-		SQ_OBJECT_RAWINIT()
-		_type = OT_BOOL;
-		_unVal.nInteger = bBool?1:0;
-	}
-	inline SQObjectPtr& operator=(bool b)
-	{ 
-		__Release(_type,_unVal);
-		SQ_OBJECT_RAWINIT()
-		_type = OT_BOOL;
-		_unVal.nInteger = b?1:0;
-		return *this;
-	}
-
-	~SQObjectPtr()
-	{
-		__Release(_type,_unVal);
-	}
-			
-	inline SQObjectPtr& operator=(const SQObjectPtr& obj)
-	{ 
-		SQObjectType tOldType;
-		SQObjectValue unOldVal;
-		tOldType=_type;
-		unOldVal=_unVal;
-		_unVal = obj._unVal;
-		_type = obj._type;
-		__AddRef(_type,_unVal);
-		__Release(tOldType,unOldVal);
-		return *this;
-	}
-	inline SQObjectPtr& operator=(const SQObject& obj)
-	{ 
-		SQObjectType tOldType;
-		SQObjectValue unOldVal;
-		tOldType=_type;
-		unOldVal=_unVal;
-		_unVal = obj._unVal;
-		_type = obj._type;
-		__AddRef(_type,_unVal);
-		__Release(tOldType,unOldVal);
-		return *this;
-	}
-	inline void Null()
-	{
-		SQObjectType tOldType = _type;
-		SQObjectValue unOldVal = _unVal;
-		_type = OT_NULL;
-		_unVal.raw = (SQRawObjectVal)NULL;
-		__Release(tOldType ,unOldVal);
-	}
-	private:
-		SQObjectPtr(const SQChar *){} //safety
-};
-
-
-inline void _Swap(SQObject &a,SQObject &b)
-{
-	SQObjectType tOldType = a._type;
-	SQObjectValue unOldVal = a._unVal;
-	a._type = b._type;
-	a._unVal = b._unVal;
-	b._type = tOldType;
-	b._unVal = unOldVal;
-}
-
-/////////////////////////////////////////////////////////////////////////////////////
-#ifndef NO_GARBAGE_COLLECTOR
-#define MARK_FLAG 0x80000000
-struct SQCollectable : public SQRefCounted {
-	SQCollectable *_next;
-	SQCollectable *_prev;
-	SQSharedState *_sharedstate;
-	virtual SQObjectType GetType()=0;
-	virtual void Release()=0;
-	virtual void Mark(SQCollectable **chain)=0;
-	void UnMark();
-	virtual void Finalize()=0;
-	static void AddToChain(SQCollectable **chain,SQCollectable *c);
-	static void RemoveFromChain(SQCollectable **chain,SQCollectable *c);
-};
-
-
-#define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj)
-#define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);}
-#define CHAINABLE_OBJ SQCollectable
-#define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;}
-#else
-
-#define ADD_TO_CHAIN(chain,obj) ((void)0)
-#define REMOVE_FROM_CHAIN(chain,obj) ((void)0)
-#define CHAINABLE_OBJ SQRefCounted
-#define INIT_CHAIN() ((void)0)
-#endif
-
-struct SQDelegable : public CHAINABLE_OBJ {
-	bool SetDelegate(SQTable *m);
-	virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);
-	SQTable *_delegate;
-};
-
-SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx);
-typedef sqvector<SQObjectPtr> SQObjectPtrVec;
-typedef sqvector<SQInteger> SQIntVec;
-const SQChar *GetTypeName(const SQObjectPtr &obj1);
-const SQChar *IdType2Name(SQObjectType type);
-
-
-
-#endif //_SQOBJECT_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQOBJECT_H_
+#define _SQOBJECT_H_
+
+#include "squtils.h"
+
+#ifdef _SQ64
+#define UINT_MINUS_ONE (0xFFFFFFFFFFFFFFFF)
+#else
+#define UINT_MINUS_ONE (0xFFFFFFFF)
+#endif
+
+#define SQ_CLOSURESTREAM_HEAD (('S'<<24)|('Q'<<16)|('I'<<8)|('R'))
+#define SQ_CLOSURESTREAM_PART (('P'<<24)|('A'<<16)|('R'<<8)|('T'))
+#define SQ_CLOSURESTREAM_TAIL (('T'<<24)|('A'<<16)|('I'<<8)|('L'))
+
+struct SQSharedState;
+
+enum SQMetaMethod{
+    MT_ADD=0,
+    MT_SUB=1,
+    MT_MUL=2,
+    MT_DIV=3,
+    MT_UNM=4,
+    MT_MODULO=5,
+    MT_SET=6,
+    MT_GET=7,
+    MT_TYPEOF=8,
+    MT_NEXTI=9,
+    MT_CMP=10,
+    MT_CALL=11,
+    MT_CLONED=12,
+    MT_NEWSLOT=13,
+    MT_DELSLOT=14,
+    MT_TOSTRING=15,
+    MT_NEWMEMBER=16,
+    MT_INHERITED=17,
+    MT_LAST = 18
+};
+
+#define MM_ADD      _SC("_add")
+#define MM_SUB      _SC("_sub")
+#define MM_MUL      _SC("_mul")
+#define MM_DIV      _SC("_div")
+#define MM_UNM      _SC("_unm")
+#define MM_MODULO   _SC("_modulo")
+#define MM_SET      _SC("_set")
+#define MM_GET      _SC("_get")
+#define MM_TYPEOF   _SC("_typeof")
+#define MM_NEXTI    _SC("_nexti")
+#define MM_CMP      _SC("_cmp")
+#define MM_CALL     _SC("_call")
+#define MM_CLONED   _SC("_cloned")
+#define MM_NEWSLOT  _SC("_newslot")
+#define MM_DELSLOT  _SC("_delslot")
+#define MM_TOSTRING _SC("_tostring")
+#define MM_NEWMEMBER _SC("_newmember")
+#define MM_INHERITED _SC("_inherited")
+
+
+#define _CONSTRUCT_VECTOR(type,size,ptr) { \
+    for(SQInteger n = 0; n < ((SQInteger)size); n++) { \
+            new (&ptr[n]) type(); \
+        } \
+}
+
+#define _DESTRUCT_VECTOR(type,size,ptr) { \
+    for(SQInteger nl = 0; nl < ((SQInteger)size); nl++) { \
+            ptr[nl].~type(); \
+    } \
+}
+
+#define _COPY_VECTOR(dest,src,size) { \
+    for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \
+        dest[_n_] = src[_n_]; \
+    } \
+}
+
+#define _NULL_SQOBJECT_VECTOR(vec,size) { \
+    for(SQInteger _n_ = 0; _n_ < ((SQInteger)size); _n_++) { \
+        vec[_n_].Null(); \
+    } \
+}
+
+#define MINPOWER2 4
+
+struct SQRefCounted
+{
+    SQUnsignedInteger _uiRef;
+    struct SQWeakRef *_weakref;
+    SQRefCounted() { _uiRef = 0; _weakref = NULL; }
+    virtual ~SQRefCounted();
+    SQWeakRef *GetWeakRef(SQObjectType type);
+    virtual void Release()=0;
+
+};
+
+struct SQWeakRef : SQRefCounted
+{
+    void Release();
+    SQObject _obj;
+};
+
+#define _realval(o) (type((o)) != OT_WEAKREF?(SQObject)o:_weakref(o)->_obj)
+
+struct SQObjectPtr;
+
+#define __AddRef(type,unval) if(ISREFCOUNTED(type)) \
+        { \
+            unval.pRefCounted->_uiRef++; \
+        }
+
+#define __Release(type,unval) if(ISREFCOUNTED(type) && ((--unval.pRefCounted->_uiRef)==0))  \
+        {   \
+            unval.pRefCounted->Release();   \
+        }
+
+#define __ObjRelease(obj) { \
+    if((obj)) { \
+        (obj)->_uiRef--; \
+        if((obj)->_uiRef == 0) \
+            (obj)->Release(); \
+        (obj) = NULL;   \
+    } \
+}
+
+#define __ObjAddRef(obj) { \
+    (obj)->_uiRef++; \
+}
+
+#define type(obj) ((obj)._type)
+#define is_delegable(t) (type(t)&SQOBJECT_DELEGABLE)
+#define raw_type(obj) _RAW_TYPE((obj)._type)
+
+#define _integer(obj) ((obj)._unVal.nInteger)
+#define _float(obj) ((obj)._unVal.fFloat)
+#define _string(obj) ((obj)._unVal.pString)
+#define _table(obj) ((obj)._unVal.pTable)
+#define _array(obj) ((obj)._unVal.pArray)
+#define _closure(obj) ((obj)._unVal.pClosure)
+#define _generator(obj) ((obj)._unVal.pGenerator)
+#define _nativeclosure(obj) ((obj)._unVal.pNativeClosure)
+#define _userdata(obj) ((obj)._unVal.pUserData)
+#define _userpointer(obj) ((obj)._unVal.pUserPointer)
+#define _thread(obj) ((obj)._unVal.pThread)
+#define _funcproto(obj) ((obj)._unVal.pFunctionProto)
+#define _class(obj) ((obj)._unVal.pClass)
+#define _instance(obj) ((obj)._unVal.pInstance)
+#define _delegable(obj) ((SQDelegable *)(obj)._unVal.pDelegable)
+#define _weakref(obj) ((obj)._unVal.pWeakRef)
+#define _outer(obj) ((obj)._unVal.pOuter)
+#define _refcounted(obj) ((obj)._unVal.pRefCounted)
+#define _rawval(obj) ((obj)._unVal.raw)
+
+#define _stringval(obj) (obj)._unVal.pString->_val
+#define _userdataval(obj) ((SQUserPointer)sq_aligning((obj)._unVal.pUserData + 1))
+
+#define tofloat(num) ((type(num)==OT_INTEGER)?(SQFloat)_integer(num):_float(num))
+#define tointeger(num) ((type(num)==OT_FLOAT)?(SQInteger)_float(num):_integer(num))
+/////////////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////////////
+#if defined(SQUSEDOUBLE) && !defined(_SQ64) || !defined(SQUSEDOUBLE) && defined(_SQ64)
+#define SQ_REFOBJECT_INIT() SQ_OBJECT_RAWINIT()
+#else
+#define SQ_REFOBJECT_INIT()
+#endif
+
+#define _REF_TYPE_DECL(type,_class,sym) \
+    SQObjectPtr(_class * x) \
+    { \
+        SQ_OBJECT_RAWINIT() \
+        _type=type; \
+        _unVal.sym = x; \
+        assert(_unVal.pTable); \
+        _unVal.pRefCounted->_uiRef++; \
+    } \
+    inline SQObjectPtr& operator=(_class *x) \
+    {  \
+        SQObjectType tOldType; \
+        SQObjectValue unOldVal; \
+        tOldType=_type; \
+        unOldVal=_unVal; \
+        _type = type; \
+        SQ_REFOBJECT_INIT() \
+        _unVal.sym = x; \
+        _unVal.pRefCounted->_uiRef++; \
+        __Release(tOldType,unOldVal); \
+        return *this; \
+    }
+
+#define _SCALAR_TYPE_DECL(type,_class,sym) \
+    SQObjectPtr(_class x) \
+    { \
+        SQ_OBJECT_RAWINIT() \
+        _type=type; \
+        _unVal.sym = x; \
+    } \
+    inline SQObjectPtr& operator=(_class x) \
+    {  \
+        __Release(_type,_unVal); \
+        _type = type; \
+        SQ_OBJECT_RAWINIT() \
+        _unVal.sym = x; \
+        return *this; \
+    }
+struct SQObjectPtr : public SQObject
+{
+    SQObjectPtr()
+    {
+        SQ_OBJECT_RAWINIT()
+        _type=OT_NULL;
+        _unVal.pUserPointer=NULL;
+    }
+    SQObjectPtr(const SQObjectPtr &o)
+    {
+        _type = o._type;
+        _unVal = o._unVal;
+        __AddRef(_type,_unVal);
+    }
+    SQObjectPtr(const SQObject &o)
+    {
+        _type = o._type;
+        _unVal = o._unVal;
+        __AddRef(_type,_unVal);
+    }
+    _REF_TYPE_DECL(OT_TABLE,SQTable,pTable)
+    _REF_TYPE_DECL(OT_CLASS,SQClass,pClass)
+    _REF_TYPE_DECL(OT_INSTANCE,SQInstance,pInstance)
+    _REF_TYPE_DECL(OT_ARRAY,SQArray,pArray)
+    _REF_TYPE_DECL(OT_CLOSURE,SQClosure,pClosure)
+    _REF_TYPE_DECL(OT_NATIVECLOSURE,SQNativeClosure,pNativeClosure)
+    _REF_TYPE_DECL(OT_OUTER,SQOuter,pOuter)
+    _REF_TYPE_DECL(OT_GENERATOR,SQGenerator,pGenerator)
+    _REF_TYPE_DECL(OT_STRING,SQString,pString)
+    _REF_TYPE_DECL(OT_USERDATA,SQUserData,pUserData)
+    _REF_TYPE_DECL(OT_WEAKREF,SQWeakRef,pWeakRef)
+    _REF_TYPE_DECL(OT_THREAD,SQVM,pThread)
+    _REF_TYPE_DECL(OT_FUNCPROTO,SQFunctionProto,pFunctionProto)
+
+    _SCALAR_TYPE_DECL(OT_INTEGER,SQInteger,nInteger)
+    _SCALAR_TYPE_DECL(OT_FLOAT,SQFloat,fFloat)
+    _SCALAR_TYPE_DECL(OT_USERPOINTER,SQUserPointer,pUserPointer)
+
+    SQObjectPtr(bool bBool)
+    {
+        SQ_OBJECT_RAWINIT()
+        _type = OT_BOOL;
+        _unVal.nInteger = bBool?1:0;
+    }
+    inline SQObjectPtr& operator=(bool b)
+    {
+        __Release(_type,_unVal);
+        SQ_OBJECT_RAWINIT()
+        _type = OT_BOOL;
+        _unVal.nInteger = b?1:0;
+        return *this;
+    }
+
+    ~SQObjectPtr()
+    {
+        __Release(_type,_unVal);
+    }
+
+    inline SQObjectPtr& operator=(const SQObjectPtr& obj)
+    {
+        SQObjectType tOldType;
+        SQObjectValue unOldVal;
+        tOldType=_type;
+        unOldVal=_unVal;
+        _unVal = obj._unVal;
+        _type = obj._type;
+        __AddRef(_type,_unVal);
+        __Release(tOldType,unOldVal);
+        return *this;
+    }
+    inline SQObjectPtr& operator=(const SQObject& obj)
+    {
+        SQObjectType tOldType;
+        SQObjectValue unOldVal;
+        tOldType=_type;
+        unOldVal=_unVal;
+        _unVal = obj._unVal;
+        _type = obj._type;
+        __AddRef(_type,_unVal);
+        __Release(tOldType,unOldVal);
+        return *this;
+    }
+    inline void Null()
+    {
+        SQObjectType tOldType = _type;
+        SQObjectValue unOldVal = _unVal;
+        _type = OT_NULL;
+        _unVal.raw = (SQRawObjectVal)NULL;
+        __Release(tOldType ,unOldVal);
+    }
+    private:
+        SQObjectPtr(const SQChar *){} //safety
+};
+
+
+inline void _Swap(SQObject &a,SQObject &b)
+{
+    SQObjectType tOldType = a._type;
+    SQObjectValue unOldVal = a._unVal;
+    a._type = b._type;
+    a._unVal = b._unVal;
+    b._type = tOldType;
+    b._unVal = unOldVal;
+}
+
+/////////////////////////////////////////////////////////////////////////////////////
+#ifndef NO_GARBAGE_COLLECTOR
+#define MARK_FLAG 0x80000000
+struct SQCollectable : public SQRefCounted {
+    SQCollectable *_next;
+    SQCollectable *_prev;
+    SQSharedState *_sharedstate;
+    virtual SQObjectType GetType()=0;
+    virtual void Release()=0;
+    virtual void Mark(SQCollectable **chain)=0;
+    void UnMark();
+    virtual void Finalize()=0;
+    static void AddToChain(SQCollectable **chain,SQCollectable *c);
+    static void RemoveFromChain(SQCollectable **chain,SQCollectable *c);
+};
+
+
+#define ADD_TO_CHAIN(chain,obj) AddToChain(chain,obj)
+#define REMOVE_FROM_CHAIN(chain,obj) {if(!(_uiRef&MARK_FLAG))RemoveFromChain(chain,obj);}
+#define CHAINABLE_OBJ SQCollectable
+#define INIT_CHAIN() {_next=NULL;_prev=NULL;_sharedstate=ss;}
+#else
+
+#define ADD_TO_CHAIN(chain,obj) ((void)0)
+#define REMOVE_FROM_CHAIN(chain,obj) ((void)0)
+#define CHAINABLE_OBJ SQRefCounted
+#define INIT_CHAIN() ((void)0)
+#endif
+
+struct SQDelegable : public CHAINABLE_OBJ {
+    bool SetDelegate(SQTable *m);
+    virtual bool GetMetaMethod(SQVM *v,SQMetaMethod mm,SQObjectPtr &res);
+    SQTable *_delegate;
+};
+
+SQUnsignedInteger TranslateIndex(const SQObjectPtr &idx);
+typedef sqvector<SQObjectPtr> SQObjectPtrVec;
+typedef sqvector<SQInteger> SQIntVec;
+const SQChar *GetTypeName(const SQObjectPtr &obj1);
+const SQChar *IdType2Name(SQObjectType type);
+
+
+
+#endif //_SQOBJECT_H_

+ 132 - 132
squirrel/sqopcodes.h

@@ -1,132 +1,132 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQOPCODES_H_
-#define _SQOPCODES_H_
-
-#define MAX_FUNC_STACKSIZE 0xFF
-#define MAX_LITERALS ((SQInteger)0x7FFFFFFF)
-
-enum BitWiseOP {
-	BW_AND = 0,
-	BW_OR = 2,	
-	BW_XOR = 3,
-	BW_SHIFTL = 4,
-	BW_SHIFTR = 5,
-	BW_USHIFTR = 6
-};
-
-enum CmpOP {
-	CMP_G = 0,
-	CMP_GE = 2,	
-	CMP_L = 3,
-	CMP_LE = 4,
-	CMP_3W = 5
-};
-
-enum NewObjectType {
-	NOT_TABLE = 0,
-	NOT_ARRAY = 1,
-	NOT_CLASS = 2
-};
-
-enum AppendArrayType {
-	AAT_STACK = 0,
-	AAT_LITERAL = 1,
-	AAT_INT = 2,
-	AAT_FLOAT = 3,
-	AAT_BOOL = 4
-};
-
-enum SQOpcode
-{
-	_OP_LINE=				0x00,	
-	_OP_LOAD=				0x01,
-	_OP_LOADINT=			0x02,
-	_OP_LOADFLOAT=			0x03,
-	_OP_DLOAD=				0x04,
-	_OP_TAILCALL=			0x05,	
-	_OP_CALL=				0x06,	
-	_OP_PREPCALL=			0x07,	
-	_OP_PREPCALLK=			0x08,	
-	_OP_GETK=				0x09,	
-	_OP_MOVE=				0x0A,	
-	_OP_NEWSLOT=			0x0B,	
-	_OP_DELETE=				0x0C,	
-	_OP_SET=				0x0D,	
-	_OP_GET=				0x0E,
-	_OP_EQ=					0x0F,
-	_OP_NE=					0x10,
-	_OP_ADD=				0x11,
-	_OP_SUB=				0x12,
-	_OP_MUL=				0x13,
-	_OP_DIV=				0x14,
-	_OP_MOD=				0x15,
-	_OP_BITW=				0x16,
-	_OP_RETURN=				0x17,	
-	_OP_LOADNULLS=			0x18,	
-	_OP_LOADROOT=			0x19,
-	_OP_LOADBOOL=			0x1A,
-	_OP_DMOVE=				0x1B,	
-	_OP_JMP=				0x1C,	
-	//_OP_JNZ=				0x1D,
-	_OP_JCMP=				0x1D,
-	_OP_JZ=					0x1E,	
-	_OP_SETOUTER=			0x1F,	
-	_OP_GETOUTER=			0x20,	
-	_OP_NEWOBJ=				0x21,
-	_OP_APPENDARRAY=		0x22,	
-	_OP_COMPARITH=			0x23,	
-	_OP_INC=				0x24,	
-	_OP_INCL=				0x25,	
-	_OP_PINC=				0x26,	
-	_OP_PINCL=				0x27,	
-	_OP_CMP=				0x28,
-	_OP_EXISTS=				0x29,	
-	_OP_INSTANCEOF=			0x2A,
-	_OP_AND=				0x2B,
-	_OP_OR=					0x2C,
-	_OP_NEG=				0x2D,
-	_OP_NOT=				0x2E,
-	_OP_BWNOT=				0x2F,	
-	_OP_CLOSURE=			0x30,	
-	_OP_YIELD=				0x31,	
-	_OP_RESUME=				0x32,
-	_OP_FOREACH=			0x33,
-	_OP_POSTFOREACH=		0x34,
-	_OP_CLONE=				0x35,
-	_OP_TYPEOF=				0x36,
-	_OP_PUSHTRAP=			0x37,
-	_OP_POPTRAP=			0x38,
-	_OP_THROW=				0x39,
-	_OP_NEWSLOTA=			0x3A,
-	_OP_GETBASE=			0x3B,
-	_OP_CLOSE=				0x3C
-};							  
-
-struct SQInstructionDesc {	  
-	const SQChar *name;		  
-};							  
-
-struct SQInstruction 
-{
-	SQInstruction(){};
-	SQInstruction(SQOpcode _op,SQInteger a0=0,SQInteger a1=0,SQInteger a2=0,SQInteger a3=0)
-	{	op = _op;
-		_arg0 = (unsigned char)a0;_arg1 = (SQInt32)a1;
-		_arg2 = (unsigned char)a2;_arg3 = (unsigned char)a3;
-	}
-    
-	
-	SQInt32 _arg1;
-	unsigned char op;
-	unsigned char _arg0;
-	unsigned char _arg2;
-	unsigned char _arg3;
-};
-
-#include "squtils.h"
-typedef sqvector<SQInstruction> SQInstructionVec;
-
-#define NEW_SLOT_ATTRIBUTES_FLAG	0x01
-#define NEW_SLOT_STATIC_FLAG		0x02
-
-#endif // _SQOPCODES_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQOPCODES_H_
+#define _SQOPCODES_H_
+
+#define MAX_FUNC_STACKSIZE 0xFF
+#define MAX_LITERALS ((SQInteger)0x7FFFFFFF)
+
+enum BitWiseOP {
+    BW_AND = 0,
+    BW_OR = 2,
+    BW_XOR = 3,
+    BW_SHIFTL = 4,
+    BW_SHIFTR = 5,
+    BW_USHIFTR = 6
+};
+
+enum CmpOP {
+    CMP_G = 0,
+    CMP_GE = 2,
+    CMP_L = 3,
+    CMP_LE = 4,
+    CMP_3W = 5
+};
+
+enum NewObjectType {
+    NOT_TABLE = 0,
+    NOT_ARRAY = 1,
+    NOT_CLASS = 2
+};
+
+enum AppendArrayType {
+    AAT_STACK = 0,
+    AAT_LITERAL = 1,
+    AAT_INT = 2,
+    AAT_FLOAT = 3,
+    AAT_BOOL = 4
+};
+
+enum SQOpcode
+{
+    _OP_LINE=               0x00,
+    _OP_LOAD=               0x01,
+    _OP_LOADINT=            0x02,
+    _OP_LOADFLOAT=          0x03,
+    _OP_DLOAD=              0x04,
+    _OP_TAILCALL=           0x05,
+    _OP_CALL=               0x06,
+    _OP_PREPCALL=           0x07,
+    _OP_PREPCALLK=          0x08,
+    _OP_GETK=               0x09,
+    _OP_MOVE=               0x0A,
+    _OP_NEWSLOT=            0x0B,
+    _OP_DELETE=             0x0C,
+    _OP_SET=                0x0D,
+    _OP_GET=                0x0E,
+    _OP_EQ=                 0x0F,
+    _OP_NE=                 0x10,
+    _OP_ADD=                0x11,
+    _OP_SUB=                0x12,
+    _OP_MUL=                0x13,
+    _OP_DIV=                0x14,
+    _OP_MOD=                0x15,
+    _OP_BITW=               0x16,
+    _OP_RETURN=             0x17,
+    _OP_LOADNULLS=          0x18,
+    _OP_LOADROOT=           0x19,
+    _OP_LOADBOOL=           0x1A,
+    _OP_DMOVE=              0x1B,
+    _OP_JMP=                0x1C,
+    //_OP_JNZ=              0x1D,
+    _OP_JCMP=               0x1D,
+    _OP_JZ=                 0x1E,
+    _OP_SETOUTER=           0x1F,
+    _OP_GETOUTER=           0x20,
+    _OP_NEWOBJ=             0x21,
+    _OP_APPENDARRAY=        0x22,
+    _OP_COMPARITH=          0x23,
+    _OP_INC=                0x24,
+    _OP_INCL=               0x25,
+    _OP_PINC=               0x26,
+    _OP_PINCL=              0x27,
+    _OP_CMP=                0x28,
+    _OP_EXISTS=             0x29,
+    _OP_INSTANCEOF=         0x2A,
+    _OP_AND=                0x2B,
+    _OP_OR=                 0x2C,
+    _OP_NEG=                0x2D,
+    _OP_NOT=                0x2E,
+    _OP_BWNOT=              0x2F,
+    _OP_CLOSURE=            0x30,
+    _OP_YIELD=              0x31,
+    _OP_RESUME=             0x32,
+    _OP_FOREACH=            0x33,
+    _OP_POSTFOREACH=        0x34,
+    _OP_CLONE=              0x35,
+    _OP_TYPEOF=             0x36,
+    _OP_PUSHTRAP=           0x37,
+    _OP_POPTRAP=            0x38,
+    _OP_THROW=              0x39,
+    _OP_NEWSLOTA=           0x3A,
+    _OP_GETBASE=            0x3B,
+    _OP_CLOSE=              0x3C
+};
+
+struct SQInstructionDesc {
+    const SQChar *name;
+};
+
+struct SQInstruction
+{
+    SQInstruction(){};
+    SQInstruction(SQOpcode _op,SQInteger a0=0,SQInteger a1=0,SQInteger a2=0,SQInteger a3=0)
+    {   op = _op;
+        _arg0 = (unsigned char)a0;_arg1 = (SQInt32)a1;
+        _arg2 = (unsigned char)a2;_arg3 = (unsigned char)a3;
+    }
+
+
+    SQInt32 _arg1;
+    unsigned char op;
+    unsigned char _arg0;
+    unsigned char _arg2;
+    unsigned char _arg3;
+};
+
+#include "squtils.h"
+typedef sqvector<SQInstruction> SQInstructionVec;
+
+#define NEW_SLOT_ATTRIBUTES_FLAG    0x01
+#define NEW_SLOT_STATIC_FLAG        0x02
+
+#endif // _SQOPCODES_H_

+ 20 - 20
squirrel/sqpcheader.h

@@ -1,20 +1,20 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQPCHEADER_H_
-#define _SQPCHEADER_H_
-
-#if defined(_MSC_VER) && defined(_DEBUG)
-#include <crtdbg.h>
-#endif 
-
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <assert.h>
-#include <new>
-//squirrel stuff
-#include <squirrel.h>
-#include "sqobject.h"
-#include "sqstate.h"
-
-#endif //_SQPCHEADER_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQPCHEADER_H_
+#define _SQPCHEADER_H_
+
+#if defined(_MSC_VER) && defined(_DEBUG)
+#include <crtdbg.h>
+#endif
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <new>
+//squirrel stuff
+#include <squirrel.h>
+#include "sqobject.h"
+#include "sqstate.h"
+
+#endif //_SQPCHEADER_H_

+ 658 - 658
squirrel/sqstate.cpp

@@ -1,658 +1,658 @@
-/*
-	see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include "sqopcodes.h"
-#include "sqvm.h"
-#include "sqfuncproto.h"
-#include "sqclosure.h"
-#include "sqstring.h"
-#include "sqtable.h"
-#include "sqarray.h"
-#include "squserdata.h"
-#include "sqclass.h"
-
-//SQObjectPtr _null_;
-//SQObjectPtr _true_(true);
-//SQObjectPtr _false_(false);
-//SQObjectPtr _one_((SQInteger)1);
-//SQObjectPtr _minusone_((SQInteger)-1);
-
-SQSharedState::SQSharedState()
-{
-	_compilererrorhandler = NULL;
-	_printfunc = NULL;
-	_errorfunc = NULL;
-	_debuginfo = false;
-	_notifyallexceptions = false;
-	_foreignptr = NULL;
-	_releasehook = NULL;
-}
-
-#define newsysstring(s) {	\
-	_systemstrings->push_back(SQString::Create(this,s));	\
-	}
-
-#define newmetamethod(s) {	\
-	_metamethods->push_back(SQString::Create(this,s));	\
-	_table(_metamethodsmap)->NewSlot(_metamethods->back(),(SQInteger)(_metamethods->size()-1)); \
-	}
-
-bool CompileTypemask(SQIntVec &res,const SQChar *typemask)
-{
-	SQInteger i = 0;
-	
-	SQInteger mask = 0;
-	while(typemask[i] != 0) {
-		
-		switch(typemask[i]){
-				case 'o': mask |= _RT_NULL; break;
-				case 'i': mask |= _RT_INTEGER; break;
-				case 'f': mask |= _RT_FLOAT; break;
-				case 'n': mask |= (_RT_FLOAT | _RT_INTEGER); break;
-				case 's': mask |= _RT_STRING; break;
-				case 't': mask |= _RT_TABLE; break;
-				case 'a': mask |= _RT_ARRAY; break;
-				case 'u': mask |= _RT_USERDATA; break;
-				case 'c': mask |= (_RT_CLOSURE | _RT_NATIVECLOSURE); break;
-				case 'b': mask |= _RT_BOOL; break;
-				case 'g': mask |= _RT_GENERATOR; break;
-				case 'p': mask |= _RT_USERPOINTER; break;
-				case 'v': mask |= _RT_THREAD; break;
-				case 'x': mask |= _RT_INSTANCE; break;
-				case 'y': mask |= _RT_CLASS; break;
-				case 'r': mask |= _RT_WEAKREF; break;
-				case '.': mask = -1; res.push_back(mask); i++; mask = 0; continue;
-				case ' ': i++; continue; //ignores spaces
-				default:
-					return false;
-		}
-		i++;
-		if(typemask[i] == '|') { 
-			i++; 
-			if(typemask[i] == 0)
-				return false;
-			continue; 
-		}
-		res.push_back(mask);
-		mask = 0;
-		
-	}
-	return true;
-}
-
-SQTable *CreateDefaultDelegate(SQSharedState *ss,SQRegFunction *funcz)
-{
-	SQInteger i=0;
-	SQTable *t=SQTable::Create(ss,0);
-	while(funcz[i].name!=0){
-		SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f,0);
-		nc->_nparamscheck = funcz[i].nparamscheck;
-		nc->_name = SQString::Create(ss,funcz[i].name);
-		if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask))
-			return NULL;
-		t->NewSlot(SQString::Create(ss,funcz[i].name),nc);
-		i++;
-	}
-	return t;
-}
-
-void SQSharedState::Init()
-{	
-	_scratchpad=NULL;
-	_scratchpadsize=0;
-#ifndef NO_GARBAGE_COLLECTOR
-	_gc_chain=NULL;
-#endif
-	_stringtable = (SQStringTable*)SQ_MALLOC(sizeof(SQStringTable));
-	new (_stringtable) SQStringTable(this);
-	sq_new(_metamethods,SQObjectPtrVec);
-	sq_new(_systemstrings,SQObjectPtrVec);
-	sq_new(_types,SQObjectPtrVec);
-	_metamethodsmap = SQTable::Create(this,MT_LAST-1);
-	//adding type strings to avoid memory trashing
-	//types names
-	newsysstring(_SC("null"));
-	newsysstring(_SC("table"));
-	newsysstring(_SC("array"));
-	newsysstring(_SC("closure"));
-	newsysstring(_SC("string"));
-	newsysstring(_SC("userdata"));
-	newsysstring(_SC("integer"));
-	newsysstring(_SC("float"));
-	newsysstring(_SC("userpointer"));
-	newsysstring(_SC("function"));
-	newsysstring(_SC("generator"));
-	newsysstring(_SC("thread"));
-	newsysstring(_SC("class"));
-	newsysstring(_SC("instance"));
-	newsysstring(_SC("bool"));
-	//meta methods
-	newmetamethod(MM_ADD);
-	newmetamethod(MM_SUB);
-	newmetamethod(MM_MUL);
-	newmetamethod(MM_DIV);
-	newmetamethod(MM_UNM);
-	newmetamethod(MM_MODULO);
-	newmetamethod(MM_SET);
-	newmetamethod(MM_GET);
-	newmetamethod(MM_TYPEOF);
-	newmetamethod(MM_NEXTI);
-	newmetamethod(MM_CMP);
-	newmetamethod(MM_CALL);
-	newmetamethod(MM_CLONED);
-	newmetamethod(MM_NEWSLOT);
-	newmetamethod(MM_DELSLOT);
-	newmetamethod(MM_TOSTRING);
-	newmetamethod(MM_NEWMEMBER);
-	newmetamethod(MM_INHERITED);
-
-	_constructoridx = SQString::Create(this,_SC("constructor"));
-	_registry = SQTable::Create(this,0);
-	_consts = SQTable::Create(this,0);
-	_table_default_delegate = CreateDefaultDelegate(this,_table_default_delegate_funcz);
-	_array_default_delegate = CreateDefaultDelegate(this,_array_default_delegate_funcz);
-	_string_default_delegate = CreateDefaultDelegate(this,_string_default_delegate_funcz);
-	_number_default_delegate = CreateDefaultDelegate(this,_number_default_delegate_funcz);
-	_closure_default_delegate = CreateDefaultDelegate(this,_closure_default_delegate_funcz);
-	_generator_default_delegate = CreateDefaultDelegate(this,_generator_default_delegate_funcz);
-	_thread_default_delegate = CreateDefaultDelegate(this,_thread_default_delegate_funcz);
-	_class_default_delegate = CreateDefaultDelegate(this,_class_default_delegate_funcz);
-	_instance_default_delegate = CreateDefaultDelegate(this,_instance_default_delegate_funcz);
-	_weakref_default_delegate = CreateDefaultDelegate(this,_weakref_default_delegate_funcz);
-
-}
-
-SQSharedState::~SQSharedState()
-{
-	if(_releasehook) { _releasehook(_foreignptr,0); _releasehook = NULL; }
-	_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;
-	if(t) {
-		t->_uiRef++;
-		while(t) {
-			t->Finalize();
-			nx = t->_next;
-			if(nx) nx->_uiRef++;
-			if(--t->_uiRef == 0)
-				t->Release();
-			t = nx;
-		}
-	}
-	assert(_gc_chain==NULL); //just to proove a theory
-	while(_gc_chain){
-		_gc_chain->_uiRef++;
-		_gc_chain->Release();
-	}
-#endif
-
-	sq_delete(_types,SQObjectPtrVec);
-	sq_delete(_systemstrings,SQObjectPtrVec);
-	sq_delete(_metamethods,SQObjectPtrVec);
-	sq_delete(_stringtable,SQStringTable);
-	if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);
-}
-
-
-SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name)
-{
-	if(type(name) != OT_STRING)
-		return -1;
-	SQObjectPtr ret;
-	if(_table(_metamethodsmap)->Get(name,ret)) {
-		return _integer(ret);
-	}
-	return -1;
-}
-
-#ifndef NO_GARBAGE_COLLECTOR
-
-void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)
-{
-	switch(type(o)){
-	case OT_TABLE:_table(o)->Mark(chain);break;
-	case OT_ARRAY:_array(o)->Mark(chain);break;
-	case OT_USERDATA:_userdata(o)->Mark(chain);break;
-	case OT_CLOSURE:_closure(o)->Mark(chain);break;
-	case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break;
-	case OT_GENERATOR:_generator(o)->Mark(chain);break;
-	case OT_THREAD:_thread(o)->Mark(chain);break;
-	case OT_CLASS:_class(o)->Mark(chain);break;
-	case OT_INSTANCE:_instance(o)->Mark(chain);break;
-	case OT_OUTER:_outer(o)->Mark(chain);break;
-	case OT_FUNCPROTO:_funcproto(o)->Mark(chain);break;
-	default: break; //shutup compiler
-	}
-}
-
-
-void SQSharedState::RunMark(SQVM *vm,SQCollectable **tchain)
-{
-	SQVM *vms = _thread(_root_vm);
-	
-	vms->Mark(tchain);
-	
-	_refs_table.Mark(tchain);
-	MarkObject(_registry,tchain);
-	MarkObject(_consts,tchain);
-	MarkObject(_metamethodsmap,tchain);
-	MarkObject(_table_default_delegate,tchain);
-	MarkObject(_array_default_delegate,tchain);
-	MarkObject(_string_default_delegate,tchain);
-	MarkObject(_number_default_delegate,tchain);
-	MarkObject(_generator_default_delegate,tchain);
-	MarkObject(_thread_default_delegate,tchain);
-	MarkObject(_closure_default_delegate,tchain);
-	MarkObject(_class_default_delegate,tchain);
-	MarkObject(_instance_default_delegate,tchain);
-	MarkObject(_weakref_default_delegate,tchain);
-
-}
-
-SQInteger SQSharedState::ResurrectUnreachable(SQVM *vm)
-{
-	SQInteger n=0;
-	SQCollectable *tchain=NULL;
-
-	RunMark(vm,&tchain);
-
-	SQCollectable *resurrected = _gc_chain;
-	SQCollectable *t = resurrected;
-	//SQCollectable *nx = NULL;
-
-	_gc_chain = tchain;
-
-	SQArray *ret = NULL;
-	if(resurrected) {
-		ret = SQArray::Create(this,0);
-		SQCollectable *rlast = NULL;
-		while(t) {
-			rlast = t;
-			SQObjectType type = t->GetType();
-			if(type != OT_FUNCPROTO && type != OT_OUTER) {
-				SQObject sqo;
-				sqo._type = type;
-				sqo._unVal.pRefCounted = t;
-				ret->Append(sqo);
-			}
-			t = t->_next;
-			n++;
-		}
-
-		assert(rlast->_next == NULL);
-		rlast->_next = _gc_chain;
-		if(_gc_chain)
-		{
-			_gc_chain->_prev = rlast;
-		}
-		_gc_chain = resurrected;
-	}
-
-	t = _gc_chain;
-	while(t) {
-		t->UnMark();
-		t = t->_next;
-	}
-
-	if(ret) {
-		SQObjectPtr temp = ret;
-		vm->Push(temp);
-	}
-	else {
-		vm->PushNull();
-	}
-	return n;
-}
-
-SQInteger SQSharedState::CollectGarbage(SQVM *vm)
-{
-	SQInteger n = 0;
-	SQCollectable *tchain = NULL;
-
-	RunMark(vm,&tchain);
-
-	SQCollectable *t = _gc_chain;
-	SQCollectable *nx = NULL;
-	if(t) {
-		t->_uiRef++;
-		while(t) {
-			t->Finalize();
-			nx = t->_next;
-			if(nx) nx->_uiRef++;
-			if(--t->_uiRef == 0)
-				t->Release();
-			t = nx;
-			n++;
-		}
-	}
-
-	t = tchain;
-	while(t) {
-		t->UnMark();
-		t = t->_next;
-	}
-	_gc_chain = tchain;
-	
-	return n;
-}
-#endif
-
-#ifndef NO_GARBAGE_COLLECTOR
-void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)
-{
-    c->_prev = NULL;
-	c->_next = *chain;
-	if(*chain) (*chain)->_prev = c;
-	*chain = c;
-}
-
-void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)
-{
-	if(c->_prev) c->_prev->_next = c->_next;
-	else *chain = c->_next;
-	if(c->_next)
-		c->_next->_prev = c->_prev;
-	c->_next = NULL;
-	c->_prev = NULL;
-}
-#endif
-
-SQChar* SQSharedState::GetScratchPad(SQInteger size)
-{
-	SQInteger newsize;
-	if(size>0) {
-		if(_scratchpadsize < size) {
-			newsize = size + (size>>1);
-			_scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
-			_scratchpadsize = newsize;
-
-		}else if(_scratchpadsize >= (size<<5)) {
-			newsize = _scratchpadsize >> 1;
-			_scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
-			_scratchpadsize = newsize;
-		}
-	}
-	return _scratchpad;
-}
-
-RefTable::RefTable()
-{
-	AllocNodes(4);
-}
-
-void RefTable::Finalize()
-{
-	RefNode *nodes = _nodes;
-	for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
-		nodes->obj.Null();
-		nodes++;
-	}
-}
-
-RefTable::~RefTable()
-{
-	SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode)));
-}
-
-#ifndef NO_GARBAGE_COLLECTOR
-void RefTable::Mark(SQCollectable **chain)
-{
-	RefNode *nodes = (RefNode *)_nodes;
-	for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
-		if(type(nodes->obj) != OT_NULL) {
-			SQSharedState::MarkObject(nodes->obj,chain);
-		}
-		nodes++;
-	}
-}
-#endif
-
-void RefTable::AddRef(SQObject &obj)
-{
-	SQHash mainpos;
-	RefNode *prev;
-	RefNode *ref = Get(obj,mainpos,&prev,true);
-	ref->refs++;
-}
-
-SQUnsignedInteger RefTable::GetRefCount(SQObject &obj)
-{
-     SQHash mainpos;
-     RefNode *prev;
-     RefNode *ref = Get(obj,mainpos,&prev,true);
-     return ref->refs;
-}
-
-
-SQBool RefTable::Release(SQObject &obj)
-{
-	SQHash mainpos;
-	RefNode *prev;
-	RefNode *ref = Get(obj,mainpos,&prev,false);
-	if(ref) {
-		if(--ref->refs == 0) {
-			SQObjectPtr o = ref->obj;
-			if(prev) {
-				prev->next = ref->next;
-			}
-			else {
-				_buckets[mainpos] = ref->next;
-			}
-			ref->next = _freelist;
-			_freelist = ref;
-			_slotused--;
-			ref->obj.Null();
-			//<<FIXME>>test for shrink?
-			return SQTrue;
-		}
-	}
-	else {
-		assert(0);
-	}
-	return SQFalse;
-}
-
-void RefTable::Resize(SQUnsignedInteger size)
-{
-	RefNode **oldbucks = _buckets;
-	RefNode *t = _nodes;
-	SQUnsignedInteger oldnumofslots = _numofslots;
-	AllocNodes(size);
-	//rehash
-	SQUnsignedInteger nfound = 0;
-	for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {
-		if(type(t->obj) != OT_NULL) {
-			//add back;
-			assert(t->refs != 0);
-			RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj);
-			nn->refs = t->refs; 
-			t->obj.Null();
-			nfound++;
-		}
-		t++;
-	}
-	assert(nfound == oldnumofslots);
-	SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode)));
-}
-
-RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj)
-{
-	RefNode *t = _buckets[mainpos];
-	RefNode *newnode = _freelist;
-	newnode->obj = obj;
-	_buckets[mainpos] = newnode;
-	_freelist = _freelist->next;
-	newnode->next = t;
-	assert(newnode->refs == 0);
-	_slotused++;
-	return newnode;
-}
-
-RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add)
-{
-	RefNode *ref;
-	mainpos = ::HashObj(obj)&(_numofslots-1);
-	*prev = NULL;
-	for (ref = _buckets[mainpos]; ref; ) {
-		if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj))
-			break;
-		*prev = ref;
-		ref = ref->next;
-	}
-	if(ref == NULL && add) {
-		if(_numofslots == _slotused) {
-			assert(_freelist == 0);
-			Resize(_numofslots*2);
-			mainpos = ::HashObj(obj)&(_numofslots-1);
-		}
-		ref = Add(mainpos,obj);
-	}
-	return ref;
-}
-
-void RefTable::AllocNodes(SQUnsignedInteger size)
-{
-	RefNode **bucks;
-	RefNode *nodes;
-	bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode)));
-	nodes = (RefNode *)&bucks[size];
-	RefNode *temp = nodes;
-	SQUnsignedInteger n;
-	for(n = 0; n < size - 1; n++) {
-		bucks[n] = NULL;
-		temp->refs = 0;
-		new (&temp->obj) SQObjectPtr;
-		temp->next = temp+1;
-		temp++;
-	}
-	bucks[n] = NULL;
-	temp->refs = 0;
-	new (&temp->obj) SQObjectPtr;
-	temp->next = NULL;
-	_freelist = nodes;
-	_nodes = nodes;
-	_buckets = bucks;
-	_slotused = 0;
-	_numofslots = size;
-}
-//////////////////////////////////////////////////////////////////////////
-//SQStringTable
-/*
-* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
-* http://www.lua.org/copyright.html#4
-* http://www.lua.org/source/4.0.1/src_lstring.c.html
-*/
-
-SQStringTable::SQStringTable(SQSharedState *ss)
-{
-	_sharedstate = ss;
-	AllocNodes(4);
-	_slotused = 0;
-}
-
-SQStringTable::~SQStringTable()
-{
-	SQ_FREE(_strings,sizeof(SQString*)*_numofslots);
-	_strings = NULL;
-}
-
-void SQStringTable::AllocNodes(SQInteger size)
-{
-	_numofslots = size;
-	_strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
-	memset(_strings,0,sizeof(SQString*)*_numofslots);
-}
-
-SQString *SQStringTable::Add(const SQChar *news,SQInteger len)
-{
-	if(len<0)
-		len = (SQInteger)scstrlen(news);
-	SQHash newhash = ::_hashstr(news,len);
-	SQHash h = newhash&(_numofslots-1);
-	SQString *s;
-	for (s = _strings[h]; s; s = s->_next){
-		if(s->_len == len && (!memcmp(news,s->_val,sq_rsl(len))))
-			return s; //found
-	}
-
-	SQString *t = (SQString *)SQ_MALLOC(sq_rsl(len)+sizeof(SQString));
-	new (t) SQString;
-	t->_sharedstate = _sharedstate;
-	memcpy(t->_val,news,sq_rsl(len));
-	t->_val[len] = _SC('\0');
-	t->_len = len;
-	t->_hash = newhash;
-	t->_next = _strings[h];
-	_strings[h] = t;
-	_slotused++;
-	if (_slotused > _numofslots)  /* too crowded? */
-		Resize(_numofslots*2);
-	return t;
-}
-
-void SQStringTable::Resize(SQInteger size)
-{
-	SQInteger oldsize=_numofslots;
-	SQString **oldtable=_strings;
-	AllocNodes(size);
-	for (SQInteger i=0; i<oldsize; i++){
-		SQString *p = oldtable[i];
-		while(p){
-			SQString *next = p->_next;
-			SQHash h = p->_hash&(_numofslots-1);
-			p->_next = _strings[h];
-			_strings[h] = p;
-			p = next;
-		}
-	}
-	SQ_FREE(oldtable,oldsize*sizeof(SQString*));
-}
-
-void SQStringTable::Remove(SQString *bs)
-{
-	SQString *s;
-	SQString *prev=NULL;
-	SQHash h = bs->_hash&(_numofslots - 1);
-	
-	for (s = _strings[h]; s; ){
-		if(s == bs){
-			if(prev)
-				prev->_next = s->_next;
-			else
-				_strings[h] = s->_next;
-			_slotused--;
-			SQInteger slen = s->_len;
-			s->~SQString();
-			SQ_FREE(s,sizeof(SQString) + sq_rsl(slen));
-			return;
-		}
-		prev = s;
-		s = s->_next;
-	}
-	assert(0);//if this fail something is wrong
-}
+/*
+    see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqopcodes.h"
+#include "sqvm.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+#include "sqstring.h"
+#include "sqtable.h"
+#include "sqarray.h"
+#include "squserdata.h"
+#include "sqclass.h"
+
+//SQObjectPtr _null_;
+//SQObjectPtr _true_(true);
+//SQObjectPtr _false_(false);
+//SQObjectPtr _one_((SQInteger)1);
+//SQObjectPtr _minusone_((SQInteger)-1);
+
+SQSharedState::SQSharedState()
+{
+    _compilererrorhandler = NULL;
+    _printfunc = NULL;
+    _errorfunc = NULL;
+    _debuginfo = false;
+    _notifyallexceptions = false;
+    _foreignptr = NULL;
+    _releasehook = NULL;
+}
+
+#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,const SQRegFunction *funcz)
+{
+    SQInteger i=0;
+    SQTable *t=SQTable::Create(ss,0);
+    while(funcz[i].name!=0){
+        SQNativeClosure *nc = SQNativeClosure::Create(ss,funcz[i].f,0);
+        nc->_nparamscheck = funcz[i].nparamscheck;
+        nc->_name = SQString::Create(ss,funcz[i].name);
+        if(funcz[i].typemask && !CompileTypemask(nc->_typecheck,funcz[i].typemask))
+            return NULL;
+        t->NewSlot(SQString::Create(ss,funcz[i].name),nc);
+        i++;
+    }
+    return t;
+}
+
+void SQSharedState::Init()
+{
+    _scratchpad=NULL;
+    _scratchpadsize=0;
+#ifndef NO_GARBAGE_COLLECTOR
+    _gc_chain=NULL;
+#endif
+    _stringtable = (SQStringTable*)SQ_MALLOC(sizeof(SQStringTable));
+    new (_stringtable) SQStringTable(this);
+    sq_new(_metamethods,SQObjectPtrVec);
+    sq_new(_systemstrings,SQObjectPtrVec);
+    sq_new(_types,SQObjectPtrVec);
+    _metamethodsmap = SQTable::Create(this,MT_LAST-1);
+    //adding type strings to avoid memory trashing
+    //types names
+    newsysstring(_SC("null"));
+    newsysstring(_SC("table"));
+    newsysstring(_SC("array"));
+    newsysstring(_SC("closure"));
+    newsysstring(_SC("string"));
+    newsysstring(_SC("userdata"));
+    newsysstring(_SC("integer"));
+    newsysstring(_SC("float"));
+    newsysstring(_SC("userpointer"));
+    newsysstring(_SC("function"));
+    newsysstring(_SC("generator"));
+    newsysstring(_SC("thread"));
+    newsysstring(_SC("class"));
+    newsysstring(_SC("instance"));
+    newsysstring(_SC("bool"));
+    //meta methods
+    newmetamethod(MM_ADD);
+    newmetamethod(MM_SUB);
+    newmetamethod(MM_MUL);
+    newmetamethod(MM_DIV);
+    newmetamethod(MM_UNM);
+    newmetamethod(MM_MODULO);
+    newmetamethod(MM_SET);
+    newmetamethod(MM_GET);
+    newmetamethod(MM_TYPEOF);
+    newmetamethod(MM_NEXTI);
+    newmetamethod(MM_CMP);
+    newmetamethod(MM_CALL);
+    newmetamethod(MM_CLONED);
+    newmetamethod(MM_NEWSLOT);
+    newmetamethod(MM_DELSLOT);
+    newmetamethod(MM_TOSTRING);
+    newmetamethod(MM_NEWMEMBER);
+    newmetamethod(MM_INHERITED);
+
+    _constructoridx = SQString::Create(this,_SC("constructor"));
+    _registry = SQTable::Create(this,0);
+    _consts = SQTable::Create(this,0);
+    _table_default_delegate = CreateDefaultDelegate(this,_table_default_delegate_funcz);
+    _array_default_delegate = CreateDefaultDelegate(this,_array_default_delegate_funcz);
+    _string_default_delegate = CreateDefaultDelegate(this,_string_default_delegate_funcz);
+    _number_default_delegate = CreateDefaultDelegate(this,_number_default_delegate_funcz);
+    _closure_default_delegate = CreateDefaultDelegate(this,_closure_default_delegate_funcz);
+    _generator_default_delegate = CreateDefaultDelegate(this,_generator_default_delegate_funcz);
+    _thread_default_delegate = CreateDefaultDelegate(this,_thread_default_delegate_funcz);
+    _class_default_delegate = CreateDefaultDelegate(this,_class_default_delegate_funcz);
+    _instance_default_delegate = CreateDefaultDelegate(this,_instance_default_delegate_funcz);
+    _weakref_default_delegate = CreateDefaultDelegate(this,_weakref_default_delegate_funcz);
+
+}
+
+SQSharedState::~SQSharedState()
+{
+    if(_releasehook) { _releasehook(_foreignptr,0); _releasehook = NULL; }
+    _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;
+    if(t) {
+        t->_uiRef++;
+        while(t) {
+            t->Finalize();
+            nx = t->_next;
+            if(nx) nx->_uiRef++;
+            if(--t->_uiRef == 0)
+                t->Release();
+            t = nx;
+        }
+    }
+    assert(_gc_chain==NULL); //just to proove a theory
+    while(_gc_chain){
+        _gc_chain->_uiRef++;
+        _gc_chain->Release();
+    }
+#endif
+
+    sq_delete(_types,SQObjectPtrVec);
+    sq_delete(_systemstrings,SQObjectPtrVec);
+    sq_delete(_metamethods,SQObjectPtrVec);
+    sq_delete(_stringtable,SQStringTable);
+    if(_scratchpad)SQ_FREE(_scratchpad,_scratchpadsize);
+}
+
+
+SQInteger SQSharedState::GetMetaMethodIdxByName(const SQObjectPtr &name)
+{
+    if(type(name) != OT_STRING)
+        return -1;
+    SQObjectPtr ret;
+    if(_table(_metamethodsmap)->Get(name,ret)) {
+        return _integer(ret);
+    }
+    return -1;
+}
+
+#ifndef NO_GARBAGE_COLLECTOR
+
+void SQSharedState::MarkObject(SQObjectPtr &o,SQCollectable **chain)
+{
+    switch(type(o)){
+    case OT_TABLE:_table(o)->Mark(chain);break;
+    case OT_ARRAY:_array(o)->Mark(chain);break;
+    case OT_USERDATA:_userdata(o)->Mark(chain);break;
+    case OT_CLOSURE:_closure(o)->Mark(chain);break;
+    case OT_NATIVECLOSURE:_nativeclosure(o)->Mark(chain);break;
+    case OT_GENERATOR:_generator(o)->Mark(chain);break;
+    case OT_THREAD:_thread(o)->Mark(chain);break;
+    case OT_CLASS:_class(o)->Mark(chain);break;
+    case OT_INSTANCE:_instance(o)->Mark(chain);break;
+    case OT_OUTER:_outer(o)->Mark(chain);break;
+    case OT_FUNCPROTO:_funcproto(o)->Mark(chain);break;
+    default: break; //shutup compiler
+    }
+}
+
+
+void SQSharedState::RunMark(SQVM *vm,SQCollectable **tchain)
+{
+    SQVM *vms = _thread(_root_vm);
+
+    vms->Mark(tchain);
+
+    _refs_table.Mark(tchain);
+    MarkObject(_registry,tchain);
+    MarkObject(_consts,tchain);
+    MarkObject(_metamethodsmap,tchain);
+    MarkObject(_table_default_delegate,tchain);
+    MarkObject(_array_default_delegate,tchain);
+    MarkObject(_string_default_delegate,tchain);
+    MarkObject(_number_default_delegate,tchain);
+    MarkObject(_generator_default_delegate,tchain);
+    MarkObject(_thread_default_delegate,tchain);
+    MarkObject(_closure_default_delegate,tchain);
+    MarkObject(_class_default_delegate,tchain);
+    MarkObject(_instance_default_delegate,tchain);
+    MarkObject(_weakref_default_delegate,tchain);
+
+}
+
+SQInteger SQSharedState::ResurrectUnreachable(SQVM *vm)
+{
+    SQInteger n=0;
+    SQCollectable *tchain=NULL;
+
+    RunMark(vm,&tchain);
+
+    SQCollectable *resurrected = _gc_chain;
+    SQCollectable *t = resurrected;
+    //SQCollectable *nx = NULL;
+
+    _gc_chain = tchain;
+
+    SQArray *ret = NULL;
+    if(resurrected) {
+        ret = SQArray::Create(this,0);
+        SQCollectable *rlast = NULL;
+        while(t) {
+            rlast = t;
+            SQObjectType type = t->GetType();
+            if(type != OT_FUNCPROTO && type != OT_OUTER) {
+                SQObject sqo;
+                sqo._type = type;
+                sqo._unVal.pRefCounted = t;
+                ret->Append(sqo);
+            }
+            t = t->_next;
+            n++;
+        }
+
+        assert(rlast->_next == NULL);
+        rlast->_next = _gc_chain;
+        if(_gc_chain)
+        {
+            _gc_chain->_prev = rlast;
+        }
+        _gc_chain = resurrected;
+    }
+
+    t = _gc_chain;
+    while(t) {
+        t->UnMark();
+        t = t->_next;
+    }
+
+    if(ret) {
+        SQObjectPtr temp = ret;
+        vm->Push(temp);
+    }
+    else {
+        vm->PushNull();
+    }
+    return n;
+}
+
+SQInteger SQSharedState::CollectGarbage(SQVM *vm)
+{
+    SQInteger n = 0;
+    SQCollectable *tchain = NULL;
+
+    RunMark(vm,&tchain);
+
+    SQCollectable *t = _gc_chain;
+    SQCollectable *nx = NULL;
+    if(t) {
+        t->_uiRef++;
+        while(t) {
+            t->Finalize();
+            nx = t->_next;
+            if(nx) nx->_uiRef++;
+            if(--t->_uiRef == 0)
+                t->Release();
+            t = nx;
+            n++;
+        }
+    }
+
+    t = tchain;
+    while(t) {
+        t->UnMark();
+        t = t->_next;
+    }
+    _gc_chain = tchain;
+
+    return n;
+}
+#endif
+
+#ifndef NO_GARBAGE_COLLECTOR
+void SQCollectable::AddToChain(SQCollectable **chain,SQCollectable *c)
+{
+    c->_prev = NULL;
+    c->_next = *chain;
+    if(*chain) (*chain)->_prev = c;
+    *chain = c;
+}
+
+void SQCollectable::RemoveFromChain(SQCollectable **chain,SQCollectable *c)
+{
+    if(c->_prev) c->_prev->_next = c->_next;
+    else *chain = c->_next;
+    if(c->_next)
+        c->_next->_prev = c->_prev;
+    c->_next = NULL;
+    c->_prev = NULL;
+}
+#endif
+
+SQChar* SQSharedState::GetScratchPad(SQInteger size)
+{
+    SQInteger newsize;
+    if(size>0) {
+        if(_scratchpadsize < size) {
+            newsize = size + (size>>1);
+            _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
+            _scratchpadsize = newsize;
+
+        }else if(_scratchpadsize >= (size<<5)) {
+            newsize = _scratchpadsize >> 1;
+            _scratchpad = (SQChar *)SQ_REALLOC(_scratchpad,_scratchpadsize,newsize);
+            _scratchpadsize = newsize;
+        }
+    }
+    return _scratchpad;
+}
+
+RefTable::RefTable()
+{
+    AllocNodes(4);
+}
+
+void RefTable::Finalize()
+{
+    RefNode *nodes = _nodes;
+    for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
+        nodes->obj.Null();
+        nodes++;
+    }
+}
+
+RefTable::~RefTable()
+{
+    SQ_FREE(_buckets,(_numofslots * sizeof(RefNode *)) + (_numofslots * sizeof(RefNode)));
+}
+
+#ifndef NO_GARBAGE_COLLECTOR
+void RefTable::Mark(SQCollectable **chain)
+{
+    RefNode *nodes = (RefNode *)_nodes;
+    for(SQUnsignedInteger n = 0; n < _numofslots; n++) {
+        if(type(nodes->obj) != OT_NULL) {
+            SQSharedState::MarkObject(nodes->obj,chain);
+        }
+        nodes++;
+    }
+}
+#endif
+
+void RefTable::AddRef(SQObject &obj)
+{
+    SQHash mainpos;
+    RefNode *prev;
+    RefNode *ref = Get(obj,mainpos,&prev,true);
+    ref->refs++;
+}
+
+SQUnsignedInteger RefTable::GetRefCount(SQObject &obj)
+{
+     SQHash mainpos;
+     RefNode *prev;
+     RefNode *ref = Get(obj,mainpos,&prev,true);
+     return ref->refs;
+}
+
+
+SQBool RefTable::Release(SQObject &obj)
+{
+    SQHash mainpos;
+    RefNode *prev;
+    RefNode *ref = Get(obj,mainpos,&prev,false);
+    if(ref) {
+        if(--ref->refs == 0) {
+            SQObjectPtr o = ref->obj;
+            if(prev) {
+                prev->next = ref->next;
+            }
+            else {
+                _buckets[mainpos] = ref->next;
+            }
+            ref->next = _freelist;
+            _freelist = ref;
+            _slotused--;
+            ref->obj.Null();
+            //<<FIXME>>test for shrink?
+            return SQTrue;
+        }
+    }
+    else {
+        assert(0);
+    }
+    return SQFalse;
+}
+
+void RefTable::Resize(SQUnsignedInteger size)
+{
+    RefNode **oldbucks = _buckets;
+    RefNode *t = _nodes;
+    SQUnsignedInteger oldnumofslots = _numofslots;
+    AllocNodes(size);
+    //rehash
+    SQUnsignedInteger nfound = 0;
+    for(SQUnsignedInteger n = 0; n < oldnumofslots; n++) {
+        if(type(t->obj) != OT_NULL) {
+            //add back;
+            assert(t->refs != 0);
+            RefNode *nn = Add(::HashObj(t->obj)&(_numofslots-1),t->obj);
+            nn->refs = t->refs;
+            t->obj.Null();
+            nfound++;
+        }
+        t++;
+    }
+    assert(nfound == oldnumofslots);
+    SQ_FREE(oldbucks,(oldnumofslots * sizeof(RefNode *)) + (oldnumofslots * sizeof(RefNode)));
+}
+
+RefTable::RefNode *RefTable::Add(SQHash mainpos,SQObject &obj)
+{
+    RefNode *t = _buckets[mainpos];
+    RefNode *newnode = _freelist;
+    newnode->obj = obj;
+    _buckets[mainpos] = newnode;
+    _freelist = _freelist->next;
+    newnode->next = t;
+    assert(newnode->refs == 0);
+    _slotused++;
+    return newnode;
+}
+
+RefTable::RefNode *RefTable::Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add)
+{
+    RefNode *ref;
+    mainpos = ::HashObj(obj)&(_numofslots-1);
+    *prev = NULL;
+    for (ref = _buckets[mainpos]; ref; ) {
+        if(_rawval(ref->obj) == _rawval(obj) && type(ref->obj) == type(obj))
+            break;
+        *prev = ref;
+        ref = ref->next;
+    }
+    if(ref == NULL && add) {
+        if(_numofslots == _slotused) {
+            assert(_freelist == 0);
+            Resize(_numofslots*2);
+            mainpos = ::HashObj(obj)&(_numofslots-1);
+        }
+        ref = Add(mainpos,obj);
+    }
+    return ref;
+}
+
+void RefTable::AllocNodes(SQUnsignedInteger size)
+{
+    RefNode **bucks;
+    RefNode *nodes;
+    bucks = (RefNode **)SQ_MALLOC((size * sizeof(RefNode *)) + (size * sizeof(RefNode)));
+    nodes = (RefNode *)&bucks[size];
+    RefNode *temp = nodes;
+    SQUnsignedInteger n;
+    for(n = 0; n < size - 1; n++) {
+        bucks[n] = NULL;
+        temp->refs = 0;
+        new (&temp->obj) SQObjectPtr;
+        temp->next = temp+1;
+        temp++;
+    }
+    bucks[n] = NULL;
+    temp->refs = 0;
+    new (&temp->obj) SQObjectPtr;
+    temp->next = NULL;
+    _freelist = nodes;
+    _nodes = nodes;
+    _buckets = bucks;
+    _slotused = 0;
+    _numofslots = size;
+}
+//////////////////////////////////////////////////////////////////////////
+//SQStringTable
+/*
+* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
+* http://www.lua.org/copyright.html#4
+* http://www.lua.org/source/4.0.1/src_lstring.c.html
+*/
+
+SQStringTable::SQStringTable(SQSharedState *ss)
+{
+    _sharedstate = ss;
+    AllocNodes(4);
+    _slotused = 0;
+}
+
+SQStringTable::~SQStringTable()
+{
+    SQ_FREE(_strings,sizeof(SQString*)*_numofslots);
+    _strings = NULL;
+}
+
+void SQStringTable::AllocNodes(SQInteger size)
+{
+    _numofslots = size;
+    _strings = (SQString**)SQ_MALLOC(sizeof(SQString*)*_numofslots);
+    memset(_strings,0,sizeof(SQString*)*_numofslots);
+}
+
+SQString *SQStringTable::Add(const SQChar *news,SQInteger len)
+{
+    if(len<0)
+        len = (SQInteger)scstrlen(news);
+    SQHash newhash = ::_hashstr(news,len);
+    SQHash h = newhash&(_numofslots-1);
+    SQString *s;
+    for (s = _strings[h]; s; s = s->_next){
+        if(s->_len == len && (!memcmp(news,s->_val,sq_rsl(len))))
+            return s; //found
+    }
+
+    SQString *t = (SQString *)SQ_MALLOC(sq_rsl(len)+sizeof(SQString));
+    new (t) SQString;
+    t->_sharedstate = _sharedstate;
+    memcpy(t->_val,news,sq_rsl(len));
+    t->_val[len] = _SC('\0');
+    t->_len = len;
+    t->_hash = newhash;
+    t->_next = _strings[h];
+    _strings[h] = t;
+    _slotused++;
+    if (_slotused > _numofslots)  /* too crowded? */
+        Resize(_numofslots*2);
+    return t;
+}
+
+void SQStringTable::Resize(SQInteger size)
+{
+    SQInteger oldsize=_numofslots;
+    SQString **oldtable=_strings;
+    AllocNodes(size);
+    for (SQInteger i=0; i<oldsize; i++){
+        SQString *p = oldtable[i];
+        while(p){
+            SQString *next = p->_next;
+            SQHash h = p->_hash&(_numofslots-1);
+            p->_next = _strings[h];
+            _strings[h] = p;
+            p = next;
+        }
+    }
+    SQ_FREE(oldtable,oldsize*sizeof(SQString*));
+}
+
+void SQStringTable::Remove(SQString *bs)
+{
+    SQString *s;
+    SQString *prev=NULL;
+    SQHash h = bs->_hash&(_numofslots - 1);
+
+    for (s = _strings[h]; s; ){
+        if(s == bs){
+            if(prev)
+                prev->_next = s->_next;
+            else
+                _strings[h] = s->_next;
+            _slotused--;
+            SQInteger slen = s->_len;
+            s->~SQString();
+            SQ_FREE(s,sizeof(SQString) + sq_rsl(slen));
+            return;
+        }
+        prev = s;
+        s = s->_next;
+    }
+    assert(0);//if this fail something is wrong
+}

+ 136 - 136
squirrel/sqstate.h

@@ -1,136 +1,136 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQSTATE_H_
-#define _SQSTATE_H_
-
-#include "squtils.h"
-#include "sqobject.h"
-struct SQString;
-struct SQTable;
-//max number of character for a printed number
-#define NUMBER_MAX_CHAR 50
-
-struct SQStringTable
-{
-	SQStringTable(SQSharedState*ss);
-	~SQStringTable();
-	SQString *Add(const SQChar *,SQInteger len);
-	void Remove(SQString *);
-private:
-	void Resize(SQInteger size);
-	void AllocNodes(SQInteger size);
-	SQString **_strings;
-	SQUnsignedInteger _numofslots;
-	SQUnsignedInteger _slotused;
-	SQSharedState *_sharedstate;
-};
-
-struct RefTable {
-	struct RefNode {
-		SQObjectPtr obj;
-		SQUnsignedInteger refs;
-		struct RefNode *next;
-	};
-	RefTable();
-	~RefTable();
-	void AddRef(SQObject &obj);
-	SQBool Release(SQObject &obj);
-	SQUnsignedInteger GetRefCount(SQObject &obj);
-#ifndef NO_GARBAGE_COLLECTOR
-	void Mark(SQCollectable **chain);
-#endif
-	void Finalize();
-private:
-	RefNode *Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add);
-	RefNode *Add(SQHash mainpos,SQObject &obj);
-	void Resize(SQUnsignedInteger size);
-	void AllocNodes(SQUnsignedInteger size);
-	SQUnsignedInteger _numofslots;
-	SQUnsignedInteger _slotused;
-	RefNode *_nodes;
-	RefNode *_freelist;
-	RefNode **_buckets;
-};
-
-#define ADD_STRING(ss,str,len) ss->_stringtable->Add(str,len)
-#define REMOVE_STRING(ss,bstr) ss->_stringtable->Remove(bstr)
-
-struct SQObjectPtr;
-
-struct SQSharedState
-{
-	SQSharedState();
-	~SQSharedState();
-	void Init();
-public:
-	SQChar* GetScratchPad(SQInteger size);
-	SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name);
-#ifndef NO_GARBAGE_COLLECTOR
-	SQInteger CollectGarbage(SQVM *vm);
-	void RunMark(SQVM *vm,SQCollectable **tchain);
-	SQInteger ResurrectUnreachable(SQVM *vm);
-	static void MarkObject(SQObjectPtr &o,SQCollectable **chain);
-#endif
-	SQObjectPtrVec *_metamethods;
-	SQObjectPtr _metamethodsmap;
-	SQObjectPtrVec *_systemstrings;
-	SQObjectPtrVec *_types;
-	SQStringTable *_stringtable;
-	RefTable _refs_table;
-	SQObjectPtr _registry;
-	SQObjectPtr _consts;
-	SQObjectPtr _constructoridx;
-#ifndef NO_GARBAGE_COLLECTOR
-	SQCollectable *_gc_chain;
-#endif
-	SQObjectPtr _root_vm;
-	SQObjectPtr _table_default_delegate;
-	static SQRegFunction _table_default_delegate_funcz[];
-	SQObjectPtr _array_default_delegate;
-	static SQRegFunction _array_default_delegate_funcz[];
-	SQObjectPtr _string_default_delegate;
-	static SQRegFunction _string_default_delegate_funcz[];
-	SQObjectPtr _number_default_delegate;
-	static SQRegFunction _number_default_delegate_funcz[];
-	SQObjectPtr _generator_default_delegate;
-	static SQRegFunction _generator_default_delegate_funcz[];
-	SQObjectPtr _closure_default_delegate;
-	static SQRegFunction _closure_default_delegate_funcz[];
-	SQObjectPtr _thread_default_delegate;
-	static SQRegFunction _thread_default_delegate_funcz[];
-	SQObjectPtr _class_default_delegate;
-	static SQRegFunction _class_default_delegate_funcz[];
-	SQObjectPtr _instance_default_delegate;
-	static SQRegFunction _instance_default_delegate_funcz[];
-	SQObjectPtr _weakref_default_delegate;
-	static SQRegFunction _weakref_default_delegate_funcz[];
-	
-	SQCOMPILERERROR _compilererrorhandler;
-	SQPRINTFUNCTION _printfunc;
-	SQPRINTFUNCTION _errorfunc;
-	bool _debuginfo;
-	bool _notifyallexceptions;
-	SQUserPointer _foreignptr;
-	SQRELEASEHOOK _releasehook;
-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) 
-
-bool CompileTypemask(SQIntVec &res,const SQChar *typemask);
-
-
-#endif //_SQSTATE_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQSTATE_H_
+#define _SQSTATE_H_
+
+#include "squtils.h"
+#include "sqobject.h"
+struct SQString;
+struct SQTable;
+//max number of character for a printed number
+#define NUMBER_MAX_CHAR 50
+
+struct SQStringTable
+{
+    SQStringTable(SQSharedState*ss);
+    ~SQStringTable();
+    SQString *Add(const SQChar *,SQInteger len);
+    void Remove(SQString *);
+private:
+    void Resize(SQInteger size);
+    void AllocNodes(SQInteger size);
+    SQString **_strings;
+    SQUnsignedInteger _numofslots;
+    SQUnsignedInteger _slotused;
+    SQSharedState *_sharedstate;
+};
+
+struct RefTable {
+    struct RefNode {
+        SQObjectPtr obj;
+        SQUnsignedInteger refs;
+        struct RefNode *next;
+    };
+    RefTable();
+    ~RefTable();
+    void AddRef(SQObject &obj);
+    SQBool Release(SQObject &obj);
+    SQUnsignedInteger GetRefCount(SQObject &obj);
+#ifndef NO_GARBAGE_COLLECTOR
+    void Mark(SQCollectable **chain);
+#endif
+    void Finalize();
+private:
+    RefNode *Get(SQObject &obj,SQHash &mainpos,RefNode **prev,bool add);
+    RefNode *Add(SQHash mainpos,SQObject &obj);
+    void Resize(SQUnsignedInteger size);
+    void AllocNodes(SQUnsignedInteger size);
+    SQUnsignedInteger _numofslots;
+    SQUnsignedInteger _slotused;
+    RefNode *_nodes;
+    RefNode *_freelist;
+    RefNode **_buckets;
+};
+
+#define ADD_STRING(ss,str,len) ss->_stringtable->Add(str,len)
+#define REMOVE_STRING(ss,bstr) ss->_stringtable->Remove(bstr)
+
+struct SQObjectPtr;
+
+struct SQSharedState
+{
+    SQSharedState();
+    ~SQSharedState();
+    void Init();
+public:
+    SQChar* GetScratchPad(SQInteger size);
+    SQInteger GetMetaMethodIdxByName(const SQObjectPtr &name);
+#ifndef NO_GARBAGE_COLLECTOR
+    SQInteger CollectGarbage(SQVM *vm);
+    void RunMark(SQVM *vm,SQCollectable **tchain);
+    SQInteger ResurrectUnreachable(SQVM *vm);
+    static void MarkObject(SQObjectPtr &o,SQCollectable **chain);
+#endif
+    SQObjectPtrVec *_metamethods;
+    SQObjectPtr _metamethodsmap;
+    SQObjectPtrVec *_systemstrings;
+    SQObjectPtrVec *_types;
+    SQStringTable *_stringtable;
+    RefTable _refs_table;
+    SQObjectPtr _registry;
+    SQObjectPtr _consts;
+    SQObjectPtr _constructoridx;
+#ifndef NO_GARBAGE_COLLECTOR
+    SQCollectable *_gc_chain;
+#endif
+    SQObjectPtr _root_vm;
+    SQObjectPtr _table_default_delegate;
+    static const SQRegFunction _table_default_delegate_funcz[];
+    SQObjectPtr _array_default_delegate;
+    static const SQRegFunction _array_default_delegate_funcz[];
+    SQObjectPtr _string_default_delegate;
+    static const SQRegFunction _string_default_delegate_funcz[];
+    SQObjectPtr _number_default_delegate;
+    static const SQRegFunction _number_default_delegate_funcz[];
+    SQObjectPtr _generator_default_delegate;
+    static const SQRegFunction _generator_default_delegate_funcz[];
+    SQObjectPtr _closure_default_delegate;
+    static const SQRegFunction _closure_default_delegate_funcz[];
+    SQObjectPtr _thread_default_delegate;
+    static const SQRegFunction _thread_default_delegate_funcz[];
+    SQObjectPtr _class_default_delegate;
+    static const SQRegFunction _class_default_delegate_funcz[];
+    SQObjectPtr _instance_default_delegate;
+    static const SQRegFunction _instance_default_delegate_funcz[];
+    SQObjectPtr _weakref_default_delegate;
+    static const SQRegFunction _weakref_default_delegate_funcz[];
+
+    SQCOMPILERERROR _compilererrorhandler;
+    SQPRINTFUNCTION _printfunc;
+    SQPRINTFUNCTION _errorfunc;
+    bool _debuginfo;
+    bool _notifyallexceptions;
+    SQUserPointer _foreignptr;
+    SQRELEASEHOOK _releasehook;
+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)
+
+bool CompileTypemask(SQIntVec &res,const SQChar *typemask);
+
+
+#endif //_SQSTATE_H_

+ 31 - 31
squirrel/sqstring.h

@@ -1,31 +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_
+/*  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_

+ 221 - 221
squirrel/sqtable.cpp

@@ -1,221 +1,221 @@
-/*
-see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include "sqvm.h"
-#include "sqtable.h"
-#include "sqfuncproto.h"
-#include "sqclosure.h"
-
-SQTable::SQTable(SQSharedState *ss,SQInteger nInitialSize)
-{
-	SQInteger pow2size=MINPOWER2;
-	while(nInitialSize>pow2size)pow2size=pow2size<<1;
-	AllocNodes(pow2size);
-	_usednodes = 0;
-	_delegate = NULL;
-	INIT_CHAIN();
-	ADD_TO_CHAIN(&_sharedstate->_gc_chain,this);
-}
-
-void SQTable::Remove(const SQObjectPtr &key)
-{
-	
-	_HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
-	if (n) {
-		n->val.Null();
-		n->key.Null();
-		_usednodes--;
-		Rehash(false);
-	}
-}
-
-void SQTable::AllocNodes(SQInteger nSize)
-{
-	_HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize);
-	for(SQInteger i=0;i<nSize;i++){
-		_HashNode &n = nodes[i];
-		new (&n) _HashNode;
-		n.next=NULL;
-	}
-	_numofnodes=nSize;
-	_nodes=nodes;
-	_firstfree=&_nodes[_numofnodes-1];
-}
-
-void SQTable::Rehash(bool force)
-{
-	SQInteger oldsize=_numofnodes;
-	//prevent problems with the integer division
-	if(oldsize<4)oldsize=4;
-	_HashNode *nold=_nodes;
-	SQInteger nelems=CountUsed();
-	if (nelems >= oldsize-oldsize/4)  /* using more than 3/4? */
-		AllocNodes(oldsize*2);
-	else if (nelems <= oldsize/4 &&  /* less than 1/4? */
-		oldsize > MINPOWER2)
-		AllocNodes(oldsize/2);
-	else if(force)
-		AllocNodes(oldsize);
-	else
-		return;
-	_usednodes = 0;
-	for (SQInteger i=0; i<oldsize; i++) {
-		_HashNode *old = nold+i;
-		if (type(old->key) != OT_NULL)
-			NewSlot(old->key,old->val);
-	}
-	for(SQInteger k=0;k<oldsize;k++) 
-		nold[k].~_HashNode();
-	SQ_FREE(nold,oldsize*sizeof(_HashNode));
-}
-
-SQTable *SQTable::Clone()
-{
-	SQTable *nt=Create(_opt_ss(this),_numofnodes);
-#ifdef _FAST_CLONE
-	_HashNode *basesrc = _nodes;
-	_HashNode *basedst = nt->_nodes;
-	_HashNode *src = _nodes;
-	_HashNode *dst = nt->_nodes;
-	SQInteger n = 0;
-	for(n = 0; n < _numofnodes; n++) {
-		dst->key = src->key;
-		dst->val = src->val;
-		if(src->next) {
-			assert(src->next > basesrc);
-			dst->next = basedst + (src->next - basesrc);
-			assert(dst != dst->next);
-		}
-		dst++;
-		src++;
-	}
-	assert(_firstfree > basesrc);
-	assert(_firstfree != NULL);
-	nt->_firstfree = basedst + (_firstfree - basesrc);
-	nt->_usednodes = _usednodes;
-#else
-	SQInteger ridx=0;
-	SQObjectPtr key,val;
-	while((ridx=Next(true,ridx,key,val))!=-1){
-		nt->NewSlot(key,val);
-	}
-#endif
-	nt->SetDelegate(_delegate);
-	return nt;
-}
-
-bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val)
-{
-	if(type(key) == OT_NULL)
-		return false;
-	_HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
-	if (n) {
-		val = _realval(n->val);
-		return true;
-	}
-	return false;
-}
-bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)
-{
-	assert(type(key) != OT_NULL);
-	SQHash h = HashObj(key) & (_numofnodes - 1);
-	_HashNode *n = _Get(key, h);
-	if (n) {
-		n->val = val;
-		return false;
-	}
-	_HashNode *mp = &_nodes[h];
-	n = mp;
-
-
-	//key not found I'll insert it
-	//main pos is not free
-
-	if(type(mp->key) != OT_NULL) {
-		n = _firstfree;  /* get a free place */
-		SQHash mph = HashObj(mp->key) & (_numofnodes - 1);
-		_HashNode *othern;  /* main position of colliding node */
-		
-		if (mp > n && (othern = &_nodes[mph]) != mp){
-			/* yes; move colliding node into free position */
-			while (othern->next != mp){
-				assert(othern->next != NULL);
-				othern = othern->next;  /* find previous */
-			}
-			othern->next = n;  /* redo the chain with `n' in place of `mp' */
-			n->key = mp->key;
-			n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */
-			n->next = mp->next;
-			mp->key.Null();
-			mp->val.Null();
-			mp->next = NULL;  /* now `mp' is free */
-		}
-		else{
-			/* new node will go into free position */
-			n->next = mp->next;  /* chain new position */
-			mp->next = n;
-			mp = n;
-		}
-	}
-	mp->key = key;
-
-	for (;;) {  /* correct `firstfree' */
-		if (type(_firstfree->key) == OT_NULL && _firstfree->next == NULL) {
-			mp->val = val;
-			_usednodes++;
-			return true;  /* OK; table still has a free place */
-		}
-		else if (_firstfree == _nodes) break;  /* cannot decrement from here */
-		else (_firstfree)--;
-	}
-	Rehash(true);
-	return NewSlot(key, val);
-}
-
-SQInteger SQTable::Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
-{
-	SQInteger idx = (SQInteger)TranslateIndex(refpos);
-	while (idx < _numofnodes) {
-		if(type(_nodes[idx].key) != OT_NULL) {
-			//first found
-			_HashNode &n = _nodes[idx];
-			outkey = n.key;
-			outval = getweakrefs?(SQObject)n.val:_realval(n.val);
-			//return idx for the next iteration
-			return ++idx;
-		}
-		++idx;
-	}
-	//nothing to iterate anymore
-	return -1;
-}
-
-
-bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val)
-{
-	_HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
-	if (n) {
-		n->val = val;
-		return true;
-	}
-	return false;
-}
-
-void SQTable::_ClearNodes()
-{
-	for(SQInteger i = 0;i < _numofnodes; i++) { _HashNode &n = _nodes[i]; n.key.Null(); n.val.Null(); }
-}
-
-void SQTable::Finalize()
-{
-	_ClearNodes();
-	SetDelegate(NULL);
-}
-
-void SQTable::Clear()
-{
-	_ClearNodes();
-	_usednodes = 0;
-	Rehash(true);
-}
+/*
+see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include "sqvm.h"
+#include "sqtable.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+
+SQTable::SQTable(SQSharedState *ss,SQInteger nInitialSize)
+{
+    SQInteger pow2size=MINPOWER2;
+    while(nInitialSize>pow2size)pow2size=pow2size<<1;
+    AllocNodes(pow2size);
+    _usednodes = 0;
+    _delegate = NULL;
+    INIT_CHAIN();
+    ADD_TO_CHAIN(&_sharedstate->_gc_chain,this);
+}
+
+void SQTable::Remove(const SQObjectPtr &key)
+{
+
+    _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
+    if (n) {
+        n->val.Null();
+        n->key.Null();
+        _usednodes--;
+        Rehash(false);
+    }
+}
+
+void SQTable::AllocNodes(SQInteger nSize)
+{
+    _HashNode *nodes=(_HashNode *)SQ_MALLOC(sizeof(_HashNode)*nSize);
+    for(SQInteger i=0;i<nSize;i++){
+        _HashNode &n = nodes[i];
+        new (&n) _HashNode;
+        n.next=NULL;
+    }
+    _numofnodes=nSize;
+    _nodes=nodes;
+    _firstfree=&_nodes[_numofnodes-1];
+}
+
+void SQTable::Rehash(bool force)
+{
+    SQInteger oldsize=_numofnodes;
+    //prevent problems with the integer division
+    if(oldsize<4)oldsize=4;
+    _HashNode *nold=_nodes;
+    SQInteger nelems=CountUsed();
+    if (nelems >= oldsize-oldsize/4)  /* using more than 3/4? */
+        AllocNodes(oldsize*2);
+    else if (nelems <= oldsize/4 &&  /* less than 1/4? */
+        oldsize > MINPOWER2)
+        AllocNodes(oldsize/2);
+    else if(force)
+        AllocNodes(oldsize);
+    else
+        return;
+    _usednodes = 0;
+    for (SQInteger i=0; i<oldsize; i++) {
+        _HashNode *old = nold+i;
+        if (type(old->key) != OT_NULL)
+            NewSlot(old->key,old->val);
+    }
+    for(SQInteger k=0;k<oldsize;k++)
+        nold[k].~_HashNode();
+    SQ_FREE(nold,oldsize*sizeof(_HashNode));
+}
+
+SQTable *SQTable::Clone()
+{
+    SQTable *nt=Create(_opt_ss(this),_numofnodes);
+#ifdef _FAST_CLONE
+    _HashNode *basesrc = _nodes;
+    _HashNode *basedst = nt->_nodes;
+    _HashNode *src = _nodes;
+    _HashNode *dst = nt->_nodes;
+    SQInteger n = 0;
+    for(n = 0; n < _numofnodes; n++) {
+        dst->key = src->key;
+        dst->val = src->val;
+        if(src->next) {
+            assert(src->next > basesrc);
+            dst->next = basedst + (src->next - basesrc);
+            assert(dst != dst->next);
+        }
+        dst++;
+        src++;
+    }
+    assert(_firstfree > basesrc);
+    assert(_firstfree != NULL);
+    nt->_firstfree = basedst + (_firstfree - basesrc);
+    nt->_usednodes = _usednodes;
+#else
+    SQInteger ridx=0;
+    SQObjectPtr key,val;
+    while((ridx=Next(true,ridx,key,val))!=-1){
+        nt->NewSlot(key,val);
+    }
+#endif
+    nt->SetDelegate(_delegate);
+    return nt;
+}
+
+bool SQTable::Get(const SQObjectPtr &key,SQObjectPtr &val)
+{
+    if(type(key) == OT_NULL)
+        return false;
+    _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
+    if (n) {
+        val = _realval(n->val);
+        return true;
+    }
+    return false;
+}
+bool SQTable::NewSlot(const SQObjectPtr &key,const SQObjectPtr &val)
+{
+    assert(type(key) != OT_NULL);
+    SQHash h = HashObj(key) & (_numofnodes - 1);
+    _HashNode *n = _Get(key, h);
+    if (n) {
+        n->val = val;
+        return false;
+    }
+    _HashNode *mp = &_nodes[h];
+    n = mp;
+
+
+    //key not found I'll insert it
+    //main pos is not free
+
+    if(type(mp->key) != OT_NULL) {
+        n = _firstfree;  /* get a free place */
+        SQHash mph = HashObj(mp->key) & (_numofnodes - 1);
+        _HashNode *othern;  /* main position of colliding node */
+
+        if (mp > n && (othern = &_nodes[mph]) != mp){
+            /* yes; move colliding node into free position */
+            while (othern->next != mp){
+                assert(othern->next != NULL);
+                othern = othern->next;  /* find previous */
+            }
+            othern->next = n;  /* redo the chain with `n' in place of `mp' */
+            n->key = mp->key;
+            n->val = mp->val;/* copy colliding node into free pos. (mp->next also goes) */
+            n->next = mp->next;
+            mp->key.Null();
+            mp->val.Null();
+            mp->next = NULL;  /* now `mp' is free */
+        }
+        else{
+            /* new node will go into free position */
+            n->next = mp->next;  /* chain new position */
+            mp->next = n;
+            mp = n;
+        }
+    }
+    mp->key = key;
+
+    for (;;) {  /* correct `firstfree' */
+        if (type(_firstfree->key) == OT_NULL && _firstfree->next == NULL) {
+            mp->val = val;
+            _usednodes++;
+            return true;  /* OK; table still has a free place */
+        }
+        else if (_firstfree == _nodes) break;  /* cannot decrement from here */
+        else (_firstfree)--;
+    }
+    Rehash(true);
+    return NewSlot(key, val);
+}
+
+SQInteger SQTable::Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval)
+{
+    SQInteger idx = (SQInteger)TranslateIndex(refpos);
+    while (idx < _numofnodes) {
+        if(type(_nodes[idx].key) != OT_NULL) {
+            //first found
+            _HashNode &n = _nodes[idx];
+            outkey = n.key;
+            outval = getweakrefs?(SQObject)n.val:_realval(n.val);
+            //return idx for the next iteration
+            return ++idx;
+        }
+        ++idx;
+    }
+    //nothing to iterate anymore
+    return -1;
+}
+
+
+bool SQTable::Set(const SQObjectPtr &key, const SQObjectPtr &val)
+{
+    _HashNode *n = _Get(key, HashObj(key) & (_numofnodes - 1));
+    if (n) {
+        n->val = val;
+        return true;
+    }
+    return false;
+}
+
+void SQTable::_ClearNodes()
+{
+    for(SQInteger i = 0;i < _numofnodes; i++) { _HashNode &n = _nodes[i]; n.key.Null(); n.val.Null(); }
+}
+
+void SQTable::Finalize()
+{
+    _ClearNodes();
+    SetDelegate(NULL);
+}
+
+void SQTable::Clear()
+{
+    _ClearNodes();
+    _usednodes = 0;
+    Rehash(true);
+}

+ 110 - 110
squirrel/sqtable.h

@@ -1,110 +1,110 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQTABLE_H_
-#define _SQTABLE_H_
-/*
-* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
-* http://www.lua.org/copyright.html#4
-* http://www.lua.org/source/4.0.1/src_ltable.c.html
-*/
-
-#include "sqstring.h"
-
-
-#define hashptr(p)  ((SQHash)(((SQInteger)p) >> 3))
-
-inline SQHash HashObj(const SQObjectPtr &key)
-{
-	switch(type(key)) {
-		case OT_STRING:		return _string(key)->_hash;
-		case OT_FLOAT:		return (SQHash)((SQInteger)_float(key));
-		case OT_BOOL: case OT_INTEGER:	return (SQHash)((SQInteger)_integer(key));
-		default:			return hashptr(key._unVal.pRefCounted);
-	}
-}
-
-struct SQTable : public SQDelegable 
-{
-private:
-	struct _HashNode
-	{
-		_HashNode() { next = NULL; }
-		SQObjectPtr val;
-		SQObjectPtr key;
-		_HashNode *next;
-	};
-	_HashNode *_firstfree;
-	_HashNode *_nodes;
-	SQInteger _numofnodes;
-	SQInteger _usednodes;
-	
-///////////////////////////
-	void AllocNodes(SQInteger nSize);
-	void Rehash(bool force);
-	SQTable(SQSharedState *ss, SQInteger nInitialSize);
-	void _ClearNodes();
-public:
-	static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize)
-	{
-		SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable));
-		new (newtable) SQTable(ss, nInitialSize);
-		newtable->_delegate = NULL;
-		return newtable;
-	}
-	void Finalize();
-	SQTable *Clone();
-	~SQTable()
-	{
-		SetDelegate(NULL);
-		REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
-		for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();
-		SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode));
-	}
-#ifndef NO_GARBAGE_COLLECTOR 
-	void Mark(SQCollectable **chain);
-	SQObjectType GetType() {return OT_TABLE;}
-#endif
-	inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash)
-	{
-		_HashNode *n = &_nodes[hash];
-		do{
-			if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){
-				return n;
-			}
-		}while((n = n->next));
-		return NULL;
-	}
-	//for compiler use
-	inline bool GetStr(const SQChar* key,SQInteger keylen,SQObjectPtr &val)
-	{
-		SQHash hash = _hashstr(key,keylen);
-		_HashNode *n = &_nodes[hash & (_numofnodes - 1)];
-		_HashNode *res = NULL;
-		do{
-			if(type(n->key) == OT_STRING && (scstrcmp(_stringval(n->key),key) == 0)){
-				res = n;
-				break;
-			}
-		}while((n = n->next));
-		if (res) {
-			val = _realval(res->val);
-			return true;
-		}
-		return false;
-	}
-	bool Get(const SQObjectPtr &key,SQObjectPtr &val);
-	void Remove(const SQObjectPtr &key);
-	bool Set(const SQObjectPtr &key, const SQObjectPtr &val);
-	//returns true if a new slot has been created false if it was already present
-	bool NewSlot(const SQObjectPtr &key,const SQObjectPtr &val);
-	SQInteger Next(bool getweakrefs,const SQObjectPtr &refpos, SQObjectPtr &outkey, SQObjectPtr &outval);
-	
-	SQInteger CountUsed(){ return _usednodes;}
-	void Clear();
-	void Release()
-	{
-		sq_delete(this, SQTable);
-	}
-	
-};
-
-#endif //_SQTABLE_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQTABLE_H_
+#define _SQTABLE_H_
+/*
+* The following code is based on Lua 4.0 (Copyright 1994-2002 Tecgraf, PUC-Rio.)
+* http://www.lua.org/copyright.html#4
+* http://www.lua.org/source/4.0.1/src_ltable.c.html
+*/
+
+#include "sqstring.h"
+
+
+#define hashptr(p)  ((SQHash)(((SQInteger)p) >> 3))
+
+inline SQHash HashObj(const SQObjectPtr &key)
+{
+    switch(type(key)) {
+        case OT_STRING:     return _string(key)->_hash;
+        case OT_FLOAT:      return (SQHash)((SQInteger)_float(key));
+        case OT_BOOL: case OT_INTEGER:  return (SQHash)((SQInteger)_integer(key));
+        default:            return hashptr(key._unVal.pRefCounted);
+    }
+}
+
+struct SQTable : public SQDelegable
+{
+private:
+    struct _HashNode
+    {
+        _HashNode() { next = NULL; }
+        SQObjectPtr val;
+        SQObjectPtr key;
+        _HashNode *next;
+    };
+    _HashNode *_firstfree;
+    _HashNode *_nodes;
+    SQInteger _numofnodes;
+    SQInteger _usednodes;
+
+///////////////////////////
+    void AllocNodes(SQInteger nSize);
+    void Rehash(bool force);
+    SQTable(SQSharedState *ss, SQInteger nInitialSize);
+    void _ClearNodes();
+public:
+    static SQTable* Create(SQSharedState *ss,SQInteger nInitialSize)
+    {
+        SQTable *newtable = (SQTable*)SQ_MALLOC(sizeof(SQTable));
+        new (newtable) SQTable(ss, nInitialSize);
+        newtable->_delegate = NULL;
+        return newtable;
+    }
+    void Finalize();
+    SQTable *Clone();
+    ~SQTable()
+    {
+        SetDelegate(NULL);
+        REMOVE_FROM_CHAIN(&_sharedstate->_gc_chain, this);
+        for (SQInteger i = 0; i < _numofnodes; i++) _nodes[i].~_HashNode();
+        SQ_FREE(_nodes, _numofnodes * sizeof(_HashNode));
+    }
+#ifndef NO_GARBAGE_COLLECTOR
+    void Mark(SQCollectable **chain);
+    SQObjectType GetType() {return OT_TABLE;}
+#endif
+    inline _HashNode *_Get(const SQObjectPtr &key,SQHash hash)
+    {
+        _HashNode *n = &_nodes[hash];
+        do{
+            if(_rawval(n->key) == _rawval(key) && type(n->key) == type(key)){
+                return n;
+            }
+        }while((n = n->next));
+        return NULL;
+    }
+    //for compiler use
+    inline bool GetStr(const SQChar* key,SQInteger keylen,SQObjectPtr &val)
+    {
+        SQHash hash = _hashstr(key,keylen);
+        _HashNode *n = &_nodes[hash & (_numofnodes - 1)];
+        _HashNode *res = NULL;
+        do{
+            if(type(n->key) == OT_STRING && (scstrcmp(_stringval(n->key),key) == 0)){
+                res = n;
+                break;
+            }
+        }while((n = n->next));
+        if (res) {
+            val = _realval(res->val);
+            return true;
+        }
+        return false;
+    }
+    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_

+ 40 - 40
squirrel/squserdata.h

@@ -1,40 +1,40 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQUSERDATA_H_
-#define _SQUSERDATA_H_
-
-struct SQUserData : SQDelegable
-{
-	SQUserData(SQSharedState *ss){ _delegate = 0; _hook = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); }
-	~SQUserData()
-	{
-		REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain, this);
-		SetDelegate(NULL);
-	}
-	static SQUserData* Create(SQSharedState *ss, SQInteger size)
-	{
-		SQUserData* ud = (SQUserData*)SQ_MALLOC(sq_aligning(sizeof(SQUserData))+size);
-		new (ud) SQUserData(ss);
-		ud->_size = size;
-		ud->_typetag = 0;
-		return ud;
-	}
-#ifndef NO_GARBAGE_COLLECTOR
-	void Mark(SQCollectable **chain);
-	void Finalize(){SetDelegate(NULL);}
-	SQObjectType GetType(){ return OT_USERDATA;}
-#endif
-	void Release() {
-		if (_hook) _hook((SQUserPointer)sq_aligning(this + 1),_size);
-		SQInteger tsize = _size;
-		this->~SQUserData();
-		SQ_FREE(this, sq_aligning(sizeof(SQUserData)) + tsize);
-	}
-	
-		
-	SQInteger _size;
-	SQRELEASEHOOK _hook;
-	SQUserPointer _typetag;
-	//SQChar _val[1];
-};
-
-#endif //_SQUSERDATA_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQUSERDATA_H_
+#define _SQUSERDATA_H_
+
+struct SQUserData : SQDelegable
+{
+    SQUserData(SQSharedState *ss){ _delegate = 0; _hook = NULL; INIT_CHAIN(); ADD_TO_CHAIN(&_ss(this)->_gc_chain, this); }
+    ~SQUserData()
+    {
+        REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain, this);
+        SetDelegate(NULL);
+    }
+    static SQUserData* Create(SQSharedState *ss, SQInteger size)
+    {
+        SQUserData* ud = (SQUserData*)SQ_MALLOC(sq_aligning(sizeof(SQUserData))+size);
+        new (ud) SQUserData(ss);
+        ud->_size = size;
+        ud->_typetag = 0;
+        return ud;
+    }
+#ifndef NO_GARBAGE_COLLECTOR
+    void Mark(SQCollectable **chain);
+    void Finalize(){SetDelegate(NULL);}
+    SQObjectType GetType(){ return OT_USERDATA;}
+#endif
+    void Release() {
+        if (_hook) _hook((SQUserPointer)sq_aligning(this + 1),_size);
+        SQInteger tsize = _size;
+        this->~SQUserData();
+        SQ_FREE(this, sq_aligning(sizeof(SQUserData)) + tsize);
+    }
+
+
+    SQInteger _size;
+    SQRELEASEHOOK _hook;
+    SQUserPointer _typetag;
+    //SQChar _val[1];
+};
+
+#endif //_SQUSERDATA_H_

+ 116 - 116
squirrel/squtils.h

@@ -1,116 +1,116 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQUTILS_H_
-#define _SQUTILS_H_
-
-void *sq_vm_malloc(SQUnsignedInteger size);
-void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size);
-void sq_vm_free(void *p,SQUnsignedInteger size);
-
-#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;}
-#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));}
-#define SQ_MALLOC(__size) sq_vm_malloc((__size));
-#define SQ_FREE(__ptr,__size) sq_vm_free((__ptr),(__size));
-#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc((__ptr),(__oldsize),(__size));
-
-#define sq_aligning(v) (((size_t)(v) + (SQ_ALIGNMENT-1)) & (~(SQ_ALIGNMENT-1)))
-
-//sqvector mini vector class, supports objects by value
-template<typename T> class sqvector
-{
-public:
-	sqvector()
-	{
-		_vals = NULL;
-		_size = 0;
-		_allocated = 0;
-	}
-	sqvector(const sqvector<T>& v)
-	{
-		copy(v);
-	}
-	void copy(const sqvector<T>& v)
-	{
-		if(_size) {
-			resize(0); //destroys all previous stuff
-		}
-		//resize(v._size);
-		if(v._size > _allocated) {
-			_realloc(v._size);
-		}
-		for(SQUnsignedInteger i = 0; i < v._size; i++) {
-			new ((void *)&_vals[i]) T(v._vals[i]);
-		}
-		_size = v._size;
-	}
-	~sqvector()
-	{
-		if(_allocated) {
-			for(SQUnsignedInteger i = 0; i < _size; i++)
-				_vals[i].~T();
-			SQ_FREE(_vals, (_allocated * sizeof(T)));
-		}
-	}
-	void reserve(SQUnsignedInteger newsize) { _realloc(newsize); }
-	void resize(SQUnsignedInteger newsize, const T& fill = T())
-	{
-		if(newsize > _allocated)
-			_realloc(newsize);
-		if(newsize > _size) {
-			while(_size < newsize) {
-				new ((void *)&_vals[_size]) T(fill);
-				_size++;
-			}
-		}
-		else{
-			for(SQUnsignedInteger i = newsize; i < _size; i++) {
-				_vals[i].~T();
-			}
-			_size = newsize;
-		}
-	}
-	void shrinktofit() { if(_size > 4) { _realloc(_size); } }
-	T& top() const { return _vals[_size - 1]; }
-	inline SQUnsignedInteger size() const { return _size; }
-	bool empty() const { return (_size <= 0); }
-	inline T &push_back(const T& val = T())
-	{
-		if(_allocated <= _size)
-			_realloc(_size * 2);
-		return *(new ((void *)&_vals[_size++]) T(val));
-	}
-	inline void pop_back()
-	{
-		_size--; _vals[_size].~T();
-	}
-	void insert(SQUnsignedInteger idx, const T& val)
-	{
-		resize(_size + 1);
-		for(SQUnsignedInteger i = _size - 1; i > idx; i--) {
-			_vals[i] = _vals[i - 1];
-		}
-    	_vals[idx] = val;
-	}
-	void remove(SQUnsignedInteger idx)
-	{
-		_vals[idx].~T();
-		if(idx < (_size - 1)) {
-			memmove(&_vals[idx], &_vals[idx+1], sizeof(T) * (_size - idx - 1));
-		}
-		_size--;
-	}
-	SQUnsignedInteger capacity() { return _allocated; }
-	inline T &back() const { return _vals[_size - 1]; }
-	inline T& operator[](SQUnsignedInteger pos) const{ return _vals[pos]; }
-	T* _vals;
-private:
-	void _realloc(SQUnsignedInteger newsize)
-	{
-		newsize = (newsize > 0)?newsize:4;
-		_vals = (T*)SQ_REALLOC(_vals, _allocated * sizeof(T), newsize * sizeof(T));
-		_allocated = newsize;
-	}
-	SQUnsignedInteger _size;
-	SQUnsignedInteger _allocated;
-};
-
-#endif //_SQUTILS_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQUTILS_H_
+#define _SQUTILS_H_
+
+void *sq_vm_malloc(SQUnsignedInteger size);
+void *sq_vm_realloc(void *p,SQUnsignedInteger oldsize,SQUnsignedInteger size);
+void sq_vm_free(void *p,SQUnsignedInteger size);
+
+#define sq_new(__ptr,__type) {__ptr=(__type *)sq_vm_malloc(sizeof(__type));new (__ptr) __type;}
+#define sq_delete(__ptr,__type) {__ptr->~__type();sq_vm_free(__ptr,sizeof(__type));}
+#define SQ_MALLOC(__size) sq_vm_malloc((__size));
+#define SQ_FREE(__ptr,__size) sq_vm_free((__ptr),(__size));
+#define SQ_REALLOC(__ptr,__oldsize,__size) sq_vm_realloc((__ptr),(__oldsize),(__size));
+
+#define sq_aligning(v) (((size_t)(v) + (SQ_ALIGNMENT-1)) & (~(SQ_ALIGNMENT-1)))
+
+//sqvector mini vector class, supports objects by value
+template<typename T> class sqvector
+{
+public:
+    sqvector()
+    {
+        _vals = NULL;
+        _size = 0;
+        _allocated = 0;
+    }
+    sqvector(const sqvector<T>& v)
+    {
+        copy(v);
+    }
+    void copy(const sqvector<T>& v)
+    {
+        if(_size) {
+            resize(0); //destroys all previous stuff
+        }
+        //resize(v._size);
+        if(v._size > _allocated) {
+            _realloc(v._size);
+        }
+        for(SQUnsignedInteger i = 0; i < v._size; i++) {
+            new ((void *)&_vals[i]) T(v._vals[i]);
+        }
+        _size = v._size;
+    }
+    ~sqvector()
+    {
+        if(_allocated) {
+            for(SQUnsignedInteger i = 0; i < _size; i++)
+                _vals[i].~T();
+            SQ_FREE(_vals, (_allocated * sizeof(T)));
+        }
+    }
+    void reserve(SQUnsignedInteger newsize) { _realloc(newsize); }
+    void resize(SQUnsignedInteger newsize, const T& fill = T())
+    {
+        if(newsize > _allocated)
+            _realloc(newsize);
+        if(newsize > _size) {
+            while(_size < newsize) {
+                new ((void *)&_vals[_size]) T(fill);
+                _size++;
+            }
+        }
+        else{
+            for(SQUnsignedInteger i = newsize; i < _size; i++) {
+                _vals[i].~T();
+            }
+            _size = newsize;
+        }
+    }
+    void shrinktofit() { if(_size > 4) { _realloc(_size); } }
+    T& top() const { return _vals[_size - 1]; }
+    inline SQUnsignedInteger size() const { return _size; }
+    bool empty() const { return (_size <= 0); }
+    inline T &push_back(const T& val = T())
+    {
+        if(_allocated <= _size)
+            _realloc(_size * 2);
+        return *(new ((void *)&_vals[_size++]) T(val));
+    }
+    inline void pop_back()
+    {
+        _size--; _vals[_size].~T();
+    }
+    void insert(SQUnsignedInteger idx, const T& val)
+    {
+        resize(_size + 1);
+        for(SQUnsignedInteger i = _size - 1; i > idx; i--) {
+            _vals[i] = _vals[i - 1];
+        }
+        _vals[idx] = val;
+    }
+    void remove(SQUnsignedInteger idx)
+    {
+        _vals[idx].~T();
+        if(idx < (_size - 1)) {
+            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_

+ 1748 - 1748
squirrel/sqvm.cpp

@@ -1,1748 +1,1748 @@
-/*
-	see copyright notice in squirrel.h
-*/
-#include "sqpcheader.h"
-#include <math.h>
-#include <stdlib.h>
-#include "sqopcodes.h"
-#include "sqvm.h"
-#include "sqfuncproto.h"
-#include "sqclosure.h"
-#include "sqstring.h"
-#include "sqtable.h"
-#include "squserdata.h"
-#include "sqarray.h"
-#include "sqclass.h"
-
-#define TOP() (_stack._vals[_top-1])
-
-bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)
-{
-	SQInteger res;
-	if((type(o1)|type(o2)) == OT_INTEGER)
-	{
-		SQInteger i1 = _integer(o1), i2 = _integer(o2);
-		switch(op) {
-			case BW_AND:	res = i1 & i2; break;
-			case BW_OR:		res = i1 | i2; break;
-			case BW_XOR:	res = i1 ^ i2; break;
-			case BW_SHIFTL:	res = i1 << i2; break;
-			case BW_SHIFTR:	res = i1 >> i2; break;
-			case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); break;
-			default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; }
-		}
-	} 
-	else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;}
-	trg = res;
-	return true;
-}
-
-#define _ARITH_(op,trg,o1,o2) \
-{ \
-	SQInteger tmask = type(o1)|type(o2); \
-	switch(tmask) { \
-		case OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \
-		case (OT_FLOAT|OT_INTEGER): \
-		case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\
-		default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\
-	} \
-}
-
-#define _ARITH_NOZERO(op,trg,o1,o2,err) \
-{ \
-	SQInteger tmask = type(o1)|type(o2); \
-	switch(tmask) { \
-		case OT_INTEGER: { SQInteger i2 = _integer(o2); if(i2 == 0) { Raise_Error(err); SQ_THROW(); } trg = _integer(o1) op i2; } break;\
-		case (OT_FLOAT|OT_INTEGER): \
-		case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\
-		default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\
-	} \
-}
-
-bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)
-{
-	SQInteger tmask = type(o1)|type(o2);
-	switch(tmask) {
-		case OT_INTEGER:{
-			SQInteger res, i1 = _integer(o1), i2 = _integer(o2);
-			switch(op) {
-			case '+': res = i1 + i2; break;
-			case '-': res = i1 - i2; break;
-			case '/': if (i2 == 0) { Raise_Error(_SC("division by zero")); return false; }
-					else if (i2 == -1 && i1 == INT_MIN) { Raise_Error(_SC("integer overflow")); return false; }
-					res = i1 / i2;
-					break;
-			case '*': res = i1 * i2; break;
-			case '%': if (i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; }
-					else if (i2 == -1 && i1 == INT_MIN) { res = 0; break; }
-					res = i1 % i2;
-					break;
-			default: res = 0xDEADBEEF;
-			}
-			trg = res; }
-			break;
-		case (OT_FLOAT|OT_INTEGER):
-		case (OT_FLOAT):{
-			SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2);
-			switch(op) {
-			case '+': res = f1 + f2; break;
-			case '-': res = f1 - f2; break;
-			case '/': res = f1 / f2; break;
-			case '*': res = f1 * f2; break;
-			case '%': res = SQFloat(fmod((double)f1,(double)f2)); break;
-			default: res = 0x0f;
-			}
-			trg = res; }
-			break;
-		default:
-			if(op == '+' &&	(tmask & _RT_STRING)){
-				if(!StringCat(o1, o2, trg)) return false;
-			}
-			else if(!ArithMetaMethod(op,o1,o2,trg)) { 
-				return false; 
-			}
-	}
-	return true;
-}
-
-SQVM::SQVM(SQSharedState *ss)
-{
-	_sharedstate=ss;
-	_suspended = SQFalse;
-	_suspended_target = -1;
-	_suspended_root = SQFalse;
-	_suspended_traps = -1;
-	_foreignptr = NULL;
-	_nnativecalls = 0;
-	_nmetamethodscall = 0;
-	_lasterror.Null();
-	_errorhandler.Null();
-	_debughook = false;
-	_debughook_native = NULL;
-	_debughook_closure.Null();
-	_openouters = NULL;
-	ci = NULL;
-	_releasehook = NULL;
-	INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);
-}
-
-void SQVM::Finalize()
-{
-	if(_releasehook) { _releasehook(_foreignptr,0); _releasehook = NULL; }
-	if(_openouters) CloseOuters(&_stack._vals[0]);
-	_roottable.Null();
-	_lasterror.Null();
-	_errorhandler.Null();
-	_debughook = false;
-	_debughook_native = NULL;
-	_debughook_closure.Null();
-	temp_reg.Null();
-	_callstackdata.resize(0);
-	SQInteger size=_stack.size();
-	for(SQInteger i=0;i<size;i++)
-		_stack[i].Null();
-}
-
-SQVM::~SQVM()
-{
-	Finalize();
-	REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
-}
-
-bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &dest)
-{
-	SQMetaMethod mm;
-	switch(op){
-		case _SC('+'): mm=MT_ADD; break;
-		case _SC('-'): mm=MT_SUB; break;
-		case _SC('/'): mm=MT_DIV; break;
-		case _SC('*'): mm=MT_MUL; break;
-		case _SC('%'): mm=MT_MODULO; break;
-		default: mm = MT_ADD; assert(0); break; //shutup compiler
-	}
-	if(is_delegable(o1) && _delegable(o1)->_delegate) {
-		
-		SQObjectPtr closure;
-		if(_delegable(o1)->GetMetaMethod(this, mm, closure)) {
-			Push(o1);Push(o2);
-			return CallMetaMethod(closure,mm,2,dest);
-		}
-	}
-	Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2)); 
-	return false;
-}
-
-bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o)
-{
-	
-	switch(type(o)) {
-	case OT_INTEGER:
-		trg = -_integer(o);
-		return true;
-	case OT_FLOAT:
-		trg = -_float(o);
-		return true;
-	case OT_TABLE:
-	case OT_USERDATA:
-	case OT_INSTANCE:
-		if(_delegable(o)->_delegate) {
-			SQObjectPtr closure;
-			if(_delegable(o)->GetMetaMethod(this, MT_UNM, closure)) {
-				Push(o);
-				if(!CallMetaMethod(closure, MT_UNM, 1, temp_reg)) return false;
-				_Swap(trg,temp_reg);
-				return true;
-
-			}
-		}
-	default:break; //shutup compiler
-	}
-	Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o));
-	return false;
-}
-
-#define _RET_SUCCEED(exp) { result = (exp); return true; } 
-bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result)
-{
-	SQObjectType t1 = type(o1), t2 = type(o2);
-	if(t1 == t2) {
-		if(_rawval(o1) == _rawval(o2))_RET_SUCCEED(0);
-		SQObjectPtr res;
-		switch(t1){
-		case OT_STRING:
-			_RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2)));
-		case OT_INTEGER:
-			_RET_SUCCEED((_integer(o1)<_integer(o2))?-1:1);
-		case OT_FLOAT:
-			_RET_SUCCEED((_float(o1)<_float(o2))?-1:1);
-		case OT_TABLE:
-		case OT_USERDATA:
-		case OT_INSTANCE:
-			if(_delegable(o1)->_delegate) {
-				SQObjectPtr closure;
-				if(_delegable(o1)->GetMetaMethod(this, MT_CMP, closure)) {
-					Push(o1);Push(o2);
-					if(CallMetaMethod(closure,MT_CMP,2,res)) {
-						if(type(res) != OT_INTEGER) {
-							Raise_Error(_SC("_cmp must return an integer"));
-							return false;
-						}
-						_RET_SUCCEED(_integer(res))
-					}
-					return false;
-				}
-			}
-			//continues through (no break needed)
-		default: 
-			_RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 );
-		}
-		assert(0);
-		//if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; }
-		//	_RET_SUCCEED(_integer(res));
-		
-	}
-	else{
-		if(sq_isnumeric(o1) && sq_isnumeric(o2)){
-			if((t1==OT_INTEGER) && (t2==OT_FLOAT)) { 
-				if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); }
-				else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); }
-				_RET_SUCCEED(1);
-			}
-			else{
-				if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); }
-				else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); }
-				_RET_SUCCEED(1);
-			}
-		}
-		else if(t1==OT_NULL) {_RET_SUCCEED(-1);}
-		else if(t2==OT_NULL) {_RET_SUCCEED(1);}
-		else { Raise_CompareError(o1,o2); return false; }
-		
-	}
-	assert(0);
-	_RET_SUCCEED(0); //cannot happen
-}
-
-bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res)
-{
-	SQInteger r;
-	if(ObjCmp(o1,o2,r)) {
-		switch(op) {
-			case CMP_G: res = (r > 0); return true;
-			case CMP_GE: res = (r >= 0); return true;
-			case CMP_L: res = (r < 0); return true;
-			case CMP_LE: res = (r <= 0); return true;
-			case CMP_3W: res = r; return true;
-		}
-		assert(0);
-	}
-	return false;
-}
-
-bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
-{
-	switch(type(o)) {
-	case OT_STRING:
-		res = o;
-		return true;
-	case OT_FLOAT:
-		scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR),_SC("%g"),_float(o));
-		break;
-	case OT_INTEGER:
-		scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR),_PRINT_INT_FMT,_integer(o));
-		break;
-	case OT_BOOL:
-		scsprintf(_sp(sq_rsl(6)),sq_rsl(6),_integer(o)?_SC("true"):_SC("false"));
-		break;
-	case OT_TABLE:
-	case OT_USERDATA:
-	case OT_INSTANCE:
-		if(_delegable(o)->_delegate) {
-			SQObjectPtr closure;
-			if(_delegable(o)->GetMetaMethod(this, MT_TOSTRING, closure)) {
-				Push(o);
-				if(CallMetaMethod(closure,MT_TOSTRING,1,res)) {;
-					if(type(res) == OT_STRING)
-						return true;
-				} 
-				else {
-					return false;
-				}
-			}
-		}
-	default:
-		scsprintf(_sp(sq_rsl((sizeof(void*)*2)+NUMBER_MAX_CHAR)),sq_rsl((sizeof(void*)*2)+NUMBER_MAX_CHAR),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o));
-	}
-	res = SQString::Create(_ss(this),_spval);
-	return true;
-}
-
-
-bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)
-{
-	SQObjectPtr a, b;
-	if(!ToString(str, a)) return false;
-	if(!ToString(obj, b)) return false;
-	SQInteger l = _string(a)->_len , ol = _string(b)->_len;
-	SQChar *s = _sp(sq_rsl(l + ol + 1));
-	memcpy(s, _stringval(a), sq_rsl(l)); 
-	memcpy(s + l, _stringval(b), sq_rsl(ol));
-	dest = SQString::Create(_ss(this), _spval, l + ol);
-	return true;
-}
-
-bool SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest)
-{
-	if(is_delegable(obj1) && _delegable(obj1)->_delegate) {
-		SQObjectPtr closure;
-		if(_delegable(obj1)->GetMetaMethod(this, MT_TYPEOF, closure)) {
-			Push(obj1);
-			return CallMetaMethod(closure,MT_TYPEOF,1,dest);
-		}
-	}
-	dest = SQString::Create(_ss(this),GetTypeName(obj1));
-	return true;
-}
-
-bool SQVM::Init(SQVM *friendvm, SQInteger stacksize)
-{
-	_stack.resize(stacksize);
-	_alloccallsstacksize = 4;
-	_callstackdata.resize(_alloccallsstacksize);
-	_callsstacksize = 0;
-	_callsstack = &_callstackdata[0];
-	_stackbase = 0;
-	_top = 0;
-	if(!friendvm) {
-		_roottable = SQTable::Create(_ss(this), 0);
-		sq_base_register(this);
-	}
-	else {
-		_roottable = friendvm->_roottable;
-		_errorhandler = friendvm->_errorhandler;
-		_debughook = friendvm->_debughook;
-		_debughook_native = friendvm->_debughook_native;
-		_debughook_closure = friendvm->_debughook_closure;
-	}
-	
-	
-	return true;
-}
-
-
-bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall)
-{
-	SQFunctionProto *func = closure->_function;
-
-	SQInteger paramssize = func->_nparameters;
-	const SQInteger newtop = stackbase + func->_stacksize;
-	SQInteger nargs = args;
-	if(func->_varparams)
-	{
-		paramssize--;
-		if (nargs < paramssize) {
-			Raise_Error(_SC("wrong number of parameters"));
-			return false;
-		}
-
-		//dumpstack(stackbase);
-		SQInteger nvargs = nargs - paramssize;
-		SQArray *arr = SQArray::Create(_ss(this),nvargs);
-		SQInteger pbase = stackbase+paramssize;
-		for(SQInteger n = 0; n < nvargs; n++) {
-			arr->_values[n] = _stack._vals[pbase];
-			_stack._vals[pbase].Null();
-			pbase++;
-
-		}
-		_stack._vals[stackbase+paramssize] = arr;
-		//dumpstack(stackbase);
-	}
-	else if (paramssize != nargs) {
-		SQInteger ndef = func->_ndefaultparams;
-		SQInteger diff;
-		if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) {
-			for(SQInteger n = ndef - diff; n < ndef; n++) {
-				_stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n];
-			}
-		}
-		else {
-			Raise_Error(_SC("wrong number of parameters"));
-			return false;
-		}
-	}
-
-	if(closure->_env) {
-		_stack._vals[stackbase] = closure->_env->_obj;
-	}
-
-	if(!EnterFrame(stackbase, newtop, tailcall)) return false;
-
-	ci->_closure  = closure;
-	ci->_literals = func->_literals;
-	ci->_ip       = func->_instructions;
-	ci->_target   = (SQInt32)target;
-
-	if (_debughook) {
-		CallDebugHook(_SC('c'));
-	}
-
-	if (closure->_function->_bgenerator) {
-		SQFunctionProto *f = closure->_function;
-		SQGenerator *gen = SQGenerator::Create(_ss(this), closure);
-		if(!gen->Yield(this,f->_stacksize))
-			return false;
-		SQObjectPtr temp;
-		Return(1, target, temp);
-		STK(target) = gen;
-	}
-
-
-	return true;
-}
-
-bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval)
-{
-	SQBool    _isroot      = ci->_root;
-	SQInteger callerbase   = _stackbase - ci->_prevstkbase;
-
-	if (_debughook) {
-		for(SQInteger i=0; i<ci->_ncalls; i++) {
-			CallDebugHook(_SC('r'));
-		}
-	}
-
-	SQObjectPtr *dest;
-	if (_isroot) {
-		dest = &(retval);
-	} else if (ci->_target == -1) {
-		dest = NULL;
-	} else {
-		dest = &_stack._vals[callerbase + ci->_target];
-	}
-	if (dest) {
-		if(_arg0 != 0xFF) {
-			*dest = _stack._vals[_stackbase+_arg1];
-		}
-		else {
-			dest->Null();
-		}
-		//*dest = (_arg0 != 0xFF) ? _stack._vals[_stackbase+_arg1] : _null_;
-	}
-	LeaveFrame();
-	return _isroot ? true : false;
-}
-
-#define _RET_ON_FAIL(exp) { if(!exp) return false; }
-
-bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)
-{
- 	SQObjectPtr trg;
-	_RET_ON_FAIL(ARITH_OP( op , trg, a, incr));
-	target = a;
-	a = trg;
-	return true;
-}
-
-bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger selfidx)
-{
-	SQObjectPtr tmp, tself = self, tkey = key;
-	if (!Get(tself, tkey, tmp, 0, selfidx)) { return false; }
-	_RET_ON_FAIL(ARITH_OP( op , target, tmp, incr))
-	if (!Set(tself, tkey, target,selfidx)) { return false; }
-	if (postfix) target = tmp;
-	return true;
-}
-
-#define arg0 (_i_._arg0)
-#define sarg0 ((SQInteger)*((signed char *)&_i_._arg0))
-#define arg1 (_i_._arg1)
-#define sarg1 (*((SQInt32 *)&_i_._arg1))
-#define arg2 (_i_._arg2)
-#define arg3 (_i_._arg3)
-#define sarg3 ((SQInteger)*((signed char *)&_i_._arg3))
-
-SQRESULT SQVM::Suspend()
-{
-	if (_suspended)
-		return sq_throwerror(this, _SC("cannot suspend an already suspended vm"));
-	if (_nnativecalls!=2)
-		return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods"));
-	return SQ_SUSPEND_FLAG;
-}
-
-
-#define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; }
-bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr 
-&o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump)
-{
-	SQInteger nrefidx;
-	switch(type(o1)) {
-	case OT_TABLE:
-		if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(exitpos);
-		o4 = (SQInteger)nrefidx; _FINISH(1);
-	case OT_ARRAY:
-		if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(exitpos);
-		o4 = (SQInteger) nrefidx; _FINISH(1);
-	case OT_STRING:
-		if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos);
-		o4 = (SQInteger)nrefidx; _FINISH(1);
-	case OT_CLASS:
-		if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos);
-		o4 = (SQInteger)nrefidx; _FINISH(1);
-	case OT_USERDATA:
-	case OT_INSTANCE:
-		if(_delegable(o1)->_delegate) {
-			SQObjectPtr itr;
-			SQObjectPtr closure;
-			if(_delegable(o1)->GetMetaMethod(this, MT_NEXTI, closure)) {
-				Push(o1);
-				Push(o4);
-				if(CallMetaMethod(closure, MT_NEXTI, 2, itr)) {
-					o4 = o2 = itr;
-					if(type(itr) == OT_NULL) _FINISH(exitpos);
-					if(!Get(o1, itr, o3, 0, DONT_FALL_BACK)) {
-						Raise_Error(_SC("_nexti returned an invalid idx")); // cloud be changed
-						return false;
-					}
-					_FINISH(1);
-				}
-				else {
-					return false;
-				}
-			}
-			Raise_Error(_SC("_nexti failed"));
-			return false;
-		}
-		break;
-	case OT_GENERATOR:
-		if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(exitpos);
-		if(_generator(o1)->_state == SQGenerator::eSuspended) {
-			SQInteger idx = 0;
-			if(type(o4) == OT_INTEGER) {
-				idx = _integer(o4) + 1;
-			}
-			o2 = idx;
-			o4 = idx;
-			_generator(o1)->Resume(this, o3);
-			_FINISH(0);
-		}
-	default: 
-		Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));
-	}
-	return false; //cannot be hit(just to avoid warnings)
-}
-
-#define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1))
-
-#define SQ_THROW() { goto exception_trap; }
-
-#define _GUARD(exp) { if(!exp) { SQ_THROW();} }
-
-bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)
-{
-	SQInteger nouters;
-	SQClosure *closure = SQClosure::Create(_ss(this), func,_table(_roottable)->GetWeakRef(OT_TABLE));
-	if((nouters = func->_noutervalues)) {
-		for(SQInteger i = 0; i<nouters; i++) {
-			SQOuterVar &v = func->_outervalues[i];
-			switch(v._type){
-			case otLOCAL:
-				FindOuter(closure->_outervalues[i], &STK(_integer(v._src)));
-				break;
-			case otOUTER:
-				closure->_outervalues[i] = _closure(ci->_closure)->_outervalues[_integer(v._src)];
-				break;
-			}
-		}
-	}
-	SQInteger ndefparams;
-	if((ndefparams = func->_ndefaultparams)) {
-		for(SQInteger i = 0; i < ndefparams; i++) {
-			SQInteger spos = func->_defaultparams[i];
-			closure->_defaultparams[i] = _stack._vals[_stackbase + spos];
-		}
-	}
-	target = closure;
-	return true;
-
-}
-
-
-bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes)
-{
-	SQClass *base = NULL;
-	SQObjectPtr attrs;
-	if(baseclass != -1) {
-		if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; }
-		base = _class(_stack._vals[_stackbase + baseclass]);
-	}
-	if(attributes != MAX_FUNC_STACKSIZE) {
-		attrs = _stack._vals[_stackbase+attributes];
-	}
-	target = SQClass::Create(_ss(this),base);
-	if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) {
-		int nparams = 2;
-		SQObjectPtr ret;
-		Push(target); Push(attrs);
-		if(!Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false)) {
-			Pop(nparams);
-			return false;
-		}
-		Pop(nparams);
-	}
-	_class(target)->_attributes = attrs;
-	return true;
-}
-
-bool SQVM::IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res)
-{
-	if(type(o1) == type(o2)) {
-		res = (_rawval(o1) == _rawval(o2));
-	}
-	else {
-		if(sq_isnumeric(o1) && sq_isnumeric(o2)) {
-			res = (tofloat(o1) == tofloat(o2));
-		}
-		else {
-			res = false;
-		}
-	}
-	return true;
-}
-
-bool SQVM::IsFalse(SQObjectPtr &o)
-{
-	if(((type(o) & SQOBJECT_CANBEFALSE) 
-		&& ( ((type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) ))
-#if !defined(SQUSEDOUBLE) || (defined(SQUSEDOUBLE) && defined(_SQ64))
-		|| (_integer(o) == 0) )  //OT_NULL|OT_INTEGER|OT_BOOL
-#else
-		|| (((type(o) != OT_FLOAT) && (_integer(o) == 0))) )  //OT_NULL|OT_INTEGER|OT_BOOL
-#endif
-	{
-		return true;
-	}
-	return false;
-}
-extern SQInstructionDesc g_InstrDesc[];
-bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et)
-{
-	if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }
-	_nnativecalls++;
-	AutoDec ad(&_nnativecalls);
-	SQInteger traps = 0;
-	CallInfo *prevci = ci;
-		
-	switch(et) {
-		case ET_CALL: {
-			temp_reg = closure;
-			if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) { 
-				//call the handler if there are no calls in the stack, if not relies on the previous node
-				if(ci == NULL) CallErrorHandler(_lasterror);
-				return false;
-			}
-			if(ci == prevci) {
-				outres = STK(_top-nargs);
-				return true;
-			}
-			ci->_root = SQTrue;
-					  }
-			break;
-		case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = SQTrue; traps += ci->_etraps; break;
-		case ET_RESUME_VM:
-		case ET_RESUME_THROW_VM:
-			traps = _suspended_traps;
-			ci->_root = _suspended_root;
-			_suspended = SQFalse;
-			if(et  == ET_RESUME_THROW_VM) { SQ_THROW(); }
-			break;
-	}
-	
-exception_restore:
-	//
-	{
-		for(;;)
-		{
-			const SQInstruction &_i_ = *ci->_ip++;
-			//dumpstack(_stackbase);
-			//scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-_closure(ci->_closure)->_function->_instructions,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3);
-			switch(_i_.op)
-			{
-			case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue;
-			case _OP_LOAD: TARGET = ci->_literals[arg1]; continue;
-			case _OP_LOADINT: 
-#ifndef _SQ64
-				TARGET = (SQInteger)arg1; continue;
-#else
-				TARGET = (SQInteger)((SQInt32)arg1); continue;
-#endif
-			case _OP_LOADFLOAT: TARGET = *((SQFloat *)&arg1); continue;
-			case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;
-			case _OP_TAILCALL:{
-				SQObjectPtr &t = STK(arg1);
-				if (type(t) == OT_CLOSURE 
-					&& (!_closure(t)->_function->_bgenerator)){
-					SQObjectPtr clo = t;
-					if(_openouters) CloseOuters(&(_stack._vals[_stackbase]));
-					for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);
-					_GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true));
-					continue;
-				}
-							  }
-			case _OP_CALL: {
-					SQObjectPtr clo = STK(arg1);
-					switch (type(clo)) {
-					case OT_CLOSURE:
-						_GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false));
-						continue;
-					case OT_NATIVECLOSURE: {
-						bool suspend;
-						_GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo,suspend));
-						if(suspend){
-							_suspended = SQTrue;
-							_suspended_target = sarg0;
-							_suspended_root = ci->_root;
-							_suspended_traps = traps;
-							outres = clo;
-							return true;
-						}
-						if(sarg0 != -1) {
-							STK(arg0) = clo;
-						}
-										   }
-						continue;
-					case OT_CLASS:{
-						SQObjectPtr inst;
-						_GUARD(CreateClassInstance(_class(clo),inst,clo));
-						if(sarg0 != -1) {
-							STK(arg0) = inst;
-						}
-						SQInteger stkbase;
-						switch(type(clo)) {
-							case OT_CLOSURE:
-								stkbase = _stackbase+arg2;
-								_stack._vals[stkbase] = inst;
-								_GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false));
-								break;
-							case OT_NATIVECLOSURE:
-								bool suspend;
-								stkbase = _stackbase+arg2;
-								_stack._vals[stkbase] = inst;
-								_GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend));
-								break;
-							default: break; //shutup GCC 4.x
-						}
-						}
-						break;
-					case OT_TABLE:
-					case OT_USERDATA:
-					case OT_INSTANCE:{
-						SQObjectPtr closure;
-						if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) {
-							Push(clo);
-							for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i));
-							if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) SQ_THROW();
-							if(sarg0 != -1) {
-								STK(arg0) = clo;
-							}
-							break;
-						}
-									 
-						//Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
-						//SQ_THROW();
-					  }
-					default:
-						Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
-						SQ_THROW();
-					}
-				}
-				  continue;
-			case _OP_PREPCALL:
-			case _OP_PREPCALLK:	{
-					SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1);
-					SQObjectPtr &o = STK(arg2);
-					if (!Get(o, key, temp_reg,0,arg2)) {
-						SQ_THROW();
-					}
-					STK(arg3) = o;
-					_Swap(TARGET,temp_reg);//TARGET = temp_reg;
-				}
-				continue;
-			case _OP_GETK:
-				if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, 0,arg2)) { SQ_THROW();}
-				_Swap(TARGET,temp_reg);//TARGET = temp_reg;
-				continue;
-			case _OP_MOVE: TARGET = STK(arg1); continue;
-			case _OP_NEWSLOT:
-				_GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false));
-				if(arg0 != 0xFF) TARGET = STK(arg3);
-				continue;
-			case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue;
-			case _OP_SET:
-				if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { SQ_THROW(); }
-				if (arg0 != 0xFF) TARGET = STK(arg3);
-				continue;
-			case _OP_GET:
-				if (!Get(STK(arg1), STK(arg2), temp_reg, 0,arg1)) { SQ_THROW(); }
-				_Swap(TARGET,temp_reg);//TARGET = temp_reg;
-				continue;
-			case _OP_EQ:{
-				bool res;
-				if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }
-				TARGET = res?true:false;
-				}continue;
-			case _OP_NE:{ 
-				bool res;
-				if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }
-				TARGET = (!res)?true:false;
-				} continue;
-			case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue;
-			case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue;
-			case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue;
-			case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue;
-			case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue;
-			case _OP_BITW:	_GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue;
-			case _OP_RETURN:
-				if((ci)->_generator) {
-					(ci)->_generator->Kill();
-				}
-				if(Return(arg0, arg1, temp_reg)){
-					assert(traps==0);
-					//outres = temp_reg;
-					_Swap(outres,temp_reg);
-					return true;
-				}
-				continue;
-			case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue;
-			case _OP_LOADROOT:	{
-				SQWeakRef *w = _closure(ci->_closure)->_root;
-				if(type(w->_obj) != OT_NULL) {
-					TARGET = w->_obj;
-				} else {
-					TARGET = _roottable; //shoud this be like this? or null
-				}
-								}
-				continue;
-			case _OP_LOADBOOL: TARGET = arg1?true:false; continue;
-			case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue;
-			case _OP_JMP: ci->_ip += (sarg1); continue;
-			//case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
-			case _OP_JCMP: 
-				_GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg));
-				if(IsFalse(temp_reg)) ci->_ip+=(sarg1);
-				continue;
-			case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
-			case _OP_GETOUTER: {
-				SQClosure *cur_cls = _closure(ci->_closure);
-				SQOuter *otr = _outer(cur_cls->_outervalues[arg1]);
-				TARGET = *(otr->_valptr);
-				}
-			continue;
-			case _OP_SETOUTER: {
-				SQClosure *cur_cls = _closure(ci->_closure);
-				SQOuter   *otr = _outer(cur_cls->_outervalues[arg1]);
-				*(otr->_valptr) = STK(arg2);
-				if(arg0 != 0xFF) {
-					TARGET = STK(arg2);
-				}
-				}
-			continue;
-			case _OP_NEWOBJ: 
-				switch(arg3) {
-					case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;
-					case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;
-					case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;
-					default: assert(0); continue;
-				}
-			case _OP_APPENDARRAY: 
-				{
-					SQObject val;
-					val._unVal.raw = 0;
-				switch(arg2) {
-				case AAT_STACK:
-					val = STK(arg1); break;
-				case AAT_LITERAL:
-					val = ci->_literals[arg1]; break;
-				case AAT_INT:
-					val._type = OT_INTEGER;
-#ifndef _SQ64
-					val._unVal.nInteger = (SQInteger)arg1; 
-#else
-					val._unVal.nInteger = (SQInteger)((SQInt32)arg1);
-#endif
-					break;
-				case AAT_FLOAT:
-					val._type = OT_FLOAT;
-					val._unVal.fFloat = *((SQFloat *)&arg1);
-					break;
-				case AAT_BOOL:
-					val._type = OT_BOOL;
-					val._unVal.nInteger = arg1;
-					break;
-				default: val._type = OT_INTEGER; assert(0); break;
-
-				}
-				_array(STK(arg0))->Append(val);	continue;
-				}
-			case _OP_COMPARITH: {
-				SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16);
-				_GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx)); 
-								}
-				continue;
-			case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue;
-			case _OP_INCL: {
-				SQObjectPtr &a = STK(arg1);
-				if(type(a) == OT_INTEGER) {
-					a._unVal.nInteger = _integer(a) + sarg3;
-				}
-				else {
-					SQObjectPtr o(sarg3); //_GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));
-					_ARITH_(+,a,a,o);
-				}
-						   } continue;
-			case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue;
-			case _OP_PINCL:	{
-				SQObjectPtr &a = STK(arg1);
-				if(type(a) == OT_INTEGER) {
-					TARGET = a;
-					a._unVal.nInteger = _integer(a) + sarg3;
-				}
-				else {
-					SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));
-				}
-				
-						} continue;
-			case _OP_CMP:	_GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET))	continue;
-			case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, GET_FLAG_DO_NOT_RAISE_ERROR | GET_FLAG_RAW, DONT_FALL_BACK) ? true : false; continue;
-			case _OP_INSTANCEOF: 
-				if(type(STK(arg1)) != OT_CLASS)
-				{Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();}
-				TARGET = (type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false;
-				continue;
-			case _OP_AND: 
-				if(IsFalse(STK(arg2))) {
-					TARGET = STK(arg2);
-					ci->_ip += (sarg1);
-				}
-				continue;
-			case _OP_OR:
-				if(!IsFalse(STK(arg2))) {
-					TARGET = STK(arg2);
-					ci->_ip += (sarg1);
-				}
-				continue;
-			case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue;
-			case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue;
-			case _OP_BWNOT:
-				if(type(STK(arg1)) == OT_INTEGER) {
-					SQInteger t = _integer(STK(arg1));
-					TARGET = SQInteger(~t);
-					continue;
-				}
-				Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1)));
-				SQ_THROW();
-			case _OP_CLOSURE: {
-				SQClosure *c = ci->_closure._unVal.pClosure;
-				SQFunctionProto *fp = c->_function;
-				if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); }
-				continue;
-			}
-			case _OP_YIELD:{
-				if(ci->_generator) {
-					if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);
-					_GUARD(ci->_generator->Yield(this,arg2));
-					traps -= ci->_etraps;
-					if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);//STK(arg1) = temp_reg;
-				}
-				else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();}
-				if(Return(arg0, arg1, temp_reg)){
-					assert(traps == 0);
-					outres = temp_reg;
-					return true;
-				}
-					
-				}
-				continue;
-			case _OP_RESUME:
-				if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();}
-				_GUARD(_generator(STK(arg1))->Resume(this, TARGET));
-				traps += ci->_etraps;
-                continue;
-			case _OP_FOREACH:{ int tojump;
-				_GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump));
-				ci->_ip += tojump; }
-				continue;
-			case _OP_POSTFOREACH:
-				assert(type(STK(arg0)) == OT_GENERATOR);
-				if(_generator(STK(arg0))->_state == SQGenerator::eDead) 
-					ci->_ip += (sarg1 - 1);
-				continue;
-			case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue;
-			case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue;
-			case _OP_PUSHTRAP:{
-				SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions;
-				_etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++;
-				ci->_etraps++;
-							  }
-				continue;
-			case _OP_POPTRAP: {
-				for(SQInteger i = 0; i < arg0; i++) {
-					_etraps.pop_back(); traps--;
-					ci->_etraps--;
-				}
-							  }
-				continue;
-			case _OP_THROW:	Raise_Error(TARGET); SQ_THROW(); continue;
-			case _OP_NEWSLOTA:
-				_GUARD(NewSlotA(STK(arg1),STK(arg2),STK(arg3),(arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : SQObjectPtr(),(arg0&NEW_SLOT_STATIC_FLAG)?true:false,false));
-				continue;
-			case _OP_GETBASE:{
-				SQClosure *clo = _closure(ci->_closure);
-				if(clo->_base) {
-					TARGET = clo->_base;
-				}
-				else {
-					TARGET.Null();
-				}
-				continue;
-			}
-			case _OP_CLOSE:
-				if(_openouters) CloseOuters(&(STK(arg1)));
-				continue;
-			}
-			
-		}
-	}
-exception_trap:
-	{
-		SQObjectPtr currerror = _lasterror;
-//		dumpstack(_stackbase);
-//		SQInteger n = 0;
-		SQInteger last_top = _top;
-		
-		if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror);
-
-		while( ci ) {
-			if(ci->_etraps > 0) {
-				SQExceptionTrap &et = _etraps.top();
-				ci->_ip = et._ip;
-				_top = et._stacksize;
-				_stackbase = et._stackbase;
-				_stack._vals[_stackbase + et._extarget] = currerror;
-				_etraps.pop_back(); traps--; ci->_etraps--;
-				while(last_top >= _top) _stack._vals[last_top--].Null();
-				goto exception_restore;
-			}
-			else if (_debughook) { 
-					//notify debugger of a "return"
-					//even if it really an exception unwinding the stack
-					for(SQInteger i = 0; i < ci->_ncalls; i++) {
-						CallDebugHook(_SC('r'));
-					}
-			}
-			if(ci->_generator) ci->_generator->Kill();
-			bool mustbreak = ci && ci->_root;
-			LeaveFrame();
-			if(mustbreak) break;
-		}
-						
-		_lasterror = currerror;
-		return false;
-	}
-	assert(0);
-}
-
-bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor)
-{
-	inst = theclass->CreateInstance();
-	if(!theclass->GetConstructor(constructor)) {
-		constructor.Null();
-	}
-	return true;
-}
-
-void SQVM::CallErrorHandler(SQObjectPtr &error)
-{
-	if(type(_errorhandler) != OT_NULL) {
-		SQObjectPtr out;
-		Push(_roottable); Push(error);
-		Call(_errorhandler, 2, _top-2, out,SQFalse);
-		Pop(2);
-	}
-}
-
-
-void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline)
-{
-	_debughook = false;
-	SQFunctionProto *func=_closure(ci->_closure)->_function;
-	if(_debughook_native) {
-		const SQChar *src = type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL;
-		const SQChar *fname = type(func->_name) == OT_STRING?_stringval(func->_name):NULL;
-		SQInteger line = forcedline?forcedline:func->GetLine(ci->_ip);
-		_debughook_native(this,type,src,line,fname);
-	}
-	else {
-		SQObjectPtr temp_reg;
-		SQInteger nparams=5;
-		Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);
-		Call(_debughook_closure,nparams,_top-nparams,temp_reg,SQFalse);
-		Pop(nparams);
-	}
-	_debughook = true;
-}
-
-bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, bool &suspend)
-{
-	SQInteger nparamscheck = nclosure->_nparamscheck;
-	SQInteger newtop = newbase + nargs + nclosure->_noutervalues;
-	
-	if (_nnativecalls + 1 > MAX_NATIVE_CALLS) {
-		Raise_Error(_SC("Native stack overflow"));
-		return false;
-	}
-
-	if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) ||
-		((nparamscheck < 0) && (nargs < (-nparamscheck)))))
-	{
-		Raise_Error(_SC("wrong number of parameters"));
-		return false;
-	}
-
-	SQInteger tcs;
-	SQIntVec &tc = nclosure->_typecheck;
-	if((tcs = tc.size())) {
-		for(SQInteger i = 0; i < nargs && i < tcs; i++) {
-			if((tc._vals[i] != -1) && !(type(_stack._vals[newbase+i]) & tc._vals[i])) {
-				Raise_ParamTypeError(i,tc._vals[i],type(_stack._vals[newbase+i]));
-				return false;
-			}
-		}
-	}
-
-	if(!EnterFrame(newbase, newtop, false)) return false;
-	ci->_closure  = nclosure;
-
-	SQInteger outers = nclosure->_noutervalues;
-	for (SQInteger i = 0; i < outers; i++) {
-		_stack._vals[newbase+nargs+i] = nclosure->_outervalues[i];
-	}
-	if(nclosure->_env) {
-		_stack._vals[newbase] = nclosure->_env->_obj;
-	}
-
-	_nnativecalls++;
-	SQInteger ret = (nclosure->_function)(this);
-	_nnativecalls--;
-
-	suspend = false;
-	if (ret == SQ_SUSPEND_FLAG) {
-		suspend = true;
-	}
-	else if (ret < 0) {
-		LeaveFrame();
-		Raise_Error(_lasterror);
-		return false;
-	}
-	if(ret) {
-		retval = _stack._vals[_top-1];
-	}
-	else {
-		retval.Null();
-	}
-	//retval = ret ? _stack._vals[_top-1] : _null_;
-	LeaveFrame();
-	return true;
-}
-
-#define FALLBACK_OK			0
-#define FALLBACK_NO_MATCH	1
-#define FALLBACK_ERROR		2
-
-bool SQVM::Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, SQUnsignedInteger getflags, SQInteger selfidx)
-{
-	switch(type(self)){
-	case OT_TABLE:
-		if(_table(self)->Get(key,dest))return true;
-		break;
-	case OT_ARRAY:
-		if (sq_isnumeric(key)) { if (_array(self)->Get(tointeger(key), dest)) { return true; } if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key); return false; }
-		break;
-	case OT_INSTANCE:
-		if(_instance(self)->Get(key,dest)) return true;
-		break;
-	case OT_CLASS: 
-		if(_class(self)->Get(key,dest)) return true;
-		break;
-	case OT_STRING:
-		if(sq_isnumeric(key)){
-			SQInteger n = tointeger(key);
-			SQInteger len = _string(self)->_len;
-			if (n < 0) { n += len; }
-			if (n >= 0 && n < len) {
-				dest = SQInteger(_stringval(self)[n]);
-				return true;
-			}
-			if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key);
-			return false;
-		}
-		break;
-	default:break; //shut up compiler
-	}
-	if ((getflags & GET_FLAG_RAW) == 0) {
-		switch(FallBackGet(self,key,dest)) {
-			case FALLBACK_OK: return true; //okie
-			case FALLBACK_NO_MATCH: break; //keep falling back
-			case FALLBACK_ERROR: return false; // the metamethod failed
-		}
-		if(InvokeDefaultDelegate(self,key,dest)) {
-			return true;
-		}
-	}
-//#ifdef ROOT_FALLBACK
-	if(selfidx == 0) {
-		SQWeakRef *w = _closure(ci->_closure)->_root;
-		if(type(w->_obj) != OT_NULL) 
-		{
-			if(Get(*((const SQObjectPtr *)&w->_obj),key,dest,0,DONT_FALL_BACK)) return true;
-		}
-		
-	}
-//#endif
-	if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key);
-	return false;
-}
-
-bool SQVM::InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest)
-{
-	SQTable *ddel = NULL;
-	switch(type(self)) {
-		case OT_CLASS: ddel = _class_ddel; break;
-		case OT_TABLE: ddel = _table_ddel; break;
-		case OT_ARRAY: ddel = _array_ddel; break;
-		case OT_STRING: ddel = _string_ddel; break;
-		case OT_INSTANCE: ddel = _instance_ddel; break;
-		case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break;
-		case OT_GENERATOR: ddel = _generator_ddel; break;
-		case OT_CLOSURE: case OT_NATIVECLOSURE:	ddel = _closure_ddel; break;
-		case OT_THREAD: ddel = _thread_ddel; break;
-		case OT_WEAKREF: ddel = _weakref_ddel; break;
-		default: return false;
-	}
-	return  ddel->Get(key,dest);
-}
-
-
-SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest)
-{
-	switch(type(self)){
-	case OT_TABLE:
-	case OT_USERDATA:
-        //delegation
-		if(_delegable(self)->_delegate) {
-			if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,0,DONT_FALL_BACK)) return FALLBACK_OK;	
-		}
-		else {
-			return FALLBACK_NO_MATCH;
-		}
-		//go through
-	case OT_INSTANCE: {
-		SQObjectPtr closure;
-		if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) {
-			Push(self);Push(key);
-			_nmetamethodscall++;
-			AutoDec ad(&_nmetamethodscall);
-			if(Call(closure, 2, _top - 2, dest, SQFalse)) {
-				Pop(2);
-				return FALLBACK_OK;
-			}
-			else {
-				Pop(2);
-				if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found)
-					return FALLBACK_ERROR;
-				}
-			}
-		}
-					  }
-		break;
-	default: break;//shutup GCC 4.x
-	}
-	// no metamethod or no fallback type
-	return FALLBACK_NO_MATCH;
-}
-
-bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,SQInteger selfidx)
-{
-	switch(type(self)){
-	case OT_TABLE:
-		if(_table(self)->Set(key,val)) return true;
-		break;
-	case OT_INSTANCE:
-		if(_instance(self)->Set(key,val)) return true;
-		break;
-	case OT_ARRAY:
-		if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; }
-		if(!_array(self)->Set(tointeger(key),val)) {
-			Raise_IdxError(key);
-			return false;
-		}
-		return true;
-	default:
-		Raise_Error(_SC("trying to set '%s'"),GetTypeName(self));
-		return false;
-	}
-
-	switch(FallBackSet(self,key,val)) {
-		case FALLBACK_OK: return true; //okie
-		case FALLBACK_NO_MATCH: break; //keep falling back
-		case FALLBACK_ERROR: return false; // the metamethod failed
-	}
-	if(selfidx == 0) {
-		if(_table(_roottable)->Set(key,val))
-			return true;
-	}
-	Raise_IdxError(key);
-	return false;
-}
-
-SQInteger SQVM::FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val)
-{
-	switch(type(self)) {
-	case OT_TABLE:
-		if(_table(self)->_delegate) {
-			if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK))	return FALLBACK_OK;
-		}
-		//keps on going
-	case OT_INSTANCE:
-	case OT_USERDATA:{
-		SQObjectPtr closure;
-		SQObjectPtr t;
-		if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) {
-			Push(self);Push(key);Push(val);
-			_nmetamethodscall++;
-			AutoDec ad(&_nmetamethodscall);
-			if(Call(closure, 3, _top - 3, t, SQFalse)) {
-				Pop(3);
-				return FALLBACK_OK;
-			}
-			else {
-				if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found)
-					//error
-					Pop(3);
-					return FALLBACK_ERROR;
-				}
-			}
-		}
-					 }
-		break;
-		default: break;//shutup GCC 4.x
-	}
-	// no metamethod or no fallback type
-	return FALLBACK_NO_MATCH;
-}
-
-bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target)
-{
-	SQObjectPtr temp_reg;
-	SQObjectPtr newobj;
-	switch(type(self)){
-	case OT_TABLE:
-		newobj = _table(self)->Clone();
-		goto cloned_mt;
-	case OT_INSTANCE: {
-		newobj = _instance(self)->Clone(_ss(this));
-cloned_mt:
-		SQObjectPtr closure;
-		if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) {
-			Push(newobj);
-			Push(self);
-			if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg))
-				return false;
-		}
-		}
-		target = newobj;
-		return true;
-	case OT_ARRAY: 
-		target = _array(self)->Clone();
-		return true;
-	default: 
-		Raise_Error(_SC("cloning a %s"), GetTypeName(self));
-		return false;
-	}
-}
-
-bool SQVM::NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw)
-{
-	if(type(self) != OT_CLASS) {
-		Raise_Error(_SC("object must be a class"));
-		return false;
-	}
-	SQClass *c = _class(self);
-	if(!raw) {
-		SQObjectPtr &mm = c->_metamethods[MT_NEWMEMBER];
-		if(type(mm) != OT_NULL ) {
-			Push(self); Push(key); Push(val);
-			Push(attrs);
-			Push(bstatic);
-			return CallMetaMethod(mm,MT_NEWMEMBER,5,temp_reg);
-		}
-	}
-	if(!NewSlot(self, key, val,bstatic))
-		return false;
-	if(type(attrs) != OT_NULL) {
-		c->SetAttributes(key,attrs);
-	}
-	return true;
-}
-
-bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
-{
-	if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; }
-	switch(type(self)) {
-	case OT_TABLE: {
-		bool rawcall = true;
-		if(_table(self)->_delegate) {
-			SQObjectPtr res;
-			if(!_table(self)->Get(key,res)) {
-				SQObjectPtr closure;
-				if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {
-					Push(self);Push(key);Push(val);
-					if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {
-						return false;
-					}
-					rawcall = false;
-				}
-				else {
-					rawcall = true;
-				}
-			}
-		}
-		if(rawcall) _table(self)->NewSlot(key,val); //cannot fail
-		
-		break;}
-	case OT_INSTANCE: {
-		SQObjectPtr res;
-		SQObjectPtr closure;
-		if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {
-			Push(self);Push(key);Push(val);
-			if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {
-				return false;
-			}
-			break;
-		}
-		Raise_Error(_SC("class instances do not support the new slot operator"));
-		return false;
-		break;}
-	case OT_CLASS: 
-		if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) {
-			if(_class(self)->_locked) {
-				Raise_Error(_SC("trying to modify a class that has already been instantiated"));
-				return false;
-			}
-			else {
-				SQObjectPtr oval = PrintObjVal(key);
-				Raise_Error(_SC("the property '%s' already exists"),_stringval(oval));
-				return false;
-			}
-		}
-		break;
-	default:
-		Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key));
-		return false;
-		break;
-	}
-	return true;
-}
-
-
-
-bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res)
-{
-	switch(type(self)) {
-	case OT_TABLE:
-	case OT_INSTANCE:
-	case OT_USERDATA: {
-		SQObjectPtr t;
-		//bool handled = false;
-		SQObjectPtr closure;
-		if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) {
-			Push(self);Push(key);
-			return CallMetaMethod(closure,MT_DELSLOT,2,res);
-		}
-		else {
-			if(type(self) == OT_TABLE) {
-				if(_table(self)->Get(key,t)) {
-					_table(self)->Remove(key);
-				}
-				else {
-					Raise_IdxError((SQObject &)key);
-					return false;
-				}
-			}
-			else {
-				Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self));
-				return false;
-			}
-		}
-		res = t;
-				}
-		break;
-	default:
-		Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self));
-		return false;
-	}
-	return true;
-}
-
-bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror)
-{
-#ifdef _DEBUG
-SQInteger prevstackbase = _stackbase;
-#endif
-	switch(type(closure)) {
-	case OT_CLOSURE:
-		return Execute(closure, nparams, stackbase, outres, raiseerror);
-		break;
-	case OT_NATIVECLOSURE:{
-		bool suspend;
-		return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend);
-		
-						  }
-		break;
-	case OT_CLASS: {
-		SQObjectPtr constr;
-		SQObjectPtr temp;
-		CreateClassInstance(_class(closure),outres,constr);
-		SQObjectType ctype = type(constr);
-		if (ctype == OT_NATIVECLOSURE || ctype == OT_CLOSURE) {
-			_stack[stackbase] = outres;
-			return Call(constr,nparams,stackbase,temp,raiseerror);
-		}
-		return true;
-				   }
-		break;
-	default:
-		return false;
-	}
-#ifdef _DEBUG
-	if(!_suspended) {
-		assert(_stackbase == prevstackbase);
-	}
-#endif
-	return true;
-}
-
-bool SQVM::CallMetaMethod(SQObjectPtr &closure,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres)
-{
-	//SQObjectPtr closure;
-	
-	_nmetamethodscall++;
-	if(Call(closure, nparams, _top - nparams, outres, SQFalse)) {
-		_nmetamethodscall--;
-		Pop(nparams);
-		return true;
-	}
-	_nmetamethodscall--;
-	//}
-	Pop(nparams);
-	return false;
-}
-
-void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex)
-{
-	SQOuter **pp = &_openouters;
-	SQOuter *p;
-	SQOuter *otr;
-
-	while ((p = *pp) != NULL && p->_valptr >= stackindex) {
-		if (p->_valptr == stackindex) {
-			target = SQObjectPtr(p);
-			return;
-		}
-		pp = &p->_next;
-	}
-	otr = SQOuter::Create(_ss(this), stackindex);
-	otr->_next = *pp;
-	otr->_idx  = (stackindex - _stack._vals);
-	__ObjAddRef(otr);
-	*pp = otr;
-	target = SQObjectPtr(otr);
-}
-
-bool SQVM::EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall)
-{
-	if( !tailcall ) {
-		if( _callsstacksize == _alloccallsstacksize ) {
-			GrowCallStack();
-		}
-		ci = &_callsstack[_callsstacksize++];
-		ci->_prevstkbase = (SQInt32)(newbase - _stackbase);
-		ci->_prevtop = (SQInt32)(_top - _stackbase);
-		ci->_etraps = 0;
-		ci->_ncalls = 1;
-		ci->_generator = NULL;
-		ci->_root = SQFalse;
-	}
-	else {
-		ci->_ncalls++;
-	}
-
-	_stackbase = newbase;
-	_top = newtop;
-	if(newtop + MIN_STACK_OVERHEAD > (SQInteger)_stack.size()) {
-		if(_nmetamethodscall) {
-			Raise_Error(_SC("stack overflow, cannot resize stack while in  a metamethod"));
-			return false;
-		}
-		_stack.resize(newtop + (MIN_STACK_OVERHEAD << 2));
-		RelocateOuters();
-	}
-	return true;
-}
-
-void SQVM::LeaveFrame() {
-	SQInteger last_top = _top;
-	SQInteger last_stackbase = _stackbase;
-	SQInteger css = --_callsstacksize;
-
-	/* First clean out the call stack frame */
-	ci->_closure.Null();
-	_stackbase -= ci->_prevstkbase;
-	_top = _stackbase + ci->_prevtop;
-	ci = (css) ? &_callsstack[css-1] : NULL;
-
-	if(_openouters) CloseOuters(&(_stack._vals[last_stackbase]));
-	while (last_top >= _top) {
-		_stack._vals[last_top--].Null();
-	}
-}
-
-void SQVM::RelocateOuters()
-{
-	SQOuter *p = _openouters;
-	while (p) {
-		p->_valptr = _stack._vals + p->_idx;
-		p = p->_next;
-	}
-}
-
-void SQVM::CloseOuters(SQObjectPtr *stackindex) {
-  SQOuter *p;
-  while ((p = _openouters) != NULL && p->_valptr >= stackindex) {
-    p->_value = *(p->_valptr);
-    p->_valptr = &p->_value;
-    _openouters = p->_next;
-  	__ObjRelease(p);
-  }
-}
-
-void SQVM::Remove(SQInteger n) {
-	n = (n >= 0)?n + _stackbase - 1:_top + n;
-	for(SQInteger i = n; i < _top; i++){
-		_stack[i] = _stack[i+1];
-	}
-	_stack[_top].Null();
-	_top--;
-}
-
-void SQVM::Pop() {
-	_stack[--_top].Null();
-}
-
-void SQVM::Pop(SQInteger n) {
-	for(SQInteger i = 0; i < n; i++){
-		_stack[--_top].Null();
-	}
-}
-
-void SQVM::PushNull() { _stack[_top++].Null(); }
-void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; }
-SQObjectPtr &SQVM::Top() { return _stack[_top-1]; }
-SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; }
-SQObjectPtr &SQVM::GetUp(SQInteger n) { return _stack[_top+n]; }
-SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; }
-
-#ifdef _DEBUG_DUMP
-void SQVM::dumpstack(SQInteger stackbase,bool dumpall)
-{
-	SQInteger size=dumpall?_stack.size():_top;
-	SQInteger n=0;
-	scprintf(_SC("\n>>>>stack dump<<<<\n"));
-	CallInfo &ci=_callsstack[_callsstacksize-1];
-	scprintf(_SC("IP: %p\n"),ci._ip);
-	scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase);
-	scprintf(_SC("prev top: %d\n"),ci._prevtop);
-	for(SQInteger i=0;i<size;i++){
-		SQObjectPtr &obj=_stack[i];	
-		if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));
-		scprintf(_SC("[%d]:"),n);
-		switch(type(obj)){
-		case OT_FLOAT:			scprintf(_SC("FLOAT %.3f"),_float(obj));break;
-		case OT_INTEGER:		scprintf(_SC("INTEGER %d"),_integer(obj));break;
-		case OT_BOOL:			scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break;
-		case OT_STRING:			scprintf(_SC("STRING %s"),_stringval(obj));break;
-		case OT_NULL:			scprintf(_SC("NULL"));	break;
-		case OT_TABLE:			scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break;
-		case OT_ARRAY:			scprintf(_SC("ARRAY %p"),_array(obj));break;
-		case OT_CLOSURE:		scprintf(_SC("CLOSURE [%p]"),_closure(obj));break;
-		case OT_NATIVECLOSURE:	scprintf(_SC("NATIVECLOSURE"));break;
-		case OT_USERDATA:		scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break;
-		case OT_GENERATOR:		scprintf(_SC("GENERATOR %p"),_generator(obj));break;
-		case OT_THREAD:			scprintf(_SC("THREAD [%p]"),_thread(obj));break;
-		case OT_USERPOINTER:	scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break;
-		case OT_CLASS:			scprintf(_SC("CLASS %p"),_class(obj));break;
-		case OT_INSTANCE:		scprintf(_SC("INSTANCE %p"),_instance(obj));break;
-		case OT_WEAKREF:		scprintf(_SC("WEAKERF %p"),_weakref(obj));break;
-		default:
-			assert(0);
-			break;
-		};
-		scprintf(_SC("\n"));
-		++n;
-	}
-}
-
-
-
-#endif
+/*
+    see copyright notice in squirrel.h
+*/
+#include "sqpcheader.h"
+#include <math.h>
+#include <stdlib.h>
+#include "sqopcodes.h"
+#include "sqvm.h"
+#include "sqfuncproto.h"
+#include "sqclosure.h"
+#include "sqstring.h"
+#include "sqtable.h"
+#include "squserdata.h"
+#include "sqarray.h"
+#include "sqclass.h"
+
+#define TOP() (_stack._vals[_top-1])
+
+bool SQVM::BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)
+{
+    SQInteger res;
+    if((type(o1)|type(o2)) == OT_INTEGER)
+    {
+        SQInteger i1 = _integer(o1), i2 = _integer(o2);
+        switch(op) {
+            case BW_AND:    res = i1 & i2; break;
+            case BW_OR:     res = i1 | i2; break;
+            case BW_XOR:    res = i1 ^ i2; break;
+            case BW_SHIFTL: res = i1 << i2; break;
+            case BW_SHIFTR: res = i1 >> i2; break;
+            case BW_USHIFTR:res = (SQInteger)(*((SQUnsignedInteger*)&i1) >> i2); break;
+            default: { Raise_Error(_SC("internal vm error bitwise op failed")); return false; }
+        }
+    }
+    else { Raise_Error(_SC("bitwise op between '%s' and '%s'"),GetTypeName(o1),GetTypeName(o2)); return false;}
+    trg = res;
+    return true;
+}
+
+#define _ARITH_(op,trg,o1,o2) \
+{ \
+    SQInteger tmask = type(o1)|type(o2); \
+    switch(tmask) { \
+        case OT_INTEGER: trg = _integer(o1) op _integer(o2);break; \
+        case (OT_FLOAT|OT_INTEGER): \
+        case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\
+        default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\
+    } \
+}
+
+#define _ARITH_NOZERO(op,trg,o1,o2,err) \
+{ \
+    SQInteger tmask = type(o1)|type(o2); \
+    switch(tmask) { \
+        case OT_INTEGER: { SQInteger i2 = _integer(o2); if(i2 == 0) { Raise_Error(err); SQ_THROW(); } trg = _integer(o1) op i2; } break;\
+        case (OT_FLOAT|OT_INTEGER): \
+        case (OT_FLOAT): trg = tofloat(o1) op tofloat(o2); break;\
+        default: _GUARD(ARITH_OP((#op)[0],trg,o1,o2)); break;\
+    } \
+}
+
+bool SQVM::ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2)
+{
+    SQInteger tmask = type(o1)|type(o2);
+    switch(tmask) {
+        case OT_INTEGER:{
+            SQInteger res, i1 = _integer(o1), i2 = _integer(o2);
+            switch(op) {
+            case '+': res = i1 + i2; break;
+            case '-': res = i1 - i2; break;
+            case '/': if (i2 == 0) { Raise_Error(_SC("division by zero")); return false; }
+                    else if (i2 == -1 && i1 == INT_MIN) { Raise_Error(_SC("integer overflow")); return false; }
+                    res = i1 / i2;
+                    break;
+            case '*': res = i1 * i2; break;
+            case '%': if (i2 == 0) { Raise_Error(_SC("modulo by zero")); return false; }
+                    else if (i2 == -1 && i1 == INT_MIN) { res = 0; break; }
+                    res = i1 % i2;
+                    break;
+            default: res = 0xDEADBEEF;
+            }
+            trg = res; }
+            break;
+        case (OT_FLOAT|OT_INTEGER):
+        case (OT_FLOAT):{
+            SQFloat res, f1 = tofloat(o1), f2 = tofloat(o2);
+            switch(op) {
+            case '+': res = f1 + f2; break;
+            case '-': res = f1 - f2; break;
+            case '/': res = f1 / f2; break;
+            case '*': res = f1 * f2; break;
+            case '%': res = SQFloat(fmod((double)f1,(double)f2)); break;
+            default: res = 0x0f;
+            }
+            trg = res; }
+            break;
+        default:
+            if(op == '+' && (tmask & _RT_STRING)){
+                if(!StringCat(o1, o2, trg)) return false;
+            }
+            else if(!ArithMetaMethod(op,o1,o2,trg)) {
+                return false;
+            }
+    }
+    return true;
+}
+
+SQVM::SQVM(SQSharedState *ss)
+{
+    _sharedstate=ss;
+    _suspended = SQFalse;
+    _suspended_target = -1;
+    _suspended_root = SQFalse;
+    _suspended_traps = -1;
+    _foreignptr = NULL;
+    _nnativecalls = 0;
+    _nmetamethodscall = 0;
+    _lasterror.Null();
+    _errorhandler.Null();
+    _debughook = false;
+    _debughook_native = NULL;
+    _debughook_closure.Null();
+    _openouters = NULL;
+    ci = NULL;
+    _releasehook = NULL;
+    INIT_CHAIN();ADD_TO_CHAIN(&_ss(this)->_gc_chain,this);
+}
+
+void SQVM::Finalize()
+{
+    if(_releasehook) { _releasehook(_foreignptr,0); _releasehook = NULL; }
+    if(_openouters) CloseOuters(&_stack._vals[0]);
+    _roottable.Null();
+    _lasterror.Null();
+    _errorhandler.Null();
+    _debughook = false;
+    _debughook_native = NULL;
+    _debughook_closure.Null();
+    temp_reg.Null();
+    _callstackdata.resize(0);
+    SQInteger size=_stack.size();
+    for(SQInteger i=0;i<size;i++)
+        _stack[i].Null();
+}
+
+SQVM::~SQVM()
+{
+    Finalize();
+    REMOVE_FROM_CHAIN(&_ss(this)->_gc_chain,this);
+}
+
+bool SQVM::ArithMetaMethod(SQInteger op,const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &dest)
+{
+    SQMetaMethod mm;
+    switch(op){
+        case _SC('+'): mm=MT_ADD; break;
+        case _SC('-'): mm=MT_SUB; break;
+        case _SC('/'): mm=MT_DIV; break;
+        case _SC('*'): mm=MT_MUL; break;
+        case _SC('%'): mm=MT_MODULO; break;
+        default: mm = MT_ADD; assert(0); break; //shutup compiler
+    }
+    if(is_delegable(o1) && _delegable(o1)->_delegate) {
+
+        SQObjectPtr closure;
+        if(_delegable(o1)->GetMetaMethod(this, mm, closure)) {
+            Push(o1);Push(o2);
+            return CallMetaMethod(closure,mm,2,dest);
+        }
+    }
+    Raise_Error(_SC("arith op %c on between '%s' and '%s'"),op,GetTypeName(o1),GetTypeName(o2));
+    return false;
+}
+
+bool SQVM::NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o)
+{
+
+    switch(type(o)) {
+    case OT_INTEGER:
+        trg = -_integer(o);
+        return true;
+    case OT_FLOAT:
+        trg = -_float(o);
+        return true;
+    case OT_TABLE:
+    case OT_USERDATA:
+    case OT_INSTANCE:
+        if(_delegable(o)->_delegate) {
+            SQObjectPtr closure;
+            if(_delegable(o)->GetMetaMethod(this, MT_UNM, closure)) {
+                Push(o);
+                if(!CallMetaMethod(closure, MT_UNM, 1, temp_reg)) return false;
+                _Swap(trg,temp_reg);
+                return true;
+
+            }
+        }
+    default:break; //shutup compiler
+    }
+    Raise_Error(_SC("attempt to negate a %s"), GetTypeName(o));
+    return false;
+}
+
+#define _RET_SUCCEED(exp) { result = (exp); return true; }
+bool SQVM::ObjCmp(const SQObjectPtr &o1,const SQObjectPtr &o2,SQInteger &result)
+{
+    SQObjectType t1 = type(o1), t2 = type(o2);
+    if(t1 == t2) {
+        if(_rawval(o1) == _rawval(o2))_RET_SUCCEED(0);
+        SQObjectPtr res;
+        switch(t1){
+        case OT_STRING:
+            _RET_SUCCEED(scstrcmp(_stringval(o1),_stringval(o2)));
+        case OT_INTEGER:
+            _RET_SUCCEED((_integer(o1)<_integer(o2))?-1:1);
+        case OT_FLOAT:
+            _RET_SUCCEED((_float(o1)<_float(o2))?-1:1);
+        case OT_TABLE:
+        case OT_USERDATA:
+        case OT_INSTANCE:
+            if(_delegable(o1)->_delegate) {
+                SQObjectPtr closure;
+                if(_delegable(o1)->GetMetaMethod(this, MT_CMP, closure)) {
+                    Push(o1);Push(o2);
+                    if(CallMetaMethod(closure,MT_CMP,2,res)) {
+                        if(type(res) != OT_INTEGER) {
+                            Raise_Error(_SC("_cmp must return an integer"));
+                            return false;
+                        }
+                        _RET_SUCCEED(_integer(res))
+                    }
+                    return false;
+                }
+            }
+            //continues through (no break needed)
+        default:
+            _RET_SUCCEED( _userpointer(o1) < _userpointer(o2)?-1:1 );
+        }
+        assert(0);
+        //if(type(res)!=OT_INTEGER) { Raise_CompareError(o1,o2); return false; }
+        //  _RET_SUCCEED(_integer(res));
+
+    }
+    else{
+        if(sq_isnumeric(o1) && sq_isnumeric(o2)){
+            if((t1==OT_INTEGER) && (t2==OT_FLOAT)) {
+                if( _integer(o1)==_float(o2) ) { _RET_SUCCEED(0); }
+                else if( _integer(o1)<_float(o2) ) { _RET_SUCCEED(-1); }
+                _RET_SUCCEED(1);
+            }
+            else{
+                if( _float(o1)==_integer(o2) ) { _RET_SUCCEED(0); }
+                else if( _float(o1)<_integer(o2) ) { _RET_SUCCEED(-1); }
+                _RET_SUCCEED(1);
+            }
+        }
+        else if(t1==OT_NULL) {_RET_SUCCEED(-1);}
+        else if(t2==OT_NULL) {_RET_SUCCEED(1);}
+        else { Raise_CompareError(o1,o2); return false; }
+
+    }
+    assert(0);
+    _RET_SUCCEED(0); //cannot happen
+}
+
+bool SQVM::CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res)
+{
+    SQInteger r;
+    if(ObjCmp(o1,o2,r)) {
+        switch(op) {
+            case CMP_G: res = (r > 0); return true;
+            case CMP_GE: res = (r >= 0); return true;
+            case CMP_L: res = (r < 0); return true;
+            case CMP_LE: res = (r <= 0); return true;
+            case CMP_3W: res = r; return true;
+        }
+        assert(0);
+    }
+    return false;
+}
+
+bool SQVM::ToString(const SQObjectPtr &o,SQObjectPtr &res)
+{
+    switch(type(o)) {
+    case OT_STRING:
+        res = o;
+        return true;
+    case OT_FLOAT:
+        scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR),_SC("%g"),_float(o));
+        break;
+    case OT_INTEGER:
+        scsprintf(_sp(sq_rsl(NUMBER_MAX_CHAR+1)),sq_rsl(NUMBER_MAX_CHAR),_PRINT_INT_FMT,_integer(o));
+        break;
+    case OT_BOOL:
+        scsprintf(_sp(sq_rsl(6)),sq_rsl(6),_integer(o)?_SC("true"):_SC("false"));
+        break;
+    case OT_TABLE:
+    case OT_USERDATA:
+    case OT_INSTANCE:
+        if(_delegable(o)->_delegate) {
+            SQObjectPtr closure;
+            if(_delegable(o)->GetMetaMethod(this, MT_TOSTRING, closure)) {
+                Push(o);
+                if(CallMetaMethod(closure,MT_TOSTRING,1,res)) {;
+                    if(type(res) == OT_STRING)
+                        return true;
+                }
+                else {
+                    return false;
+                }
+            }
+        }
+    default:
+        scsprintf(_sp(sq_rsl((sizeof(void*)*2)+NUMBER_MAX_CHAR)),sq_rsl((sizeof(void*)*2)+NUMBER_MAX_CHAR),_SC("(%s : 0x%p)"),GetTypeName(o),(void*)_rawval(o));
+    }
+    res = SQString::Create(_ss(this),_spval);
+    return true;
+}
+
+
+bool SQVM::StringCat(const SQObjectPtr &str,const SQObjectPtr &obj,SQObjectPtr &dest)
+{
+    SQObjectPtr a, b;
+    if(!ToString(str, a)) return false;
+    if(!ToString(obj, b)) return false;
+    SQInteger l = _string(a)->_len , ol = _string(b)->_len;
+    SQChar *s = _sp(sq_rsl(l + ol + 1));
+    memcpy(s, _stringval(a), sq_rsl(l));
+    memcpy(s + l, _stringval(b), sq_rsl(ol));
+    dest = SQString::Create(_ss(this), _spval, l + ol);
+    return true;
+}
+
+bool SQVM::TypeOf(const SQObjectPtr &obj1,SQObjectPtr &dest)
+{
+    if(is_delegable(obj1) && _delegable(obj1)->_delegate) {
+        SQObjectPtr closure;
+        if(_delegable(obj1)->GetMetaMethod(this, MT_TYPEOF, closure)) {
+            Push(obj1);
+            return CallMetaMethod(closure,MT_TYPEOF,1,dest);
+        }
+    }
+    dest = SQString::Create(_ss(this),GetTypeName(obj1));
+    return true;
+}
+
+bool SQVM::Init(SQVM *friendvm, SQInteger stacksize)
+{
+    _stack.resize(stacksize);
+    _alloccallsstacksize = 4;
+    _callstackdata.resize(_alloccallsstacksize);
+    _callsstacksize = 0;
+    _callsstack = &_callstackdata[0];
+    _stackbase = 0;
+    _top = 0;
+    if(!friendvm) {
+        _roottable = SQTable::Create(_ss(this), 0);
+        sq_base_register(this);
+    }
+    else {
+        _roottable = friendvm->_roottable;
+        _errorhandler = friendvm->_errorhandler;
+        _debughook = friendvm->_debughook;
+        _debughook_native = friendvm->_debughook_native;
+        _debughook_closure = friendvm->_debughook_closure;
+    }
+
+
+    return true;
+}
+
+
+bool SQVM::StartCall(SQClosure *closure,SQInteger target,SQInteger args,SQInteger stackbase,bool tailcall)
+{
+    SQFunctionProto *func = closure->_function;
+
+    SQInteger paramssize = func->_nparameters;
+    const SQInteger newtop = stackbase + func->_stacksize;
+    SQInteger nargs = args;
+    if(func->_varparams)
+    {
+        paramssize--;
+        if (nargs < paramssize) {
+            Raise_Error(_SC("wrong number of parameters"));
+            return false;
+        }
+
+        //dumpstack(stackbase);
+        SQInteger nvargs = nargs - paramssize;
+        SQArray *arr = SQArray::Create(_ss(this),nvargs);
+        SQInteger pbase = stackbase+paramssize;
+        for(SQInteger n = 0; n < nvargs; n++) {
+            arr->_values[n] = _stack._vals[pbase];
+            _stack._vals[pbase].Null();
+            pbase++;
+
+        }
+        _stack._vals[stackbase+paramssize] = arr;
+        //dumpstack(stackbase);
+    }
+    else if (paramssize != nargs) {
+        SQInteger ndef = func->_ndefaultparams;
+        SQInteger diff;
+        if(ndef && nargs < paramssize && (diff = paramssize - nargs) <= ndef) {
+            for(SQInteger n = ndef - diff; n < ndef; n++) {
+                _stack._vals[stackbase + (nargs++)] = closure->_defaultparams[n];
+            }
+        }
+        else {
+            Raise_Error(_SC("wrong number of parameters"));
+            return false;
+        }
+    }
+
+    if(closure->_env) {
+        _stack._vals[stackbase] = closure->_env->_obj;
+    }
+
+    if(!EnterFrame(stackbase, newtop, tailcall)) return false;
+
+    ci->_closure  = closure;
+    ci->_literals = func->_literals;
+    ci->_ip       = func->_instructions;
+    ci->_target   = (SQInt32)target;
+
+    if (_debughook) {
+        CallDebugHook(_SC('c'));
+    }
+
+    if (closure->_function->_bgenerator) {
+        SQFunctionProto *f = closure->_function;
+        SQGenerator *gen = SQGenerator::Create(_ss(this), closure);
+        if(!gen->Yield(this,f->_stacksize))
+            return false;
+        SQObjectPtr temp;
+        Return(1, target, temp);
+        STK(target) = gen;
+    }
+
+
+    return true;
+}
+
+bool SQVM::Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval)
+{
+    SQBool    _isroot      = ci->_root;
+    SQInteger callerbase   = _stackbase - ci->_prevstkbase;
+
+    if (_debughook) {
+        for(SQInteger i=0; i<ci->_ncalls; i++) {
+            CallDebugHook(_SC('r'));
+        }
+    }
+
+    SQObjectPtr *dest;
+    if (_isroot) {
+        dest = &(retval);
+    } else if (ci->_target == -1) {
+        dest = NULL;
+    } else {
+        dest = &_stack._vals[callerbase + ci->_target];
+    }
+    if (dest) {
+        if(_arg0 != 0xFF) {
+            *dest = _stack._vals[_stackbase+_arg1];
+        }
+        else {
+            dest->Null();
+        }
+        //*dest = (_arg0 != 0xFF) ? _stack._vals[_stackbase+_arg1] : _null_;
+    }
+    LeaveFrame();
+    return _isroot ? true : false;
+}
+
+#define _RET_ON_FAIL(exp) { if(!exp) return false; }
+
+bool SQVM::PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr)
+{
+    SQObjectPtr trg;
+    _RET_ON_FAIL(ARITH_OP( op , trg, a, incr));
+    target = a;
+    a = trg;
+    return true;
+}
+
+bool SQVM::DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger selfidx)
+{
+    SQObjectPtr tmp, tself = self, tkey = key;
+    if (!Get(tself, tkey, tmp, 0, selfidx)) { return false; }
+    _RET_ON_FAIL(ARITH_OP( op , target, tmp, incr))
+    if (!Set(tself, tkey, target,selfidx)) { return false; }
+    if (postfix) target = tmp;
+    return true;
+}
+
+#define arg0 (_i_._arg0)
+#define sarg0 ((SQInteger)*((const signed char *)&_i_._arg0))
+#define arg1 (_i_._arg1)
+#define sarg1 (*((const SQInt32 *)&_i_._arg1))
+#define arg2 (_i_._arg2)
+#define arg3 (_i_._arg3)
+#define sarg3 ((SQInteger)*((const signed char *)&_i_._arg3))
+
+SQRESULT SQVM::Suspend()
+{
+    if (_suspended)
+        return sq_throwerror(this, _SC("cannot suspend an already suspended vm"));
+    if (_nnativecalls!=2)
+        return sq_throwerror(this, _SC("cannot suspend through native calls/metamethods"));
+    return SQ_SUSPEND_FLAG;
+}
+
+
+#define _FINISH(howmuchtojump) {jump = howmuchtojump; return true; }
+bool SQVM::FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr
+&o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump)
+{
+    SQInteger nrefidx;
+    switch(type(o1)) {
+    case OT_TABLE:
+        if((nrefidx = _table(o1)->Next(false,o4, o2, o3)) == -1) _FINISH(exitpos);
+        o4 = (SQInteger)nrefidx; _FINISH(1);
+    case OT_ARRAY:
+        if((nrefidx = _array(o1)->Next(o4, o2, o3)) == -1) _FINISH(exitpos);
+        o4 = (SQInteger) nrefidx; _FINISH(1);
+    case OT_STRING:
+        if((nrefidx = _string(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos);
+        o4 = (SQInteger)nrefidx; _FINISH(1);
+    case OT_CLASS:
+        if((nrefidx = _class(o1)->Next(o4, o2, o3)) == -1)_FINISH(exitpos);
+        o4 = (SQInteger)nrefidx; _FINISH(1);
+    case OT_USERDATA:
+    case OT_INSTANCE:
+        if(_delegable(o1)->_delegate) {
+            SQObjectPtr itr;
+            SQObjectPtr closure;
+            if(_delegable(o1)->GetMetaMethod(this, MT_NEXTI, closure)) {
+                Push(o1);
+                Push(o4);
+                if(CallMetaMethod(closure, MT_NEXTI, 2, itr)) {
+                    o4 = o2 = itr;
+                    if(type(itr) == OT_NULL) _FINISH(exitpos);
+                    if(!Get(o1, itr, o3, 0, DONT_FALL_BACK)) {
+                        Raise_Error(_SC("_nexti returned an invalid idx")); // cloud be changed
+                        return false;
+                    }
+                    _FINISH(1);
+                }
+                else {
+                    return false;
+                }
+            }
+            Raise_Error(_SC("_nexti failed"));
+            return false;
+        }
+        break;
+    case OT_GENERATOR:
+        if(_generator(o1)->_state == SQGenerator::eDead) _FINISH(exitpos);
+        if(_generator(o1)->_state == SQGenerator::eSuspended) {
+            SQInteger idx = 0;
+            if(type(o4) == OT_INTEGER) {
+                idx = _integer(o4) + 1;
+            }
+            o2 = idx;
+            o4 = idx;
+            _generator(o1)->Resume(this, o3);
+            _FINISH(0);
+        }
+    default:
+        Raise_Error(_SC("cannot iterate %s"), GetTypeName(o1));
+    }
+    return false; //cannot be hit(just to avoid warnings)
+}
+
+#define COND_LITERAL (arg3!=0?ci->_literals[arg1]:STK(arg1))
+
+#define SQ_THROW() { goto exception_trap; }
+
+#define _GUARD(exp) { if(!exp) { SQ_THROW();} }
+
+bool SQVM::CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func)
+{
+    SQInteger nouters;
+    SQClosure *closure = SQClosure::Create(_ss(this), func,_table(_roottable)->GetWeakRef(OT_TABLE));
+    if((nouters = func->_noutervalues)) {
+        for(SQInteger i = 0; i<nouters; i++) {
+            SQOuterVar &v = func->_outervalues[i];
+            switch(v._type){
+            case otLOCAL:
+                FindOuter(closure->_outervalues[i], &STK(_integer(v._src)));
+                break;
+            case otOUTER:
+                closure->_outervalues[i] = _closure(ci->_closure)->_outervalues[_integer(v._src)];
+                break;
+            }
+        }
+    }
+    SQInteger ndefparams;
+    if((ndefparams = func->_ndefaultparams)) {
+        for(SQInteger i = 0; i < ndefparams; i++) {
+            SQInteger spos = func->_defaultparams[i];
+            closure->_defaultparams[i] = _stack._vals[_stackbase + spos];
+        }
+    }
+    target = closure;
+    return true;
+
+}
+
+
+bool SQVM::CLASS_OP(SQObjectPtr &target,SQInteger baseclass,SQInteger attributes)
+{
+    SQClass *base = NULL;
+    SQObjectPtr attrs;
+    if(baseclass != -1) {
+        if(type(_stack._vals[_stackbase+baseclass]) != OT_CLASS) { Raise_Error(_SC("trying to inherit from a %s"),GetTypeName(_stack._vals[_stackbase+baseclass])); return false; }
+        base = _class(_stack._vals[_stackbase + baseclass]);
+    }
+    if(attributes != MAX_FUNC_STACKSIZE) {
+        attrs = _stack._vals[_stackbase+attributes];
+    }
+    target = SQClass::Create(_ss(this),base);
+    if(type(_class(target)->_metamethods[MT_INHERITED]) != OT_NULL) {
+        int nparams = 2;
+        SQObjectPtr ret;
+        Push(target); Push(attrs);
+        if(!Call(_class(target)->_metamethods[MT_INHERITED],nparams,_top - nparams, ret, false)) {
+            Pop(nparams);
+            return false;
+        }
+        Pop(nparams);
+    }
+    _class(target)->_attributes = attrs;
+    return true;
+}
+
+bool SQVM::IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res)
+{
+    if(type(o1) == type(o2)) {
+        res = (_rawval(o1) == _rawval(o2));
+    }
+    else {
+        if(sq_isnumeric(o1) && sq_isnumeric(o2)) {
+            res = (tofloat(o1) == tofloat(o2));
+        }
+        else {
+            res = false;
+        }
+    }
+    return true;
+}
+
+bool SQVM::IsFalse(SQObjectPtr &o)
+{
+    if(((type(o) & SQOBJECT_CANBEFALSE)
+        && ( ((type(o) == OT_FLOAT) && (_float(o) == SQFloat(0.0))) ))
+#if !defined(SQUSEDOUBLE) || (defined(SQUSEDOUBLE) && defined(_SQ64))
+        || (_integer(o) == 0) )  //OT_NULL|OT_INTEGER|OT_BOOL
+#else
+        || (((type(o) != OT_FLOAT) && (_integer(o) == 0))) )  //OT_NULL|OT_INTEGER|OT_BOOL
+#endif
+    {
+        return true;
+    }
+    return false;
+}
+extern SQInstructionDesc g_InstrDesc[];
+bool SQVM::Execute(SQObjectPtr &closure, SQInteger nargs, SQInteger stackbase,SQObjectPtr &outres, SQBool raiseerror,ExecutionType et)
+{
+    if ((_nnativecalls + 1) > MAX_NATIVE_CALLS) { Raise_Error(_SC("Native stack overflow")); return false; }
+    _nnativecalls++;
+    AutoDec ad(&_nnativecalls);
+    SQInteger traps = 0;
+    CallInfo *prevci = ci;
+
+    switch(et) {
+        case ET_CALL: {
+            temp_reg = closure;
+            if(!StartCall(_closure(temp_reg), _top - nargs, nargs, stackbase, false)) {
+                //call the handler if there are no calls in the stack, if not relies on the previous node
+                if(ci == NULL) CallErrorHandler(_lasterror);
+                return false;
+            }
+            if(ci == prevci) {
+                outres = STK(_top-nargs);
+                return true;
+            }
+            ci->_root = SQTrue;
+                      }
+            break;
+        case ET_RESUME_GENERATOR: _generator(closure)->Resume(this, outres); ci->_root = SQTrue; traps += ci->_etraps; break;
+        case ET_RESUME_VM:
+        case ET_RESUME_THROW_VM:
+            traps = _suspended_traps;
+            ci->_root = _suspended_root;
+            _suspended = SQFalse;
+            if(et  == ET_RESUME_THROW_VM) { SQ_THROW(); }
+            break;
+    }
+
+exception_restore:
+    //
+    {
+        for(;;)
+        {
+            const SQInstruction &_i_ = *ci->_ip++;
+            //dumpstack(_stackbase);
+            //scprintf("\n[%d] %s %d %d %d %d\n",ci->_ip-_closure(ci->_closure)->_function->_instructions,g_InstrDesc[_i_.op].name,arg0,arg1,arg2,arg3);
+            switch(_i_.op)
+            {
+            case _OP_LINE: if (_debughook) CallDebugHook(_SC('l'),arg1); continue;
+            case _OP_LOAD: TARGET = ci->_literals[arg1]; continue;
+            case _OP_LOADINT:
+#ifndef _SQ64
+                TARGET = (SQInteger)arg1; continue;
+#else
+                TARGET = (SQInteger)((SQInt32)arg1); continue;
+#endif
+            case _OP_LOADFLOAT: TARGET = *((const SQFloat *)&arg1); continue;
+            case _OP_DLOAD: TARGET = ci->_literals[arg1]; STK(arg2) = ci->_literals[arg3];continue;
+            case _OP_TAILCALL:{
+                SQObjectPtr &t = STK(arg1);
+                if (type(t) == OT_CLOSURE
+                    && (!_closure(t)->_function->_bgenerator)){
+                    SQObjectPtr clo = t;
+                    if(_openouters) CloseOuters(&(_stack._vals[_stackbase]));
+                    for (SQInteger i = 0; i < arg3; i++) STK(i) = STK(arg2 + i);
+                    _GUARD(StartCall(_closure(clo), ci->_target, arg3, _stackbase, true));
+                    continue;
+                }
+                              }
+            case _OP_CALL: {
+                    SQObjectPtr clo = STK(arg1);
+                    switch (type(clo)) {
+                    case OT_CLOSURE:
+                        _GUARD(StartCall(_closure(clo), sarg0, arg3, _stackbase+arg2, false));
+                        continue;
+                    case OT_NATIVECLOSURE: {
+                        bool suspend;
+                        _GUARD(CallNative(_nativeclosure(clo), arg3, _stackbase+arg2, clo,suspend));
+                        if(suspend){
+                            _suspended = SQTrue;
+                            _suspended_target = sarg0;
+                            _suspended_root = ci->_root;
+                            _suspended_traps = traps;
+                            outres = clo;
+                            return true;
+                        }
+                        if(sarg0 != -1) {
+                            STK(arg0) = clo;
+                        }
+                                           }
+                        continue;
+                    case OT_CLASS:{
+                        SQObjectPtr inst;
+                        _GUARD(CreateClassInstance(_class(clo),inst,clo));
+                        if(sarg0 != -1) {
+                            STK(arg0) = inst;
+                        }
+                        SQInteger stkbase;
+                        switch(type(clo)) {
+                            case OT_CLOSURE:
+                                stkbase = _stackbase+arg2;
+                                _stack._vals[stkbase] = inst;
+                                _GUARD(StartCall(_closure(clo), -1, arg3, stkbase, false));
+                                break;
+                            case OT_NATIVECLOSURE:
+                                bool suspend;
+                                stkbase = _stackbase+arg2;
+                                _stack._vals[stkbase] = inst;
+                                _GUARD(CallNative(_nativeclosure(clo), arg3, stkbase, clo,suspend));
+                                break;
+                            default: break; //shutup GCC 4.x
+                        }
+                        }
+                        break;
+                    case OT_TABLE:
+                    case OT_USERDATA:
+                    case OT_INSTANCE:{
+                        SQObjectPtr closure;
+                        if(_delegable(clo)->_delegate && _delegable(clo)->GetMetaMethod(this,MT_CALL,closure)) {
+                            Push(clo);
+                            for (SQInteger i = 0; i < arg3; i++) Push(STK(arg2 + i));
+                            if(!CallMetaMethod(closure, MT_CALL, arg3+1, clo)) SQ_THROW();
+                            if(sarg0 != -1) {
+                                STK(arg0) = clo;
+                            }
+                            break;
+                        }
+
+                        //Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
+                        //SQ_THROW();
+                      }
+                    default:
+                        Raise_Error(_SC("attempt to call '%s'"), GetTypeName(clo));
+                        SQ_THROW();
+                    }
+                }
+                  continue;
+            case _OP_PREPCALL:
+            case _OP_PREPCALLK: {
+                    SQObjectPtr &key = _i_.op == _OP_PREPCALLK?(ci->_literals)[arg1]:STK(arg1);
+                    SQObjectPtr &o = STK(arg2);
+                    if (!Get(o, key, temp_reg,0,arg2)) {
+                        SQ_THROW();
+                    }
+                    STK(arg3) = o;
+                    _Swap(TARGET,temp_reg);//TARGET = temp_reg;
+                }
+                continue;
+            case _OP_GETK:
+                if (!Get(STK(arg2), ci->_literals[arg1], temp_reg, 0,arg2)) { SQ_THROW();}
+                _Swap(TARGET,temp_reg);//TARGET = temp_reg;
+                continue;
+            case _OP_MOVE: TARGET = STK(arg1); continue;
+            case _OP_NEWSLOT:
+                _GUARD(NewSlot(STK(arg1), STK(arg2), STK(arg3),false));
+                if(arg0 != 0xFF) TARGET = STK(arg3);
+                continue;
+            case _OP_DELETE: _GUARD(DeleteSlot(STK(arg1), STK(arg2), TARGET)); continue;
+            case _OP_SET:
+                if (!Set(STK(arg1), STK(arg2), STK(arg3),arg1)) { SQ_THROW(); }
+                if (arg0 != 0xFF) TARGET = STK(arg3);
+                continue;
+            case _OP_GET:
+                if (!Get(STK(arg1), STK(arg2), temp_reg, 0,arg1)) { SQ_THROW(); }
+                _Swap(TARGET,temp_reg);//TARGET = temp_reg;
+                continue;
+            case _OP_EQ:{
+                bool res;
+                if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }
+                TARGET = res?true:false;
+                }continue;
+            case _OP_NE:{
+                bool res;
+                if(!IsEqual(STK(arg2),COND_LITERAL,res)) { SQ_THROW(); }
+                TARGET = (!res)?true:false;
+                } continue;
+            case _OP_ADD: _ARITH_(+,TARGET,STK(arg2),STK(arg1)); continue;
+            case _OP_SUB: _ARITH_(-,TARGET,STK(arg2),STK(arg1)); continue;
+            case _OP_MUL: _ARITH_(*,TARGET,STK(arg2),STK(arg1)); continue;
+            case _OP_DIV: _ARITH_NOZERO(/,TARGET,STK(arg2),STK(arg1),_SC("division by zero")); continue;
+            case _OP_MOD: ARITH_OP('%',TARGET,STK(arg2),STK(arg1)); continue;
+            case _OP_BITW:  _GUARD(BW_OP( arg3,TARGET,STK(arg2),STK(arg1))); continue;
+            case _OP_RETURN:
+                if((ci)->_generator) {
+                    (ci)->_generator->Kill();
+                }
+                if(Return(arg0, arg1, temp_reg)){
+                    assert(traps==0);
+                    //outres = temp_reg;
+                    _Swap(outres,temp_reg);
+                    return true;
+                }
+                continue;
+            case _OP_LOADNULLS:{ for(SQInt32 n=0; n < arg1; n++) STK(arg0+n).Null(); }continue;
+            case _OP_LOADROOT:  {
+                SQWeakRef *w = _closure(ci->_closure)->_root;
+                if(type(w->_obj) != OT_NULL) {
+                    TARGET = w->_obj;
+                } else {
+                    TARGET = _roottable; //shoud this be like this? or null
+                }
+                                }
+                continue;
+            case _OP_LOADBOOL: TARGET = arg1?true:false; continue;
+            case _OP_DMOVE: STK(arg0) = STK(arg1); STK(arg2) = STK(arg3); continue;
+            case _OP_JMP: ci->_ip += (sarg1); continue;
+            //case _OP_JNZ: if(!IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
+            case _OP_JCMP:
+                _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg0),temp_reg));
+                if(IsFalse(temp_reg)) ci->_ip+=(sarg1);
+                continue;
+            case _OP_JZ: if(IsFalse(STK(arg0))) ci->_ip+=(sarg1); continue;
+            case _OP_GETOUTER: {
+                SQClosure *cur_cls = _closure(ci->_closure);
+                SQOuter *otr = _outer(cur_cls->_outervalues[arg1]);
+                TARGET = *(otr->_valptr);
+                }
+            continue;
+            case _OP_SETOUTER: {
+                SQClosure *cur_cls = _closure(ci->_closure);
+                SQOuter   *otr = _outer(cur_cls->_outervalues[arg1]);
+                *(otr->_valptr) = STK(arg2);
+                if(arg0 != 0xFF) {
+                    TARGET = STK(arg2);
+                }
+                }
+            continue;
+            case _OP_NEWOBJ:
+                switch(arg3) {
+                    case NOT_TABLE: TARGET = SQTable::Create(_ss(this), arg1); continue;
+                    case NOT_ARRAY: TARGET = SQArray::Create(_ss(this), 0); _array(TARGET)->Reserve(arg1); continue;
+                    case NOT_CLASS: _GUARD(CLASS_OP(TARGET,arg1,arg2)); continue;
+                    default: assert(0); continue;
+                }
+            case _OP_APPENDARRAY:
+                {
+                    SQObject val;
+                    val._unVal.raw = 0;
+                switch(arg2) {
+                case AAT_STACK:
+                    val = STK(arg1); break;
+                case AAT_LITERAL:
+                    val = ci->_literals[arg1]; break;
+                case AAT_INT:
+                    val._type = OT_INTEGER;
+#ifndef _SQ64
+                    val._unVal.nInteger = (SQInteger)arg1;
+#else
+                    val._unVal.nInteger = (SQInteger)((SQInt32)arg1);
+#endif
+                    break;
+                case AAT_FLOAT:
+                    val._type = OT_FLOAT;
+                    val._unVal.fFloat = *((const SQFloat *)&arg1);
+                    break;
+                case AAT_BOOL:
+                    val._type = OT_BOOL;
+                    val._unVal.nInteger = arg1;
+                    break;
+                default: val._type = OT_INTEGER; assert(0); break;
+
+                }
+                _array(STK(arg0))->Append(val); continue;
+                }
+            case _OP_COMPARITH: {
+                SQInteger selfidx = (((SQUnsignedInteger)arg1&0xFFFF0000)>>16);
+                _GUARD(DerefInc(arg3, TARGET, STK(selfidx), STK(arg2), STK(arg1&0x0000FFFF), false, selfidx));
+                                }
+                continue;
+            case _OP_INC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, false, arg1));} continue;
+            case _OP_INCL: {
+                SQObjectPtr &a = STK(arg1);
+                if(type(a) == OT_INTEGER) {
+                    a._unVal.nInteger = _integer(a) + sarg3;
+                }
+                else {
+                    SQObjectPtr o(sarg3); //_GUARD(LOCAL_INC('+',TARGET, STK(arg1), o));
+                    _ARITH_(+,a,a,o);
+                }
+                           } continue;
+            case _OP_PINC: {SQObjectPtr o(sarg3); _GUARD(DerefInc('+',TARGET, STK(arg1), STK(arg2), o, true, arg1));} continue;
+            case _OP_PINCL: {
+                SQObjectPtr &a = STK(arg1);
+                if(type(a) == OT_INTEGER) {
+                    TARGET = a;
+                    a._unVal.nInteger = _integer(a) + sarg3;
+                }
+                else {
+                    SQObjectPtr o(sarg3); _GUARD(PLOCAL_INC('+',TARGET, STK(arg1), o));
+                }
+
+                        } continue;
+            case _OP_CMP:   _GUARD(CMP_OP((CmpOP)arg3,STK(arg2),STK(arg1),TARGET))  continue;
+            case _OP_EXISTS: TARGET = Get(STK(arg1), STK(arg2), temp_reg, GET_FLAG_DO_NOT_RAISE_ERROR | GET_FLAG_RAW, DONT_FALL_BACK) ? true : false; continue;
+            case _OP_INSTANCEOF:
+                if(type(STK(arg1)) != OT_CLASS)
+                {Raise_Error(_SC("cannot apply instanceof between a %s and a %s"),GetTypeName(STK(arg1)),GetTypeName(STK(arg2))); SQ_THROW();}
+                TARGET = (type(STK(arg2)) == OT_INSTANCE) ? (_instance(STK(arg2))->InstanceOf(_class(STK(arg1)))?true:false) : false;
+                continue;
+            case _OP_AND:
+                if(IsFalse(STK(arg2))) {
+                    TARGET = STK(arg2);
+                    ci->_ip += (sarg1);
+                }
+                continue;
+            case _OP_OR:
+                if(!IsFalse(STK(arg2))) {
+                    TARGET = STK(arg2);
+                    ci->_ip += (sarg1);
+                }
+                continue;
+            case _OP_NEG: _GUARD(NEG_OP(TARGET,STK(arg1))); continue;
+            case _OP_NOT: TARGET = IsFalse(STK(arg1)); continue;
+            case _OP_BWNOT:
+                if(type(STK(arg1)) == OT_INTEGER) {
+                    SQInteger t = _integer(STK(arg1));
+                    TARGET = SQInteger(~t);
+                    continue;
+                }
+                Raise_Error(_SC("attempt to perform a bitwise op on a %s"), GetTypeName(STK(arg1)));
+                SQ_THROW();
+            case _OP_CLOSURE: {
+                SQClosure *c = ci->_closure._unVal.pClosure;
+                SQFunctionProto *fp = c->_function;
+                if(!CLOSURE_OP(TARGET,fp->_functions[arg1]._unVal.pFunctionProto)) { SQ_THROW(); }
+                continue;
+            }
+            case _OP_YIELD:{
+                if(ci->_generator) {
+                    if(sarg1 != MAX_FUNC_STACKSIZE) temp_reg = STK(arg1);
+                    _GUARD(ci->_generator->Yield(this,arg2));
+                    traps -= ci->_etraps;
+                    if(sarg1 != MAX_FUNC_STACKSIZE) _Swap(STK(arg1),temp_reg);//STK(arg1) = temp_reg;
+                }
+                else { Raise_Error(_SC("trying to yield a '%s',only genenerator can be yielded"), GetTypeName(ci->_generator)); SQ_THROW();}
+                if(Return(arg0, arg1, temp_reg)){
+                    assert(traps == 0);
+                    outres = temp_reg;
+                    return true;
+                }
+
+                }
+                continue;
+            case _OP_RESUME:
+                if(type(STK(arg1)) != OT_GENERATOR){ Raise_Error(_SC("trying to resume a '%s',only genenerator can be resumed"), GetTypeName(STK(arg1))); SQ_THROW();}
+                _GUARD(_generator(STK(arg1))->Resume(this, TARGET));
+                traps += ci->_etraps;
+                continue;
+            case _OP_FOREACH:{ int tojump;
+                _GUARD(FOREACH_OP(STK(arg0),STK(arg2),STK(arg2+1),STK(arg2+2),arg2,sarg1,tojump));
+                ci->_ip += tojump; }
+                continue;
+            case _OP_POSTFOREACH:
+                assert(type(STK(arg0)) == OT_GENERATOR);
+                if(_generator(STK(arg0))->_state == SQGenerator::eDead)
+                    ci->_ip += (sarg1 - 1);
+                continue;
+            case _OP_CLONE: _GUARD(Clone(STK(arg1), TARGET)); continue;
+            case _OP_TYPEOF: _GUARD(TypeOf(STK(arg1), TARGET)) continue;
+            case _OP_PUSHTRAP:{
+                SQInstruction *_iv = _closure(ci->_closure)->_function->_instructions;
+                _etraps.push_back(SQExceptionTrap(_top,_stackbase, &_iv[(ci->_ip-_iv)+arg1], arg0)); traps++;
+                ci->_etraps++;
+                              }
+                continue;
+            case _OP_POPTRAP: {
+                for(SQInteger i = 0; i < arg0; i++) {
+                    _etraps.pop_back(); traps--;
+                    ci->_etraps--;
+                }
+                              }
+                continue;
+            case _OP_THROW: Raise_Error(TARGET); SQ_THROW(); continue;
+            case _OP_NEWSLOTA:
+                _GUARD(NewSlotA(STK(arg1),STK(arg2),STK(arg3),(arg0&NEW_SLOT_ATTRIBUTES_FLAG) ? STK(arg2-1) : SQObjectPtr(),(arg0&NEW_SLOT_STATIC_FLAG)?true:false,false));
+                continue;
+            case _OP_GETBASE:{
+                SQClosure *clo = _closure(ci->_closure);
+                if(clo->_base) {
+                    TARGET = clo->_base;
+                }
+                else {
+                    TARGET.Null();
+                }
+                continue;
+            }
+            case _OP_CLOSE:
+                if(_openouters) CloseOuters(&(STK(arg1)));
+                continue;
+            }
+
+        }
+    }
+exception_trap:
+    {
+        SQObjectPtr currerror = _lasterror;
+//      dumpstack(_stackbase);
+//      SQInteger n = 0;
+        SQInteger last_top = _top;
+
+        if(_ss(this)->_notifyallexceptions || (!traps && raiseerror)) CallErrorHandler(currerror);
+
+        while( ci ) {
+            if(ci->_etraps > 0) {
+                SQExceptionTrap &et = _etraps.top();
+                ci->_ip = et._ip;
+                _top = et._stacksize;
+                _stackbase = et._stackbase;
+                _stack._vals[_stackbase + et._extarget] = currerror;
+                _etraps.pop_back(); traps--; ci->_etraps--;
+                while(last_top >= _top) _stack._vals[last_top--].Null();
+                goto exception_restore;
+            }
+            else if (_debughook) {
+                    //notify debugger of a "return"
+                    //even if it really an exception unwinding the stack
+                    for(SQInteger i = 0; i < ci->_ncalls; i++) {
+                        CallDebugHook(_SC('r'));
+                    }
+            }
+            if(ci->_generator) ci->_generator->Kill();
+            bool mustbreak = ci && ci->_root;
+            LeaveFrame();
+            if(mustbreak) break;
+        }
+
+        _lasterror = currerror;
+        return false;
+    }
+    assert(0);
+}
+
+bool SQVM::CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor)
+{
+    inst = theclass->CreateInstance();
+    if(!theclass->GetConstructor(constructor)) {
+        constructor.Null();
+    }
+    return true;
+}
+
+void SQVM::CallErrorHandler(SQObjectPtr &error)
+{
+    if(type(_errorhandler) != OT_NULL) {
+        SQObjectPtr out;
+        Push(_roottable); Push(error);
+        Call(_errorhandler, 2, _top-2, out,SQFalse);
+        Pop(2);
+    }
+}
+
+
+void SQVM::CallDebugHook(SQInteger type,SQInteger forcedline)
+{
+    _debughook = false;
+    SQFunctionProto *func=_closure(ci->_closure)->_function;
+    if(_debughook_native) {
+        const SQChar *src = type(func->_sourcename) == OT_STRING?_stringval(func->_sourcename):NULL;
+        const SQChar *fname = type(func->_name) == OT_STRING?_stringval(func->_name):NULL;
+        SQInteger line = forcedline?forcedline:func->GetLine(ci->_ip);
+        _debughook_native(this,type,src,line,fname);
+    }
+    else {
+        SQObjectPtr temp_reg;
+        SQInteger nparams=5;
+        Push(_roottable); Push(type); Push(func->_sourcename); Push(forcedline?forcedline:func->GetLine(ci->_ip)); Push(func->_name);
+        Call(_debughook_closure,nparams,_top-nparams,temp_reg,SQFalse);
+        Pop(nparams);
+    }
+    _debughook = true;
+}
+
+bool SQVM::CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval, bool &suspend)
+{
+    SQInteger nparamscheck = nclosure->_nparamscheck;
+    SQInteger newtop = newbase + nargs + nclosure->_noutervalues;
+
+    if (_nnativecalls + 1 > MAX_NATIVE_CALLS) {
+        Raise_Error(_SC("Native stack overflow"));
+        return false;
+    }
+
+    if(nparamscheck && (((nparamscheck > 0) && (nparamscheck != nargs)) ||
+        ((nparamscheck < 0) && (nargs < (-nparamscheck)))))
+    {
+        Raise_Error(_SC("wrong number of parameters"));
+        return false;
+    }
+
+    SQInteger tcs;
+    SQIntVec &tc = nclosure->_typecheck;
+    if((tcs = tc.size())) {
+        for(SQInteger i = 0; i < nargs && i < tcs; i++) {
+            if((tc._vals[i] != -1) && !(type(_stack._vals[newbase+i]) & tc._vals[i])) {
+                Raise_ParamTypeError(i,tc._vals[i],type(_stack._vals[newbase+i]));
+                return false;
+            }
+        }
+    }
+
+    if(!EnterFrame(newbase, newtop, false)) return false;
+    ci->_closure  = nclosure;
+
+    SQInteger outers = nclosure->_noutervalues;
+    for (SQInteger i = 0; i < outers; i++) {
+        _stack._vals[newbase+nargs+i] = nclosure->_outervalues[i];
+    }
+    if(nclosure->_env) {
+        _stack._vals[newbase] = nclosure->_env->_obj;
+    }
+
+    _nnativecalls++;
+    SQInteger ret = (nclosure->_function)(this);
+    _nnativecalls--;
+
+    suspend = false;
+    if (ret == SQ_SUSPEND_FLAG) {
+        suspend = true;
+    }
+    else if (ret < 0) {
+        LeaveFrame();
+        Raise_Error(_lasterror);
+        return false;
+    }
+    if(ret) {
+        retval = _stack._vals[_top-1];
+    }
+    else {
+        retval.Null();
+    }
+    //retval = ret ? _stack._vals[_top-1] : _null_;
+    LeaveFrame();
+    return true;
+}
+
+#define FALLBACK_OK         0
+#define FALLBACK_NO_MATCH   1
+#define FALLBACK_ERROR      2
+
+bool SQVM::Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, SQUnsignedInteger getflags, SQInteger selfidx)
+{
+    switch(type(self)){
+    case OT_TABLE:
+        if(_table(self)->Get(key,dest))return true;
+        break;
+    case OT_ARRAY:
+        if (sq_isnumeric(key)) { if (_array(self)->Get(tointeger(key), dest)) { return true; } if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key); return false; }
+        break;
+    case OT_INSTANCE:
+        if(_instance(self)->Get(key,dest)) return true;
+        break;
+    case OT_CLASS:
+        if(_class(self)->Get(key,dest)) return true;
+        break;
+    case OT_STRING:
+        if(sq_isnumeric(key)){
+            SQInteger n = tointeger(key);
+            SQInteger len = _string(self)->_len;
+            if (n < 0) { n += len; }
+            if (n >= 0 && n < len) {
+                dest = SQInteger(_stringval(self)[n]);
+                return true;
+            }
+            if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key);
+            return false;
+        }
+        break;
+    default:break; //shut up compiler
+    }
+    if ((getflags & GET_FLAG_RAW) == 0) {
+        switch(FallBackGet(self,key,dest)) {
+            case FALLBACK_OK: return true; //okie
+            case FALLBACK_NO_MATCH: break; //keep falling back
+            case FALLBACK_ERROR: return false; // the metamethod failed
+        }
+        if(InvokeDefaultDelegate(self,key,dest)) {
+            return true;
+        }
+    }
+//#ifdef ROOT_FALLBACK
+    if(selfidx == 0) {
+        SQWeakRef *w = _closure(ci->_closure)->_root;
+        if(type(w->_obj) != OT_NULL)
+        {
+            if(Get(*((const SQObjectPtr *)&w->_obj),key,dest,0,DONT_FALL_BACK)) return true;
+        }
+
+    }
+//#endif
+    if ((getflags & GET_FLAG_DO_NOT_RAISE_ERROR) == 0) Raise_IdxError(key);
+    return false;
+}
+
+bool SQVM::InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest)
+{
+    SQTable *ddel = NULL;
+    switch(type(self)) {
+        case OT_CLASS: ddel = _class_ddel; break;
+        case OT_TABLE: ddel = _table_ddel; break;
+        case OT_ARRAY: ddel = _array_ddel; break;
+        case OT_STRING: ddel = _string_ddel; break;
+        case OT_INSTANCE: ddel = _instance_ddel; break;
+        case OT_INTEGER:case OT_FLOAT:case OT_BOOL: ddel = _number_ddel; break;
+        case OT_GENERATOR: ddel = _generator_ddel; break;
+        case OT_CLOSURE: case OT_NATIVECLOSURE: ddel = _closure_ddel; break;
+        case OT_THREAD: ddel = _thread_ddel; break;
+        case OT_WEAKREF: ddel = _weakref_ddel; break;
+        default: return false;
+    }
+    return  ddel->Get(key,dest);
+}
+
+
+SQInteger SQVM::FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest)
+{
+    switch(type(self)){
+    case OT_TABLE:
+    case OT_USERDATA:
+        //delegation
+        if(_delegable(self)->_delegate) {
+            if(Get(SQObjectPtr(_delegable(self)->_delegate),key,dest,0,DONT_FALL_BACK)) return FALLBACK_OK;
+        }
+        else {
+            return FALLBACK_NO_MATCH;
+        }
+        //go through
+    case OT_INSTANCE: {
+        SQObjectPtr closure;
+        if(_delegable(self)->GetMetaMethod(this, MT_GET, closure)) {
+            Push(self);Push(key);
+            _nmetamethodscall++;
+            AutoDec ad(&_nmetamethodscall);
+            if(Call(closure, 2, _top - 2, dest, SQFalse)) {
+                Pop(2);
+                return FALLBACK_OK;
+            }
+            else {
+                Pop(2);
+                if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found)
+                    return FALLBACK_ERROR;
+                }
+            }
+        }
+                      }
+        break;
+    default: break;//shutup GCC 4.x
+    }
+    // no metamethod or no fallback type
+    return FALLBACK_NO_MATCH;
+}
+
+bool SQVM::Set(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,SQInteger selfidx)
+{
+    switch(type(self)){
+    case OT_TABLE:
+        if(_table(self)->Set(key,val)) return true;
+        break;
+    case OT_INSTANCE:
+        if(_instance(self)->Set(key,val)) return true;
+        break;
+    case OT_ARRAY:
+        if(!sq_isnumeric(key)) { Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key)); return false; }
+        if(!_array(self)->Set(tointeger(key),val)) {
+            Raise_IdxError(key);
+            return false;
+        }
+        return true;
+    default:
+        Raise_Error(_SC("trying to set '%s'"),GetTypeName(self));
+        return false;
+    }
+
+    switch(FallBackSet(self,key,val)) {
+        case FALLBACK_OK: return true; //okie
+        case FALLBACK_NO_MATCH: break; //keep falling back
+        case FALLBACK_ERROR: return false; // the metamethod failed
+    }
+    if(selfidx == 0) {
+        if(_table(_roottable)->Set(key,val))
+            return true;
+    }
+    Raise_IdxError(key);
+    return false;
+}
+
+SQInteger SQVM::FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val)
+{
+    switch(type(self)) {
+    case OT_TABLE:
+        if(_table(self)->_delegate) {
+            if(Set(_table(self)->_delegate,key,val,DONT_FALL_BACK)) return FALLBACK_OK;
+        }
+        //keps on going
+    case OT_INSTANCE:
+    case OT_USERDATA:{
+        SQObjectPtr closure;
+        SQObjectPtr t;
+        if(_delegable(self)->GetMetaMethod(this, MT_SET, closure)) {
+            Push(self);Push(key);Push(val);
+            _nmetamethodscall++;
+            AutoDec ad(&_nmetamethodscall);
+            if(Call(closure, 3, _top - 3, t, SQFalse)) {
+                Pop(3);
+                return FALLBACK_OK;
+            }
+            else {
+                if(type(_lasterror) != OT_NULL) { //NULL means "clean failure" (not found)
+                    //error
+                    Pop(3);
+                    return FALLBACK_ERROR;
+                }
+            }
+        }
+                     }
+        break;
+        default: break;//shutup GCC 4.x
+    }
+    // no metamethod or no fallback type
+    return FALLBACK_NO_MATCH;
+}
+
+bool SQVM::Clone(const SQObjectPtr &self,SQObjectPtr &target)
+{
+    SQObjectPtr temp_reg;
+    SQObjectPtr newobj;
+    switch(type(self)){
+    case OT_TABLE:
+        newobj = _table(self)->Clone();
+        goto cloned_mt;
+    case OT_INSTANCE: {
+        newobj = _instance(self)->Clone(_ss(this));
+cloned_mt:
+        SQObjectPtr closure;
+        if(_delegable(newobj)->_delegate && _delegable(newobj)->GetMetaMethod(this,MT_CLONED,closure)) {
+            Push(newobj);
+            Push(self);
+            if(!CallMetaMethod(closure,MT_CLONED,2,temp_reg))
+                return false;
+        }
+        }
+        target = newobj;
+        return true;
+    case OT_ARRAY:
+        target = _array(self)->Clone();
+        return true;
+    default:
+        Raise_Error(_SC("cloning a %s"), GetTypeName(self));
+        return false;
+    }
+}
+
+bool SQVM::NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw)
+{
+    if(type(self) != OT_CLASS) {
+        Raise_Error(_SC("object must be a class"));
+        return false;
+    }
+    SQClass *c = _class(self);
+    if(!raw) {
+        SQObjectPtr &mm = c->_metamethods[MT_NEWMEMBER];
+        if(type(mm) != OT_NULL ) {
+            Push(self); Push(key); Push(val);
+            Push(attrs);
+            Push(bstatic);
+            return CallMetaMethod(mm,MT_NEWMEMBER,5,temp_reg);
+        }
+    }
+    if(!NewSlot(self, key, val,bstatic))
+        return false;
+    if(type(attrs) != OT_NULL) {
+        c->SetAttributes(key,attrs);
+    }
+    return true;
+}
+
+bool SQVM::NewSlot(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,bool bstatic)
+{
+    if(type(key) == OT_NULL) { Raise_Error(_SC("null cannot be used as index")); return false; }
+    switch(type(self)) {
+    case OT_TABLE: {
+        bool rawcall = true;
+        if(_table(self)->_delegate) {
+            SQObjectPtr res;
+            if(!_table(self)->Get(key,res)) {
+                SQObjectPtr closure;
+                if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {
+                    Push(self);Push(key);Push(val);
+                    if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {
+                        return false;
+                    }
+                    rawcall = false;
+                }
+                else {
+                    rawcall = true;
+                }
+            }
+        }
+        if(rawcall) _table(self)->NewSlot(key,val); //cannot fail
+
+        break;}
+    case OT_INSTANCE: {
+        SQObjectPtr res;
+        SQObjectPtr closure;
+        if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_NEWSLOT,closure)) {
+            Push(self);Push(key);Push(val);
+            if(!CallMetaMethod(closure,MT_NEWSLOT,3,res)) {
+                return false;
+            }
+            break;
+        }
+        Raise_Error(_SC("class instances do not support the new slot operator"));
+        return false;
+        break;}
+    case OT_CLASS:
+        if(!_class(self)->NewSlot(_ss(this),key,val,bstatic)) {
+            if(_class(self)->_locked) {
+                Raise_Error(_SC("trying to modify a class that has already been instantiated"));
+                return false;
+            }
+            else {
+                SQObjectPtr oval = PrintObjVal(key);
+                Raise_Error(_SC("the property '%s' already exists"),_stringval(oval));
+                return false;
+            }
+        }
+        break;
+    default:
+        Raise_Error(_SC("indexing %s with %s"),GetTypeName(self),GetTypeName(key));
+        return false;
+        break;
+    }
+    return true;
+}
+
+
+
+bool SQVM::DeleteSlot(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &res)
+{
+    switch(type(self)) {
+    case OT_TABLE:
+    case OT_INSTANCE:
+    case OT_USERDATA: {
+        SQObjectPtr t;
+        //bool handled = false;
+        SQObjectPtr closure;
+        if(_delegable(self)->_delegate && _delegable(self)->GetMetaMethod(this,MT_DELSLOT,closure)) {
+            Push(self);Push(key);
+            return CallMetaMethod(closure,MT_DELSLOT,2,res);
+        }
+        else {
+            if(type(self) == OT_TABLE) {
+                if(_table(self)->Get(key,t)) {
+                    _table(self)->Remove(key);
+                }
+                else {
+                    Raise_IdxError((const SQObject &)key);
+                    return false;
+                }
+            }
+            else {
+                Raise_Error(_SC("cannot delete a slot from %s"),GetTypeName(self));
+                return false;
+            }
+        }
+        res = t;
+                }
+        break;
+    default:
+        Raise_Error(_SC("attempt to delete a slot from a %s"),GetTypeName(self));
+        return false;
+    }
+    return true;
+}
+
+bool SQVM::Call(SQObjectPtr &closure,SQInteger nparams,SQInteger stackbase,SQObjectPtr &outres,SQBool raiseerror)
+{
+#ifdef _DEBUG
+SQInteger prevstackbase = _stackbase;
+#endif
+    switch(type(closure)) {
+    case OT_CLOSURE:
+        return Execute(closure, nparams, stackbase, outres, raiseerror);
+        break;
+    case OT_NATIVECLOSURE:{
+        bool suspend;
+        return CallNative(_nativeclosure(closure), nparams, stackbase, outres,suspend);
+
+                          }
+        break;
+    case OT_CLASS: {
+        SQObjectPtr constr;
+        SQObjectPtr temp;
+        CreateClassInstance(_class(closure),outres,constr);
+        SQObjectType ctype = type(constr);
+        if (ctype == OT_NATIVECLOSURE || ctype == OT_CLOSURE) {
+            _stack[stackbase] = outres;
+            return Call(constr,nparams,stackbase,temp,raiseerror);
+        }
+        return true;
+                   }
+        break;
+    default:
+        return false;
+    }
+#ifdef _DEBUG
+    if(!_suspended) {
+        assert(_stackbase == prevstackbase);
+    }
+#endif
+    return true;
+}
+
+bool SQVM::CallMetaMethod(SQObjectPtr &closure,SQMetaMethod mm,SQInteger nparams,SQObjectPtr &outres)
+{
+    //SQObjectPtr closure;
+
+    _nmetamethodscall++;
+    if(Call(closure, nparams, _top - nparams, outres, SQFalse)) {
+        _nmetamethodscall--;
+        Pop(nparams);
+        return true;
+    }
+    _nmetamethodscall--;
+    //}
+    Pop(nparams);
+    return false;
+}
+
+void SQVM::FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex)
+{
+    SQOuter **pp = &_openouters;
+    SQOuter *p;
+    SQOuter *otr;
+
+    while ((p = *pp) != NULL && p->_valptr >= stackindex) {
+        if (p->_valptr == stackindex) {
+            target = SQObjectPtr(p);
+            return;
+        }
+        pp = &p->_next;
+    }
+    otr = SQOuter::Create(_ss(this), stackindex);
+    otr->_next = *pp;
+    otr->_idx  = (stackindex - _stack._vals);
+    __ObjAddRef(otr);
+    *pp = otr;
+    target = SQObjectPtr(otr);
+}
+
+bool SQVM::EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall)
+{
+    if( !tailcall ) {
+        if( _callsstacksize == _alloccallsstacksize ) {
+            GrowCallStack();
+        }
+        ci = &_callsstack[_callsstacksize++];
+        ci->_prevstkbase = (SQInt32)(newbase - _stackbase);
+        ci->_prevtop = (SQInt32)(_top - _stackbase);
+        ci->_etraps = 0;
+        ci->_ncalls = 1;
+        ci->_generator = NULL;
+        ci->_root = SQFalse;
+    }
+    else {
+        ci->_ncalls++;
+    }
+
+    _stackbase = newbase;
+    _top = newtop;
+    if(newtop + MIN_STACK_OVERHEAD > (SQInteger)_stack.size()) {
+        if(_nmetamethodscall) {
+            Raise_Error(_SC("stack overflow, cannot resize stack while in  a metamethod"));
+            return false;
+        }
+        _stack.resize(newtop + (MIN_STACK_OVERHEAD << 2));
+        RelocateOuters();
+    }
+    return true;
+}
+
+void SQVM::LeaveFrame() {
+    SQInteger last_top = _top;
+    SQInteger last_stackbase = _stackbase;
+    SQInteger css = --_callsstacksize;
+
+    /* First clean out the call stack frame */
+    ci->_closure.Null();
+    _stackbase -= ci->_prevstkbase;
+    _top = _stackbase + ci->_prevtop;
+    ci = (css) ? &_callsstack[css-1] : NULL;
+
+    if(_openouters) CloseOuters(&(_stack._vals[last_stackbase]));
+    while (last_top >= _top) {
+        _stack._vals[last_top--].Null();
+    }
+}
+
+void SQVM::RelocateOuters()
+{
+    SQOuter *p = _openouters;
+    while (p) {
+        p->_valptr = _stack._vals + p->_idx;
+        p = p->_next;
+    }
+}
+
+void SQVM::CloseOuters(SQObjectPtr *stackindex) {
+  SQOuter *p;
+  while ((p = _openouters) != NULL && p->_valptr >= stackindex) {
+    p->_value = *(p->_valptr);
+    p->_valptr = &p->_value;
+    _openouters = p->_next;
+    __ObjRelease(p);
+  }
+}
+
+void SQVM::Remove(SQInteger n) {
+    n = (n >= 0)?n + _stackbase - 1:_top + n;
+    for(SQInteger i = n; i < _top; i++){
+        _stack[i] = _stack[i+1];
+    }
+    _stack[_top].Null();
+    _top--;
+}
+
+void SQVM::Pop() {
+    _stack[--_top].Null();
+}
+
+void SQVM::Pop(SQInteger n) {
+    for(SQInteger i = 0; i < n; i++){
+        _stack[--_top].Null();
+    }
+}
+
+void SQVM::PushNull() { _stack[_top++].Null(); }
+void SQVM::Push(const SQObjectPtr &o) { _stack[_top++] = o; }
+SQObjectPtr &SQVM::Top() { return _stack[_top-1]; }
+SQObjectPtr &SQVM::PopGet() { return _stack[--_top]; }
+SQObjectPtr &SQVM::GetUp(SQInteger n) { return _stack[_top+n]; }
+SQObjectPtr &SQVM::GetAt(SQInteger n) { return _stack[n]; }
+
+#ifdef _DEBUG_DUMP
+void SQVM::dumpstack(SQInteger stackbase,bool dumpall)
+{
+    SQInteger size=dumpall?_stack.size():_top;
+    SQInteger n=0;
+    scprintf(_SC("\n>>>>stack dump<<<<\n"));
+    CallInfo &ci=_callsstack[_callsstacksize-1];
+    scprintf(_SC("IP: %p\n"),ci._ip);
+    scprintf(_SC("prev stack base: %d\n"),ci._prevstkbase);
+    scprintf(_SC("prev top: %d\n"),ci._prevtop);
+    for(SQInteger i=0;i<size;i++){
+        SQObjectPtr &obj=_stack[i];
+        if(stackbase==i)scprintf(_SC(">"));else scprintf(_SC(" "));
+        scprintf(_SC("[%d]:"),n);
+        switch(type(obj)){
+        case OT_FLOAT:          scprintf(_SC("FLOAT %.3f"),_float(obj));break;
+        case OT_INTEGER:        scprintf(_SC("INTEGER %d"),_integer(obj));break;
+        case OT_BOOL:           scprintf(_SC("BOOL %s"),_integer(obj)?"true":"false");break;
+        case OT_STRING:         scprintf(_SC("STRING %s"),_stringval(obj));break;
+        case OT_NULL:           scprintf(_SC("NULL"));  break;
+        case OT_TABLE:          scprintf(_SC("TABLE %p[%p]"),_table(obj),_table(obj)->_delegate);break;
+        case OT_ARRAY:          scprintf(_SC("ARRAY %p"),_array(obj));break;
+        case OT_CLOSURE:        scprintf(_SC("CLOSURE [%p]"),_closure(obj));break;
+        case OT_NATIVECLOSURE:  scprintf(_SC("NATIVECLOSURE"));break;
+        case OT_USERDATA:       scprintf(_SC("USERDATA %p[%p]"),_userdataval(obj),_userdata(obj)->_delegate);break;
+        case OT_GENERATOR:      scprintf(_SC("GENERATOR %p"),_generator(obj));break;
+        case OT_THREAD:         scprintf(_SC("THREAD [%p]"),_thread(obj));break;
+        case OT_USERPOINTER:    scprintf(_SC("USERPOINTER %p"),_userpointer(obj));break;
+        case OT_CLASS:          scprintf(_SC("CLASS %p"),_class(obj));break;
+        case OT_INSTANCE:       scprintf(_SC("INSTANCE %p"),_instance(obj));break;
+        case OT_WEAKREF:        scprintf(_SC("WEAKERF %p"),_weakref(obj));break;
+        default:
+            assert(0);
+            break;
+        };
+        scprintf(_SC("\n"));
+        ++n;
+    }
+}
+
+
+
+#endif

+ 214 - 214
squirrel/sqvm.h

@@ -1,214 +1,214 @@
-/*	see copyright notice in squirrel.h */
-#ifndef _SQVM_H_
-#define _SQVM_H_
-
-#include "sqopcodes.h"
-#include "sqobject.h"
-#define MAX_NATIVE_CALLS 100
-#define MIN_STACK_OVERHEAD 15
-
-#define SQ_SUSPEND_FLAG -666
-#define DONT_FALL_BACK 666
-//#define EXISTS_FALL_BACK -1
-
-#define GET_FLAG_RAW				0x00000001
-#define GET_FLAG_DO_NOT_RAISE_ERROR	0x00000002
-//base lib
-void sq_base_register(HSQUIRRELVM v);
-
-struct SQExceptionTrap{
-	SQExceptionTrap() {}
-	SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}
-	SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et;	}
-	SQInteger _stackbase;
-	SQInteger _stacksize;
-	SQInstruction *_ip;
-	SQInteger _extarget;
-};
-
-#define _INLINE 
-
-#define STK(a) _stack._vals[_stackbase+(a)]
-#define TARGET _stack._vals[_stackbase+arg0]
-
-typedef sqvector<SQExceptionTrap> ExceptionsTraps;
-
-struct SQVM : public CHAINABLE_OBJ
-{
-	struct CallInfo{
-		//CallInfo() { _generator = NULL;}
-		SQInstruction *_ip;
-		SQObjectPtr *_literals;
-		SQObjectPtr _closure;
-		SQGenerator *_generator;
-		SQInt32 _etraps;
-		SQInt32 _prevstkbase;
-		SQInt32 _prevtop;
-		SQInt32 _target;
-		SQInt32 _ncalls;
-		SQBool _root;
-	};
-	
-typedef sqvector<CallInfo> CallInfoVec;
-public:
-	void DebugHookProxy(SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname);
-	static void _DebugHookProxy(HSQUIRRELVM v, SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname);
-	enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM,ET_RESUME_THROW_VM };
-	SQVM(SQSharedState *ss);
-	~SQVM();
-	bool Init(SQVM *friendvm, SQInteger stacksize);
-	bool Execute(SQObjectPtr &func, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL);
-	//starts a native call return when the NATIVE closure returns
-	bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval,bool &suspend);
-	//starts a SQUIRREL call in the same "Execution loop"
-	bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);
-	bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor);
-	//call a generic closure pure SQUIRREL or NATIVE
-	bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror);
-	SQRESULT Suspend();
-
-	void CallDebugHook(SQInteger type,SQInteger forcedline=0);
-	void CallErrorHandler(SQObjectPtr &e);
-	bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, SQUnsignedInteger getflags, SQInteger selfidx);
-	SQInteger FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);
-	bool InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);
-	bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, SQInteger selfidx);
-	SQInteger FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val);
-	bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic);
-	bool NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw);
-	bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res);
-	bool Clone(const SQObjectPtr &self, SQObjectPtr &target);
-	bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res);
-	bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);
-	static bool IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res);
-	bool ToString(const SQObjectPtr &o,SQObjectPtr &res);
-	SQString *PrintObjVal(const SQObjectPtr &o);
-
- 
-	void Raise_Error(const SQChar *s, ...);
-	void Raise_Error(const SQObjectPtr &desc);
-	void Raise_IdxError(const SQObjectPtr &o);
-	void Raise_CompareError(const SQObject &o1, const SQObject &o2);
-	void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type);
-
-	void FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex);
-	void RelocateOuters();
-	void CloseOuters(SQObjectPtr *stackindex);
-
-	bool TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);
-	bool CallMetaMethod(SQObjectPtr &closure, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres);
-	bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
-	bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval);
-	//new stuff
-	_INLINE bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
-	_INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
-	_INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);
-	_INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);
-	bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);
-	bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs);
-	//return true if the loop is finished
-	bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump);
-	//_INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
-	_INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
-	_INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger arg0);
-#ifdef _DEBUG_DUMP
-	void dumpstack(SQInteger stackbase=-1, bool dumpall = false);
-#endif
-
-#ifndef NO_GARBAGE_COLLECTOR
-	void Mark(SQCollectable **chain);
-	SQObjectType GetType() {return OT_THREAD;}
-#endif
-	void Finalize();
-	void GrowCallStack() {
-		SQInteger newsize = _alloccallsstacksize*2;
-		_callstackdata.resize(newsize);
-		_callsstack = &_callstackdata[0];
-		_alloccallsstacksize = newsize;
-	}
-	bool EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall);
-	void LeaveFrame();
-	void Release(){ sq_delete(this,SQVM); }
-////////////////////////////////////////////////////////////////////////////
-	//stack functions for the api
-	void Remove(SQInteger n);
-
-	static bool IsFalse(SQObjectPtr &o);
-	
-	void Pop();
-	void Pop(SQInteger n);
-	void Push(const SQObjectPtr &o);
-	void PushNull();
-	SQObjectPtr &Top();
-	SQObjectPtr &PopGet();
-	SQObjectPtr &GetUp(SQInteger n);
-	SQObjectPtr &GetAt(SQInteger n);
-
-	SQObjectPtrVec _stack;
-
-	SQInteger _top;
-	SQInteger _stackbase;
-	SQOuter	*_openouters;
-	SQObjectPtr _roottable;
-	SQObjectPtr _lasterror;
-	SQObjectPtr _errorhandler;
-
-	bool _debughook;
-	SQDEBUGHOOK _debughook_native;
-	SQObjectPtr _debughook_closure;
-
-	SQObjectPtr temp_reg;
-	
-
-	CallInfo* _callsstack;
-	SQInteger _callsstacksize;
-	SQInteger _alloccallsstacksize;
-	sqvector<CallInfo>  _callstackdata;
-
-	ExceptionsTraps _etraps;
-	CallInfo *ci;
-	SQUserPointer _foreignptr;
-	//VMs sharing the same state
-	SQSharedState *_sharedstate;
-	SQInteger _nnativecalls;
-	SQInteger _nmetamethodscall;
-	SQRELEASEHOOK _releasehook;
-	//suspend infos
-	SQBool _suspended;
-	SQBool _suspended_root;
-	SQInteger _suspended_target;
-	SQInteger _suspended_traps;
-};
-
-struct AutoDec{
-	AutoDec(SQInteger *n) { _n = n; }
-	~AutoDec() { (*_n)--; }
-	SQInteger *_n;
-};
-
-inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}
-
-#define _ss(_vm_) (_vm_)->_sharedstate
-
-#ifndef NO_GARBAGE_COLLECTOR
-#define _opt_ss(_vm_) (_vm_)->_sharedstate
-#else
-#define _opt_ss(_vm_) NULL
-#endif
-
-#define PUSH_CALLINFO(v,nci){ \
-	SQInteger css = v->_callsstacksize; \
-	if(css == v->_alloccallsstacksize) { \
-		v->GrowCallStack(); \
-	} \
-	v->ci = &v->_callsstack[css]; \
-	*(v->ci) = nci; \
-	v->_callsstacksize++; \
-}
-
-#define POP_CALLINFO(v){ \
-	SQInteger css = --v->_callsstacksize; \
-	v->ci->_closure.Null(); \
-	v->ci = css?&v->_callsstack[css-1]:NULL;	\
-}
-#endif //_SQVM_H_
+/*  see copyright notice in squirrel.h */
+#ifndef _SQVM_H_
+#define _SQVM_H_
+
+#include "sqopcodes.h"
+#include "sqobject.h"
+#define MAX_NATIVE_CALLS 100
+#define MIN_STACK_OVERHEAD 15
+
+#define SQ_SUSPEND_FLAG -666
+#define DONT_FALL_BACK 666
+//#define EXISTS_FALL_BACK -1
+
+#define GET_FLAG_RAW                0x00000001
+#define GET_FLAG_DO_NOT_RAISE_ERROR 0x00000002
+//base lib
+void sq_base_register(HSQUIRRELVM v);
+
+struct SQExceptionTrap{
+    SQExceptionTrap() {}
+    SQExceptionTrap(SQInteger ss, SQInteger stackbase,SQInstruction *ip, SQInteger ex_target){ _stacksize = ss; _stackbase = stackbase; _ip = ip; _extarget = ex_target;}
+    SQExceptionTrap(const SQExceptionTrap &et) { (*this) = et;  }
+    SQInteger _stackbase;
+    SQInteger _stacksize;
+    SQInstruction *_ip;
+    SQInteger _extarget;
+};
+
+#define _INLINE
+
+#define STK(a) _stack._vals[_stackbase+(a)]
+#define TARGET _stack._vals[_stackbase+arg0]
+
+typedef sqvector<SQExceptionTrap> ExceptionsTraps;
+
+struct SQVM : public CHAINABLE_OBJ
+{
+    struct CallInfo{
+        //CallInfo() { _generator = NULL;}
+        SQInstruction *_ip;
+        SQObjectPtr *_literals;
+        SQObjectPtr _closure;
+        SQGenerator *_generator;
+        SQInt32 _etraps;
+        SQInt32 _prevstkbase;
+        SQInt32 _prevtop;
+        SQInt32 _target;
+        SQInt32 _ncalls;
+        SQBool _root;
+    };
+
+typedef sqvector<CallInfo> CallInfoVec;
+public:
+    void DebugHookProxy(SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname);
+    static void _DebugHookProxy(HSQUIRRELVM v, SQInteger type, const SQChar * sourcename, SQInteger line, const SQChar * funcname);
+    enum ExecutionType { ET_CALL, ET_RESUME_GENERATOR, ET_RESUME_VM,ET_RESUME_THROW_VM };
+    SQVM(SQSharedState *ss);
+    ~SQVM();
+    bool Init(SQVM *friendvm, SQInteger stacksize);
+    bool Execute(SQObjectPtr &func, SQInteger nargs, SQInteger stackbase, SQObjectPtr &outres, SQBool raiseerror, ExecutionType et = ET_CALL);
+    //starts a native call return when the NATIVE closure returns
+    bool CallNative(SQNativeClosure *nclosure, SQInteger nargs, SQInteger newbase, SQObjectPtr &retval,bool &suspend);
+    //starts a SQUIRREL call in the same "Execution loop"
+    bool StartCall(SQClosure *closure, SQInteger target, SQInteger nargs, SQInteger stackbase, bool tailcall);
+    bool CreateClassInstance(SQClass *theclass, SQObjectPtr &inst, SQObjectPtr &constructor);
+    //call a generic closure pure SQUIRREL or NATIVE
+    bool Call(SQObjectPtr &closure, SQInteger nparams, SQInteger stackbase, SQObjectPtr &outres,SQBool raiseerror);
+    SQRESULT Suspend();
+
+    void CallDebugHook(SQInteger type,SQInteger forcedline=0);
+    void CallErrorHandler(SQObjectPtr &e);
+    bool Get(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &dest, SQUnsignedInteger getflags, SQInteger selfidx);
+    SQInteger FallBackGet(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);
+    bool InvokeDefaultDelegate(const SQObjectPtr &self,const SQObjectPtr &key,SQObjectPtr &dest);
+    bool Set(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val, SQInteger selfidx);
+    SQInteger FallBackSet(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val);
+    bool NewSlot(const SQObjectPtr &self, const SQObjectPtr &key, const SQObjectPtr &val,bool bstatic);
+    bool NewSlotA(const SQObjectPtr &self,const SQObjectPtr &key,const SQObjectPtr &val,const SQObjectPtr &attrs,bool bstatic,bool raw);
+    bool DeleteSlot(const SQObjectPtr &self, const SQObjectPtr &key, SQObjectPtr &res);
+    bool Clone(const SQObjectPtr &self, SQObjectPtr &target);
+    bool ObjCmp(const SQObjectPtr &o1, const SQObjectPtr &o2,SQInteger &res);
+    bool StringCat(const SQObjectPtr &str, const SQObjectPtr &obj, SQObjectPtr &dest);
+    static bool IsEqual(const SQObjectPtr &o1,const SQObjectPtr &o2,bool &res);
+    bool ToString(const SQObjectPtr &o,SQObjectPtr &res);
+    SQString *PrintObjVal(const SQObjectPtr &o);
+
+
+    void Raise_Error(const SQChar *s, ...);
+    void Raise_Error(const SQObjectPtr &desc);
+    void Raise_IdxError(const SQObjectPtr &o);
+    void Raise_CompareError(const SQObject &o1, const SQObject &o2);
+    void Raise_ParamTypeError(SQInteger nparam,SQInteger typemask,SQInteger type);
+
+    void FindOuter(SQObjectPtr &target, SQObjectPtr *stackindex);
+    void RelocateOuters();
+    void CloseOuters(SQObjectPtr *stackindex);
+
+    bool TypeOf(const SQObjectPtr &obj1, SQObjectPtr &dest);
+    bool CallMetaMethod(SQObjectPtr &closure, SQMetaMethod mm, SQInteger nparams, SQObjectPtr &outres);
+    bool ArithMetaMethod(SQInteger op, const SQObjectPtr &o1, const SQObjectPtr &o2, SQObjectPtr &dest);
+    bool Return(SQInteger _arg0, SQInteger _arg1, SQObjectPtr &retval);
+    //new stuff
+    _INLINE bool ARITH_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
+    _INLINE bool BW_OP(SQUnsignedInteger op,SQObjectPtr &trg,const SQObjectPtr &o1,const SQObjectPtr &o2);
+    _INLINE bool NEG_OP(SQObjectPtr &trg,const SQObjectPtr &o1);
+    _INLINE bool CMP_OP(CmpOP op, const SQObjectPtr &o1,const SQObjectPtr &o2,SQObjectPtr &res);
+    bool CLOSURE_OP(SQObjectPtr &target, SQFunctionProto *func);
+    bool CLASS_OP(SQObjectPtr &target,SQInteger base,SQInteger attrs);
+    //return true if the loop is finished
+    bool FOREACH_OP(SQObjectPtr &o1,SQObjectPtr &o2,SQObjectPtr &o3,SQObjectPtr &o4,SQInteger arg_2,int exitpos,int &jump);
+    //_INLINE bool LOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
+    _INLINE bool PLOCAL_INC(SQInteger op,SQObjectPtr &target, SQObjectPtr &a, SQObjectPtr &incr);
+    _INLINE bool DerefInc(SQInteger op,SQObjectPtr &target, SQObjectPtr &self, SQObjectPtr &key, SQObjectPtr &incr, bool postfix,SQInteger arg0);
+#ifdef _DEBUG_DUMP
+    void dumpstack(SQInteger stackbase=-1, bool dumpall = false);
+#endif
+
+#ifndef NO_GARBAGE_COLLECTOR
+    void Mark(SQCollectable **chain);
+    SQObjectType GetType() {return OT_THREAD;}
+#endif
+    void Finalize();
+    void GrowCallStack() {
+        SQInteger newsize = _alloccallsstacksize*2;
+        _callstackdata.resize(newsize);
+        _callsstack = &_callstackdata[0];
+        _alloccallsstacksize = newsize;
+    }
+    bool EnterFrame(SQInteger newbase, SQInteger newtop, bool tailcall);
+    void LeaveFrame();
+    void Release(){ sq_delete(this,SQVM); }
+////////////////////////////////////////////////////////////////////////////
+    //stack functions for the api
+    void Remove(SQInteger n);
+
+    static bool IsFalse(SQObjectPtr &o);
+
+    void Pop();
+    void Pop(SQInteger n);
+    void Push(const SQObjectPtr &o);
+    void PushNull();
+    SQObjectPtr &Top();
+    SQObjectPtr &PopGet();
+    SQObjectPtr &GetUp(SQInteger n);
+    SQObjectPtr &GetAt(SQInteger n);
+
+    SQObjectPtrVec _stack;
+
+    SQInteger _top;
+    SQInteger _stackbase;
+    SQOuter *_openouters;
+    SQObjectPtr _roottable;
+    SQObjectPtr _lasterror;
+    SQObjectPtr _errorhandler;
+
+    bool _debughook;
+    SQDEBUGHOOK _debughook_native;
+    SQObjectPtr _debughook_closure;
+
+    SQObjectPtr temp_reg;
+
+
+    CallInfo* _callsstack;
+    SQInteger _callsstacksize;
+    SQInteger _alloccallsstacksize;
+    sqvector<CallInfo>  _callstackdata;
+
+    ExceptionsTraps _etraps;
+    CallInfo *ci;
+    SQUserPointer _foreignptr;
+    //VMs sharing the same state
+    SQSharedState *_sharedstate;
+    SQInteger _nnativecalls;
+    SQInteger _nmetamethodscall;
+    SQRELEASEHOOK _releasehook;
+    //suspend infos
+    SQBool _suspended;
+    SQBool _suspended_root;
+    SQInteger _suspended_target;
+    SQInteger _suspended_traps;
+};
+
+struct AutoDec{
+    AutoDec(SQInteger *n) { _n = n; }
+    ~AutoDec() { (*_n)--; }
+    SQInteger *_n;
+};
+
+inline SQObjectPtr &stack_get(HSQUIRRELVM v,SQInteger idx){return ((idx>=0)?(v->GetAt(idx+v->_stackbase-1)):(v->GetUp(idx)));}
+
+#define _ss(_vm_) (_vm_)->_sharedstate
+
+#ifndef NO_GARBAGE_COLLECTOR
+#define _opt_ss(_vm_) (_vm_)->_sharedstate
+#else
+#define _opt_ss(_vm_) NULL
+#endif
+
+#define PUSH_CALLINFO(v,nci){ \
+    SQInteger css = v->_callsstacksize; \
+    if(css == v->_alloccallsstacksize) { \
+        v->GrowCallStack(); \
+    } \
+    v->ci = &v->_callsstack[css]; \
+    *(v->ci) = nci; \
+    v->_callsstacksize++; \
+}
+
+#define POP_CALLINFO(v){ \
+    SQInteger css = --v->_callsstacksize; \
+    v->ci->_closure.Null(); \
+    v->ci = css?&v->_callsstack[css-1]:NULL;    \
+}
+#endif //_SQVM_H_