From 009dd0f23aab6bb022cacfa62cd1c73bfac22d14 Mon Sep 17 00:00:00 2001 From: zeromus Date: Tue, 3 Nov 2009 05:09:17 +0000 Subject: [PATCH] add lua source files so that we can compile lua once more in linux. --- SConstruct | 16 +- src/SConscript | 1 + src/lua/COPYRIGHT | 34 + src/lua/HISTORY | 183 ++++++ src/lua/README | 37 ++ src/lua/SConscript | 36 + src/lua/lua.vcproj | 366 +++++++++++ src/lua/src/Makefile | 182 ++++++ src/lua/src/lapi.c | 1087 +++++++++++++++++++++++++++++++ src/lua/src/lapi.h | 16 + src/lua/src/lauxlib.c | 652 +++++++++++++++++++ src/lua/src/lauxlib.h | 174 +++++ src/lua/src/lbaselib.c | 653 +++++++++++++++++++ src/lua/src/lcode.c | 839 ++++++++++++++++++++++++ src/lua/src/lcode.h | 76 +++ src/lua/src/ldblib.c | 397 +++++++++++ src/lua/src/ldebug.c | 638 ++++++++++++++++++ src/lua/src/ldebug.h | 33 + src/lua/src/ldo.c | 518 +++++++++++++++ src/lua/src/ldo.h | 57 ++ src/lua/src/ldump.c | 164 +++++ src/lua/src/lfunc.c | 174 +++++ src/lua/src/lfunc.h | 34 + src/lua/src/lgc.c | 711 ++++++++++++++++++++ src/lua/src/lgc.h | 110 ++++ src/lua/src/linit.c | 38 ++ src/lua/src/liolib.c | 553 ++++++++++++++++ src/lua/src/llex.c | 461 +++++++++++++ src/lua/src/llex.h | 81 +++ src/lua/src/llimits.h | 128 ++++ src/lua/src/lmathlib.c | 263 ++++++++ src/lua/src/lmem.c | 86 +++ src/lua/src/lmem.h | 49 ++ src/lua/src/loadlib.c | 666 +++++++++++++++++++ src/lua/src/lobject.c | 214 ++++++ src/lua/src/lobject.h | 381 +++++++++++ src/lua/src/lopcodes.c | 102 +++ src/lua/src/lopcodes.h | 268 ++++++++ src/lua/src/loslib.c | 243 +++++++ src/lua/src/lparser.c | 1339 ++++++++++++++++++++++++++++++++++++++ src/lua/src/lparser.h | 82 +++ src/lua/src/lstate.c | 214 ++++++ src/lua/src/lstate.h | 169 +++++ src/lua/src/lstring.c | 111 ++++ src/lua/src/lstring.h | 31 + src/lua/src/lstrlib.c | 869 +++++++++++++++++++++++++ src/lua/src/ltable.c | 588 +++++++++++++++++ src/lua/src/ltable.h | 40 ++ src/lua/src/ltablib.c | 287 ++++++++ src/lua/src/ltm.c | 75 +++ src/lua/src/ltm.h | 54 ++ src/lua/src/lua.c | 392 +++++++++++ src/lua/src/lua.h | 388 +++++++++++ src/lua/src/luac.c | 200 ++++++ src/lua/src/luaconf.h | 763 ++++++++++++++++++++++ src/lua/src/lualib.h | 53 ++ src/lua/src/lundump.c | 227 +++++++ src/lua/src/lundump.h | 36 + src/lua/src/lvm.c | 763 ++++++++++++++++++++++ src/lua/src/lvm.h | 36 + src/lua/src/lzio.c | 82 +++ src/lua/src/lzio.h | 67 ++ src/lua/src/print.c | 227 +++++++ vc/lua/lua-5.1.4-x86.lib | Bin 490982 -> 0 bytes vc/vc8_fceux.vcproj | 424 +++++++++--- vc/vc9_fceux.vcproj | 220 ++++++- 66 files changed, 18338 insertions(+), 120 deletions(-) create mode 100644 src/lua/COPYRIGHT create mode 100644 src/lua/HISTORY create mode 100644 src/lua/README create mode 100644 src/lua/SConscript create mode 100644 src/lua/lua.vcproj create mode 100644 src/lua/src/Makefile create mode 100644 src/lua/src/lapi.c create mode 100644 src/lua/src/lapi.h create mode 100644 src/lua/src/lauxlib.c create mode 100644 src/lua/src/lauxlib.h create mode 100644 src/lua/src/lbaselib.c create mode 100644 src/lua/src/lcode.c create mode 100644 src/lua/src/lcode.h create mode 100644 src/lua/src/ldblib.c create mode 100644 src/lua/src/ldebug.c create mode 100644 src/lua/src/ldebug.h create mode 100644 src/lua/src/ldo.c create mode 100644 src/lua/src/ldo.h create mode 100644 src/lua/src/ldump.c create mode 100644 src/lua/src/lfunc.c create mode 100644 src/lua/src/lfunc.h create mode 100644 src/lua/src/lgc.c create mode 100644 src/lua/src/lgc.h create mode 100644 src/lua/src/linit.c create mode 100644 src/lua/src/liolib.c create mode 100644 src/lua/src/llex.c create mode 100644 src/lua/src/llex.h create mode 100644 src/lua/src/llimits.h create mode 100644 src/lua/src/lmathlib.c create mode 100644 src/lua/src/lmem.c create mode 100644 src/lua/src/lmem.h create mode 100644 src/lua/src/loadlib.c create mode 100644 src/lua/src/lobject.c create mode 100644 src/lua/src/lobject.h create mode 100644 src/lua/src/lopcodes.c create mode 100644 src/lua/src/lopcodes.h create mode 100644 src/lua/src/loslib.c create mode 100644 src/lua/src/lparser.c create mode 100644 src/lua/src/lparser.h create mode 100644 src/lua/src/lstate.c create mode 100644 src/lua/src/lstate.h create mode 100644 src/lua/src/lstring.c create mode 100644 src/lua/src/lstring.h create mode 100644 src/lua/src/lstrlib.c create mode 100644 src/lua/src/ltable.c create mode 100644 src/lua/src/ltable.h create mode 100644 src/lua/src/ltablib.c create mode 100644 src/lua/src/ltm.c create mode 100644 src/lua/src/ltm.h create mode 100644 src/lua/src/lua.c create mode 100644 src/lua/src/lua.h create mode 100644 src/lua/src/luac.c create mode 100644 src/lua/src/luaconf.h create mode 100644 src/lua/src/lualib.h create mode 100644 src/lua/src/lundump.c create mode 100644 src/lua/src/lundump.h create mode 100644 src/lua/src/lvm.c create mode 100644 src/lua/src/lvm.h create mode 100644 src/lua/src/lzio.c create mode 100644 src/lua/src/lzio.h create mode 100644 src/lua/src/print.c delete mode 100644 vc/lua/lua-5.1.4-x86.lib diff --git a/SConstruct b/SConstruct index 24433854..1512cef6 100644 --- a/SConstruct +++ b/SConstruct @@ -21,7 +21,7 @@ if platform.system == "ppc": env['LSB_FIRST'] = 0 # Default compiler flags: -env.Append(CCFLAGS = ['-Wall', '-Wno-write-strings', '-Wno-sign-compare', '-O2']) +env.Append(CCFLAGS = ['-Wall', '-Wno-write-strings', '-Wno-sign-compare', '-O2', '-Isrc/lua/src']) if os.environ.has_key('PLATFORM'): env.Replace(PLATFORM = os.environ['PLATFORM']) @@ -57,12 +57,6 @@ else: if not conf.CheckLib('z', autoadd=1): print 'Did not find libz or z.lib, exiting!' Exit(1) - if env['LUA']: - lua51 = conf.CheckLib('lua5.1', autoadd=1) - lua = conf.CheckLib('lua', autoadd=1) - if lua == 0 and lua51 == 0: - print 'Did not find liblua5.1, liblua, lua.lib or lua5.1.lib, compiling anyway!' - env['LUA'] = 0 ### Search for zenity if we're not in windows if env['PLATFORM'] != 'win32' and env['PLATFORM'] != 'cygwin': @@ -103,13 +97,7 @@ else: conf.env.Append(CPPDEFINES = ['PSS_STYLE=1']) # parse SDL cflags/libs env.ParseConfig('sdl-config --cflags --libs') - if env['LUA']: - # parse liblua cflags - if lua51: - env.Append(CPPPATH = ['/usr/local/include/lua5.1', '/usr/include/lua5.1']) - if lua: - env.Append(CPPPATH = ['/usr/local/include/lua', '/usr/include/lua']) - env.Append(CPPDEFINES=["_S9XLUA_H"]) + env.Append(CPPDEFINES=["_S9XLUA_H"]) env = conf.Finish() if sys.byteorder == 'little' or env['PLATFORM'] == 'win32': diff --git a/src/SConscript b/src/SConscript index 11de3a73..18d15e5a 100644 --- a/src/SConscript +++ b/src/SConscript @@ -34,6 +34,7 @@ fir input utils mappers +lua """) #palettes diff --git a/src/lua/COPYRIGHT b/src/lua/COPYRIGHT new file mode 100644 index 00000000..3a53e741 --- /dev/null +++ b/src/lua/COPYRIGHT @@ -0,0 +1,34 @@ +Lua License +----------- + +Lua is licensed under the terms of the MIT license reproduced below. +This means that Lua is free software and can be used for both academic +and commercial purposes at absolutely no cost. + +For details and rationale, see http://www.lua.org/license.html . + +=============================================================================== + +Copyright (C) 1994-2008 Lua.org, PUC-Rio. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +=============================================================================== + +(end of COPYRIGHT) diff --git a/src/lua/HISTORY b/src/lua/HISTORY new file mode 100644 index 00000000..ce0c95bc --- /dev/null +++ b/src/lua/HISTORY @@ -0,0 +1,183 @@ +HISTORY for Lua 5.1 + +* Changes from version 5.0 to 5.1 + ------------------------------- + Language: + + new module system. + + new semantics for control variables of fors. + + new semantics for setn/getn. + + new syntax/semantics for varargs. + + new long strings and comments. + + new `mod' operator (`%') + + new length operator #t + + metatables for all types + API: + + new functions: lua_createtable, lua_get(set)field, lua_push(to)integer. + + user supplies memory allocator (lua_open becomes lua_newstate). + + luaopen_* functions must be called through Lua. + Implementation: + + new configuration scheme via luaconf.h. + + incremental garbage collection. + + better handling of end-of-line in the lexer. + + fully reentrant parser (new Lua function `load') + + better support for 64-bit machines. + + native loadlib support for Mac OS X. + + standard distribution in only one library (lualib.a merged into lua.a) + +* Changes from version 4.0 to 5.0 + ------------------------------- + Language: + + lexical scoping. + + Lua coroutines. + + standard libraries now packaged in tables. + + tags replaced by metatables and tag methods replaced by metamethods, + stored in metatables. + + proper tail calls. + + each function can have its own global table, which can be shared. + + new __newindex metamethod, called when we insert a new key into a table. + + new block comments: --[[ ... ]]. + + new generic for. + + new weak tables. + + new boolean type. + + new syntax "local function". + + (f()) returns the first value returned by f. + + {f()} fills a table with all values returned by f. + + \n ignored in [[\n . + + fixed and-or priorities. + + more general syntax for function definition (e.g. function a.x.y:f()...end). + + more general syntax for function calls (e.g. (print or write)(9)). + + new functions (time/date, tmpfile, unpack, require, load*, etc.). + API: + + chunks are loaded by using lua_load; new luaL_loadfile and luaL_loadbuffer. + + introduced lightweight userdata, a simple "void*" without a metatable. + + new error handling protocol: the core no longer prints error messages; + all errors are reported to the caller on the stack. + + new lua_atpanic for host cleanup. + + new, signal-safe, hook scheme. + Implementation: + + new license: MIT. + + new, faster, register-based virtual machine. + + support for external multithreading and coroutines. + + new and consistent error message format. + + the core no longer needs "stdio.h" for anything (except for a single + use of sprintf to convert numbers to strings). + + lua.c now runs the environment variable LUA_INIT, if present. It can + be "@filename", to run a file, or the chunk itself. + + support for user extensions in lua.c. + sample implementation given for command line editing. + + new dynamic loading library, active by default on several platforms. + + safe garbage-collector metamethods. + + precompiled bytecodes checked for integrity (secure binary dostring). + + strings are fully aligned. + + position capture in string.find. + + read('*l') can read lines with embedded zeros. + +* Changes from version 3.2 to 4.0 + ------------------------------- + Language: + + new "break" and "for" statements (both numerical and for tables). + + uniform treatment of globals: globals are now stored in a Lua table. + + improved error messages. + + no more '$debug': full speed *and* full debug information. + + new read form: read(N) for next N bytes. + + general read patterns now deprecated. + (still available with -DCOMPAT_READPATTERNS.) + + all return values are passed as arguments for the last function + (old semantics still available with -DLUA_COMPAT_ARGRET) + + garbage collection tag methods for tables now deprecated. + + there is now only one tag method for order. + API: + + New API: fully re-entrant, simpler, and more efficient. + + New debug API. + Implementation: + + faster than ever: cleaner virtual machine and new hashing algorithm. + + non-recursive garbage-collector algorithm. + + reduced memory usage for programs with many strings. + + improved treatment for memory allocation errors. + + improved support for 16-bit machines (we hope). + + code now compiles unmodified as both ANSI C and C++. + + numbers in bases other than 10 are converted using strtoul. + + new -f option in Lua to support #! scripts. + + luac can now combine text and binaries. + +* Changes from version 3.1 to 3.2 + ------------------------------- + + redirected all output in Lua's core to _ERRORMESSAGE and _ALERT. + + increased limit on the number of constants and globals per function + (from 2^16 to 2^24). + + debugging info (lua_debug and hooks) moved into lua_state and new API + functions provided to get and set this info. + + new debug lib gives full debugging access within Lua. + + new table functions "foreachi", "sort", "tinsert", "tremove", "getn". + + new io functions "flush", "seek". + +* Changes from version 3.0 to 3.1 + ------------------------------- + + NEW FEATURE: anonymous functions with closures (via "upvalues"). + + new syntax: + - local variables in chunks. + - better scope control with DO block END. + - constructors can now be also written: { record-part; list-part }. + - more general syntax for function calls and lvalues, e.g.: + f(x).y=1 + o:f(x,y):g(z) + f"string" is sugar for f("string") + + strings may now contain arbitrary binary data (e.g., embedded zeros). + + major code re-organization and clean-up; reduced module interdependecies. + + no arbitrary limits on the total number of constants and globals. + + support for multiple global contexts. + + better syntax error messages. + + new traversal functions "foreach" and "foreachvar". + + the default for numbers is now double. + changing it to use floats or longs is easy. + + complete debug information stored in pre-compiled chunks. + + sample interpreter now prompts user when run interactively, and also + handles control-C interruptions gracefully. + +* Changes from version 2.5 to 3.0 + ------------------------------- + + NEW CONCEPT: "tag methods". + Tag methods replace fallbacks as the meta-mechanism for extending the + semantics of Lua. Whereas fallbacks had a global nature, tag methods + work on objects having the same tag (e.g., groups of tables). + Existing code that uses fallbacks should work without change. + + new, general syntax for constructors {[exp] = exp, ... }. + + support for handling variable number of arguments in functions (varargs). + + support for conditional compilation ($if ... $else ... $end). + + cleaner semantics in API simplifies host code. + + better support for writing libraries (auxlib.h). + + better type checking and error messages in the standard library. + + luac can now also undump. + +* Changes from version 2.4 to 2.5 + ------------------------------- + + io and string libraries are now based on pattern matching; + the old libraries are still available for compatibility + + dofile and dostring can now return values (via return statement) + + better support for 16- and 64-bit machines + + expanded documentation, with more examples + +* Changes from version 2.2 to 2.4 + ------------------------------- + + external compiler creates portable binary files that can be loaded faster + + interface for debugging and profiling + + new "getglobal" fallback + + new functions for handling references to Lua objects + + new functions in standard lib + + only one copy of each string is stored + + expanded documentation, with more examples + +* Changes from version 2.1 to 2.2 + ------------------------------- + + functions now may be declared with any "lvalue" as a name + + garbage collection of functions + + support for pipes + +* Changes from version 1.1 to 2.1 + ------------------------------- + + object-oriented support + + fallbacks + + simplified syntax for tables + + many internal improvements + +(end of HISTORY) diff --git a/src/lua/README b/src/lua/README new file mode 100644 index 00000000..11b4dff7 --- /dev/null +++ b/src/lua/README @@ -0,0 +1,37 @@ +README for Lua 5.1 + +See INSTALL for installation instructions. +See HISTORY for a summary of changes since the last released version. + +* What is Lua? + ------------ + Lua is a powerful, light-weight programming language designed for extending + applications. Lua is also frequently used as a general-purpose, stand-alone + language. Lua is free software. + + For complete information, visit Lua's web site at http://www.lua.org/ . + For an executive summary, see http://www.lua.org/about.html . + + Lua has been used in many different projects around the world. + For a short list, see http://www.lua.org/uses.html . + +* Availability + ------------ + Lua is freely available for both academic and commercial purposes. + See COPYRIGHT and http://www.lua.org/license.html for details. + Lua can be downloaded at http://www.lua.org/download.html . + +* Installation + ------------ + Lua is implemented in pure ANSI C, and compiles unmodified in all known + platforms that have an ANSI C compiler. In most Unix-like platforms, simply + do "make" with a suitable target. See INSTALL for detailed instructions. + +* Origin + ------ + Lua is developed at Lua.org, a laboratory of the Department of Computer + Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro + in Brazil). + For more information about the authors, see http://www.lua.org/authors.html . + +(end of README) diff --git a/src/lua/SConscript b/src/lua/SConscript new file mode 100644 index 00000000..f451546d --- /dev/null +++ b/src/lua/SConscript @@ -0,0 +1,36 @@ +my_list = Split(""" +lapi.c +lauxlib.c +lbaselib.c +lcode.c +ldblib.c +ldebug.c +ldo.c +ldump.c +lfunc.c +lgc.c +linit.c +liolib.c +llex.c +lmathlib.c +lmem.c +loadlib.c +lobject.c +lopcodes.c +loslib.c +lparser.c +lstate.c +lstring.c +lstrlib.c +ltable.c +ltablib.c +ltm.c +lundump.c +lvm.c +lzio.c +print.c +""") + +for x in range(len(my_list)): + my_list[x] = 'lua/src/' + my_list[x] +Return('my_list') diff --git a/src/lua/lua.vcproj b/src/lua/lua.vcproj new file mode 100644 index 00000000..7839a759 --- /dev/null +++ b/src/lua/lua.vcproj @@ -0,0 +1,366 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/lua/src/Makefile b/src/lua/src/Makefile new file mode 100644 index 00000000..e4a3cd61 --- /dev/null +++ b/src/lua/src/Makefile @@ -0,0 +1,182 @@ +# makefile for building Lua +# see ../INSTALL for installation instructions +# see ../Makefile and luaconf.h for further customization + +# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT ======================= + +# Your platform. See PLATS for possible values. +PLAT= none + +CC= gcc +CFLAGS= -O2 -Wall $(MYCFLAGS) +AR= ar rcu +RANLIB= ranlib +RM= rm -f +LIBS= -lm $(MYLIBS) + +MYCFLAGS= +MYLDFLAGS= +MYLIBS= + +# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE ========= + +PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris + +LUA_A= liblua.a +CORE_O= lapi.o lcode.o ldebug.o ldo.o ldump.o lfunc.o lgc.o llex.o lmem.o \ + lobject.o lopcodes.o lparser.o lstate.o lstring.o ltable.o ltm.o \ + lundump.o lvm.o lzio.o +LIB_O= lauxlib.o lbaselib.o ldblib.o liolib.o lmathlib.o loslib.o ltablib.o \ + lstrlib.o loadlib.o linit.o + +LUA_T= lua +LUA_O= lua.o + +LUAC_T= luac +LUAC_O= luac.o print.o + +ALL_O= $(CORE_O) $(LIB_O) $(LUA_O) $(LUAC_O) +ALL_T= $(LUA_A) $(LUA_T) $(LUAC_T) +ALL_A= $(LUA_A) + +default: $(PLAT) + +all: $(ALL_T) + +o: $(ALL_O) + +a: $(ALL_A) + +$(LUA_A): $(CORE_O) $(LIB_O) + $(AR) $@ $? + $(RANLIB) $@ + +$(LUA_T): $(LUA_O) $(LUA_A) + $(CC) -o $@ $(MYLDFLAGS) $(LUA_O) $(LUA_A) $(LIBS) + +$(LUAC_T): $(LUAC_O) $(LUA_A) + $(CC) -o $@ $(MYLDFLAGS) $(LUAC_O) $(LUA_A) $(LIBS) + +clean: + $(RM) $(ALL_T) $(ALL_O) + +depend: + @$(CC) $(CFLAGS) -MM l*.c print.c + +echo: + @echo "PLAT = $(PLAT)" + @echo "CC = $(CC)" + @echo "CFLAGS = $(CFLAGS)" + @echo "AR = $(AR)" + @echo "RANLIB = $(RANLIB)" + @echo "RM = $(RM)" + @echo "MYCFLAGS = $(MYCFLAGS)" + @echo "MYLDFLAGS = $(MYLDFLAGS)" + @echo "MYLIBS = $(MYLIBS)" + +# convenience targets for popular platforms + +none: + @echo "Please choose a platform:" + @echo " $(PLATS)" + +aix: + $(MAKE) all CC="xlc" CFLAGS="-O2 -DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" MYLDFLAGS="-brtl -bexpall" + +ansi: + $(MAKE) all MYCFLAGS=-DLUA_ANSI + +bsd: + $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-Wl,-E" + +freebsd: + $(MAKE) all MYCFLAGS="-DLUA_USE_LINUX" MYLIBS="-Wl,-E -lreadline" + +generic: + $(MAKE) all MYCFLAGS= + +linux: + $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-Wl,-E -ldl -lreadline -lhistory -lncurses" + +macosx: + $(MAKE) all MYCFLAGS=-DLUA_USE_LINUX MYLIBS="-lreadline" +# use this on Mac OS X 10.3- +# $(MAKE) all MYCFLAGS=-DLUA_USE_MACOSX + +mingw: + $(MAKE) "LUA_A=lua51.dll" "LUA_T=lua.exe" \ + "AR=$(CC) -shared -o" "RANLIB=strip --strip-unneeded" \ + "MYCFLAGS=-DLUA_BUILD_AS_DLL" "MYLIBS=" "MYLDFLAGS=-s" lua.exe + $(MAKE) "LUAC_T=luac.exe" luac.exe + +posix: + $(MAKE) all MYCFLAGS=-DLUA_USE_POSIX + +solaris: + $(MAKE) all MYCFLAGS="-DLUA_USE_POSIX -DLUA_USE_DLOPEN" MYLIBS="-ldl" + +# list targets that do not create files (but not all makes understand .PHONY) +.PHONY: all $(PLATS) default o a clean depend echo none + +# DO NOT DELETE + +lapi.o: lapi.c lua.h luaconf.h lapi.h lobject.h llimits.h ldebug.h \ + lstate.h ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h \ + lundump.h lvm.h +lauxlib.o: lauxlib.c lua.h luaconf.h lauxlib.h +lbaselib.o: lbaselib.c lua.h luaconf.h lauxlib.h lualib.h +lcode.o: lcode.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ + lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h lgc.h \ + ltable.h +ldblib.o: ldblib.c lua.h luaconf.h lauxlib.h lualib.h +ldebug.o: ldebug.c lua.h luaconf.h lapi.h lobject.h llimits.h lcode.h \ + llex.h lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \ + lfunc.h lstring.h lgc.h ltable.h lvm.h +ldo.o: ldo.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lparser.h lstring.h \ + ltable.h lundump.h lvm.h +ldump.o: ldump.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h \ + lzio.h lmem.h lundump.h +lfunc.o: lfunc.c lua.h luaconf.h lfunc.h lobject.h llimits.h lgc.h lmem.h \ + lstate.h ltm.h lzio.h +lgc.o: lgc.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lstring.h ltable.h +linit.o: linit.c lua.h luaconf.h lualib.h lauxlib.h +liolib.o: liolib.c lua.h luaconf.h lauxlib.h lualib.h +llex.o: llex.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h ltm.h \ + lzio.h lmem.h llex.h lparser.h lstring.h lgc.h ltable.h +lmathlib.o: lmathlib.c lua.h luaconf.h lauxlib.h lualib.h +lmem.o: lmem.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h +loadlib.o: loadlib.c lua.h luaconf.h lauxlib.h lualib.h +lobject.o: lobject.c lua.h luaconf.h ldo.h lobject.h llimits.h lstate.h \ + ltm.h lzio.h lmem.h lstring.h lgc.h lvm.h +lopcodes.o: lopcodes.c lopcodes.h llimits.h lua.h luaconf.h +loslib.o: loslib.c lua.h luaconf.h lauxlib.h lualib.h +lparser.o: lparser.c lua.h luaconf.h lcode.h llex.h lobject.h llimits.h \ + lzio.h lmem.h lopcodes.h lparser.h ldebug.h lstate.h ltm.h ldo.h \ + lfunc.h lstring.h lgc.h ltable.h +lstate.o: lstate.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h lfunc.h lgc.h llex.h lstring.h ltable.h +lstring.o: lstring.c lua.h luaconf.h lmem.h llimits.h lobject.h lstate.h \ + ltm.h lzio.h lstring.h lgc.h +lstrlib.o: lstrlib.c lua.h luaconf.h lauxlib.h lualib.h +ltable.o: ltable.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h ldo.h lgc.h ltable.h +ltablib.o: ltablib.c lua.h luaconf.h lauxlib.h lualib.h +ltm.o: ltm.c lua.h luaconf.h lobject.h llimits.h lstate.h ltm.h lzio.h \ + lmem.h lstring.h lgc.h ltable.h +lua.o: lua.c lua.h luaconf.h lauxlib.h lualib.h +luac.o: luac.c lua.h luaconf.h lauxlib.h ldo.h lobject.h llimits.h \ + lstate.h ltm.h lzio.h lmem.h lfunc.h lopcodes.h lstring.h lgc.h \ + lundump.h +lundump.o: lundump.c lua.h luaconf.h ldebug.h lstate.h lobject.h \ + llimits.h ltm.h lzio.h lmem.h ldo.h lfunc.h lstring.h lgc.h lundump.h +lvm.o: lvm.c lua.h luaconf.h ldebug.h lstate.h lobject.h llimits.h ltm.h \ + lzio.h lmem.h ldo.h lfunc.h lgc.h lopcodes.h lstring.h ltable.h lvm.h +lzio.o: lzio.c lua.h luaconf.h llimits.h lmem.h lstate.h lobject.h ltm.h \ + lzio.h +print.o: print.c ldebug.h lstate.h lua.h luaconf.h lobject.h llimits.h \ + ltm.h lzio.h lmem.h lopcodes.h lundump.h + +# (end of Makefile) diff --git a/src/lua/src/lapi.c b/src/lua/src/lapi.c new file mode 100644 index 00000000..5d5145d2 --- /dev/null +++ b/src/lua/src/lapi.c @@ -0,0 +1,1087 @@ +/* +** $Id: lapi.c,v 2.55.1.5 2008/07/04 18:41:18 roberto Exp $ +** Lua API +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define lapi_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" + + + +const char lua_ident[] = + "$Lua: " LUA_RELEASE " " LUA_COPYRIGHT " $\n" + "$Authors: " LUA_AUTHORS " $\n" + "$URL: www.lua.org $\n"; + + + +#define api_checknelems(L, n) api_check(L, (n) <= (L->top - L->base)) + +#define api_checkvalidindex(L, i) api_check(L, (i) != luaO_nilobject) + +#define api_incr_top(L) {api_check(L, L->top < L->ci->top); L->top++;} + + + +static TValue *index2adr (lua_State *L, int idx) { + if (idx > 0) { + TValue *o = L->base + (idx - 1); + api_check(L, idx <= L->ci->top - L->base); + if (o >= L->top) return cast(TValue *, luaO_nilobject); + else return o; + } + else if (idx > LUA_REGISTRYINDEX) { + api_check(L, idx != 0 && -idx <= L->top - L->base); + return L->top + idx; + } + else switch (idx) { /* pseudo-indices */ + case LUA_REGISTRYINDEX: return registry(L); + case LUA_ENVIRONINDEX: { + Closure *func = curr_func(L); + sethvalue(L, &L->env, func->c.env); + return &L->env; + } + case LUA_GLOBALSINDEX: return gt(L); + default: { + Closure *func = curr_func(L); + idx = LUA_GLOBALSINDEX - idx; + return (idx <= func->c.nupvalues) + ? &func->c.upvalue[idx-1] + : cast(TValue *, luaO_nilobject); + } + } +} + + +static Table *getcurrenv (lua_State *L) { + if (L->ci == L->base_ci) /* no enclosing function? */ + return hvalue(gt(L)); /* use global table as environment */ + else { + Closure *func = curr_func(L); + return func->c.env; + } +} + + +void luaA_pushobject (lua_State *L, const TValue *o) { + setobj2s(L, L->top, o); + api_incr_top(L); +} + + +LUA_API int lua_checkstack (lua_State *L, int size) { + int res = 1; + lua_lock(L); + if (size > LUAI_MAXCSTACK || (L->top - L->base + size) > LUAI_MAXCSTACK) + res = 0; /* stack overflow */ + else if (size > 0) { + luaD_checkstack(L, size); + if (L->ci->top < L->top + size) + L->ci->top = L->top + size; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { + int i; + if (from == to) return; + lua_lock(to); + api_checknelems(from, n); + api_check(from, G(from) == G(to)); + api_check(from, to->ci->top - to->top >= n); + from->top -= n; + for (i = 0; i < n; i++) { + setobj2s(to, to->top++, from->top + i); + } + lua_unlock(to); +} + + +LUA_API void lua_setlevel (lua_State *from, lua_State *to) { + to->nCcalls = from->nCcalls; +} + + +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { + lua_CFunction old; + lua_lock(L); + old = G(L)->panic; + G(L)->panic = panicf; + lua_unlock(L); + return old; +} + + +LUA_API lua_State *lua_newthread (lua_State *L) { + lua_State *L1; + lua_lock(L); + luaC_checkGC(L); + L1 = luaE_newthread(L); + setthvalue(L, L->top, L1); + api_incr_top(L); + lua_unlock(L); + luai_userstatethread(L, L1); + return L1; +} + + + +/* +** basic stack manipulation +*/ + + +LUA_API int lua_gettop (lua_State *L) { + return cast_int(L->top - L->base); +} + + +LUA_API void lua_settop (lua_State *L, int idx) { + lua_lock(L); + if (idx >= 0) { + api_check(L, idx <= L->stack_last - L->base); + while (L->top < L->base + idx) + setnilvalue(L->top++); + L->top = L->base + idx; + } + else { + api_check(L, -(idx+1) <= (L->top - L->base)); + L->top += idx+1; /* `subtract' index (index is negative) */ + } + lua_unlock(L); +} + + +LUA_API void lua_remove (lua_State *L, int idx) { + StkId p; + lua_lock(L); + p = index2adr(L, idx); + api_checkvalidindex(L, p); + while (++p < L->top) setobjs2s(L, p-1, p); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_insert (lua_State *L, int idx) { + StkId p; + StkId q; + lua_lock(L); + p = index2adr(L, idx); + api_checkvalidindex(L, p); + for (q = L->top; q>p; q--) setobjs2s(L, q, q-1); + setobjs2s(L, p, L->top); + lua_unlock(L); +} + + +LUA_API void lua_replace (lua_State *L, int idx) { + StkId o; + lua_lock(L); + /* explicit test for incompatible code */ + if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) + luaG_runerror(L, "no calling environment"); + api_checknelems(L, 1); + o = index2adr(L, idx); + api_checkvalidindex(L, o); + if (idx == LUA_ENVIRONINDEX) { + Closure *func = curr_func(L); + api_check(L, ttistable(L->top - 1)); + func->c.env = hvalue(L->top - 1); + luaC_barrier(L, func, L->top - 1); + } + else { + setobj(L, o, L->top - 1); + if (idx < LUA_GLOBALSINDEX) /* function upvalue? */ + luaC_barrier(L, curr_func(L), L->top - 1); + } + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_pushvalue (lua_State *L, int idx) { + lua_lock(L); + setobj2s(L, L->top, index2adr(L, idx)); + api_incr_top(L); + lua_unlock(L); +} + + + +/* +** access functions (stack -> C) +*/ + + +LUA_API int lua_type (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return (o == luaO_nilobject) ? LUA_TNONE : ttype(o); +} + + +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + return (t == LUA_TNONE) ? "no value" : luaT_typenames[t]; +} + + +LUA_API int lua_iscfunction (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return iscfunction(o); +} + + +LUA_API int lua_isnumber (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); + return tonumber(o, &n); +} + + +LUA_API int lua_isstring (lua_State *L, int idx) { + int t = lua_type(L, idx); + return (t == LUA_TSTRING || t == LUA_TNUMBER); +} + + +LUA_API int lua_isuserdata (lua_State *L, int idx) { + const TValue *o = index2adr(L, idx); + return (ttisuserdata(o) || ttislightuserdata(o)); +} + + +LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { + StkId o1 = index2adr(L, index1); + StkId o2 = index2adr(L, index2); + return (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 + : luaO_rawequalObj(o1, o2); +} + + +LUA_API int lua_equal (lua_State *L, int index1, int index2) { + StkId o1, o2; + int i; + lua_lock(L); /* may call tag method */ + o1 = index2adr(L, index1); + o2 = index2adr(L, index2); + i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 : equalobj(L, o1, o2); + lua_unlock(L); + return i; +} + + +LUA_API int lua_lessthan (lua_State *L, int index1, int index2) { + StkId o1, o2; + int i; + lua_lock(L); /* may call tag method */ + o1 = index2adr(L, index1); + o2 = index2adr(L, index2); + i = (o1 == luaO_nilobject || o2 == luaO_nilobject) ? 0 + : luaV_lessthan(L, o1, o2); + lua_unlock(L); + return i; +} + + + +LUA_API lua_Number lua_tonumber (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); + if (tonumber(o, &n)) + return nvalue(o); + else + return 0; +} + + +LUA_API lua_Integer lua_tointeger (lua_State *L, int idx) { + TValue n; + const TValue *o = index2adr(L, idx); + if (tonumber(o, &n)) { + lua_Integer res; + lua_Number num = nvalue(o); + lua_number2integer(res, num); + return res; + } + else + return 0; +} + + +LUA_API int lua_toboolean (lua_State *L, int idx) { + const TValue *o = index2adr(L, idx); + return !l_isfalse(o); +} + + +LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { + StkId o = index2adr(L, idx); + if (!ttisstring(o)) { + lua_lock(L); /* `luaV_tostring' may create a new string */ + if (!luaV_tostring(L, o)) { /* conversion failed? */ + if (len != NULL) *len = 0; + lua_unlock(L); + return NULL; + } + luaC_checkGC(L); + o = index2adr(L, idx); /* previous call may reallocate the stack */ + lua_unlock(L); + } + if (len != NULL) *len = tsvalue(o)->len; + return svalue(o); +} + + +LUA_API size_t lua_objlen (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + switch (ttype(o)) { + case LUA_TSTRING: return tsvalue(o)->len; + case LUA_TUSERDATA: return uvalue(o)->len; + case LUA_TTABLE: return luaH_getn(hvalue(o)); + case LUA_TNUMBER: { + size_t l; + lua_lock(L); /* `luaV_tostring' may create a new string */ + l = (luaV_tostring(L, o) ? tsvalue(o)->len : 0); + lua_unlock(L); + return l; + } + default: return 0; + } +} + + +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return (!iscfunction(o)) ? NULL : clvalue(o)->c.f; +} + + +LUA_API void *lua_touserdata (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + switch (ttype(o)) { + case LUA_TUSERDATA: return (rawuvalue(o) + 1); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } +} + + +LUA_API lua_State *lua_tothread (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + return (!ttisthread(o)) ? NULL : thvalue(o); +} + + +LUA_API const void *lua_topointer (lua_State *L, int idx) { + StkId o = index2adr(L, idx); + switch (ttype(o)) { + case LUA_TTABLE: return hvalue(o); + case LUA_TFUNCTION: return clvalue(o); + case LUA_TTHREAD: return thvalue(o); + case LUA_TUSERDATA: + case LUA_TLIGHTUSERDATA: + return lua_touserdata(L, idx); + default: return NULL; + } +} + + + +/* +** push functions (C -> stack) +*/ + + +LUA_API void lua_pushnil (lua_State *L) { + lua_lock(L); + setnilvalue(L->top); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { + lua_lock(L); + setnvalue(L->top, n); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { + lua_lock(L); + setnvalue(L->top, cast_num(n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlstring (lua_State *L, const char *s, size_t len) { + lua_lock(L); + luaC_checkGC(L); + setsvalue2s(L, L->top, luaS_newlstr(L, s, len)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushstring (lua_State *L, const char *s) { + if (s == NULL) + lua_pushnil(L); + else + lua_pushlstring(L, s, strlen(s)); +} + + +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, + va_list argp) { + const char *ret; + lua_lock(L); + luaC_checkGC(L); + ret = luaO_pushvfstring(L, fmt, argp); + lua_unlock(L); + return ret; +} + + +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { + const char *ret; + va_list argp; + lua_lock(L); + luaC_checkGC(L); + va_start(argp, fmt); + ret = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + lua_unlock(L); + return ret; +} + + +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { + Closure *cl; + lua_lock(L); + luaC_checkGC(L); + api_checknelems(L, n); + cl = luaF_newCclosure(L, n, getcurrenv(L)); + cl->c.f = fn; + L->top -= n; + while (n--) + setobj2n(L, &cl->c.upvalue[n], L->top+n); + setclvalue(L, L->top, cl); + lua_assert(iswhite(obj2gco(cl))); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushboolean (lua_State *L, int b) { + lua_lock(L); + setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { + lua_lock(L); + setpvalue(L->top, p); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_pushthread (lua_State *L) { + lua_lock(L); + setthvalue(L, L->top, L); + api_incr_top(L); + lua_unlock(L); + return (G(L)->mainthread == L); +} + + + +/* +** get functions (Lua -> stack) +*/ + + +LUA_API void lua_gettable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + luaV_gettable(L, t, L->top - 1, L->top - 1); + lua_unlock(L); +} + + +LUA_API void lua_getfield (lua_State *L, int idx, const char *k) { + StkId t; + TValue key; + lua_lock(L); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + setsvalue(L, &key, luaS_new(L, k)); + luaV_gettable(L, t, &key, L->top); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_rawget (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2adr(L, idx); + api_check(L, ttistable(t)); + setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); + lua_unlock(L); +} + + +LUA_API void lua_rawgeti (lua_State *L, int idx, int n) { + StkId o; + lua_lock(L); + o = index2adr(L, idx); + api_check(L, ttistable(o)); + setobj2s(L, L->top, luaH_getnum(hvalue(o), n)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { + lua_lock(L); + luaC_checkGC(L); + sethvalue(L, L->top, luaH_new(L, narray, nrec)); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_getmetatable (lua_State *L, int objindex) { + const TValue *obj; + Table *mt = NULL; + int res; + lua_lock(L); + obj = index2adr(L, objindex); + switch (ttype(obj)) { + case LUA_TTABLE: + mt = hvalue(obj)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(obj)->metatable; + break; + default: + mt = G(L)->mt[ttype(obj)]; + break; + } + if (mt == NULL) + res = 0; + else { + sethvalue(L, L->top, mt); + api_incr_top(L); + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API void lua_getfenv (lua_State *L, int idx) { + StkId o; + lua_lock(L); + o = index2adr(L, idx); + api_checkvalidindex(L, o); + switch (ttype(o)) { + case LUA_TFUNCTION: + sethvalue(L, L->top, clvalue(o)->c.env); + break; + case LUA_TUSERDATA: + sethvalue(L, L->top, uvalue(o)->env); + break; + case LUA_TTHREAD: + setobj2s(L, L->top, gt(thvalue(o))); + break; + default: + setnilvalue(L->top); + break; + } + api_incr_top(L); + lua_unlock(L); +} + + +/* +** set functions (stack -> Lua) +*/ + + +LUA_API void lua_settable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + luaV_settable(L, t, L->top - 2, L->top - 1); + L->top -= 2; /* pop index and value */ + lua_unlock(L); +} + + +LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { + StkId t; + TValue key; + lua_lock(L); + api_checknelems(L, 1); + t = index2adr(L, idx); + api_checkvalidindex(L, t); + setsvalue(L, &key, luaS_new(L, k)); + luaV_settable(L, t, &key, L->top - 1); + L->top--; /* pop value */ + lua_unlock(L); +} + + +LUA_API void lua_rawset (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2adr(L, idx); + api_check(L, ttistable(t)); + setobj2t(L, luaH_set(L, hvalue(t), L->top-2), L->top-1); + luaC_barriert(L, hvalue(t), L->top-1); + L->top -= 2; + lua_unlock(L); +} + + +LUA_API void lua_rawseti (lua_State *L, int idx, int n) { + StkId o; + lua_lock(L); + api_checknelems(L, 1); + o = index2adr(L, idx); + api_check(L, ttistable(o)); + setobj2t(L, luaH_setnum(L, hvalue(o), n), L->top-1); + luaC_barriert(L, hvalue(o), L->top-1); + L->top--; + lua_unlock(L); +} + + +LUA_API int lua_setmetatable (lua_State *L, int objindex) { + TValue *obj; + Table *mt; + lua_lock(L); + api_checknelems(L, 1); + obj = index2adr(L, objindex); + api_checkvalidindex(L, obj); + if (ttisnil(L->top - 1)) + mt = NULL; + else { + api_check(L, ttistable(L->top - 1)); + mt = hvalue(L->top - 1); + } + switch (ttype(obj)) { + case LUA_TTABLE: { + hvalue(obj)->metatable = mt; + if (mt) + luaC_objbarriert(L, hvalue(obj), mt); + break; + } + case LUA_TUSERDATA: { + uvalue(obj)->metatable = mt; + if (mt) + luaC_objbarrier(L, rawuvalue(obj), mt); + break; + } + default: { + G(L)->mt[ttype(obj)] = mt; + break; + } + } + L->top--; + lua_unlock(L); + return 1; +} + + +LUA_API int lua_setfenv (lua_State *L, int idx) { + StkId o; + int res = 1; + lua_lock(L); + api_checknelems(L, 1); + o = index2adr(L, idx); + api_checkvalidindex(L, o); + api_check(L, ttistable(L->top - 1)); + switch (ttype(o)) { + case LUA_TFUNCTION: + clvalue(o)->c.env = hvalue(L->top - 1); + break; + case LUA_TUSERDATA: + uvalue(o)->env = hvalue(L->top - 1); + break; + case LUA_TTHREAD: + sethvalue(L, gt(thvalue(o)), hvalue(L->top - 1)); + break; + default: + res = 0; + break; + } + if (res) luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); + L->top--; + lua_unlock(L); + return res; +} + + +/* +** `load' and `call' functions (run Lua code) +*/ + + +#define adjustresults(L,nres) \ + { if (nres == LUA_MULTRET && L->top >= L->ci->top) L->ci->top = L->top; } + + +#define checkresults(L,na,nr) \ + api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na))) + + +LUA_API void lua_call (lua_State *L, int nargs, int nresults) { + StkId func; + lua_lock(L); + api_checknelems(L, nargs+1); + checkresults(L, nargs, nresults); + func = L->top - (nargs+1); + luaD_call(L, func, nresults); + adjustresults(L, nresults); + lua_unlock(L); +} + + + +/* +** Execute a protected call. +*/ +struct CallS { /* data to `f_call' */ + StkId func; + int nresults; +}; + + +static void f_call (lua_State *L, void *ud) { + struct CallS *c = cast(struct CallS *, ud); + luaD_call(L, c->func, c->nresults); +} + + + +LUA_API int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc) { + struct CallS c; + int status; + ptrdiff_t func; + lua_lock(L); + api_checknelems(L, nargs+1); + checkresults(L, nargs, nresults); + if (errfunc == 0) + func = 0; + else { + StkId o = index2adr(L, errfunc); + api_checkvalidindex(L, o); + func = savestack(L, o); + } + c.func = L->top - (nargs+1); /* function to be called */ + c.nresults = nresults; + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + adjustresults(L, nresults); + lua_unlock(L); + return status; +} + + +/* +** Execute a protected C call. +*/ +struct CCallS { /* data to `f_Ccall' */ + lua_CFunction func; + void *ud; +}; + + +static void f_Ccall (lua_State *L, void *ud) { + struct CCallS *c = cast(struct CCallS *, ud); + Closure *cl; + cl = luaF_newCclosure(L, 0, getcurrenv(L)); + cl->c.f = c->func; + setclvalue(L, L->top, cl); /* push function */ + api_incr_top(L); + setpvalue(L->top, c->ud); /* push only argument */ + api_incr_top(L); + luaD_call(L, L->top - 2, 0); +} + + +LUA_API int lua_cpcall (lua_State *L, lua_CFunction func, void *ud) { + struct CCallS c; + int status; + lua_lock(L); + c.func = func; + c.ud = ud; + status = luaD_pcall(L, f_Ccall, &c, savestack(L, L->top), 0); + lua_unlock(L); + return status; +} + + +LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, + const char *chunkname) { + ZIO z; + int status; + lua_lock(L); + if (!chunkname) chunkname = "?"; + luaZ_init(L, &z, reader, data); + status = luaD_protectedparser(L, &z, chunkname); + lua_unlock(L); + return status; +} + + +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data) { + int status; + TValue *o; + lua_lock(L); + api_checknelems(L, 1); + o = L->top - 1; + if (isLfunction(o)) + status = luaU_dump(L, clvalue(o)->l.p, writer, data, 0); + else + status = 1; + lua_unlock(L); + return status; +} + + +LUA_API int lua_status (lua_State *L) { + return L->status; +} + + +/* +** Garbage-collection function +*/ + +LUA_API int lua_gc (lua_State *L, int what, int data) { + int res = 0; + global_State *g; + lua_lock(L); + g = G(L); + switch (what) { + case LUA_GCSTOP: { + g->GCthreshold = MAX_LUMEM; + break; + } + case LUA_GCRESTART: { + g->GCthreshold = g->totalbytes; + break; + } + case LUA_GCCOLLECT: { + luaC_fullgc(L); + break; + } + case LUA_GCCOUNT: { + /* GC values are expressed in Kbytes: #bytes/2^10 */ + res = cast_int(g->totalbytes >> 10); + break; + } + case LUA_GCCOUNTB: { + res = cast_int(g->totalbytes & 0x3ff); + break; + } + case LUA_GCSTEP: { + lu_mem a = (cast(lu_mem, data) << 10); + if (a <= g->totalbytes) + g->GCthreshold = g->totalbytes - a; + else + g->GCthreshold = 0; + while (g->GCthreshold <= g->totalbytes) { + luaC_step(L); + if (g->gcstate == GCSpause) { /* end of cycle? */ + res = 1; /* signal it */ + break; + } + } + break; + } + case LUA_GCSETPAUSE: { + res = g->gcpause; + g->gcpause = data; + break; + } + case LUA_GCSETSTEPMUL: { + res = g->gcstepmul; + g->gcstepmul = data; + break; + } + default: res = -1; /* invalid option */ + } + lua_unlock(L); + return res; +} + + + +/* +** miscellaneous functions +*/ + + +LUA_API int lua_error (lua_State *L) { + lua_lock(L); + api_checknelems(L, 1); + luaG_errormsg(L); + lua_unlock(L); + return 0; /* to avoid warnings */ +} + + +LUA_API int lua_next (lua_State *L, int idx) { + StkId t; + int more; + lua_lock(L); + t = index2adr(L, idx); + api_check(L, ttistable(t)); + more = luaH_next(L, hvalue(t), L->top - 1); + if (more) { + api_incr_top(L); + } + else /* no more elements */ + L->top -= 1; /* remove key */ + lua_unlock(L); + return more; +} + + +LUA_API void lua_concat (lua_State *L, int n) { + lua_lock(L); + api_checknelems(L, n); + if (n >= 2) { + luaC_checkGC(L); + luaV_concat(L, n, cast_int(L->top - L->base) - 1); + L->top -= (n-1); + } + else if (n == 0) { /* push empty string */ + setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); + api_incr_top(L); + } + /* else n == 1; nothing to do */ + lua_unlock(L); +} + + +LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { + lua_Alloc f; + lua_lock(L); + if (ud) *ud = G(L)->ud; + f = G(L)->frealloc; + lua_unlock(L); + return f; +} + + +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { + lua_lock(L); + G(L)->ud = ud; + G(L)->frealloc = f; + lua_unlock(L); +} + + +LUA_API void *lua_newuserdata (lua_State *L, size_t size) { + Udata *u; + lua_lock(L); + luaC_checkGC(L); + u = luaS_newudata(L, size, getcurrenv(L)); + setuvalue(L, L->top, u); + api_incr_top(L); + lua_unlock(L); + return u + 1; +} + + + + +static const char *aux_upvalue (StkId fi, int n, TValue **val) { + Closure *f; + if (!ttisfunction(fi)) return NULL; + f = clvalue(fi); + if (f->c.isC) { + if (!(1 <= n && n <= f->c.nupvalues)) return NULL; + *val = &f->c.upvalue[n-1]; + return ""; + } + else { + Proto *p = f->l.p; + if (!(1 <= n && n <= p->sizeupvalues)) return NULL; + *val = f->l.upvals[n-1]->v; + return getstr(p->upvalues[n-1]); + } +} + + +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val; + lua_lock(L); + name = aux_upvalue(index2adr(L, funcindex), n, &val); + if (name) { + setobj2s(L, L->top, val); + api_incr_top(L); + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val; + StkId fi; + lua_lock(L); + fi = index2adr(L, funcindex); + api_checknelems(L, 1); + name = aux_upvalue(fi, n, &val); + if (name) { + L->top--; + setobj(L, val, L->top); + luaC_barrier(L, clvalue(fi), L->top); + } + lua_unlock(L); + return name; +} + diff --git a/src/lua/src/lapi.h b/src/lua/src/lapi.h new file mode 100644 index 00000000..2c3fab24 --- /dev/null +++ b/src/lua/src/lapi.h @@ -0,0 +1,16 @@ +/* +** $Id: lapi.h,v 2.2.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions from Lua API +** See Copyright Notice in lua.h +*/ + +#ifndef lapi_h +#define lapi_h + + +#include "lobject.h" + + +LUAI_FUNC void luaA_pushobject (lua_State *L, const TValue *o); + +#endif diff --git a/src/lua/src/lauxlib.c b/src/lua/src/lauxlib.c new file mode 100644 index 00000000..10f14e2c --- /dev/null +++ b/src/lua/src/lauxlib.c @@ -0,0 +1,652 @@ +/* +** $Id: lauxlib.c,v 1.159.1.3 2008/01/21 13:20:51 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include +#include + + +/* This file uses only the official API of Lua. +** Any function declared here could be written as an application function. +*/ + +#define lauxlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" + + +#define FREELIST_REF 0 /* free list of references */ + + +/* convert a stack index to positive */ +#define abs_index(L, i) ((i) > 0 || (i) <= LUA_REGISTRYINDEX ? (i) : \ + lua_gettop(L) + (i) + 1) + + +/* +** {====================================================== +** Error-report functions +** ======================================================= +*/ + + +LUALIB_API int luaL_argerror (lua_State *L, int narg, const char *extramsg) { + lua_Debug ar; + if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ + return luaL_error(L, "bad argument #%d (%s)", narg, extramsg); + lua_getinfo(L, "n", &ar); + if (strcmp(ar.namewhat, "method") == 0) { + narg--; /* do not count `self' */ + if (narg == 0) /* error is in the self argument itself? */ + return luaL_error(L, "calling " LUA_QS " on bad self (%s)", + ar.name, extramsg); + } + if (ar.name == NULL) + ar.name = "?"; + return luaL_error(L, "bad argument #%d to " LUA_QS " (%s)", + narg, ar.name, extramsg); +} + + +LUALIB_API int luaL_typerror (lua_State *L, int narg, const char *tname) { + const char *msg = lua_pushfstring(L, "%s expected, got %s", + tname, luaL_typename(L, narg)); + return luaL_argerror(L, narg, msg); +} + + +static void tag_error (lua_State *L, int narg, int tag) { + luaL_typerror(L, narg, lua_typename(L, tag)); +} + + +LUALIB_API void luaL_where (lua_State *L, int level) { + lua_Debug ar; + if (lua_getstack(L, level, &ar)) { /* check function at level */ + lua_getinfo(L, "Sl", &ar); /* get info about it */ + if (ar.currentline > 0) { /* is there info? */ + lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); + return; + } + } + lua_pushliteral(L, ""); /* else, no information available... */ +} + + +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); +} + +/* }====================================================== */ + + +LUALIB_API int luaL_checkoption (lua_State *L, int narg, const char *def, + const char *const lst[]) { + const char *name = (def) ? luaL_optstring(L, narg, def) : + luaL_checkstring(L, narg); + int i; + for (i=0; lst[i]; i++) + if (strcmp(lst[i], name) == 0) + return i; + return luaL_argerror(L, narg, + lua_pushfstring(L, "invalid option " LUA_QS, name)); +} + + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get registry.name */ + if (!lua_isnil(L, -1)) /* name already in use? */ + return 0; /* leave previous value on top, but return 0 */ + lua_pop(L, 1); + lua_newtable(L); /* create metatable */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ + return 1; +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + void *p = lua_touserdata(L, ud); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ + lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + } + luaL_typerror(L, ud, tname); /* else error */ + return NULL; /* to avoid warnings */ +} + + +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *mes) { + if (!lua_checkstack(L, space)) + luaL_error(L, "stack overflow (%s)", mes); +} + + +LUALIB_API void luaL_checktype (lua_State *L, int narg, int t) { + if (lua_type(L, narg) != t) + tag_error(L, narg, t); +} + + +LUALIB_API void luaL_checkany (lua_State *L, int narg) { + if (lua_type(L, narg) == LUA_TNONE) + luaL_argerror(L, narg, "value expected"); +} + + +LUALIB_API const char *luaL_checklstring (lua_State *L, int narg, size_t *len) { + const char *s = lua_tolstring(L, narg, len); + if (!s) tag_error(L, narg, LUA_TSTRING); + return s; +} + + +LUALIB_API const char *luaL_optlstring (lua_State *L, int narg, + const char *def, size_t *len) { + if (lua_isnoneornil(L, narg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_checklstring(L, narg, len); +} + + +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int narg) { + lua_Number d = lua_tonumber(L, narg); + if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number def) { + return luaL_opt(L, luaL_checknumber, narg, def); +} + + +LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int narg) { + lua_Integer d = lua_tointeger(L, narg); + if (d == 0 && !lua_isnumber(L, narg)) /* avoid extra test when d is not 0 */ + tag_error(L, narg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int narg, + lua_Integer def) { + return luaL_opt(L, luaL_checkinteger, narg, def); +} + + +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return 0; + lua_pushstring(L, event); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { + lua_pop(L, 2); /* remove metatable and metafield */ + return 0; + } + else { + lua_remove(L, -2); /* remove only metatable */ + return 1; + } +} + + +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + obj = abs_index(L, obj); + if (!luaL_getmetafield(L, obj, event)) /* no metafield? */ + return 0; + lua_pushvalue(L, obj); + lua_call(L, 1, 1); + return 1; +} + + +LUALIB_API void (luaL_register) (lua_State *L, const char *libname, + const luaL_Reg *l) { + luaI_openlib(L, libname, l, 0); +} + + +static int libsize (const luaL_Reg *l) { + int size = 0; + for (; l->name; l++) size++; + return size; +} + + +LUALIB_API void luaI_openlib (lua_State *L, const char *libname, + const luaL_Reg *l, int nup) { + if (libname) { + int size = libsize(l); + /* check whether lib already exists */ + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 1); + lua_getfield(L, -1, libname); /* get _LOADED[libname] */ + if (!lua_istable(L, -1)) { /* not found? */ + lua_pop(L, 1); /* remove previous result */ + /* try global variable (and create one if it does not exist) */ + if (luaL_findtable(L, LUA_GLOBALSINDEX, libname, size) != NULL) + luaL_error(L, "name conflict for module " LUA_QS, libname); + lua_pushvalue(L, -1); + lua_setfield(L, -3, libname); /* _LOADED[libname] = new table */ + } + lua_remove(L, -2); /* remove _LOADED table */ + lua_insert(L, -(nup+1)); /* move library table to below upvalues */ + } + for (; l->name; l++) { + int i; + for (i=0; ifunc, nup); + lua_setfield(L, -(nup+2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + + + +/* +** {====================================================== +** getn-setn: size for arrays +** ======================================================= +*/ + +#if defined(LUA_COMPAT_GETN) + +static int checkint (lua_State *L, int topop) { + int n = (lua_type(L, -1) == LUA_TNUMBER) ? lua_tointeger(L, -1) : -1; + lua_pop(L, topop); + return n; +} + + +static void getsizes (lua_State *L) { + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); + if (lua_isnil(L, -1)) { /* no `size' table? */ + lua_pop(L, 1); /* remove nil */ + lua_newtable(L); /* create it */ + lua_pushvalue(L, -1); /* `size' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "kv"); + lua_setfield(L, -2, "__mode"); /* metatable(N).__mode = "kv" */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, "LUA_SIZES"); /* store in register */ + } +} + + +LUALIB_API void luaL_setn (lua_State *L, int t, int n) { + t = abs_index(L, t); + lua_pushliteral(L, "n"); + lua_rawget(L, t); + if (checkint(L, 1) >= 0) { /* is there a numeric field `n'? */ + lua_pushliteral(L, "n"); /* use it */ + lua_pushinteger(L, n); + lua_rawset(L, t); + } + else { /* use `sizes' */ + getsizes(L); + lua_pushvalue(L, t); + lua_pushinteger(L, n); + lua_rawset(L, -3); /* sizes[t] = n */ + lua_pop(L, 1); /* remove `sizes' */ + } +} + + +LUALIB_API int luaL_getn (lua_State *L, int t) { + int n; + t = abs_index(L, t); + lua_pushliteral(L, "n"); /* try t.n */ + lua_rawget(L, t); + if ((n = checkint(L, 1)) >= 0) return n; + getsizes(L); /* else try sizes[t] */ + lua_pushvalue(L, t); + lua_rawget(L, -2); + if ((n = checkint(L, 2)) >= 0) return n; + return (int)lua_objlen(L, t); +} + +#endif + +/* }====================================================== */ + + + +LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, + const char *r) { + const char *wild; + size_t l = strlen(p); + luaL_Buffer b; + luaL_buffinit(L, &b); + while ((wild = strstr(s, p)) != NULL) { + luaL_addlstring(&b, s, wild - s); /* push prefix */ + luaL_addstring(&b, r); /* push replacement in place of pattern */ + s = wild + l; /* continue after `p' */ + } + luaL_addstring(&b, s); /* push last suffix */ + luaL_pushresult(&b); + return lua_tostring(L, -1); +} + + +LUALIB_API const char *luaL_findtable (lua_State *L, int idx, + const char *fname, int szhint) { + const char *e; + lua_pushvalue(L, idx); + do { + e = strchr(fname, '.'); + if (e == NULL) e = fname + strlen(fname); + lua_pushlstring(L, fname, e - fname); + lua_rawget(L, -2); + if (lua_isnil(L, -1)) { /* no such field? */ + lua_pop(L, 1); /* remove this nil */ + lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ + lua_pushlstring(L, fname, e - fname); + lua_pushvalue(L, -2); + lua_settable(L, -4); /* set new table into field */ + } + else if (!lua_istable(L, -1)) { /* field has a non-table value? */ + lua_pop(L, 2); /* remove table and value */ + return fname; /* return problematic part of the name */ + } + lua_remove(L, -2); /* remove previous table */ + fname = e + 1; + } while (*e == '.'); + return NULL; +} + + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + +#define bufflen(B) ((B)->p - (B)->buffer) +#define bufffree(B) ((size_t)(LUAL_BUFFERSIZE - bufflen(B))) + +#define LIMIT (LUA_MINSTACK/2) + + +static int emptybuffer (luaL_Buffer *B) { + size_t l = bufflen(B); + if (l == 0) return 0; /* put nothing on stack */ + else { + lua_pushlstring(B->L, B->buffer, l); + B->p = B->buffer; + B->lvl++; + return 1; + } +} + + +static void adjuststack (luaL_Buffer *B) { + if (B->lvl > 1) { + lua_State *L = B->L; + int toget = 1; /* number of levels to concat */ + size_t toplen = lua_strlen(L, -1); + do { + size_t l = lua_strlen(L, -(toget+1)); + if (B->lvl - toget + 1 >= LIMIT || toplen > l) { + toplen += l; + toget++; + } + else break; + } while (toget < B->lvl); + lua_concat(L, toget); + B->lvl = B->lvl - toget + 1; + } +} + + +LUALIB_API char *luaL_prepbuffer (luaL_Buffer *B) { + if (emptybuffer(B)) + adjuststack(B); + return B->buffer; +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + while (l--) + luaL_addchar(B, *s++); +} + + +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { + luaL_addlstring(B, s, strlen(s)); +} + + +LUALIB_API void luaL_pushresult (luaL_Buffer *B) { + emptybuffer(B); + lua_concat(B->L, B->lvl); + B->lvl = 1; +} + + +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t vl; + const char *s = lua_tolstring(L, -1, &vl); + if (vl <= bufffree(B)) { /* fit into buffer? */ + memcpy(B->p, s, vl); /* put it there */ + B->p += vl; + lua_pop(L, 1); /* remove from stack */ + } + else { + if (emptybuffer(B)) + lua_insert(L, -2); /* put buffer before new value */ + B->lvl++; /* add new value into B stack */ + adjuststack(B); + } +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->p = B->buffer; + B->lvl = 0; +} + +/* }====================================================== */ + + +LUALIB_API int luaL_ref (lua_State *L, int t) { + int ref; + t = abs_index(L, t); + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* remove from stack */ + return LUA_REFNIL; /* `nil' has a unique fixed reference */ + } + lua_rawgeti(L, t, FREELIST_REF); /* get first free element */ + ref = (int)lua_tointeger(L, -1); /* ref = t[FREELIST_REF] */ + lua_pop(L, 1); /* remove it from stack */ + if (ref != 0) { /* any free element? */ + lua_rawgeti(L, t, ref); /* remove it from list */ + lua_rawseti(L, t, FREELIST_REF); /* (t[FREELIST_REF] = t[ref]) */ + } + else { /* no free elements */ + ref = (int)lua_objlen(L, t); + ref++; /* create new reference */ + } + lua_rawseti(L, t, ref); + return ref; +} + + +LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { + if (ref >= 0) { + t = abs_index(L, t); + lua_rawgeti(L, t, FREELIST_REF); + lua_rawseti(L, t, ref); /* t[ref] = t[FREELIST_REF] */ + lua_pushinteger(L, ref); + lua_rawseti(L, t, FREELIST_REF); /* t[FREELIST_REF] = ref */ + } +} + + + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + int extraline; + FILE *f; + char buff[LUAL_BUFFERSIZE]; +} LoadF; + + +static const char *getF (lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; + if (lf->extraline) { + lf->extraline = 0; + *size = 1; + return "\n"; + } + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); + return (*size > 0) ? lf->buff : NULL; +} + + +static int errfile (lua_State *L, const char *what, int fnameindex) { + const char *serr = strerror(errno); + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + + +LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) { + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + lf.extraline = 0; + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); + lf.f = fopen(filename, "r"); + if (lf.f == NULL) return errfile(L, "open", fnameindex); + } + c = getc(lf.f); + if (c == '#') { /* Unix exec. file? */ + lf.extraline = 1; + while ((c = getc(lf.f)) != EOF && c != '\n') ; /* skip first line */ + if (c == '\n') c = getc(lf.f); + } + if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + /* skip eventual `#!...' */ + while ((c = getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ; + lf.extraline = 0; + } + ungetc(c, lf.f); + status = lua_load(L, getF, &lf, lua_tostring(L, -1)); + readstatus = ferror(lf.f); + if (filename) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from `lua_load' */ + return errfile(L, "read", fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + + +typedef struct LoadS { + const char *s; + size_t size; +} LoadS; + + +static const char *getS (lua_State *L, void *ud, size_t *size) { + LoadS *ls = (LoadS *)ud; + (void)L; + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbuffer (lua_State *L, const char *buff, size_t size, + const char *name) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name); +} + + +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s) { + return luaL_loadbuffer(L, s, strlen(s), s); +} + + + +/* }====================================================== */ + + +static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { + (void)ud; + (void)osize; + if (nsize == 0) { + free(ptr); + return NULL; + } + else + return realloc(ptr, nsize); +} + + +static int panic (lua_State *L) { + (void)L; /* to avoid warnings */ + fprintf(stderr, "PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; +} + + +LUALIB_API lua_State *luaL_newstate (void) { + lua_State *L = lua_newstate(l_alloc, NULL); + if (L) lua_atpanic(L, &panic); + return L; +} + diff --git a/src/lua/src/lauxlib.h b/src/lua/src/lauxlib.h new file mode 100644 index 00000000..34258235 --- /dev/null +++ b/src/lua/src/lauxlib.h @@ -0,0 +1,174 @@ +/* +** $Id: lauxlib.h,v 1.88.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + +#if defined(LUA_COMPAT_GETN) +LUALIB_API int (luaL_getn) (lua_State *L, int t); +LUALIB_API void (luaL_setn) (lua_State *L, int t, int n); +#else +#define luaL_getn(L,i) ((int)lua_objlen(L, i)) +#define luaL_setn(L,i,j) ((void)0) /* no op! */ +#endif + +#if defined(LUA_COMPAT_OPENLIB) +#define luaI_openlib luaL_openlib +#endif + + +/* extra error code for `luaL_load' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + + +LUALIB_API void (luaI_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); +LUALIB_API void (luaL_register) (lua_State *L, const char *libname, + const luaL_Reg *l); +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_typerror) (lua_State *L, int narg, const char *tname); +LUALIB_API int (luaL_argerror) (lua_State *L, int numarg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int numArg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int numArg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int numArg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int nArg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int numArg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int nArg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int narg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int narg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int narg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfile) (lua_State *L, const char *filename); +LUALIB_API int (luaL_loadbuffer) (lua_State *L, const char *buff, size_t sz, + const char *name); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API const char *(luaL_findtable) (lua_State *L, int idx, + const char *fname, int szhint); + + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define luaL_argcheck(L, cond,numarg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + + + +typedef struct luaL_Buffer { + char *p; /* current position in buffer */ + int lvl; /* number of strings in the stack (level) */ + lua_State *L; + char buffer[LUAL_BUFFERSIZE]; +} luaL_Buffer; + +#define luaL_addchar(B,c) \ + ((void)((B)->p < ((B)->buffer+LUAL_BUFFERSIZE) || luaL_prepbuffer(B)), \ + (*(B)->p++ = (char)(c))) + +/* compatibility only */ +#define luaL_putchar(B,c) luaL_addchar(B,c) + +#define luaL_addsize(B,n) ((B)->p += (n)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffer) (luaL_Buffer *B); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); + + +/* }====================================================== */ + + +/* compatibility with ref system */ + +/* pre-defined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +#define lua_ref(L,lock) ((lock) ? luaL_ref(L, LUA_REGISTRYINDEX) : \ + (lua_pushstring(L, "unlocked references are obsolete"), lua_error(L), 0)) + +#define lua_unref(L,ref) luaL_unref(L, LUA_REGISTRYINDEX, (ref)) + +#define lua_getref(L,ref) lua_rawgeti(L, LUA_REGISTRYINDEX, (ref)) + + +#define luaL_reg luaL_Reg + +#endif + + diff --git a/src/lua/src/lbaselib.c b/src/lua/src/lbaselib.c new file mode 100644 index 00000000..2a4c079d --- /dev/null +++ b/src/lua/src/lbaselib.c @@ -0,0 +1,653 @@ +/* +** $Id: lbaselib.c,v 1.191.1.6 2008/02/14 16:46:22 roberto Exp $ +** Basic library +** See Copyright Notice in lua.h +*/ + + + +#include +#include +#include +#include + +#define lbaselib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + + +/* +** If your system does not support `stdout', you can just remove this function. +** If you need, you can define your own `print' function, following this +** model but changing `fputs' to put the strings at a proper place +** (a console window or a log file, for instance). +*/ +static int luaB_print (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + lua_getglobal(L, "tostring"); + for (i=1; i<=n; i++) { + const char *s; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + s = lua_tostring(L, -1); /* get result */ + if (s == NULL) + return luaL_error(L, LUA_QL("tostring") " must return a string to " + LUA_QL("print")); + if (i>1) fputs("\t", stdout); + fputs(s, stdout); + lua_pop(L, 1); /* pop result */ + } + fputs("\n", stdout); + return 0; +} + + +static int luaB_tonumber (lua_State *L) { + int base = luaL_optint(L, 2, 10); + if (base == 10) { /* standard conversion */ + luaL_checkany(L, 1); + if (lua_isnumber(L, 1)) { + lua_pushnumber(L, lua_tonumber(L, 1)); + return 1; + } + } + else { + const char *s1 = luaL_checkstring(L, 1); + char *s2; + unsigned long n; + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + n = strtoul(s1, &s2, base); + if (s1 != s2) { /* at least one valid digit? */ + while (isspace((unsigned char)(*s2))) s2++; /* skip trailing spaces */ + if (*s2 == '\0') { /* no invalid trailing characters? */ + lua_pushnumber(L, (lua_Number)n); + return 1; + } + } + } + lua_pushnil(L); /* else not a number */ + return 1; +} + + +static int luaB_error (lua_State *L) { + int level = luaL_optint(L, 2, 1); + lua_settop(L, 1); + if (lua_isstring(L, 1) && level > 0) { /* add extra information? */ + luaL_where(L, level); + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); +} + + +static int luaB_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); + return 1; /* no metatable */ + } + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ +} + + +static int luaB_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + if (luaL_getmetafield(L, 1, "__metatable")) + luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; +} + + +static void getfunc (lua_State *L, int opt) { + if (lua_isfunction(L, 1)) lua_pushvalue(L, 1); + else { + lua_Debug ar; + int level = opt ? luaL_optint(L, 1, 1) : luaL_checkint(L, 1); + luaL_argcheck(L, level >= 0, 1, "level must be non-negative"); + if (lua_getstack(L, level, &ar) == 0) + luaL_argerror(L, 1, "invalid level"); + lua_getinfo(L, "f", &ar); + if (lua_isnil(L, -1)) + luaL_error(L, "no function environment for tail call at level %d", + level); + } +} + + +static int luaB_getfenv (lua_State *L) { + getfunc(L, 1); + if (lua_iscfunction(L, -1)) /* is a C function? */ + lua_pushvalue(L, LUA_GLOBALSINDEX); /* return the thread's global env. */ + else + lua_getfenv(L, -1); + return 1; +} + + +static int luaB_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + getfunc(L, 0); + lua_pushvalue(L, 2); + if (lua_isnumber(L, 1) && lua_tonumber(L, 1) == 0) { + /* change environment of current thread */ + lua_pushthread(L); + lua_insert(L, -2); + lua_setfenv(L, -2); + return 0; + } + else if (lua_iscfunction(L, -2) || lua_setfenv(L, -2) == 0) + luaL_error(L, + LUA_QL("setfenv") " cannot change environment of given object"); + return 1; +} + + +static int luaB_rawequal (lua_State *L) { + luaL_checkany(L, 1); + luaL_checkany(L, 2); + lua_pushboolean(L, lua_rawequal(L, 1, 2)); + return 1; +} + + +static int luaB_rawget (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_rawget(L, 1); + return 1; +} + +static int luaB_rawset (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_settop(L, 3); + lua_rawset(L, 1); + return 1; +} + + +static int luaB_gcinfo (lua_State *L) { + lua_pushinteger(L, lua_getgccount(L)); + return 1; +} + + +static int luaB_collectgarbage (lua_State *L) { + static const char *const opts[] = {"stop", "restart", "collect", + "count", "step", "setpause", "setstepmul", NULL}; + static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL}; + int o = luaL_checkoption(L, 1, "collect", opts); + int ex = luaL_optint(L, 2, 0); + int res = lua_gc(L, optsnum[o], ex); + switch (optsnum[o]) { + case LUA_GCCOUNT: { + int b = lua_gc(L, LUA_GCCOUNTB, 0); + lua_pushnumber(L, res + ((lua_Number)b/1024)); + return 1; + } + case LUA_GCSTEP: { + lua_pushboolean(L, res); + return 1; + } + default: { + lua_pushnumber(L, res); + return 1; + } + } +} + + +static int luaB_type (lua_State *L) { + luaL_checkany(L, 1); + lua_pushstring(L, luaL_typename(L, 1)); + return 1; +} + + +static int luaB_next (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + + +static int luaB_pairs (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushnil(L); /* and initial value */ + return 3; +} + + +static int ipairsaux (lua_State *L) { + int i = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + i++; /* next value */ + lua_pushinteger(L, i); + lua_rawgeti(L, 1, i); + return (lua_isnil(L, -1)) ? 0 : 2; +} + + +static int luaB_ipairs (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushvalue(L, lua_upvalueindex(1)); /* return generator, */ + lua_pushvalue(L, 1); /* state, */ + lua_pushinteger(L, 0); /* and initial value */ + return 3; +} + + +static int load_aux (lua_State *L, int status) { + if (status == 0) /* OK? */ + return 1; + else { + lua_pushnil(L); + lua_insert(L, -2); /* put before error message */ + return 2; /* return nil plus error message */ + } +} + + +static int luaB_loadstring (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + const char *chunkname = luaL_optstring(L, 2, s); + return load_aux(L, luaL_loadbuffer(L, s, l, chunkname)); +} + + +static int luaB_loadfile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + return load_aux(L, luaL_loadfile(L, fname)); +} + + +/* +** Reader for generic `load' function: `lua_load' uses the +** stack for internal stuff, so the reader cannot change the +** stack top. Instead, it keeps its resulting string in a +** reserved slot inside the stack. +*/ +static const char *generic_reader (lua_State *L, void *ud, size_t *size) { + (void)ud; /* to avoid warnings */ + luaL_checkstack(L, 2, "too many nested functions"); + lua_pushvalue(L, 1); /* get function */ + lua_call(L, 0, 1); /* call it */ + if (lua_isnil(L, -1)) { + *size = 0; + return NULL; + } + else if (lua_isstring(L, -1)) { + lua_replace(L, 3); /* save string in a reserved stack slot */ + return lua_tolstring(L, 3, size); + } + else luaL_error(L, "reader function must return a string"); + return NULL; /* to avoid warnings */ +} + + +static int luaB_load (lua_State *L) { + int status; + const char *cname = luaL_optstring(L, 2, "=(load)"); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, 3); /* function, eventual name, plus one reserved slot */ + status = lua_load(L, generic_reader, NULL, cname); + return load_aux(L, status); +} + + +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + int n = lua_gettop(L); + if (luaL_loadfile(L, fname) != 0) lua_error(L); + lua_call(L, 0, LUA_MULTRET); + return lua_gettop(L) - n; +} + + +static int luaB_assert (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_toboolean(L, 1)) + return luaL_error(L, "%s", luaL_optstring(L, 2, "assertion failed!")); + return lua_gettop(L); +} + + +static int luaB_unpack (lua_State *L) { + int i, e, n; + luaL_checktype(L, 1, LUA_TTABLE); + i = luaL_optint(L, 2, 1); + e = luaL_opt(L, luaL_checkint, 3, luaL_getn(L, 1)); + if (i > e) return 0; /* empty range */ + n = e - i + 1; /* number of elements */ + if (n <= 0 || !lua_checkstack(L, n)) /* n <= 0 means arith. overflow */ + return luaL_error(L, "too many results to unpack"); + lua_rawgeti(L, 1, i); /* push arg[i] (avoiding overflow problems) */ + while (i++ < e) /* push arg[i + 1...e] */ + lua_rawgeti(L, 1, i); + return n; +} + + +static int luaB_select (lua_State *L) { + int n = lua_gettop(L); + if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { + lua_pushinteger(L, n-1); + return 1; + } + else { + int i = luaL_checkint(L, 1); + if (i < 0) i = n + i; + else if (i > n) i = n; + luaL_argcheck(L, 1 <= i, 1, "index out of range"); + return n - i; + } +} + + +static int luaB_pcall (lua_State *L) { + int status; + luaL_checkany(L, 1); + status = lua_pcall(L, lua_gettop(L) - 1, LUA_MULTRET, 0); + lua_pushboolean(L, (status == 0)); + lua_insert(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_xpcall (lua_State *L) { + int status; + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_insert(L, 1); /* put error function under function to be called */ + status = lua_pcall(L, 0, LUA_MULTRET, 1); + lua_pushboolean(L, (status == 0)); + lua_replace(L, 1); + return lua_gettop(L); /* return status + all results */ +} + + +static int luaB_tostring (lua_State *L) { + luaL_checkany(L, 1); + if (luaL_callmeta(L, 1, "__tostring")) /* is there a metafield? */ + return 1; /* use its value */ + switch (lua_type(L, 1)) { + case LUA_TNUMBER: + lua_pushstring(L, lua_tostring(L, 1)); + break; + case LUA_TSTRING: + lua_pushvalue(L, 1); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, 1) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: + lua_pushfstring(L, "%s: %p", luaL_typename(L, 1), lua_topointer(L, 1)); + break; + } + return 1; +} + + +static int luaB_newproxy (lua_State *L) { + lua_settop(L, 1); + lua_newuserdata(L, 0); /* create proxy */ + if (lua_toboolean(L, 1) == 0) + return 1; /* no metatable */ + else if (lua_isboolean(L, 1)) { + lua_newtable(L); /* create a new metatable `m' ... */ + lua_pushvalue(L, -1); /* ... and mark `m' as a valid metatable */ + lua_pushboolean(L, 1); + lua_rawset(L, lua_upvalueindex(1)); /* weaktable[m] = true */ + } + else { + int validproxy = 0; /* to check if weaktable[metatable(u)] == true */ + if (lua_getmetatable(L, 1)) { + lua_rawget(L, lua_upvalueindex(1)); + validproxy = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + } + luaL_argcheck(L, validproxy, 1, "boolean or proxy expected"); + lua_getmetatable(L, 1); /* metatable is valid; get it */ + } + lua_setmetatable(L, 2); + return 1; +} + + +static const luaL_Reg base_funcs[] = { + {"assert", luaB_assert}, + {"collectgarbage", luaB_collectgarbage}, + {"dofile", luaB_dofile}, + {"error", luaB_error}, + {"gcinfo", luaB_gcinfo}, + {"getfenv", luaB_getfenv}, + {"getmetatable", luaB_getmetatable}, + {"loadfile", luaB_loadfile}, + {"load", luaB_load}, + {"loadstring", luaB_loadstring}, + {"next", luaB_next}, + {"pcall", luaB_pcall}, + {"print", luaB_print}, + {"rawequal", luaB_rawequal}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"select", luaB_select}, + {"setfenv", luaB_setfenv}, + {"setmetatable", luaB_setmetatable}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"unpack", luaB_unpack}, + {"xpcall", luaB_xpcall}, + {NULL, NULL} +}; + + +/* +** {====================================================== +** Coroutine library +** ======================================================= +*/ + +#define CO_RUN 0 /* running */ +#define CO_SUS 1 /* suspended */ +#define CO_NOR 2 /* 'normal' (it resumed another coroutine) */ +#define CO_DEAD 3 + +static const char *const statnames[] = + {"running", "suspended", "normal", "dead"}; + +static int costatus (lua_State *L, lua_State *co) { + if (L == co) return CO_RUN; + switch (lua_status(co)) { + case LUA_YIELD: + return CO_SUS; + case 0: { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ + return CO_NOR; /* it is running */ + else if (lua_gettop(co) == 0) + return CO_DEAD; + else + return CO_SUS; /* initial state */ + } + default: /* some error occured */ + return CO_DEAD; + } +} + + +static int luaB_costatus (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "coroutine expected"); + lua_pushstring(L, statnames[costatus(L, co)]); + return 1; +} + + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status = costatus(L, co); + if (!lua_checkstack(co, narg)) + luaL_error(L, "too many arguments to resume"); + if (status != CO_SUS) { + lua_pushfstring(L, "cannot resume %s coroutine", statnames[status]); + return -1; /* error flag */ + } + lua_xmove(L, co, narg); + lua_setlevel(L, co); + status = lua_resume(co, narg); + if (status == 0 || status == LUA_YIELD) { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres + 1)) + luaL_error(L, "too many results to resume"); + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } +} + + +static int luaB_coresume (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + int r; + luaL_argcheck(L, co, 1, "coroutine expected"); + r = auxresume(L, co, lua_gettop(L) - 1); + if (r < 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + `resume' returns */ + } +} + + +static int luaB_auxwrap (lua_State *L) { + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (r < 0) { + if (lua_isstring(L, -1)) { /* error object is a string? */ + luaL_where(L, 1); /* add extra info */ + lua_insert(L, -2); + lua_concat(L, 2); + } + lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL = lua_newthread(L); + luaL_argcheck(L, lua_isfunction(L, 1) && !lua_iscfunction(L, 1), 1, + "Lua function expected"); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; +} + + +static int luaB_cowrap (lua_State *L) { + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; +} + + +static int luaB_yield (lua_State *L) { + return lua_yield(L, lua_gettop(L)); +} + + +static int luaB_corunning (lua_State *L) { + if (lua_pushthread(L)) + lua_pushnil(L); /* main thread is not a coroutine */ + return 1; +} + + +static const luaL_Reg co_funcs[] = { + {"create", luaB_cocreate}, + {"resume", luaB_coresume}, + {"running", luaB_corunning}, + {"status", luaB_costatus}, + {"wrap", luaB_cowrap}, + {"yield", luaB_yield}, + {NULL, NULL} +}; + +/* }====================================================== */ + + +static void auxopen (lua_State *L, const char *name, + lua_CFunction f, lua_CFunction u) { + lua_pushcfunction(L, u); + lua_pushcclosure(L, f, 1); + lua_setfield(L, -2, name); +} + + +static void base_open (lua_State *L) { + /* set global _G */ + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_setglobal(L, "_G"); + /* open lib into global table */ + luaL_register(L, "_G", base_funcs); + lua_pushliteral(L, LUA_VERSION); + lua_setglobal(L, "_VERSION"); /* set global _VERSION */ + /* `ipairs' and `pairs' need auxliliary functions as upvalues */ + auxopen(L, "ipairs", luaB_ipairs, ipairsaux); + auxopen(L, "pairs", luaB_pairs, luaB_next); + /* `newproxy' needs a weaktable as upvalue */ + lua_createtable(L, 0, 1); /* new table `w' */ + lua_pushvalue(L, -1); /* `w' will be its own metatable */ + lua_setmetatable(L, -2); + lua_pushliteral(L, "kv"); + lua_setfield(L, -2, "__mode"); /* metatable(w).__mode = "kv" */ + lua_pushcclosure(L, luaB_newproxy, 1); + lua_setglobal(L, "newproxy"); /* set global `newproxy' */ +} + + +LUALIB_API int luaopen_base (lua_State *L) { + base_open(L); + luaL_register(L, LUA_COLIBNAME, co_funcs); + return 2; +} + diff --git a/src/lua/src/lcode.c b/src/lua/src/lcode.c new file mode 100644 index 00000000..cff626b7 --- /dev/null +++ b/src/lua/src/lcode.c @@ -0,0 +1,839 @@ +/* +** $Id: lcode.c,v 2.25.1.3 2007/12/28 15:32:23 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + + +#include + +#define lcode_c +#define LUA_CORE + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "ltable.h" + + +#define hasjumps(e) ((e)->t != (e)->f) + + +static int isnumeral(expdesc *e) { + return (e->k == VKNUM && e->t == NO_JUMP && e->f == NO_JUMP); +} + + +void luaK_nil (FuncState *fs, int from, int n) { + Instruction *previous; + if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ + if (fs->pc == 0) { /* function start? */ + if (from >= fs->nactvar) + return; /* positions are already clean */ + } + else { + previous = &fs->f->code[fs->pc-1]; + if (GET_OPCODE(*previous) == OP_LOADNIL) { + int pfrom = GETARG_A(*previous); + int pto = GETARG_B(*previous); + if (pfrom <= from && from <= pto+1) { /* can connect both? */ + if (from+n-1 > pto) + SETARG_B(*previous, from+n-1); + return; + } + } + } + } + luaK_codeABC(fs, OP_LOADNIL, from, from+n-1, 0); /* else no optimization */ +} + + +int luaK_jump (FuncState *fs) { + int jpc = fs->jpc; /* save list of jumps to here */ + int j; + fs->jpc = NO_JUMP; + j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); + luaK_concat(fs, &j, jpc); /* keep them on hold */ + return j; +} + + +void luaK_ret (FuncState *fs, int first, int nret) { + luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); +} + + +static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { + luaK_codeABC(fs, op, A, B, C); + return luaK_jump(fs); +} + + +static void fixjump (FuncState *fs, int pc, int dest) { + Instruction *jmp = &fs->f->code[pc]; + int offset = dest-(pc+1); + lua_assert(dest != NO_JUMP); + if (abs(offset) > MAXARG_sBx) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_sBx(*jmp, offset); +} + + +/* +** returns current `pc' and marks it as a jump target (to avoid wrong +** optimizations with consecutive instructions not in the same basic block). +*/ +int luaK_getlabel (FuncState *fs) { + fs->lasttarget = fs->pc; + return fs->pc; +} + + +static int getjump (FuncState *fs, int pc) { + int offset = GETARG_sBx(fs->f->code[pc]); + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc+1)+offset; /* turn offset into absolute position */ +} + + +static Instruction *getjumpcontrol (FuncState *fs, int pc) { + Instruction *pi = &fs->f->code[pc]; + if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) + return pi-1; + else + return pi; +} + + +/* +** check whether list has any jump that do not produce a value +** (or produce an inverted value) +*/ +static int need_value (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + Instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TESTSET) return 1; + } + return 0; /* not found */ +} + + +static int patchtestreg (FuncState *fs, int node, int reg) { + Instruction *i = getjumpcontrol(fs, node); + if (GET_OPCODE(*i) != OP_TESTSET) + return 0; /* cannot patch other instructions */ + if (reg != NO_REG && reg != GETARG_B(*i)) + SETARG_A(*i, reg); + else /* no register to put value or register already has the value */ + *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); + + return 1; +} + + +static void removevalues (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) + patchtestreg(fs, list, NO_REG); +} + + +static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, + int dtarget) { + while (list != NO_JUMP) { + int next = getjump(fs, list); + if (patchtestreg(fs, list, reg)) + fixjump(fs, list, vtarget); + else + fixjump(fs, list, dtarget); /* jump to default target */ + list = next; + } +} + + +static void dischargejpc (FuncState *fs) { + patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); + fs->jpc = NO_JUMP; +} + + +void luaK_patchlist (FuncState *fs, int list, int target) { + if (target == fs->pc) + luaK_patchtohere(fs, list); + else { + lua_assert(target < fs->pc); + patchlistaux(fs, list, target, NO_REG, target); + } +} + + +void luaK_patchtohere (FuncState *fs, int list) { + luaK_getlabel(fs); + luaK_concat(fs, &fs->jpc, list); +} + + +void luaK_concat (FuncState *fs, int *l1, int l2) { + if (l2 == NO_JUMP) return; + else if (*l1 == NO_JUMP) + *l1 = l2; + else { + int list = *l1; + int next; + while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + fixjump(fs, list, l2); + } +} + + +void luaK_checkstack (FuncState *fs, int n) { + int newstack = fs->freereg + n; + if (newstack > fs->f->maxstacksize) { + if (newstack >= MAXSTACK) + luaX_syntaxerror(fs->ls, "function or expression too complex"); + fs->f->maxstacksize = cast_byte(newstack); + } +} + + +void luaK_reserveregs (FuncState *fs, int n) { + luaK_checkstack(fs, n); + fs->freereg += n; +} + + +static void freereg (FuncState *fs, int reg) { + if (!ISK(reg) && reg >= fs->nactvar) { + fs->freereg--; + lua_assert(reg == fs->freereg); + } +} + + +static void freeexp (FuncState *fs, expdesc *e) { + if (e->k == VNONRELOC) + freereg(fs, e->u.s.info); +} + + +static int addk (FuncState *fs, TValue *k, TValue *v) { + lua_State *L = fs->L; + TValue *idx = luaH_set(L, fs->h, k); + Proto *f = fs->f; + int oldsize = f->sizek; + if (ttisnumber(idx)) { + lua_assert(luaO_rawequalObj(&fs->f->k[cast_int(nvalue(idx))], v)); + return cast_int(nvalue(idx)); + } + else { /* constant not found; create a new entry */ + setnvalue(idx, cast_num(fs->nk)); + luaM_growvector(L, f->k, fs->nk, f->sizek, TValue, + MAXARG_Bx, "constant table overflow"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[fs->nk], v); + luaC_barrier(L, f, v); + return fs->nk++; + } +} + + +int luaK_stringK (FuncState *fs, TString *s) { + TValue o; + setsvalue(fs->L, &o, s); + return addk(fs, &o, &o); +} + + +int luaK_numberK (FuncState *fs, lua_Number r) { + TValue o; + setnvalue(&o, r); + return addk(fs, &o, &o); +} + + +static int boolK (FuncState *fs, int b) { + TValue o; + setbvalue(&o, b); + return addk(fs, &o, &o); +} + + +static int nilK (FuncState *fs) { + TValue k, v; + setnilvalue(&v); + /* cannot use nil as key; instead use table itself to represent nil */ + sethvalue(fs->L, &k, fs->h); + return addk(fs, &k, &v); +} + + +void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { + if (e->k == VCALL) { /* expression is an open function call? */ + SETARG_C(getcode(fs, e), nresults+1); + } + else if (e->k == VVARARG) { + SETARG_B(getcode(fs, e), nresults+1); + SETARG_A(getcode(fs, e), fs->freereg); + luaK_reserveregs(fs, 1); + } +} + + +void luaK_setoneret (FuncState *fs, expdesc *e) { + if (e->k == VCALL) { /* expression is an open function call? */ + e->k = VNONRELOC; + e->u.s.info = GETARG_A(getcode(fs, e)); + } + else if (e->k == VVARARG) { + SETARG_B(getcode(fs, e), 2); + e->k = VRELOCABLE; /* can relocate its simple result */ + } +} + + +void luaK_dischargevars (FuncState *fs, expdesc *e) { + switch (e->k) { + case VLOCAL: { + e->k = VNONRELOC; + break; + } + case VUPVAL: { + e->u.s.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.s.info, 0); + e->k = VRELOCABLE; + break; + } + case VGLOBAL: { + e->u.s.info = luaK_codeABx(fs, OP_GETGLOBAL, 0, e->u.s.info); + e->k = VRELOCABLE; + break; + } + case VINDEXED: { + freereg(fs, e->u.s.aux); + freereg(fs, e->u.s.info); + e->u.s.info = luaK_codeABC(fs, OP_GETTABLE, 0, e->u.s.info, e->u.s.aux); + e->k = VRELOCABLE; + break; + } + case VVARARG: + case VCALL: { + luaK_setoneret(fs, e); + break; + } + default: break; /* there is one value available (somewhere) */ + } +} + + +static int code_label (FuncState *fs, int A, int b, int jump) { + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); +} + + +static void discharge2reg (FuncState *fs, expdesc *e, int reg) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: { + luaK_nil(fs, reg, 1); + break; + } + case VFALSE: case VTRUE: { + luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); + break; + } + case VK: { + luaK_codeABx(fs, OP_LOADK, reg, e->u.s.info); + break; + } + case VKNUM: { + luaK_codeABx(fs, OP_LOADK, reg, luaK_numberK(fs, e->u.nval)); + break; + } + case VRELOCABLE: { + Instruction *pc = &getcode(fs, e); + SETARG_A(*pc, reg); + break; + } + case VNONRELOC: { + if (reg != e->u.s.info) + luaK_codeABC(fs, OP_MOVE, reg, e->u.s.info, 0); + break; + } + default: { + lua_assert(e->k == VVOID || e->k == VJMP); + return; /* nothing to do... */ + } + } + e->u.s.info = reg; + e->k = VNONRELOC; +} + + +static void discharge2anyreg (FuncState *fs, expdesc *e) { + if (e->k != VNONRELOC) { + luaK_reserveregs(fs, 1); + discharge2reg(fs, e, fs->freereg-1); + } +} + + +static void exp2reg (FuncState *fs, expdesc *e, int reg) { + discharge2reg(fs, e, reg); + if (e->k == VJMP) + luaK_concat(fs, &e->t, e->u.s.info); /* put this jump in `t' list */ + if (hasjumps(e)) { + int final; /* position after whole expression */ + int p_f = NO_JUMP; /* position of an eventual LOAD false */ + int p_t = NO_JUMP; /* position of an eventual LOAD true */ + if (need_value(fs, e->t) || need_value(fs, e->f)) { + int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); + p_f = code_label(fs, reg, 0, 1); + p_t = code_label(fs, reg, 1, 0); + luaK_patchtohere(fs, fj); + } + final = luaK_getlabel(fs); + patchlistaux(fs, e->f, final, reg, p_f); + patchlistaux(fs, e->t, final, reg, p_t); + } + e->f = e->t = NO_JUMP; + e->u.s.info = reg; + e->k = VNONRELOC; +} + + +void luaK_exp2nextreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + freeexp(fs, e); + luaK_reserveregs(fs, 1); + exp2reg(fs, e, fs->freereg - 1); +} + + +int luaK_exp2anyreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + if (e->k == VNONRELOC) { + if (!hasjumps(e)) return e->u.s.info; /* exp is already in a register */ + if (e->u.s.info >= fs->nactvar) { /* reg. is not a local? */ + exp2reg(fs, e, e->u.s.info); /* put value on it */ + return e->u.s.info; + } + } + luaK_exp2nextreg(fs, e); /* default */ + return e->u.s.info; +} + + +void luaK_exp2val (FuncState *fs, expdesc *e) { + if (hasjumps(e)) + luaK_exp2anyreg(fs, e); + else + luaK_dischargevars(fs, e); +} + + +int luaK_exp2RK (FuncState *fs, expdesc *e) { + luaK_exp2val(fs, e); + switch (e->k) { + case VKNUM: + case VTRUE: + case VFALSE: + case VNIL: { + if (fs->nk <= MAXINDEXRK) { /* constant fit in RK operand? */ + e->u.s.info = (e->k == VNIL) ? nilK(fs) : + (e->k == VKNUM) ? luaK_numberK(fs, e->u.nval) : + boolK(fs, (e->k == VTRUE)); + e->k = VK; + return RKASK(e->u.s.info); + } + else break; + } + case VK: { + if (e->u.s.info <= MAXINDEXRK) /* constant fit in argC? */ + return RKASK(e->u.s.info); + else break; + } + default: break; + } + /* not a constant in the right range: put it in a register */ + return luaK_exp2anyreg(fs, e); +} + + +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { + switch (var->k) { + case VLOCAL: { + freeexp(fs, ex); + exp2reg(fs, ex, var->u.s.info); + return; + } + case VUPVAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.s.info, 0); + break; + } + case VGLOBAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABx(fs, OP_SETGLOBAL, e, var->u.s.info); + break; + } + case VINDEXED: { + int e = luaK_exp2RK(fs, ex); + luaK_codeABC(fs, OP_SETTABLE, var->u.s.info, var->u.s.aux, e); + break; + } + default: { + lua_assert(0); /* invalid var kind to store */ + break; + } + } + freeexp(fs, ex); +} + + +void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { + int func; + luaK_exp2anyreg(fs, e); + freeexp(fs, e); + func = fs->freereg; + luaK_reserveregs(fs, 2); + luaK_codeABC(fs, OP_SELF, func, e->u.s.info, luaK_exp2RK(fs, key)); + freeexp(fs, key); + e->u.s.info = func; + e->k = VNONRELOC; +} + + +static void invertjump (FuncState *fs, expdesc *e) { + Instruction *pc = getjumpcontrol(fs, e->u.s.info); + lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && + GET_OPCODE(*pc) != OP_TEST); + SETARG_A(*pc, !(GETARG_A(*pc))); +} + + +static int jumponcond (FuncState *fs, expdesc *e, int cond) { + if (e->k == VRELOCABLE) { + Instruction ie = getcode(fs, e); + if (GET_OPCODE(ie) == OP_NOT) { + fs->pc--; /* remove previous OP_NOT */ + return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); + } + /* else go through */ + } + discharge2anyreg(fs, e); + freeexp(fs, e); + return condjump(fs, OP_TESTSET, NO_REG, e->u.s.info, cond); +} + + +void luaK_goiftrue (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VK: case VKNUM: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } + case VFALSE: { + pc = luaK_jump(fs); /* always jump */ + break; + } + case VJMP: { + invertjump(fs, e); + pc = e->u.s.info; + break; + } + default: { + pc = jumponcond(fs, e, 0); + break; + } + } + luaK_concat(fs, &e->f, pc); /* insert last jump in `f' list */ + luaK_patchtohere(fs, e->t); + e->t = NO_JUMP; +} + + +static void luaK_goiffalse (FuncState *fs, expdesc *e) { + int pc; /* pc of last jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ + break; + } + case VTRUE: { + pc = luaK_jump(fs); /* always jump */ + break; + } + case VJMP: { + pc = e->u.s.info; + break; + } + default: { + pc = jumponcond(fs, e, 1); + break; + } + } + luaK_concat(fs, &e->t, pc); /* insert last jump in `t' list */ + luaK_patchtohere(fs, e->f); + e->f = NO_JUMP; +} + + +static void codenot (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + e->k = VTRUE; + break; + } + case VK: case VKNUM: case VTRUE: { + e->k = VFALSE; + break; + } + case VJMP: { + invertjump(fs, e); + break; + } + case VRELOCABLE: + case VNONRELOC: { + discharge2anyreg(fs, e); + freeexp(fs, e); + e->u.s.info = luaK_codeABC(fs, OP_NOT, 0, e->u.s.info, 0); + e->k = VRELOCABLE; + break; + } + default: { + lua_assert(0); /* cannot happen */ + break; + } + } + /* interchange true and false lists */ + { int temp = e->f; e->f = e->t; e->t = temp; } + removevalues(fs, e->f); + removevalues(fs, e->t); +} + + +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + t->u.s.aux = luaK_exp2RK(fs, k); + t->k = VINDEXED; +} + + +static int constfolding (OpCode op, expdesc *e1, expdesc *e2) { + lua_Number v1, v2, r; + if (!isnumeral(e1) || !isnumeral(e2)) return 0; + v1 = e1->u.nval; + v2 = e2->u.nval; + switch (op) { + case OP_ADD: r = luai_numadd(v1, v2); break; + case OP_SUB: r = luai_numsub(v1, v2); break; + case OP_MUL: r = luai_nummul(v1, v2); break; + case OP_DIV: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ + r = luai_numdiv(v1, v2); break; + case OP_MOD: + if (v2 == 0) return 0; /* do not attempt to divide by 0 */ + r = luai_nummod(v1, v2); break; + case OP_POW: r = luai_numpow(v1, v2); break; + case OP_UNM: r = luai_numunm(v1); break; + case OP_LEN: return 0; /* no constant folding for 'len' */ + default: lua_assert(0); r = 0; break; + } + if (luai_numisnan(r)) return 0; /* do not attempt to produce NaN */ + e1->u.nval = r; + return 1; +} + + +static void codearith (FuncState *fs, OpCode op, expdesc *e1, expdesc *e2) { + if (constfolding(op, e1, e2)) + return; + else { + int o2 = (op != OP_UNM && op != OP_LEN) ? luaK_exp2RK(fs, e2) : 0; + int o1 = luaK_exp2RK(fs, e1); + if (o1 > o2) { + freeexp(fs, e1); + freeexp(fs, e2); + } + else { + freeexp(fs, e2); + freeexp(fs, e1); + } + e1->u.s.info = luaK_codeABC(fs, op, 0, o1, o2); + e1->k = VRELOCABLE; + } +} + + +static void codecomp (FuncState *fs, OpCode op, int cond, expdesc *e1, + expdesc *e2) { + int o1 = luaK_exp2RK(fs, e1); + int o2 = luaK_exp2RK(fs, e2); + freeexp(fs, e2); + freeexp(fs, e1); + if (cond == 0 && op != OP_EQ) { + int temp; /* exchange args to replace by `<' or `<=' */ + temp = o1; o1 = o2; o2 = temp; /* o1 <==> o2 */ + cond = 1; + } + e1->u.s.info = condjump(fs, op, cond, o1, o2); + e1->k = VJMP; +} + + +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e) { + expdesc e2; + e2.t = e2.f = NO_JUMP; e2.k = VKNUM; e2.u.nval = 0; + switch (op) { + case OPR_MINUS: { + if (!isnumeral(e)) + luaK_exp2anyreg(fs, e); /* cannot operate on non-numeric constants */ + codearith(fs, OP_UNM, e, &e2); + break; + } + case OPR_NOT: codenot(fs, e); break; + case OPR_LEN: { + luaK_exp2anyreg(fs, e); /* cannot operate on constants */ + codearith(fs, OP_LEN, e, &e2); + break; + } + default: lua_assert(0); + } +} + + +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { + switch (op) { + case OPR_AND: { + luaK_goiftrue(fs, v); + break; + } + case OPR_OR: { + luaK_goiffalse(fs, v); + break; + } + case OPR_CONCAT: { + luaK_exp2nextreg(fs, v); /* operand must be on the `stack' */ + break; + } + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_MOD: case OPR_POW: { + if (!isnumeral(v)) luaK_exp2RK(fs, v); + break; + } + default: { + luaK_exp2RK(fs, v); + break; + } + } +} + + +void luaK_posfix (FuncState *fs, BinOpr op, expdesc *e1, expdesc *e2) { + switch (op) { + case OPR_AND: { + lua_assert(e1->t == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->f, e1->f); + *e1 = *e2; + break; + } + case OPR_OR: { + lua_assert(e1->f == NO_JUMP); /* list must be closed */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->t, e1->t); + *e1 = *e2; + break; + } + case OPR_CONCAT: { + luaK_exp2val(fs, e2); + if (e2->k == VRELOCABLE && GET_OPCODE(getcode(fs, e2)) == OP_CONCAT) { + lua_assert(e1->u.s.info == GETARG_B(getcode(fs, e2))-1); + freeexp(fs, e1); + SETARG_B(getcode(fs, e2), e1->u.s.info); + e1->k = VRELOCABLE; e1->u.s.info = e2->u.s.info; + } + else { + luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ + codearith(fs, OP_CONCAT, e1, e2); + } + break; + } + case OPR_ADD: codearith(fs, OP_ADD, e1, e2); break; + case OPR_SUB: codearith(fs, OP_SUB, e1, e2); break; + case OPR_MUL: codearith(fs, OP_MUL, e1, e2); break; + case OPR_DIV: codearith(fs, OP_DIV, e1, e2); break; + case OPR_MOD: codearith(fs, OP_MOD, e1, e2); break; + case OPR_POW: codearith(fs, OP_POW, e1, e2); break; + case OPR_EQ: codecomp(fs, OP_EQ, 1, e1, e2); break; + case OPR_NE: codecomp(fs, OP_EQ, 0, e1, e2); break; + case OPR_LT: codecomp(fs, OP_LT, 1, e1, e2); break; + case OPR_LE: codecomp(fs, OP_LE, 1, e1, e2); break; + case OPR_GT: codecomp(fs, OP_LT, 0, e1, e2); break; + case OPR_GE: codecomp(fs, OP_LE, 0, e1, e2); break; + default: lua_assert(0); + } +} + + +void luaK_fixline (FuncState *fs, int line) { + fs->f->lineinfo[fs->pc - 1] = line; +} + + +static int luaK_code (FuncState *fs, Instruction i, int line) { + Proto *f = fs->f; + dischargejpc(fs); /* `pc' will change */ + /* put new instruction in code array */ + luaM_growvector(fs->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "code size overflow"); + f->code[fs->pc] = i; + /* save corresponding line information */ + luaM_growvector(fs->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "code size overflow"); + f->lineinfo[fs->pc] = line; + return fs->pc++; +} + + +int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { + lua_assert(getOpMode(o) == iABC); + lua_assert(getBMode(o) != OpArgN || b == 0); + lua_assert(getCMode(o) != OpArgN || c == 0); + return luaK_code(fs, CREATE_ABC(o, a, b, c), fs->ls->lastline); +} + + +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { + lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); + lua_assert(getCMode(o) == OpArgN); + return luaK_code(fs, CREATE_ABx(o, a, bc), fs->ls->lastline); +} + + +void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { + int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; + int b = (tostore == LUA_MULTRET) ? 0 : tostore; + lua_assert(tostore != 0); + if (c <= MAXARG_C) + luaK_codeABC(fs, OP_SETLIST, base, b, c); + else { + luaK_codeABC(fs, OP_SETLIST, base, b, 0); + luaK_code(fs, cast(Instruction, c), fs->ls->lastline); + } + fs->freereg = base + 1; /* free registers with list values */ +} + diff --git a/src/lua/src/lcode.h b/src/lua/src/lcode.h new file mode 100644 index 00000000..b941c607 --- /dev/null +++ b/src/lua/src/lcode.h @@ -0,0 +1,76 @@ +/* +** $Id: lcode.h,v 1.48.1.1 2007/12/27 13:02:25 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lcode_h +#define lcode_h + +#include "llex.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" + + +/* +** Marks the end of a patch list. It is an invalid value both as an absolute +** address, and as a list link (would link an element to itself). +*/ +#define NO_JUMP (-1) + + +/* +** grep "ORDER OPR" if you change these enums +*/ +typedef enum BinOpr { + OPR_ADD, OPR_SUB, OPR_MUL, OPR_DIV, OPR_MOD, OPR_POW, + OPR_CONCAT, + OPR_NE, OPR_EQ, + OPR_LT, OPR_LE, OPR_GT, OPR_GE, + OPR_AND, OPR_OR, + OPR_NOBINOPR +} BinOpr; + + +typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; + + +#define getcode(fs,e) ((fs)->f->code[(e)->u.s.info]) + +#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) + +#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) + +LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); +LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); +LUAI_FUNC void luaK_fixline (FuncState *fs, int line); +LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); +LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); +LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); +LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); +LUAI_FUNC int luaK_numberK (FuncState *fs, lua_Number r); +LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); +LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); +LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); +LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); +LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_jump (FuncState *fs); +LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); +LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); +LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); +LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); +LUAI_FUNC int luaK_getlabel (FuncState *fs); +LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v); +LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); +LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, expdesc *v2); +LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); + + +#endif diff --git a/src/lua/src/ldblib.c b/src/lua/src/ldblib.c new file mode 100644 index 00000000..67de1222 --- /dev/null +++ b/src/lua/src/ldblib.c @@ -0,0 +1,397 @@ +/* +** $Id: ldblib.c,v 1.104.1.3 2008/01/21 13:11:21 roberto Exp $ +** Interface from Lua to its debug API +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define ldblib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +static int db_getregistry (lua_State *L) { + lua_pushvalue(L, LUA_REGISTRYINDEX); + return 1; +} + + +static int db_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); /* no metatable */ + } + return 1; +} + + +static int db_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + lua_settop(L, 2); + lua_pushboolean(L, lua_setmetatable(L, 1)); + return 1; +} + + +static int db_getfenv (lua_State *L) { + lua_getfenv(L, 1); + return 1; +} + + +static int db_setfenv (lua_State *L) { + luaL_checktype(L, 2, LUA_TTABLE); + lua_settop(L, 2); + if (lua_setfenv(L, 1) == 0) + luaL_error(L, LUA_QL("setfenv") + " cannot change environment of given object"); + return 1; +} + + +static void settabss (lua_State *L, const char *i, const char *v) { + lua_pushstring(L, v); + lua_setfield(L, -2, i); +} + + +static void settabsi (lua_State *L, const char *i, int v) { + lua_pushinteger(L, v); + lua_setfield(L, -2, i); +} + + +static lua_State *getthread (lua_State *L, int *arg) { + if (lua_isthread(L, 1)) { + *arg = 1; + return lua_tothread(L, 1); + } + else { + *arg = 0; + return L; + } +} + + +static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { + if (L == L1) { + lua_pushvalue(L, -2); + lua_remove(L, -3); + } + else + lua_xmove(L1, L, 1); + lua_setfield(L, -2, fname); +} + + +static int db_getinfo (lua_State *L) { + lua_Debug ar; + int arg; + lua_State *L1 = getthread(L, &arg); + const char *options = luaL_optstring(L, arg+2, "flnSu"); + if (lua_isnumber(L, arg+1)) { + if (!lua_getstack(L1, (int)lua_tointeger(L, arg+1), &ar)) { + lua_pushnil(L); /* level out of range */ + return 1; + } + } + else if (lua_isfunction(L, arg+1)) { + lua_pushfstring(L, ">%s", options); + options = lua_tostring(L, -1); + lua_pushvalue(L, arg+1); + lua_xmove(L, L1, 1); + } + else + return luaL_argerror(L, arg+1, "function or level expected"); + if (!lua_getinfo(L1, options, &ar)) + return luaL_argerror(L, arg+2, "invalid option"); + lua_createtable(L, 0, 2); + if (strchr(options, 'S')) { + settabss(L, "source", ar.source); + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabsi(L, "lastlinedefined", ar.lastlinedefined); + settabss(L, "what", ar.what); + } + if (strchr(options, 'l')) + settabsi(L, "currentline", ar.currentline); + if (strchr(options, 'u')) + settabsi(L, "nups", ar.nups); + if (strchr(options, 'n')) { + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + } + if (strchr(options, 'L')) + treatstackoption(L, L1, "activelines"); + if (strchr(options, 'f')) + treatstackoption(L, L1, "func"); + return 1; /* return table */ +} + + +static int db_getlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + const char *name; + if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + name = lua_getlocal(L1, &ar, luaL_checkint(L, arg+2)); + if (name) { + lua_xmove(L1, L, 1); + lua_pushstring(L, name); + lua_pushvalue(L, -2); + return 2; + } + else { + lua_pushnil(L); + return 1; + } +} + + +static int db_setlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + if (!lua_getstack(L1, luaL_checkint(L, arg+1), &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + luaL_checkany(L, arg+3); + lua_settop(L, arg+3); + lua_xmove(L, L1, 1); + lua_pushstring(L, lua_setlocal(L1, &ar, luaL_checkint(L, arg+2))); + return 1; +} + + +static int auxupvalue (lua_State *L, int get) { + const char *name; + int n = luaL_checkint(L, 2); + luaL_checktype(L, 1, LUA_TFUNCTION); + if (lua_iscfunction(L, 1)) return 0; /* cannot touch C upvalues from Lua */ + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); + return get + 1; +} + + +static int db_getupvalue (lua_State *L) { + return auxupvalue(L, 1); +} + + +static int db_setupvalue (lua_State *L) { + luaL_checkany(L, 3); + return auxupvalue(L, 0); +} + + + +static const char KEY_HOOK = 'h'; + + +static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail return"}; + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); + lua_pushlightuserdata(L, L); + lua_rawget(L, -2); + if (lua_isfunction(L, -1)) { + lua_pushstring(L, hooknames[(int)ar->event]); + if (ar->currentline >= 0) + lua_pushinteger(L, ar->currentline); + else lua_pushnil(L); + lua_assert(lua_getinfo(L, "lS", ar)); + lua_call(L, 2, 0); + } +} + + +static int makemask (const char *smask, int count) { + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + return mask; +} + + +static char *unmakemask (int mask, char *smask) { + int i = 0; + if (mask & LUA_MASKCALL) smask[i++] = 'c'; + if (mask & LUA_MASKRET) smask[i++] = 'r'; + if (mask & LUA_MASKLINE) smask[i++] = 'l'; + smask[i] = '\0'; + return smask; +} + + +static void gethooktable (lua_State *L) { + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_rawget(L, LUA_REGISTRYINDEX); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + lua_createtable(L, 0, 1); + lua_pushlightuserdata(L, (void *)&KEY_HOOK); + lua_pushvalue(L, -2); + lua_rawset(L, LUA_REGISTRYINDEX); + } +} + + +static int db_sethook (lua_State *L) { + int arg, mask, count; + lua_Hook func; + lua_State *L1 = getthread(L, &arg); + if (lua_isnoneornil(L, arg+1)) { + lua_settop(L, arg+1); + func = NULL; mask = 0; count = 0; /* turn off hooks */ + } + else { + const char *smask = luaL_checkstring(L, arg+2); + luaL_checktype(L, arg+1, LUA_TFUNCTION); + count = luaL_optint(L, arg+3, 0); + func = hookf; mask = makemask(smask, count); + } + gethooktable(L); + lua_pushlightuserdata(L, L1); + lua_pushvalue(L, arg+1); + lua_rawset(L, -3); /* set new hook */ + lua_pop(L, 1); /* remove hook table */ + lua_sethook(L1, func, mask, count); /* set hooks */ + return 0; +} + + +static int db_gethook (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + char buff[5]; + int mask = lua_gethookmask(L1); + lua_Hook hook = lua_gethook(L1); + if (hook != NULL && hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else { + gethooktable(L); + lua_pushlightuserdata(L, L1); + lua_rawget(L, -2); /* get hook */ + lua_remove(L, -2); /* remove hook table */ + } + lua_pushstring(L, unmakemask(mask, buff)); + lua_pushinteger(L, lua_gethookcount(L1)); + return 3; +} + + +static int db_debug (lua_State *L) { + for (;;) { + char buffer[250]; + fputs("lua_debug> ", stderr); + if (fgets(buffer, sizeof(buffer), stdin) == 0 || + strcmp(buffer, "cont\n") == 0) + return 0; + if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || + lua_pcall(L, 0, 0, 0)) { + fputs(lua_tostring(L, -1), stderr); + fputs("\n", stderr); + } + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ + +static int db_errorfb (lua_State *L) { + int level; + int firstpart = 1; /* still before eventual `...' */ + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + if (lua_isnumber(L, arg+2)) { + level = (int)lua_tointeger(L, arg+2); + lua_pop(L, 1); + } + else + level = (L == L1) ? 1 : 0; /* level 0 may be this own function */ + if (lua_gettop(L) == arg) + lua_pushliteral(L, ""); + else if (!lua_isstring(L, arg+1)) return 1; /* message is not a string */ + else lua_pushliteral(L, "\n"); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (level > LEVELS1 && firstpart) { + /* no more than `LEVELS2' more levels? */ + if (!lua_getstack(L1, level+LEVELS2, &ar)) + level--; /* keep going */ + else { + lua_pushliteral(L, "\n\t..."); /* too many levels */ + while (lua_getstack(L1, level+LEVELS2, &ar)) /* find last levels */ + level++; + } + firstpart = 0; + continue; + } + lua_pushliteral(L, "\n\t"); + lua_getinfo(L1, "Snl", &ar); + lua_pushfstring(L, "%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + if (*ar.namewhat != '\0') /* is there a name? */ + lua_pushfstring(L, " in function " LUA_QS, ar.name); + else { + if (*ar.what == 'm') /* main? */ + lua_pushfstring(L, " in main chunk"); + else if (*ar.what == 'C' || *ar.what == 't') + lua_pushliteral(L, " ?"); /* C function or tail call */ + else + lua_pushfstring(L, " in function <%s:%d>", + ar.short_src, ar.linedefined); + } + lua_concat(L, lua_gettop(L) - arg); + } + lua_concat(L, lua_gettop(L) - arg); + return 1; +} + + +static const luaL_Reg dblib[] = { + {"debug", db_debug}, + {"getfenv", db_getfenv}, + {"gethook", db_gethook}, + {"getinfo", db_getinfo}, + {"getlocal", db_getlocal}, + {"getregistry", db_getregistry}, + {"getmetatable", db_getmetatable}, + {"getupvalue", db_getupvalue}, + {"setfenv", db_setfenv}, + {"sethook", db_sethook}, + {"setlocal", db_setlocal}, + {"setmetatable", db_setmetatable}, + {"setupvalue", db_setupvalue}, + {"traceback", db_errorfb}, + {NULL, NULL} +}; + + +LUALIB_API int luaopen_debug (lua_State *L) { + luaL_register(L, LUA_DBLIBNAME, dblib); + return 1; +} + diff --git a/src/lua/src/ldebug.c b/src/lua/src/ldebug.c new file mode 100644 index 00000000..50ad3d38 --- /dev/null +++ b/src/lua/src/ldebug.c @@ -0,0 +1,638 @@ +/* +** $Id: ldebug.c,v 2.29.1.6 2008/05/08 16:56:26 roberto Exp $ +** Debug Interface +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + + +#define ldebug_c +#define LUA_CORE + +#include "lua.h" + +#include "lapi.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); + + +static int currentpc (lua_State *L, CallInfo *ci) { + if (!isLua(ci)) return -1; /* function is not a Lua function? */ + if (ci == L->ci) + ci->savedpc = L->savedpc; + return pcRel(ci->savedpc, ci_func(ci)->l.p); +} + + +static int currentline (lua_State *L, CallInfo *ci) { + int pc = currentpc(L, ci); + if (pc < 0) + return -1; /* only active lua functions have current-line information */ + else + return getline(ci_func(ci)->l.p, pc); +} + + +/* +** this function can be called asynchronous (e.g. during a signal) +*/ +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { + if (func == NULL || mask == 0) { /* turn off hooks? */ + mask = 0; + func = NULL; + } + L->hook = func; + L->basehookcount = count; + resethookcount(L); + L->hookmask = cast_byte(mask); + return 1; +} + + +LUA_API lua_Hook lua_gethook (lua_State *L) { + return L->hook; +} + + +LUA_API int lua_gethookmask (lua_State *L) { + return L->hookmask; +} + + +LUA_API int lua_gethookcount (lua_State *L) { + return L->basehookcount; +} + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { + int status; + CallInfo *ci; + lua_lock(L); + for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { + level--; + if (f_isLua(ci)) /* Lua function? */ + level -= ci->tailcalls; /* skip lost tail calls */ + } + if (level == 0 && ci > L->base_ci) { /* level found? */ + status = 1; + ar->i_ci = cast_int(ci - L->base_ci); + } + else if (level < 0) { /* level is of a lost tail call? */ + status = 1; + ar->i_ci = 0; + } + else status = 0; /* no such level */ + lua_unlock(L); + return status; +} + + +static Proto *getluaproto (CallInfo *ci) { + return (isLua(ci) ? ci_func(ci)->l.p : NULL); +} + + +static const char *findlocal (lua_State *L, CallInfo *ci, int n) { + const char *name; + Proto *fp = getluaproto(ci); + if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) + return name; /* is a local variable in a Lua function */ + else { + StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; + if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ + return "(*temporary)"; + else + return NULL; + } +} + + +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { + CallInfo *ci = L->base_ci + ar->i_ci; + const char *name = findlocal(L, ci, n); + lua_lock(L); + if (name) + luaA_pushobject(L, ci->base + (n - 1)); + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + CallInfo *ci = L->base_ci + ar->i_ci; + const char *name = findlocal(L, ci, n); + lua_lock(L); + if (name) + setobjs2s(L, ci->base + (n - 1), L->top - 1); + L->top--; /* pop value */ + lua_unlock(L); + return name; +} + + +static void funcinfo (lua_Debug *ar, Closure *cl) { + if (cl->c.isC) { + ar->source = "=[C]"; + ar->linedefined = -1; + ar->lastlinedefined = -1; + ar->what = "C"; + } + else { + ar->source = getstr(cl->l.p->source); + ar->linedefined = cl->l.p->linedefined; + ar->lastlinedefined = cl->l.p->lastlinedefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); +} + + +static void info_tailcall (lua_Debug *ar) { + ar->name = ar->namewhat = ""; + ar->what = "tail"; + ar->lastlinedefined = ar->linedefined = ar->currentline = -1; + ar->source = "=(tail call)"; + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); + ar->nups = 0; +} + + +static void collectvalidlines (lua_State *L, Closure *f) { + if (f == NULL || f->c.isC) { + setnilvalue(L->top); + } + else { + Table *t = luaH_new(L, 0, 0); + int *lineinfo = f->l.p->lineinfo; + int i; + for (i=0; il.p->sizelineinfo; i++) + setbvalue(luaH_setnum(L, t, lineinfo[i]), 1); + sethvalue(L, L->top, t); + } + incr_top(L); +} + + +static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, + Closure *f, CallInfo *ci) { + int status = 1; + if (f == NULL) { + info_tailcall(ar); + return status; + } + for (; *what; what++) { + switch (*what) { + case 'S': { + funcinfo(ar, f); + break; + } + case 'l': { + ar->currentline = (ci) ? currentline(L, ci) : -1; + break; + } + case 'u': { + ar->nups = f->c.nupvalues; + break; + } + case 'n': { + ar->namewhat = (ci) ? getfuncname(L, ci, &ar->name) : NULL; + if (ar->namewhat == NULL) { + ar->namewhat = ""; /* not found */ + ar->name = NULL; + } + break; + } + case 'L': + case 'f': /* handled by lua_getinfo */ + break; + default: status = 0; /* invalid option */ + } + } + return status; +} + + +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { + int status; + Closure *f = NULL; + CallInfo *ci = NULL; + lua_lock(L); + if (*what == '>') { + StkId func = L->top - 1; + luai_apicheck(L, ttisfunction(func)); + what++; /* skip the '>' */ + f = clvalue(func); + L->top--; /* pop function */ + } + else if (ar->i_ci != 0) { /* no tail call? */ + ci = L->base_ci + ar->i_ci; + lua_assert(ttisfunction(ci->func)); + f = clvalue(ci->func); + } + status = auxgetinfo(L, what, ar, f, ci); + if (strchr(what, 'f')) { + if (f == NULL) setnilvalue(L->top); + else setclvalue(L, L->top, f); + incr_top(L); + } + if (strchr(what, 'L')) + collectvalidlines(L, f); + lua_unlock(L); + return status; +} + + +/* +** {====================================================== +** Symbolic Execution and code checker +** ======================================================= +*/ + +#define check(x) if (!(x)) return 0; + +#define checkjump(pt,pc) check(0 <= pc && pc < pt->sizecode) + +#define checkreg(pt,reg) check((reg) < (pt)->maxstacksize) + + + +static int precheck (const Proto *pt) { + check(pt->maxstacksize <= MAXSTACK); + check(pt->numparams+(pt->is_vararg & VARARG_HASARG) <= pt->maxstacksize); + check(!(pt->is_vararg & VARARG_NEEDSARG) || + (pt->is_vararg & VARARG_HASARG)); + check(pt->sizeupvalues <= pt->nups); + check(pt->sizelineinfo == pt->sizecode || pt->sizelineinfo == 0); + check(pt->sizecode > 0 && GET_OPCODE(pt->code[pt->sizecode-1]) == OP_RETURN); + return 1; +} + + +#define checkopenop(pt,pc) luaG_checkopenop((pt)->code[(pc)+1]) + +int luaG_checkopenop (Instruction i) { + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: + case OP_RETURN: + case OP_SETLIST: { + check(GETARG_B(i) == 0); + return 1; + } + default: return 0; /* invalid instruction after an open call */ + } +} + + +static int checkArgMode (const Proto *pt, int r, enum OpArgMask mode) { + switch (mode) { + case OpArgN: check(r == 0); break; + case OpArgU: break; + case OpArgR: checkreg(pt, r); break; + case OpArgK: + check(ISK(r) ? INDEXK(r) < pt->sizek : r < pt->maxstacksize); + break; + } + return 1; +} + + +static Instruction symbexec (const Proto *pt, int lastpc, int reg) { + int pc; + int last; /* stores position of last instruction that changed `reg' */ + last = pt->sizecode-1; /* points to final return (a `neutral' instruction) */ + check(precheck(pt)); + for (pc = 0; pc < lastpc; pc++) { + Instruction i = pt->code[pc]; + OpCode op = GET_OPCODE(i); + int a = GETARG_A(i); + int b = 0; + int c = 0; + check(op < NUM_OPCODES); + checkreg(pt, a); + switch (getOpMode(op)) { + case iABC: { + b = GETARG_B(i); + c = GETARG_C(i); + check(checkArgMode(pt, b, getBMode(op))); + check(checkArgMode(pt, c, getCMode(op))); + break; + } + case iABx: { + b = GETARG_Bx(i); + if (getBMode(op) == OpArgK) check(b < pt->sizek); + break; + } + case iAsBx: { + b = GETARG_sBx(i); + if (getBMode(op) == OpArgR) { + int dest = pc+1+b; + check(0 <= dest && dest < pt->sizecode); + if (dest > 0) { + int j; + /* check that it does not jump to a setlist count; this + is tricky, because the count from a previous setlist may + have the same value of an invalid setlist; so, we must + go all the way back to the first of them (if any) */ + for (j = 0; j < dest; j++) { + Instruction d = pt->code[dest-1-j]; + if (!(GET_OPCODE(d) == OP_SETLIST && GETARG_C(d) == 0)) break; + } + /* if 'j' is even, previous value is not a setlist (even if + it looks like one) */ + check((j&1) == 0); + } + } + break; + } + } + if (testAMode(op)) { + if (a == reg) last = pc; /* change register `a' */ + } + if (testTMode(op)) { + check(pc+2 < pt->sizecode); /* check skip */ + check(GET_OPCODE(pt->code[pc+1]) == OP_JMP); + } + switch (op) { + case OP_LOADBOOL: { + if (c == 1) { /* does it jump? */ + check(pc+2 < pt->sizecode); /* check its jump */ + check(GET_OPCODE(pt->code[pc+1]) != OP_SETLIST || + GETARG_C(pt->code[pc+1]) != 0); + } + break; + } + case OP_LOADNIL: { + if (a <= reg && reg <= b) + last = pc; /* set registers from `a' to `b' */ + break; + } + case OP_GETUPVAL: + case OP_SETUPVAL: { + check(b < pt->nups); + break; + } + case OP_GETGLOBAL: + case OP_SETGLOBAL: { + check(ttisstring(&pt->k[b])); + break; + } + case OP_SELF: { + checkreg(pt, a+1); + if (reg == a+1) last = pc; + break; + } + case OP_CONCAT: { + check(b < c); /* at least two operands */ + break; + } + case OP_TFORLOOP: { + check(c >= 1); /* at least one result (control variable) */ + checkreg(pt, a+2+c); /* space for results */ + if (reg >= a+2) last = pc; /* affect all regs above its base */ + break; + } + case OP_FORLOOP: + case OP_FORPREP: + checkreg(pt, a+3); + /* go through */ + case OP_JMP: { + int dest = pc+1+b; + /* not full check and jump is forward and do not skip `lastpc'? */ + if (reg != NO_REG && pc < dest && dest <= lastpc) + pc += b; /* do the jump */ + break; + } + case OP_CALL: + case OP_TAILCALL: { + if (b != 0) { + checkreg(pt, a+b-1); + } + c--; /* c = num. returns */ + if (c == LUA_MULTRET) { + check(checkopenop(pt, pc)); + } + else if (c != 0) + checkreg(pt, a+c-1); + if (reg >= a) last = pc; /* affect all registers above base */ + break; + } + case OP_RETURN: { + b--; /* b = num. returns */ + if (b > 0) checkreg(pt, a+b-1); + break; + } + case OP_SETLIST: { + if (b > 0) checkreg(pt, a + b); + if (c == 0) { + pc++; + check(pc < pt->sizecode - 1); + } + break; + } + case OP_CLOSURE: { + int nup, j; + check(b < pt->sizep); + nup = pt->p[b]->nups; + check(pc + nup < pt->sizecode); + for (j = 1; j <= nup; j++) { + OpCode op1 = GET_OPCODE(pt->code[pc + j]); + check(op1 == OP_GETUPVAL || op1 == OP_MOVE); + } + if (reg != NO_REG) /* tracing? */ + pc += nup; /* do not 'execute' these pseudo-instructions */ + break; + } + case OP_VARARG: { + check((pt->is_vararg & VARARG_ISVARARG) && + !(pt->is_vararg & VARARG_NEEDSARG)); + b--; + if (b == LUA_MULTRET) check(checkopenop(pt, pc)); + checkreg(pt, a+b-1); + break; + } + default: break; + } + } + return pt->code[last]; +} + +#undef check +#undef checkjump +#undef checkreg + +/* }====================================================== */ + + +int luaG_checkcode (const Proto *pt) { + return (symbexec(pt, pt->sizecode, NO_REG) != 0); +} + + +static const char *kname (Proto *p, int c) { + if (ISK(c) && ttisstring(&p->k[INDEXK(c)])) + return svalue(&p->k[INDEXK(c)]); + else + return "?"; +} + + +static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, + const char **name) { + if (isLua(ci)) { /* a Lua function? */ + Proto *p = ci_func(ci)->l.p; + int pc = currentpc(L, ci); + Instruction i; + *name = luaF_getlocalname(p, stackpos+1, pc); + if (*name) /* is a local? */ + return "local"; + i = symbexec(p, pc, stackpos); /* try symbolic execution */ + lua_assert(pc != -1); + switch (GET_OPCODE(i)) { + case OP_GETGLOBAL: { + int g = GETARG_Bx(i); /* global index */ + lua_assert(ttisstring(&p->k[g])); + *name = svalue(&p->k[g]); + return "global"; + } + case OP_MOVE: { + int a = GETARG_A(i); + int b = GETARG_B(i); /* move from `b' to `a' */ + if (b < a) + return getobjname(L, ci, b, name); /* get name for `b' */ + break; + } + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + *name = kname(p, k); + return "field"; + } + case OP_GETUPVAL: { + int u = GETARG_B(i); /* upvalue index */ + *name = p->upvalues ? getstr(p->upvalues[u]) : "?"; + return "upvalue"; + } + case OP_SELF: { + int k = GETARG_C(i); /* key index */ + *name = kname(p, k); + return "method"; + } + default: break; + } + } + return NULL; /* no useful name found */ +} + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { + Instruction i; + if ((isLua(ci) && ci->tailcalls > 0) || !isLua(ci - 1)) + return NULL; /* calling function is not Lua (or is unknown) */ + ci--; /* calling function */ + i = ci_func(ci)->l.p->code[currentpc(L, ci)]; + if (GET_OPCODE(i) == OP_CALL || GET_OPCODE(i) == OP_TAILCALL || + GET_OPCODE(i) == OP_TFORLOOP) + return getobjname(L, ci, GETARG_A(i), name); + else + return NULL; /* no useful name can be found */ +} + + +/* only ANSI way to check whether a pointer points to an array */ +static int isinstack (CallInfo *ci, const TValue *o) { + StkId p; + for (p = ci->base; p < ci->top; p++) + if (o == p) return 1; + return 0; +} + + +void luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + const char *name = NULL; + const char *t = luaT_typenames[ttype(o)]; + const char *kind = (isinstack(L->ci, o)) ? + getobjname(L, L->ci, cast_int(o - L->base), &name) : + NULL; + if (kind) + luaG_runerror(L, "attempt to %s %s " LUA_QS " (a %s value)", + op, kind, name, t); + else + luaG_runerror(L, "attempt to %s a %s value", op, t); +} + + +void luaG_concaterror (lua_State *L, StkId p1, StkId p2) { + if (ttisstring(p1) || ttisnumber(p1)) p1 = p2; + lua_assert(!ttisstring(p1) && !ttisnumber(p1)); + luaG_typeerror(L, p1, "concatenate"); +} + + +void luaG_aritherror (lua_State *L, const TValue *p1, const TValue *p2) { + TValue temp; + if (luaV_tonumber(p1, &temp) == NULL) + p2 = p1; /* first operand is wrong */ + luaG_typeerror(L, p2, "perform arithmetic on"); +} + + +int luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { + const char *t1 = luaT_typenames[ttype(p1)]; + const char *t2 = luaT_typenames[ttype(p2)]; + if (t1[2] == t2[2]) + luaG_runerror(L, "attempt to compare two %s values", t1); + else + luaG_runerror(L, "attempt to compare %s with %s", t1, t2); + return 0; +} + + +static void addinfo (lua_State *L, const char *msg) { + CallInfo *ci = L->ci; + if (isLua(ci)) { /* is Lua code? */ + char buff[LUA_IDSIZE]; /* add file:line information */ + int line = currentline(L, ci); + luaO_chunkid(buff, getstr(getluaproto(ci)->source), LUA_IDSIZE); + luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); + } +} + + +void luaG_errormsg (lua_State *L) { + if (L->errfunc != 0) { /* is there an error handling function? */ + StkId errfunc = restorestack(L, L->errfunc); + if (!ttisfunction(errfunc)) luaD_throw(L, LUA_ERRERR); + setobjs2s(L, L->top, L->top - 1); /* move argument */ + setobjs2s(L, L->top - 1, errfunc); /* push function */ + incr_top(L); + luaD_call(L, L->top - 2, 1); /* call it */ + } + luaD_throw(L, LUA_ERRRUN); +} + + +void luaG_runerror (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + addinfo(L, luaO_pushvfstring(L, fmt, argp)); + va_end(argp); + luaG_errormsg(L); +} + diff --git a/src/lua/src/ldebug.h b/src/lua/src/ldebug.h new file mode 100644 index 00000000..ba28a972 --- /dev/null +++ b/src/lua/src/ldebug.h @@ -0,0 +1,33 @@ +/* +** $Id: ldebug.h,v 2.3.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions from Debug Interface module +** See Copyright Notice in lua.h +*/ + +#ifndef ldebug_h +#define ldebug_h + + +#include "lstate.h" + + +#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) + +#define getline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) + +#define resethookcount(L) (L->hookcount = L->basehookcount) + + +LUAI_FUNC void luaG_typeerror (lua_State *L, const TValue *o, + const char *opname); +LUAI_FUNC void luaG_concaterror (lua_State *L, StkId p1, StkId p2); +LUAI_FUNC void luaG_aritherror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC int luaG_ordererror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC void luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC void luaG_errormsg (lua_State *L); +LUAI_FUNC int luaG_checkcode (const Proto *pt); +LUAI_FUNC int luaG_checkopenop (Instruction i); + +#endif diff --git a/src/lua/src/ldo.c b/src/lua/src/ldo.c new file mode 100644 index 00000000..8de05f72 --- /dev/null +++ b/src/lua/src/ldo.c @@ -0,0 +1,518 @@ +/* +** $Id: ldo.c,v 2.38.1.3 2008/01/18 22:31:22 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define ldo_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" +#include "lzio.h" + + + + +/* +** {====================================================== +** Error-recovery functions +** ======================================================= +*/ + + +/* chain list of long jump buffers */ +struct lua_longjmp { + struct lua_longjmp *previous; + luai_jmpbuf b; + volatile int status; /* error code */ +}; + + +void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { + switch (errcode) { + case LUA_ERRMEM: { + setsvalue2s(L, oldtop, luaS_newliteral(L, MEMERRMSG)); + break; + } + case LUA_ERRERR: { + setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); + break; + } + case LUA_ERRSYNTAX: + case LUA_ERRRUN: { + setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + break; + } + } + L->top = oldtop + 1; +} + + +static void restore_stack_limit (lua_State *L) { + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); + if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ + int inuse = cast_int(L->ci - L->base_ci); + if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ + luaD_reallocCI(L, LUAI_MAXCALLS); + } +} + + +static void resetstack (lua_State *L, int status) { + L->ci = L->base_ci; + L->base = L->ci->base; + luaF_close(L, L->base); /* close eventual pending closures */ + luaD_seterrorobj(L, status, L->base); + L->nCcalls = L->baseCcalls; + L->allowhook = 1; + restore_stack_limit(L); + L->errfunc = 0; + L->errorJmp = NULL; +} + + +void luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { + L->errorJmp->status = errcode; + LUAI_THROW(L, L->errorJmp); + } + else { + L->status = cast_byte(errcode); + if (G(L)->panic) { + resetstack(L, errcode); + lua_unlock(L); + G(L)->panic(L); + } + exit(EXIT_FAILURE); + } +} + + +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + struct lua_longjmp lj; + lj.status = 0; + lj.previous = L->errorJmp; /* chain new error handler */ + L->errorJmp = &lj; + LUAI_TRY(L, &lj, + (*f)(L, ud); + ); + L->errorJmp = lj.previous; /* restore old error handler */ + return lj.status; +} + +/* }====================================================== */ + + +static void correctstack (lua_State *L, TValue *oldstack) { + CallInfo *ci; + GCObject *up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->gch.next) + gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; + for (ci = L->base_ci; ci <= L->ci; ci++) { + ci->top = (ci->top - oldstack) + L->stack; + ci->base = (ci->base - oldstack) + L->stack; + ci->func = (ci->func - oldstack) + L->stack; + } + L->base = (L->base - oldstack) + L->stack; +} + + +void luaD_reallocstack (lua_State *L, int newsize) { + TValue *oldstack = L->stack; + int realsize = newsize + 1 + EXTRA_STACK; + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); + luaM_reallocvector(L, L->stack, L->stacksize, realsize, TValue); + L->stacksize = realsize; + L->stack_last = L->stack+newsize; + correctstack(L, oldstack); +} + + +void luaD_reallocCI (lua_State *L, int newsize) { + CallInfo *oldci = L->base_ci; + luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); + L->size_ci = newsize; + L->ci = (L->ci - oldci) + L->base_ci; + L->end_ci = L->base_ci + L->size_ci - 1; +} + + +void luaD_growstack (lua_State *L, int n) { + if (n <= L->stacksize) /* double size is enough? */ + luaD_reallocstack(L, 2*L->stacksize); + else + luaD_reallocstack(L, L->stacksize + n); +} + + +static CallInfo *growCI (lua_State *L) { + if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ + luaD_throw(L, LUA_ERRERR); + else { + luaD_reallocCI(L, 2*L->size_ci); + if (L->size_ci > LUAI_MAXCALLS) + luaG_runerror(L, "stack overflow"); + } + return ++L->ci; +} + + +void luaD_callhook (lua_State *L, int event, int line) { + lua_Hook hook = L->hook; + if (hook && L->allowhook) { + ptrdiff_t top = savestack(L, L->top); + ptrdiff_t ci_top = savestack(L, L->ci->top); + lua_Debug ar; + ar.event = event; + ar.currentline = line; + if (event == LUA_HOOKTAILRET) + ar.i_ci = 0; /* tail call; no debug information about it */ + else + ar.i_ci = cast_int(L->ci - L->base_ci); + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + L->ci->top = L->top + LUA_MINSTACK; + lua_assert(L->ci->top <= L->stack_last); + L->allowhook = 0; /* cannot call hooks inside a hook */ + lua_unlock(L); + (*hook)(L, &ar); + lua_lock(L); + lua_assert(!L->allowhook); + L->allowhook = 1; + L->ci->top = restorestack(L, ci_top); + L->top = restorestack(L, top); + } +} + + +static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { + int i; + int nfixargs = p->numparams; + Table *htab = NULL; + StkId base, fixed; + for (; actual < nfixargs; ++actual) + setnilvalue(L->top++); +#if defined(LUA_COMPAT_VARARG) + if (p->is_vararg & VARARG_NEEDSARG) { /* compat. with old-style vararg? */ + int nvar = actual - nfixargs; /* number of extra arguments */ + lua_assert(p->is_vararg & VARARG_HASARG); + luaC_checkGC(L); + htab = luaH_new(L, nvar, 1); /* create `arg' table */ + for (i=0; itop - nvar + i); + /* store counter in field `n' */ + setnvalue(luaH_setstr(L, htab, luaS_newliteral(L, "n")), cast_num(nvar)); + } +#endif + /* move fixed parameters to final position */ + fixed = L->top - actual; /* first fixed argument */ + base = L->top; /* final position of first argument */ + for (i=0; itop++, fixed+i); + setnilvalue(fixed+i); + } + /* add `arg' parameter */ + if (htab) { + sethvalue(L, L->top++, htab); + lua_assert(iswhite(obj2gco(htab))); + } + return base; +} + + +static StkId tryfuncTM (lua_State *L, StkId func) { + const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); + StkId p; + ptrdiff_t funcr = savestack(L, func); + if (!ttisfunction(tm)) + luaG_typeerror(L, func, "call"); + /* Open a hole inside the stack at `func' */ + for (p = L->top; p > func; p--) setobjs2s(L, p, p-1); + incr_top(L); + func = restorestack(L, funcr); /* previous call may change stack */ + setobj2s(L, func, tm); /* tag method is the new function to be called */ + return func; +} + + + +#define inc_ci(L) \ + ((L->ci == L->end_ci) ? growCI(L) : \ + (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) + + +int luaD_precall (lua_State *L, StkId func, int nresults) { + LClosure *cl; + ptrdiff_t funcr; + if (!ttisfunction(func)) /* `func' is not a function? */ + func = tryfuncTM(L, func); /* check the `function' tag method */ + funcr = savestack(L, func); + cl = &clvalue(func)->l; + L->ci->savedpc = L->savedpc; + if (!cl->isC) { /* Lua function? prepare its call */ + CallInfo *ci; + StkId st, base; + Proto *p = cl->p; + luaD_checkstack(L, p->maxstacksize); + func = restorestack(L, funcr); + if (!p->is_vararg) { /* no varargs? */ + base = func + 1; + if (L->top > base + p->numparams) + L->top = base + p->numparams; + } + else { /* vararg function */ + int nargs = cast_int(L->top - func) - 1; + base = adjust_varargs(L, p, nargs); + func = restorestack(L, funcr); /* previous call may change the stack */ + } + ci = inc_ci(L); /* now `enter' new function */ + ci->func = func; + L->base = ci->base = base; + ci->top = L->base + p->maxstacksize; + lua_assert(ci->top <= L->stack_last); + L->savedpc = p->code; /* starting point */ + ci->tailcalls = 0; + ci->nresults = nresults; + for (st = L->top; st < ci->top; st++) + setnilvalue(st); + L->top = ci->top; + if (L->hookmask & LUA_MASKCALL) { + L->savedpc++; /* hooks assume 'pc' is already incremented */ + luaD_callhook(L, LUA_HOOKCALL, -1); + L->savedpc--; /* correct 'pc' */ + } + return PCRLUA; + } + else { /* if is a C function, call it */ + CallInfo *ci; + int n; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci = inc_ci(L); /* now `enter' new function */ + ci->func = restorestack(L, funcr); + L->base = ci->base = ci->func + 1; + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->nresults = nresults; + if (L->hookmask & LUA_MASKCALL) + luaD_callhook(L, LUA_HOOKCALL, -1); + lua_unlock(L); + n = (*curr_func(L)->c.f)(L); /* do the actual call */ + lua_lock(L); + if (n < 0) /* yielding? */ + return PCRYIELD; + else { + luaD_poscall(L, L->top - n); + return PCRC; + } + } +} + + +static StkId callrethooks (lua_State *L, StkId firstResult) { + ptrdiff_t fr = savestack(L, firstResult); /* next call may change stack */ + luaD_callhook(L, LUA_HOOKRET, -1); + if (f_isLua(L->ci)) { /* Lua function? */ + while ((L->hookmask & LUA_MASKRET) && L->ci->tailcalls--) /* tail calls */ + luaD_callhook(L, LUA_HOOKTAILRET, -1); + } + return restorestack(L, fr); +} + + +int luaD_poscall (lua_State *L, StkId firstResult) { + StkId res; + int wanted, i; + CallInfo *ci; + if (L->hookmask & LUA_MASKRET) + firstResult = callrethooks(L, firstResult); + ci = L->ci--; + res = ci->func; /* res == final position of 1st result */ + wanted = ci->nresults; + L->base = (ci - 1)->base; /* restore base */ + L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ + /* move results to correct place */ + for (i = wanted; i != 0 && firstResult < L->top; i--) + setobjs2s(L, res++, firstResult++); + while (i-- > 0) + setnilvalue(res++); + L->top = res; + return (wanted - LUA_MULTRET); /* 0 iff wanted == LUA_MULTRET */ +} + + +/* +** Call a function (C or Lua). The function to be called is at *func. +** The arguments are on the stack, right after the function. +** When returns, all the results are on the stack, starting at the original +** function position. +*/ +void luaD_call (lua_State *L, StkId func, int nResults) { + if (++L->nCcalls >= LUAI_MAXCCALLS) { + if (L->nCcalls == LUAI_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ + } + if (luaD_precall(L, func, nResults) == PCRLUA) /* is a Lua function? */ + luaV_execute(L, 1); /* call it */ + L->nCcalls--; + luaC_checkGC(L); +} + + +static void resume (lua_State *L, void *ud) { + StkId firstArg = cast(StkId, ud); + CallInfo *ci = L->ci; + if (L->status == 0) { /* start coroutine? */ + lua_assert(ci == L->base_ci && firstArg > L->base); + if (luaD_precall(L, firstArg - 1, LUA_MULTRET) != PCRLUA) + return; + } + else { /* resuming from previous yield */ + lua_assert(L->status == LUA_YIELD); + L->status = 0; + if (!f_isLua(ci)) { /* `common' yield? */ + /* finish interrupted execution of `OP_CALL' */ + lua_assert(GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_CALL || + GET_OPCODE(*((ci-1)->savedpc - 1)) == OP_TAILCALL); + if (luaD_poscall(L, firstArg)) /* complete it... */ + L->top = L->ci->top; /* and correct top if not multiple results */ + } + else /* yielded inside a hook: just continue its execution */ + L->base = L->ci->base; + } + luaV_execute(L, cast_int(L->ci - L->base_ci)); +} + + +static int resume_error (lua_State *L, const char *msg) { + L->top = L->ci->base; + setsvalue2s(L, L->top, luaS_new(L, msg)); + incr_top(L); + lua_unlock(L); + return LUA_ERRRUN; +} + + +LUA_API int lua_resume (lua_State *L, int nargs) { + int status; + lua_lock(L); + if (L->status != LUA_YIELD && (L->status != 0 || L->ci != L->base_ci)) + return resume_error(L, "cannot resume non-suspended coroutine"); + if (L->nCcalls >= LUAI_MAXCCALLS) + return resume_error(L, "C stack overflow"); + luai_userstateresume(L, nargs); + lua_assert(L->errfunc == 0); + L->baseCcalls = ++L->nCcalls; + status = luaD_rawrunprotected(L, resume, L->top - nargs); + if (status != 0) { /* error? */ + L->status = cast_byte(status); /* mark thread as `dead' */ + luaD_seterrorobj(L, status, L->top); + L->ci->top = L->top; + } + else { + lua_assert(L->nCcalls == L->baseCcalls); + status = L->status; + } + --L->nCcalls; + lua_unlock(L); + return status; +} + + +LUA_API int lua_yield (lua_State *L, int nresults) { + luai_userstateyield(L, nresults); + lua_lock(L); + if (L->nCcalls > L->baseCcalls) + luaG_runerror(L, "attempt to yield across metamethod/C-call boundary"); + L->base = L->top - nresults; /* protect stack slots below */ + L->status = LUA_YIELD; + lua_unlock(L); + return -1; +} + + +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t old_top, ptrdiff_t ef) { + int status; + unsigned short oldnCcalls = L->nCcalls; + ptrdiff_t old_ci = saveci(L, L->ci); + lu_byte old_allowhooks = L->allowhook; + ptrdiff_t old_errfunc = L->errfunc; + L->errfunc = ef; + status = luaD_rawrunprotected(L, func, u); + if (status != 0) { /* an error occurred? */ + StkId oldtop = restorestack(L, old_top); + luaF_close(L, oldtop); /* close eventual pending closures */ + luaD_seterrorobj(L, status, oldtop); + L->nCcalls = oldnCcalls; + L->ci = restoreci(L, old_ci); + L->base = L->ci->base; + L->savedpc = L->ci->savedpc; + L->allowhook = old_allowhooks; + restore_stack_limit(L); + } + L->errfunc = old_errfunc; + return status; +} + + + +/* +** Execute a protected parser. +*/ +struct SParser { /* data to `f_parser' */ + ZIO *z; + Mbuffer buff; /* buffer to be used by the scanner */ + const char *name; +}; + +static void f_parser (lua_State *L, void *ud) { + int i; + Proto *tf; + Closure *cl; + struct SParser *p = cast(struct SParser *, ud); + int c = luaZ_lookahead(p->z); + luaC_checkGC(L); + tf = ((c == LUA_SIGNATURE[0]) ? luaU_undump : luaY_parser)(L, p->z, + &p->buff, p->name); + cl = luaF_newLclosure(L, tf->nups, hvalue(gt(L))); + cl->l.p = tf; + for (i = 0; i < tf->nups; i++) /* initialize eventual upvalues */ + cl->l.upvals[i] = luaF_newupval(L); + setclvalue(L, L->top, cl); + incr_top(L); +} + + +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { + struct SParser p; + int status; + p.z = z; p.name = name; + luaZ_initbuffer(L, &p.buff); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + luaZ_freebuffer(L, &p.buff); + return status; +} + + diff --git a/src/lua/src/ldo.h b/src/lua/src/ldo.h new file mode 100644 index 00000000..98fddac5 --- /dev/null +++ b/src/lua/src/ldo.h @@ -0,0 +1,57 @@ +/* +** $Id: ldo.h,v 2.7.1.1 2007/12/27 13:02:25 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#ifndef ldo_h +#define ldo_h + + +#include "lobject.h" +#include "lstate.h" +#include "lzio.h" + + +#define luaD_checkstack(L,n) \ + if ((char *)L->stack_last - (char *)L->top <= (n)*(int)sizeof(TValue)) \ + luaD_growstack(L, n); \ + else condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); + + +#define incr_top(L) {luaD_checkstack(L,1); L->top++;} + +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) + +#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) +#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) + + +/* results from luaD_precall */ +#define PCRLUA 0 /* initiated a call to a Lua function */ +#define PCRC 1 /* did a call to a C function */ +#define PCRYIELD 2 /* C funtion yielded */ + + +/* type of protected functions, to be ran by `runprotected' */ +typedef void (*Pfunc) (lua_State *L, void *ud); + +LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); +LUAI_FUNC void luaD_callhook (lua_State *L, int event, int line); +LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); +LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); +LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t oldtop, ptrdiff_t ef); +LUAI_FUNC int luaD_poscall (lua_State *L, StkId firstResult); +LUAI_FUNC void luaD_reallocCI (lua_State *L, int newsize); +LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); +LUAI_FUNC void luaD_growstack (lua_State *L, int n); + +LUAI_FUNC void luaD_throw (lua_State *L, int errcode); +LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); + +LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); + +#endif + diff --git a/src/lua/src/ldump.c b/src/lua/src/ldump.c new file mode 100644 index 00000000..c9d3d487 --- /dev/null +++ b/src/lua/src/ldump.c @@ -0,0 +1,164 @@ +/* +** $Id: ldump.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ +** save precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#include + +#define ldump_c +#define LUA_CORE + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lundump.h" + +typedef struct { + lua_State* L; + lua_Writer writer; + void* data; + int strip; + int status; +} DumpState; + +#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) +#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) + +static void DumpBlock(const void* b, size_t size, DumpState* D) +{ + if (D->status==0) + { + lua_unlock(D->L); + D->status=(*D->writer)(D->L,b,size,D->data); + lua_lock(D->L); + } +} + +static void DumpChar(int y, DumpState* D) +{ + char x=(char)y; + DumpVar(x,D); +} + +static void DumpInt(int x, DumpState* D) +{ + DumpVar(x,D); +} + +static void DumpNumber(lua_Number x, DumpState* D) +{ + DumpVar(x,D); +} + +static void DumpVector(const void* b, int n, size_t size, DumpState* D) +{ + DumpInt(n,D); + DumpMem(b,n,size,D); +} + +static void DumpString(const TString* s, DumpState* D) +{ + if (s==NULL || getstr(s)==NULL) + { + size_t size=0; + DumpVar(size,D); + } + else + { + size_t size=s->tsv.len+1; /* include trailing '\0' */ + DumpVar(size,D); + DumpBlock(getstr(s),size,D); + } +} + +#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) + +static void DumpFunction(const Proto* f, const TString* p, DumpState* D); + +static void DumpConstants(const Proto* f, DumpState* D) +{ + int i,n=f->sizek; + DumpInt(n,D); + for (i=0; ik[i]; + DumpChar(ttype(o),D); + switch (ttype(o)) + { + case LUA_TNIL: + break; + case LUA_TBOOLEAN: + DumpChar(bvalue(o),D); + break; + case LUA_TNUMBER: + DumpNumber(nvalue(o),D); + break; + case LUA_TSTRING: + DumpString(rawtsvalue(o),D); + break; + default: + lua_assert(0); /* cannot happen */ + break; + } + } + n=f->sizep; + DumpInt(n,D); + for (i=0; ip[i],f->source,D); +} + +static void DumpDebug(const Proto* f, DumpState* D) +{ + int i,n; + n= (D->strip) ? 0 : f->sizelineinfo; + DumpVector(f->lineinfo,n,sizeof(int),D); + n= (D->strip) ? 0 : f->sizelocvars; + DumpInt(n,D); + for (i=0; ilocvars[i].varname,D); + DumpInt(f->locvars[i].startpc,D); + DumpInt(f->locvars[i].endpc,D); + } + n= (D->strip) ? 0 : f->sizeupvalues; + DumpInt(n,D); + for (i=0; iupvalues[i],D); +} + +static void DumpFunction(const Proto* f, const TString* p, DumpState* D) +{ + DumpString((f->source==p || D->strip) ? NULL : f->source,D); + DumpInt(f->linedefined,D); + DumpInt(f->lastlinedefined,D); + DumpChar(f->nups,D); + DumpChar(f->numparams,D); + DumpChar(f->is_vararg,D); + DumpChar(f->maxstacksize,D); + DumpCode(f,D); + DumpConstants(f,D); + DumpDebug(f,D); +} + +static void DumpHeader(DumpState* D) +{ + char h[LUAC_HEADERSIZE]; + luaU_header(h); + DumpBlock(h,LUAC_HEADERSIZE,D); +} + +/* +** dump Lua function as precompiled chunk +*/ +int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip) +{ + DumpState D; + D.L=L; + D.writer=w; + D.data=data; + D.strip=strip; + D.status=0; + DumpHeader(&D); + DumpFunction(f,NULL,&D); + return D.status; +} diff --git a/src/lua/src/lfunc.c b/src/lua/src/lfunc.c new file mode 100644 index 00000000..813e88f5 --- /dev/null +++ b/src/lua/src/lfunc.c @@ -0,0 +1,174 @@ +/* +** $Id: lfunc.c,v 2.12.1.2 2007/12/28 14:58:43 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + + +#include + +#define lfunc_c +#define LUA_CORE + +#include "lua.h" + +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e) { + Closure *c = cast(Closure *, luaM_malloc(L, sizeCclosure(nelems))); + luaC_link(L, obj2gco(c), LUA_TFUNCTION); + c->c.isC = 1; + c->c.env = e; + c->c.nupvalues = cast_byte(nelems); + return c; +} + + +Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e) { + Closure *c = cast(Closure *, luaM_malloc(L, sizeLclosure(nelems))); + luaC_link(L, obj2gco(c), LUA_TFUNCTION); + c->l.isC = 0; + c->l.env = e; + c->l.nupvalues = cast_byte(nelems); + while (nelems--) c->l.upvals[nelems] = NULL; + return c; +} + + +UpVal *luaF_newupval (lua_State *L) { + UpVal *uv = luaM_new(L, UpVal); + luaC_link(L, obj2gco(uv), LUA_TUPVAL); + uv->v = &uv->u.value; + setnilvalue(uv->v); + return uv; +} + + +UpVal *luaF_findupval (lua_State *L, StkId level) { + global_State *g = G(L); + GCObject **pp = &L->openupval; + UpVal *p; + UpVal *uv; + while (*pp != NULL && (p = ngcotouv(*pp))->v >= level) { + lua_assert(p->v != &p->u.value); + if (p->v == level) { /* found a corresponding upvalue? */ + if (isdead(g, obj2gco(p))) /* is it dead? */ + changewhite(obj2gco(p)); /* ressurect it */ + return p; + } + pp = &p->next; + } + uv = luaM_new(L, UpVal); /* not found: create a new one */ + uv->tt = LUA_TUPVAL; + uv->marked = luaC_white(g); + uv->v = level; /* current value lives in the stack */ + uv->next = *pp; /* chain it in the proper position */ + *pp = obj2gco(uv); + uv->u.l.prev = &g->uvhead; /* double link it in `uvhead' list */ + uv->u.l.next = g->uvhead.u.l.next; + uv->u.l.next->u.l.prev = uv; + g->uvhead.u.l.next = uv; + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + return uv; +} + + +static void unlinkupval (UpVal *uv) { + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + uv->u.l.next->u.l.prev = uv->u.l.prev; /* remove from `uvhead' list */ + uv->u.l.prev->u.l.next = uv->u.l.next; +} + + +void luaF_freeupval (lua_State *L, UpVal *uv) { + if (uv->v != &uv->u.value) /* is it open? */ + unlinkupval(uv); /* remove from open list */ + luaM_free(L, uv); /* free upvalue */ +} + + +void luaF_close (lua_State *L, StkId level) { + UpVal *uv; + global_State *g = G(L); + while (L->openupval != NULL && (uv = ngcotouv(L->openupval))->v >= level) { + GCObject *o = obj2gco(uv); + lua_assert(!isblack(o) && uv->v != &uv->u.value); + L->openupval = uv->next; /* remove from `open' list */ + if (isdead(g, o)) + luaF_freeupval(L, uv); /* free upvalue */ + else { + unlinkupval(uv); + setobj(L, &uv->u.value, uv->v); + uv->v = &uv->u.value; /* now current value lives here */ + luaC_linkupval(L, uv); /* link upvalue into `gcroot' list */ + } + } +} + + +Proto *luaF_newproto (lua_State *L) { + Proto *f = luaM_new(L, Proto); + luaC_link(L, obj2gco(f), LUA_TPROTO); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->sizecode = 0; + f->sizelineinfo = 0; + f->sizeupvalues = 0; + f->nups = 0; + f->upvalues = NULL; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->lineinfo = NULL; + f->sizelocvars = 0; + f->locvars = NULL; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + + +void luaF_freeproto (lua_State *L, Proto *f) { + luaM_freearray(L, f->code, f->sizecode, Instruction); + luaM_freearray(L, f->p, f->sizep, Proto *); + luaM_freearray(L, f->k, f->sizek, TValue); + luaM_freearray(L, f->lineinfo, f->sizelineinfo, int); + luaM_freearray(L, f->locvars, f->sizelocvars, struct LocVar); + luaM_freearray(L, f->upvalues, f->sizeupvalues, TString *); + luaM_free(L, f); +} + + +void luaF_freeclosure (lua_State *L, Closure *c) { + int size = (c->c.isC) ? sizeCclosure(c->c.nupvalues) : + sizeLclosure(c->l.nupvalues); + luaM_freemem(L, c, size); +} + + +/* +** Look for n-th local variable at line `line' in function `func'. +** Returns NULL if not found. +*/ +const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { + int i; + for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { + if (pc < f->locvars[i].endpc) { /* is variable active? */ + local_number--; + if (local_number == 0) + return getstr(f->locvars[i].varname); + } + } + return NULL; /* not found */ +} + diff --git a/src/lua/src/lfunc.h b/src/lua/src/lfunc.h new file mode 100644 index 00000000..a68cf515 --- /dev/null +++ b/src/lua/src/lfunc.h @@ -0,0 +1,34 @@ +/* +** $Id: lfunc.h,v 2.4.1.1 2007/12/27 13:02:25 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#ifndef lfunc_h +#define lfunc_h + + +#include "lobject.h" + + +#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ + cast(int, sizeof(TValue)*((n)-1))) + +#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ + cast(int, sizeof(TValue *)*((n)-1))) + + +LUAI_FUNC Proto *luaF_newproto (lua_State *L); +LUAI_FUNC Closure *luaF_newCclosure (lua_State *L, int nelems, Table *e); +LUAI_FUNC Closure *luaF_newLclosure (lua_State *L, int nelems, Table *e); +LUAI_FUNC UpVal *luaF_newupval (lua_State *L); +LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); +LUAI_FUNC void luaF_close (lua_State *L, StkId level); +LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); +LUAI_FUNC void luaF_freeclosure (lua_State *L, Closure *c); +LUAI_FUNC void luaF_freeupval (lua_State *L, UpVal *uv); +LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, + int pc); + + +#endif diff --git a/src/lua/src/lgc.c b/src/lua/src/lgc.c new file mode 100644 index 00000000..d9e0b782 --- /dev/null +++ b/src/lua/src/lgc.c @@ -0,0 +1,711 @@ +/* +** $Id: lgc.c,v 2.38.1.1 2007/12/27 13:02:25 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#include + +#define lgc_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +#define GCSTEPSIZE 1024u +#define GCSWEEPMAX 40 +#define GCSWEEPCOST 10 +#define GCFINALIZECOST 100 + + +#define maskmarks cast_byte(~(bitmask(BLACKBIT)|WHITEBITS)) + +#define makewhite(g,x) \ + ((x)->gch.marked = cast_byte(((x)->gch.marked & maskmarks) | luaC_white(g))) + +#define white2gray(x) reset2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) +#define black2gray(x) resetbit((x)->gch.marked, BLACKBIT) + +#define stringmark(s) reset2bits((s)->tsv.marked, WHITE0BIT, WHITE1BIT) + + +#define isfinalized(u) testbit((u)->marked, FINALIZEDBIT) +#define markfinalized(u) l_setbit((u)->marked, FINALIZEDBIT) + + +#define KEYWEAK bitmask(KEYWEAKBIT) +#define VALUEWEAK bitmask(VALUEWEAKBIT) + + + +#define markvalue(g,o) { checkconsistency(o); \ + if (iscollectable(o) && iswhite(gcvalue(o))) reallymarkobject(g,gcvalue(o)); } + +#define markobject(g,t) { if (iswhite(obj2gco(t))) \ + reallymarkobject(g, obj2gco(t)); } + + +#define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) + + +static void removeentry (Node *n) { + lua_assert(ttisnil(gval(n))); + if (iscollectable(gkey(n))) + setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ +} + + +static void reallymarkobject (global_State *g, GCObject *o) { + lua_assert(iswhite(o) && !isdead(g, o)); + white2gray(o); + switch (o->gch.tt) { + case LUA_TSTRING: { + return; + } + case LUA_TUSERDATA: { + Table *mt = gco2u(o)->metatable; + gray2black(o); /* udata are never gray */ + if (mt) markobject(g, mt); + markobject(g, gco2u(o)->env); + return; + } + case LUA_TUPVAL: { + UpVal *uv = gco2uv(o); + markvalue(g, uv->v); + if (uv->v == &uv->u.value) /* closed? */ + gray2black(o); /* open upvalues are never black */ + return; + } + case LUA_TFUNCTION: { + gco2cl(o)->c.gclist = g->gray; + g->gray = o; + break; + } + case LUA_TTABLE: { + gco2h(o)->gclist = g->gray; + g->gray = o; + break; + } + case LUA_TTHREAD: { + gco2th(o)->gclist = g->gray; + g->gray = o; + break; + } + case LUA_TPROTO: { + gco2p(o)->gclist = g->gray; + g->gray = o; + break; + } + default: lua_assert(0); + } +} + + +static void marktmu (global_State *g) { + GCObject *u = g->tmudata; + if (u) { + do { + u = u->gch.next; + makewhite(g, u); /* may be marked, if left from previous GC */ + reallymarkobject(g, u); + } while (u != g->tmudata); + } +} + + +/* move `dead' udata that need finalization to list `tmudata' */ +size_t luaC_separateudata (lua_State *L, int all) { + global_State *g = G(L); + size_t deadmem = 0; + GCObject **p = &g->mainthread->next; + GCObject *curr; + while ((curr = *p) != NULL) { + if (!(iswhite(curr) || all) || isfinalized(gco2u(curr))) + p = &curr->gch.next; /* don't bother with them */ + else if (fasttm(L, gco2u(curr)->metatable, TM_GC) == NULL) { + markfinalized(gco2u(curr)); /* don't need finalization */ + p = &curr->gch.next; + } + else { /* must call its gc method */ + deadmem += sizeudata(gco2u(curr)); + markfinalized(gco2u(curr)); + *p = curr->gch.next; + /* link `curr' at the end of `tmudata' list */ + if (g->tmudata == NULL) /* list is empty? */ + g->tmudata = curr->gch.next = curr; /* creates a circular list */ + else { + curr->gch.next = g->tmudata->gch.next; + g->tmudata->gch.next = curr; + g->tmudata = curr; + } + } + } + return deadmem; +} + + +static int traversetable (global_State *g, Table *h) { + int i; + int weakkey = 0; + int weakvalue = 0; + const TValue *mode; + if (h->metatable) + markobject(g, h->metatable); + mode = gfasttm(g, h->metatable, TM_MODE); + if (mode && ttisstring(mode)) { /* is there a weak mode? */ + weakkey = (strchr(svalue(mode), 'k') != NULL); + weakvalue = (strchr(svalue(mode), 'v') != NULL); + if (weakkey || weakvalue) { /* is really weak? */ + h->marked &= ~(KEYWEAK | VALUEWEAK); /* clear bits */ + h->marked |= cast_byte((weakkey << KEYWEAKBIT) | + (weakvalue << VALUEWEAKBIT)); + h->gclist = g->weak; /* must be cleared after GC, ... */ + g->weak = obj2gco(h); /* ... so put in the appropriate list */ + } + } + if (weakkey && weakvalue) return 1; + if (!weakvalue) { + i = h->sizearray; + while (i--) + markvalue(g, &h->array[i]); + } + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + lua_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); + if (ttisnil(gval(n))) + removeentry(n); /* remove empty entries */ + else { + lua_assert(!ttisnil(gkey(n))); + if (!weakkey) markvalue(g, gkey(n)); + if (!weakvalue) markvalue(g, gval(n)); + } + } + return weakkey || weakvalue; +} + + +/* +** All marks are conditional because a GC may happen while the +** prototype is still being created +*/ +static void traverseproto (global_State *g, Proto *f) { + int i; + if (f->source) stringmark(f->source); + for (i=0; isizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i=0; isizeupvalues; i++) { /* mark upvalue names */ + if (f->upvalues[i]) + stringmark(f->upvalues[i]); + } + for (i=0; isizep; i++) { /* mark nested protos */ + if (f->p[i]) + markobject(g, f->p[i]); + } + for (i=0; isizelocvars; i++) { /* mark local-variable names */ + if (f->locvars[i].varname) + stringmark(f->locvars[i].varname); + } +} + + + +static void traverseclosure (global_State *g, Closure *cl) { + markobject(g, cl->c.env); + if (cl->c.isC) { + int i; + for (i=0; ic.nupvalues; i++) /* mark its upvalues */ + markvalue(g, &cl->c.upvalue[i]); + } + else { + int i; + lua_assert(cl->l.nupvalues == cl->l.p->nups); + markobject(g, cl->l.p); + for (i=0; il.nupvalues; i++) /* mark its upvalues */ + markobject(g, cl->l.upvals[i]); + } +} + + +static void checkstacksizes (lua_State *L, StkId max) { + int ci_used = cast_int(L->ci - L->base_ci); /* number of `ci' in use */ + int s_used = cast_int(max - L->stack); /* part of stack in use */ + if (L->size_ci > LUAI_MAXCALLS) /* handling overflow? */ + return; /* do not touch the stacks */ + if (4*ci_used < L->size_ci && 2*BASIC_CI_SIZE < L->size_ci) + luaD_reallocCI(L, L->size_ci/2); /* still big enough... */ + condhardstacktests(luaD_reallocCI(L, ci_used + 1)); + if (4*s_used < L->stacksize && + 2*(BASIC_STACK_SIZE+EXTRA_STACK) < L->stacksize) + luaD_reallocstack(L, L->stacksize/2); /* still big enough... */ + condhardstacktests(luaD_reallocstack(L, s_used)); +} + + +static void traversestack (global_State *g, lua_State *l) { + StkId o, lim; + CallInfo *ci; + markvalue(g, gt(l)); + lim = l->top; + for (ci = l->base_ci; ci <= l->ci; ci++) { + lua_assert(ci->top <= l->stack_last); + if (lim < ci->top) lim = ci->top; + } + for (o = l->stack; o < l->top; o++) + markvalue(g, o); + for (; o <= lim; o++) + setnilvalue(o); + checkstacksizes(l, lim); +} + + +/* +** traverse one gray object, turning it to black. +** Returns `quantity' traversed. +*/ +static l_mem propagatemark (global_State *g) { + GCObject *o = g->gray; + lua_assert(isgray(o)); + gray2black(o); + switch (o->gch.tt) { + case LUA_TTABLE: { + Table *h = gco2h(o); + g->gray = h->gclist; + if (traversetable(g, h)) /* table is weak? */ + black2gray(o); /* keep it gray */ + return sizeof(Table) + sizeof(TValue) * h->sizearray + + sizeof(Node) * sizenode(h); + } + case LUA_TFUNCTION: { + Closure *cl = gco2cl(o); + g->gray = cl->c.gclist; + traverseclosure(g, cl); + return (cl->c.isC) ? sizeCclosure(cl->c.nupvalues) : + sizeLclosure(cl->l.nupvalues); + } + case LUA_TTHREAD: { + lua_State *th = gco2th(o); + g->gray = th->gclist; + th->gclist = g->grayagain; + g->grayagain = o; + black2gray(o); + traversestack(g, th); + return sizeof(lua_State) + sizeof(TValue) * th->stacksize + + sizeof(CallInfo) * th->size_ci; + } + case LUA_TPROTO: { + Proto *p = gco2p(o); + g->gray = p->gclist; + traverseproto(g, p); + return sizeof(Proto) + sizeof(Instruction) * p->sizecode + + sizeof(Proto *) * p->sizep + + sizeof(TValue) * p->sizek + + sizeof(int) * p->sizelineinfo + + sizeof(LocVar) * p->sizelocvars + + sizeof(TString *) * p->sizeupvalues; + } + default: lua_assert(0); return 0; + } +} + + +static size_t propagateall (global_State *g) { + size_t m = 0; + while (g->gray) m += propagatemark(g); + return m; +} + + +/* +** The next function tells whether a key or value can be cleared from +** a weak table. Non-collectable objects are never removed from weak +** tables. Strings behave as `values', so are never removed too. for +** other objects: if really collected, cannot keep them; for userdata +** being finalized, keep them in keys, but not in values +*/ +static int iscleared (const TValue *o, int iskey) { + if (!iscollectable(o)) return 0; + if (ttisstring(o)) { + stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ + return 0; + } + return iswhite(gcvalue(o)) || + (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); +} + + +/* +** clear collected entries from weaktables +*/ +static void cleartable (GCObject *l) { + while (l) { + Table *h = gco2h(l); + int i = h->sizearray; + lua_assert(testbit(h->marked, VALUEWEAKBIT) || + testbit(h->marked, KEYWEAKBIT)); + if (testbit(h->marked, VALUEWEAKBIT)) { + while (i--) { + TValue *o = &h->array[i]; + if (iscleared(o, 0)) /* value was collected? */ + setnilvalue(o); /* remove value */ + } + } + i = sizenode(h); + while (i--) { + Node *n = gnode(h, i); + if (!ttisnil(gval(n)) && /* non-empty entry? */ + (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* remove entry from table */ + } + } + l = h->gclist; + } +} + + +static void freeobj (lua_State *L, GCObject *o) { + switch (o->gch.tt) { + case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; + case LUA_TFUNCTION: luaF_freeclosure(L, gco2cl(o)); break; + case LUA_TUPVAL: luaF_freeupval(L, gco2uv(o)); break; + case LUA_TTABLE: luaH_free(L, gco2h(o)); break; + case LUA_TTHREAD: { + lua_assert(gco2th(o) != L && gco2th(o) != G(L)->mainthread); + luaE_freethread(L, gco2th(o)); + break; + } + case LUA_TSTRING: { + G(L)->strt.nuse--; + luaM_freemem(L, o, sizestring(gco2ts(o))); + break; + } + case LUA_TUSERDATA: { + luaM_freemem(L, o, sizeudata(gco2u(o))); + break; + } + default: lua_assert(0); + } +} + + + +#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) + + +static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { + GCObject *curr; + global_State *g = G(L); + int deadmask = otherwhite(g); + while ((curr = *p) != NULL && count-- > 0) { + if (curr->gch.tt == LUA_TTHREAD) /* sweep open upvalues of each thread */ + sweepwholelist(L, &gco2th(curr)->openupval); + if ((curr->gch.marked ^ WHITEBITS) & deadmask) { /* not dead? */ + lua_assert(!isdead(g, curr) || testbit(curr->gch.marked, FIXEDBIT)); + makewhite(g, curr); /* make it white (for next cycle) */ + p = &curr->gch.next; + } + else { /* must erase `curr' */ + lua_assert(isdead(g, curr) || deadmask == bitmask(SFIXEDBIT)); + *p = curr->gch.next; + if (curr == g->rootgc) /* is the first element of the list? */ + g->rootgc = curr->gch.next; /* adjust first */ + freeobj(L, curr); + } + } + return p; +} + + +static void checkSizes (lua_State *L) { + global_State *g = G(L); + /* check size of string hash */ + if (g->strt.nuse < cast(lu_int32, g->strt.size/4) && + g->strt.size > MINSTRTABSIZE*2) + luaS_resize(L, g->strt.size/2); /* table is too big */ + /* check size of buffer */ + if (luaZ_sizebuffer(&g->buff) > LUA_MINBUFFER*2) { /* buffer too big? */ + size_t newsize = luaZ_sizebuffer(&g->buff) / 2; + luaZ_resizebuffer(L, &g->buff, newsize); + } +} + + +static void GCTM (lua_State *L) { + global_State *g = G(L); + GCObject *o = g->tmudata->gch.next; /* get first element */ + Udata *udata = rawgco2u(o); + const TValue *tm; + /* remove udata from `tmudata' */ + if (o == g->tmudata) /* last element? */ + g->tmudata = NULL; + else + g->tmudata->gch.next = udata->uv.next; + udata->uv.next = g->mainthread->next; /* return it to `root' list */ + g->mainthread->next = o; + makewhite(g, o); + tm = fasttm(L, udata->uv.metatable, TM_GC); + if (tm != NULL) { + lu_byte oldah = L->allowhook; + lu_mem oldt = g->GCthreshold; + L->allowhook = 0; /* stop debug hooks during GC tag method */ + g->GCthreshold = 2*g->totalbytes; /* avoid GC steps */ + setobj2s(L, L->top, tm); + setuvalue(L, L->top+1, udata); + L->top += 2; + luaD_call(L, L->top - 2, 0); + L->allowhook = oldah; /* restore hooks */ + g->GCthreshold = oldt; /* restore threshold */ + } +} + + +/* +** Call all GC tag methods +*/ +void luaC_callGCTM (lua_State *L) { + while (G(L)->tmudata) + GCTM(L); +} + + +void luaC_freeall (lua_State *L) { + global_State *g = G(L); + int i; + g->currentwhite = WHITEBITS | bitmask(SFIXEDBIT); /* mask to collect all elements */ + sweepwholelist(L, &g->rootgc); + for (i = 0; i < g->strt.size; i++) /* free all string lists */ + sweepwholelist(L, &g->strt.hash[i]); +} + + +static void markmt (global_State *g) { + int i; + for (i=0; imt[i]) markobject(g, g->mt[i]); +} + + +/* mark root set */ +static void markroot (lua_State *L) { + global_State *g = G(L); + g->gray = NULL; + g->grayagain = NULL; + g->weak = NULL; + markobject(g, g->mainthread); + /* make global table be traversed before main stack */ + markvalue(g, gt(g->mainthread)); + markvalue(g, registry(L)); + markmt(g); + g->gcstate = GCSpropagate; +} + + +static void remarkupvals (global_State *g) { + UpVal *uv; + for (uv = g->uvhead.u.l.next; uv != &g->uvhead; uv = uv->u.l.next) { + lua_assert(uv->u.l.next->u.l.prev == uv && uv->u.l.prev->u.l.next == uv); + if (isgray(obj2gco(uv))) + markvalue(g, uv->v); + } +} + + +static void atomic (lua_State *L) { + global_State *g = G(L); + size_t udsize; /* total size of userdata to be finalized */ + /* remark occasional upvalues of (maybe) dead threads */ + remarkupvals(g); + /* traverse objects cautch by write barrier and by 'remarkupvals' */ + propagateall(g); + /* remark weak tables */ + g->gray = g->weak; + g->weak = NULL; + lua_assert(!iswhite(obj2gco(g->mainthread))); + markobject(g, L); /* mark running thread */ + markmt(g); /* mark basic metatables (again) */ + propagateall(g); + /* remark gray again */ + g->gray = g->grayagain; + g->grayagain = NULL; + propagateall(g); + udsize = luaC_separateudata(L, 0); /* separate userdata to be finalized */ + marktmu(g); /* mark `preserved' userdata */ + udsize += propagateall(g); /* remark, to propagate `preserveness' */ + cleartable(g->weak); /* remove collected objects from weak tables */ + /* flip current white */ + g->currentwhite = cast_byte(otherwhite(g)); + g->sweepstrgc = 0; + g->sweepgc = &g->rootgc; + g->gcstate = GCSsweepstring; + g->estimate = g->totalbytes - udsize; /* first estimate */ +} + + +static l_mem singlestep (lua_State *L) { + global_State *g = G(L); + /*lua_checkmemory(L);*/ + switch (g->gcstate) { + case GCSpause: { + markroot(L); /* start a new collection */ + return 0; + } + case GCSpropagate: { + if (g->gray) + return propagatemark(g); + else { /* no more `gray' objects */ + atomic(L); /* finish mark phase */ + return 0; + } + } + case GCSsweepstring: { + lu_mem old = g->totalbytes; + sweepwholelist(L, &g->strt.hash[g->sweepstrgc++]); + if (g->sweepstrgc >= g->strt.size) /* nothing more to sweep? */ + g->gcstate = GCSsweep; /* end sweep-string phase */ + lua_assert(old >= g->totalbytes); + g->estimate -= old - g->totalbytes; + return GCSWEEPCOST; + } + case GCSsweep: { + lu_mem old = g->totalbytes; + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); + if (*g->sweepgc == NULL) { /* nothing more to sweep? */ + checkSizes(L); + g->gcstate = GCSfinalize; /* end sweep phase */ + } + lua_assert(old >= g->totalbytes); + g->estimate -= old - g->totalbytes; + return GCSWEEPMAX*GCSWEEPCOST; + } + case GCSfinalize: { + if (g->tmudata) { + GCTM(L); + if (g->estimate > GCFINALIZECOST) + g->estimate -= GCFINALIZECOST; + return GCFINALIZECOST; + } + else { + g->gcstate = GCSpause; /* end collection */ + g->gcdept = 0; + return 0; + } + } + default: lua_assert(0); return 0; + } +} + + +void luaC_step (lua_State *L) { + global_State *g = G(L); + l_mem lim = (GCSTEPSIZE/100) * g->gcstepmul; + if (lim == 0) + lim = (MAX_LUMEM-1)/2; /* no limit */ + g->gcdept += g->totalbytes - g->GCthreshold; + do { + lim -= singlestep(L); + if (g->gcstate == GCSpause) + break; + } while (lim > 0); + if (g->gcstate != GCSpause) { + if (g->gcdept < GCSTEPSIZE) + g->GCthreshold = g->totalbytes + GCSTEPSIZE; /* - lim/g->gcstepmul;*/ + else { + g->gcdept -= GCSTEPSIZE; + g->GCthreshold = g->totalbytes; + } + } + else { + lua_assert(g->totalbytes >= g->estimate); + setthreshold(g); + } +} + + +void luaC_fullgc (lua_State *L) { + global_State *g = G(L); + if (g->gcstate <= GCSpropagate) { + /* reset sweep marks to sweep all elements (returning them to white) */ + g->sweepstrgc = 0; + g->sweepgc = &g->rootgc; + /* reset other collector lists */ + g->gray = NULL; + g->grayagain = NULL; + g->weak = NULL; + g->gcstate = GCSsweepstring; + } + lua_assert(g->gcstate != GCSpause && g->gcstate != GCSpropagate); + /* finish any pending sweep phase */ + while (g->gcstate != GCSfinalize) { + lua_assert(g->gcstate == GCSsweepstring || g->gcstate == GCSsweep); + singlestep(L); + } + markroot(L); + while (g->gcstate != GCSpause) { + singlestep(L); + } + setthreshold(g); +} + + +void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v) { + global_State *g = G(L); + lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); + lua_assert(ttype(&o->gch) != LUA_TTABLE); + /* must keep invariant? */ + if (g->gcstate == GCSpropagate) + reallymarkobject(g, v); /* restore invariant */ + else /* don't mind */ + makewhite(g, o); /* mark as white just to avoid other barriers */ +} + + +void luaC_barrierback (lua_State *L, Table *t) { + global_State *g = G(L); + GCObject *o = obj2gco(t); + lua_assert(isblack(o) && !isdead(g, o)); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); + black2gray(o); /* make table gray (again) */ + t->gclist = g->grayagain; + g->grayagain = o; +} + + +void luaC_link (lua_State *L, GCObject *o, lu_byte tt) { + global_State *g = G(L); + o->gch.next = g->rootgc; + g->rootgc = o; + o->gch.marked = luaC_white(g); + o->gch.tt = tt; +} + + +void luaC_linkupval (lua_State *L, UpVal *uv) { + global_State *g = G(L); + GCObject *o = obj2gco(uv); + o->gch.next = g->rootgc; /* link upvalue into `rootgc' list */ + g->rootgc = o; + if (isgray(o)) { + if (g->gcstate == GCSpropagate) { + gray2black(o); /* closed upvalues need barrier */ + luaC_barrier(L, uv, uv->v); + } + else { /* sweep phase: sweep it (turning it into white) */ + makewhite(g, o); + lua_assert(g->gcstate != GCSfinalize && g->gcstate != GCSpause); + } + } +} + diff --git a/src/lua/src/lgc.h b/src/lua/src/lgc.h new file mode 100644 index 00000000..5a8dc605 --- /dev/null +++ b/src/lua/src/lgc.h @@ -0,0 +1,110 @@ +/* +** $Id: lgc.h,v 2.15.1.1 2007/12/27 13:02:25 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#ifndef lgc_h +#define lgc_h + + +#include "lobject.h" + + +/* +** Possible states of the Garbage Collector +*/ +#define GCSpause 0 +#define GCSpropagate 1 +#define GCSsweepstring 2 +#define GCSsweep 3 +#define GCSfinalize 4 + + +/* +** some userful bit tricks +*/ +#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) +#define setbits(x,m) ((x) |= (m)) +#define testbits(x,m) ((x) & (m)) +#define bitmask(b) (1<<(b)) +#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) +#define l_setbit(x,b) setbits(x, bitmask(b)) +#define resetbit(x,b) resetbits(x, bitmask(b)) +#define testbit(x,b) testbits(x, bitmask(b)) +#define set2bits(x,b1,b2) setbits(x, (bit2mask(b1, b2))) +#define reset2bits(x,b1,b2) resetbits(x, (bit2mask(b1, b2))) +#define test2bits(x,b1,b2) testbits(x, (bit2mask(b1, b2))) + + + +/* +** Layout for bit use in `marked' field: +** bit 0 - object is white (type 0) +** bit 1 - object is white (type 1) +** bit 2 - object is black +** bit 3 - for userdata: has been finalized +** bit 3 - for tables: has weak keys +** bit 4 - for tables: has weak values +** bit 5 - object is fixed (should not be collected) +** bit 6 - object is "super" fixed (only the main thread) +*/ + + +#define WHITE0BIT 0 +#define WHITE1BIT 1 +#define BLACKBIT 2 +#define FINALIZEDBIT 3 +#define KEYWEAKBIT 3 +#define VALUEWEAKBIT 4 +#define FIXEDBIT 5 +#define SFIXEDBIT 6 +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) + + +#define iswhite(x) test2bits((x)->gch.marked, WHITE0BIT, WHITE1BIT) +#define isblack(x) testbit((x)->gch.marked, BLACKBIT) +#define isgray(x) (!isblack(x) && !iswhite(x)) + +#define otherwhite(g) (g->currentwhite ^ WHITEBITS) +#define isdead(g,v) ((v)->gch.marked & otherwhite(g) & WHITEBITS) + +#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) +#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) + +#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) + +#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) + + +#define luaC_checkGC(L) { \ + condhardstacktests(luaD_reallocstack(L, L->stacksize - EXTRA_STACK - 1)); \ + if (G(L)->totalbytes >= G(L)->GCthreshold) \ + luaC_step(L); } + + +#define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ + luaC_barrierf(L,obj2gco(p),gcvalue(v)); } + +#define luaC_barriert(L,t,v) { if (valiswhite(v) && isblack(obj2gco(t))) \ + luaC_barrierback(L,t); } + +#define luaC_objbarrier(L,p,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ + luaC_barrierf(L,obj2gco(p),obj2gco(o)); } + +#define luaC_objbarriert(L,t,o) \ + { if (iswhite(obj2gco(o)) && isblack(obj2gco(t))) luaC_barrierback(L,t); } + +LUAI_FUNC size_t luaC_separateudata (lua_State *L, int all); +LUAI_FUNC void luaC_callGCTM (lua_State *L); +LUAI_FUNC void luaC_freeall (lua_State *L); +LUAI_FUNC void luaC_step (lua_State *L); +LUAI_FUNC void luaC_fullgc (lua_State *L); +LUAI_FUNC void luaC_link (lua_State *L, GCObject *o, lu_byte tt); +LUAI_FUNC void luaC_linkupval (lua_State *L, UpVal *uv); +LUAI_FUNC void luaC_barrierf (lua_State *L, GCObject *o, GCObject *v); +LUAI_FUNC void luaC_barrierback (lua_State *L, Table *t); + + +#endif diff --git a/src/lua/src/linit.c b/src/lua/src/linit.c new file mode 100644 index 00000000..c1f90dfa --- /dev/null +++ b/src/lua/src/linit.c @@ -0,0 +1,38 @@ +/* +** $Id: linit.c,v 1.14.1.1 2007/12/27 13:02:25 roberto Exp $ +** Initialization of libraries for lua.c +** See Copyright Notice in lua.h +*/ + + +#define linit_c +#define LUA_LIB + +#include "lua.h" + +#include "lualib.h" +#include "lauxlib.h" + + +static const luaL_Reg lualibs[] = { + {"", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_DBLIBNAME, luaopen_debug}, + {NULL, NULL} +}; + + +LUALIB_API void luaL_openlibs (lua_State *L) { + const luaL_Reg *lib = lualibs; + for (; lib->func; lib++) { + lua_pushcfunction(L, lib->func); + lua_pushstring(L, lib->name); + lua_call(L, 1, 0); + } +} + diff --git a/src/lua/src/liolib.c b/src/lua/src/liolib.c new file mode 100644 index 00000000..e79ed1cb --- /dev/null +++ b/src/lua/src/liolib.c @@ -0,0 +1,553 @@ +/* +** $Id: liolib.c,v 2.73.1.3 2008/01/18 17:47:43 roberto Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define liolib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +#define IO_INPUT 1 +#define IO_OUTPUT 2 + + +static const char *const fnames[] = {"input", "output"}; + + +static int pushresult (lua_State *L, int i, const char *filename) { + int en = errno; /* calls to Lua API may change this value */ + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (filename) + lua_pushfstring(L, "%s: %s", filename, strerror(en)); + else + lua_pushfstring(L, "%s", strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +static void fileerror (lua_State *L, int arg, const char *filename) { + lua_pushfstring(L, "%s: %s", filename, strerror(errno)); + luaL_argerror(L, arg, lua_tostring(L, -1)); +} + + +#define tofilep(L) ((FILE **)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + + +static int io_type (lua_State *L) { + void *ud; + luaL_checkany(L, 1); + ud = lua_touserdata(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_FILEHANDLE); + if (ud == NULL || !lua_getmetatable(L, 1) || !lua_rawequal(L, -2, -1)) + lua_pushnil(L); /* not a file */ + else if (*((FILE **)ud) == NULL) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static FILE *tofile (lua_State *L) { + FILE **f = tofilep(L); + if (*f == NULL) + luaL_error(L, "attempt to use a closed file"); + return *f; +} + + + +/* +** When creating file handles, always creates a `closed' file handle +** before opening the actual file; so, if there is a memory error, the +** file is not left opened. +*/ +static FILE **newfile (lua_State *L) { + FILE **pf = (FILE **)lua_newuserdata(L, sizeof(FILE *)); + *pf = NULL; /* file handle is currently `closed' */ + luaL_getmetatable(L, LUA_FILEHANDLE); + lua_setmetatable(L, -2); + return pf; +} + + +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; +} + + +/* +** function to close 'popen' files +*/ +static int io_pclose (lua_State *L) { + FILE **p = tofilep(L); + int ok = lua_pclose(L, *p); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +/* +** function to close regular files +*/ +static int io_fclose (lua_State *L) { + FILE **p = tofilep(L); + int ok = (fclose(*p) == 0); + *p = NULL; + return pushresult(L, ok, NULL); +} + + +static int aux_close (lua_State *L) { + lua_getfenv(L, 1); + lua_getfield(L, -1, "__close"); + return (lua_tocfunction(L, -1))(L); +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_OUTPUT); + tofile(L); /* make sure argument is a file */ + return aux_close(L); +} + + +static int io_gc (lua_State *L) { + FILE *f = *tofilep(L); + /* ignore closed files */ + if (f != NULL) + aux_close(L); + return 0; +} + + +static int io_tostring (lua_State *L) { + FILE *f = *tofilep(L); + if (f == NULL) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", f); + return 1; +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +/* +** this function has a separated environment, which defines the +** correct __close for 'popen' files +*/ +static int io_popen (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + FILE **pf = newfile(L); + *pf = lua_popen(L, filename, mode); + return (*pf == NULL) ? pushresult(L, 0, filename) : 1; +} + + +static int io_tmpfile (lua_State *L) { + FILE **pf = newfile(L); + *pf = tmpfile(); + return (*pf == NULL) ? pushresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, int findex) { + FILE *f; + lua_rawgeti(L, LUA_ENVIRONINDEX, findex); + f = *(FILE **)lua_touserdata(L, -1); + if (f == NULL) + luaL_error(L, "standard %s file is closed", fnames[findex - 1]); + return f; +} + + +static int g_iofile (lua_State *L, int f, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + if (filename) { + FILE **pf = newfile(L); + *pf = fopen(filename, mode); + if (*pf == NULL) + fileerror(L, 1, filename); + } + else { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_rawseti(L, LUA_ENVIRONINDEX, f); + } + /* return current value */ + lua_rawgeti(L, LUA_ENVIRONINDEX, f); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +static void aux_lines (lua_State *L, int idx, int toclose) { + lua_pushvalue(L, idx); + lua_pushboolean(L, toclose); /* close/not close file when finished */ + lua_pushcclosure(L, io_readline, 2); +} + + +static int f_lines (lua_State *L) { + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 1, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + if (lua_isnoneornil(L, 1)) { /* no arguments? */ + /* will iterate over default input */ + lua_rawgeti(L, LUA_ENVIRONINDEX, IO_INPUT); + return f_lines(L); + } + else { + const char *filename = luaL_checkstring(L, 1); + FILE **pf = newfile(L); + *pf = fopen(filename, "r"); + if (*pf == NULL) + fileerror(L, 1, filename); + aux_lines(L, lua_gettop(L), 1); + return 1; + } +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + +static int read_number (lua_State *L, FILE *f) { + lua_Number d; + if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) { + lua_pushnumber(L, d); + return 1; + } + else return 0; /* read fails */ +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); + lua_pushlstring(L, NULL, 0); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f) { + luaL_Buffer b; + luaL_buffinit(L, &b); + for (;;) { + size_t l; + char *p = luaL_prepbuffer(&b); + if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) { /* eof? */ + luaL_pushresult(&b); /* close buffer */ + return (lua_objlen(L, -1) > 0); /* check whether read something */ + } + l = strlen(p); + if (l == 0 || p[l-1] != '\n') + luaL_addsize(&b, l); + else { + luaL_addsize(&b, l - 1); /* do not include `eol' */ + luaL_pushresult(&b); /* close buffer */ + return 1; /* read at least an `eol' */ + } + } +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t rlen; /* how much to read */ + size_t nr; /* number of chars actually read */ + luaL_Buffer b; + luaL_buffinit(L, &b); + rlen = LUAL_BUFFERSIZE; /* try to read that much each time */ + do { + char *p = luaL_prepbuffer(&b); + if (rlen > n) rlen = n; /* cannot read more than asked */ + nr = fread(p, sizeof(char), rlen, f); + luaL_addsize(&b, nr); + n -= nr; /* still have to read `n' chars */ + } while (n > 0 && nr == rlen); /* until end of count or eof */ + luaL_pushresult(&b); /* close buffer */ + return (n == 0 || lua_objlen(L, -1) > 0); +} + + +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int success; + int n; + clearerr(f); + if (nargs == 0) { /* no arguments? */ + success = read_line(L, f); + n = first+1; /* to return 1 result */ + } + else { /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); + success = 1; + for (n = first; nargs-- && success; n++) { + if (lua_type(L, n) == LUA_TNUMBER) { + size_t l = (size_t)lua_tointeger(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else { + const char *p = lua_tostring(L, n); + luaL_argcheck(L, p && p[0] == '*', n, "invalid option"); + switch (p[1]) { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f); + break; + case 'a': /* file */ + read_chars(L, f, ~((size_t)0)); /* read MAX_SIZE_T chars */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (ferror(f)) + return pushresult(L, 0, NULL); + if (!success) { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return n - first; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L), 2); +} + + +static int io_readline (lua_State *L) { + FILE *f = *(FILE **)lua_touserdata(L, lua_upvalueindex(1)); + int sucess; + if (f == NULL) /* file is already closed? */ + luaL_error(L, "file is already closed"); + sucess = read_line(L, f); + if (ferror(f)) + return luaL_error(L, "%s", strerror(errno)); + if (sucess) return 1; + else { /* EOF */ + if (lua_toboolean(L, lua_upvalueindex(2))) { /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(1)); + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - 1; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + status = status && + fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0; + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + return pushresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + return g_write(L, tofile(L), 2); +} + + +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, "cur", modenames); + long offset = luaL_optlong(L, 3, 0); + op = fseek(f, offset, mode[op]); + if (op) + return pushresult(L, 0, NULL); /* error */ + else { + lua_pushinteger(L, ftell(f)); + return 1; + } +} + + +static int f_setvbuf (lua_State *L) { + static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; + static const char *const modenames[] = {"no", "full", "line", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); + lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], sz); + return pushresult(L, res == 0, NULL); +} + + + +static int io_flush (lua_State *L) { + return pushresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return pushresult(L, fflush(tofile(L)) == 0, NULL); +} + + +static const luaL_Reg iolib[] = { + {"close", io_close}, + {"flush", io_flush}, + {"input", io_input}, + {"lines", io_lines}, + {"open", io_open}, + {"output", io_output}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +static const luaL_Reg flib[] = { + {"close", io_close}, + {"flush", f_flush}, + {"lines", f_lines}, + {"read", f_read}, + {"seek", f_seek}, + {"setvbuf", f_setvbuf}, + {"write", f_write}, + {"__gc", io_gc}, + {"__tostring", io_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_register(L, NULL, flib); /* file methods */ +} + + +static void createstdfile (lua_State *L, FILE *f, int k, const char *fname) { + *newfile(L) = f; + if (k > 0) { + lua_pushvalue(L, -1); + lua_rawseti(L, LUA_ENVIRONINDEX, k); + } + lua_pushvalue(L, -2); /* copy environment */ + lua_setfenv(L, -2); /* set it */ + lua_setfield(L, -3, fname); +} + + +static void newfenv (lua_State *L, lua_CFunction cls) { + lua_createtable(L, 0, 1); + lua_pushcfunction(L, cls); + lua_setfield(L, -2, "__close"); +} + + +LUALIB_API int luaopen_io (lua_State *L) { + createmeta(L); + /* create (private) environment (with fields IO_INPUT, IO_OUTPUT, __close) */ + newfenv(L, io_fclose); + lua_replace(L, LUA_ENVIRONINDEX); + /* open library */ + luaL_register(L, LUA_IOLIBNAME, iolib); + /* create (and set) default files */ + newfenv(L, io_noclose); /* close function for default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, 0, "stderr"); + lua_pop(L, 1); /* pop environment for default files */ + lua_getfield(L, -1, "popen"); + newfenv(L, io_pclose); /* create environment for 'popen' */ + lua_setfenv(L, -2); /* set fenv for 'popen' */ + lua_pop(L, 1); /* pop 'popen' */ + return 1; +} + diff --git a/src/lua/src/llex.c b/src/lua/src/llex.c new file mode 100644 index 00000000..6dc31935 --- /dev/null +++ b/src/lua/src/llex.c @@ -0,0 +1,461 @@ +/* +** $Id: llex.c,v 2.20.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define llex_c +#define LUA_CORE + +#include "lua.h" + +#include "ldo.h" +#include "llex.h" +#include "lobject.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lzio.h" + + + +#define next(ls) (ls->current = zgetc(ls->z)) + + + + +#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') + + +/* ORDER RESERVED */ +const char *const luaX_tokens [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "..", "...", "==", ">=", "<=", "~=", + "", "", "", "", + NULL +}; + + +#define save_and_next(ls) (save(ls, ls->current), next(ls)) + + +static void save (LexState *ls, int c) { + Mbuffer *b = ls->buff; + if (b->n + 1 > b->buffsize) { + size_t newsize; + if (b->buffsize >= MAX_SIZET/2) + luaX_lexerror(ls, "lexical element too long", 0); + newsize = b->buffsize * 2; + luaZ_resizebuffer(ls->L, b, newsize); + } + b->buffer[b->n++] = cast(char, c); +} + + +void luaX_init (lua_State *L) { + int i; + for (i=0; itsv.reserved = cast_byte(i+1); /* reserved word */ + } +} + + +#define MAXSRC 80 + + +const char *luaX_token2str (LexState *ls, int token) { + if (token < FIRST_RESERVED) { + lua_assert(token == cast(unsigned char, token)); + return (iscntrl(token)) ? luaO_pushfstring(ls->L, "char(%d)", token) : + luaO_pushfstring(ls->L, "%c", token); + } + else + return luaX_tokens[token-FIRST_RESERVED]; +} + + +static const char *txtToken (LexState *ls, int token) { + switch (token) { + case TK_NAME: + case TK_STRING: + case TK_NUMBER: + save(ls, '\0'); + return luaZ_buffer(ls->buff); + default: + return luaX_token2str(ls, token); + } +} + + +void luaX_lexerror (LexState *ls, const char *msg, int token) { + char buff[MAXSRC]; + luaO_chunkid(buff, getstr(ls->source), MAXSRC); + msg = luaO_pushfstring(ls->L, "%s:%d: %s", buff, ls->linenumber, msg); + if (token) + luaO_pushfstring(ls->L, "%s near " LUA_QS, msg, txtToken(ls, token)); + luaD_throw(ls->L, LUA_ERRSYNTAX); +} + + +void luaX_syntaxerror (LexState *ls, const char *msg) { + luaX_lexerror(ls, msg, ls->t.token); +} + + +TString *luaX_newstring (LexState *ls, const char *str, size_t l) { + lua_State *L = ls->L; + TString *ts = luaS_newlstr(L, str, l); + TValue *o = luaH_setstr(L, ls->fs->h, ts); /* entry for `str' */ + if (ttisnil(o)) + setbvalue(o, 1); /* make sure `str' will not be collected */ + return ts; +} + + +static void inclinenumber (LexState *ls) { + int old = ls->current; + lua_assert(currIsNewline(ls)); + next(ls); /* skip `\n' or `\r' */ + if (currIsNewline(ls) && ls->current != old) + next(ls); /* skip `\n\r' or `\r\n' */ + if (++ls->linenumber >= MAX_INT) + luaX_syntaxerror(ls, "chunk has too many lines"); +} + + +void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source) { + ls->decpoint = '.'; + ls->L = L; + ls->lookahead.token = TK_EOS; /* no look-ahead token */ + ls->z = z; + ls->fs = NULL; + ls->linenumber = 1; + ls->lastline = 1; + ls->source = source; + luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ + next(ls); /* read first char */ +} + + + +/* +** ======================================================= +** LEXICAL ANALYZER +** ======================================================= +*/ + + + +static int check_next (LexState *ls, const char *set) { + if (!strchr(set, ls->current)) + return 0; + save_and_next(ls); + return 1; +} + + +static void buffreplace (LexState *ls, char from, char to) { + size_t n = luaZ_bufflen(ls->buff); + char *p = luaZ_buffer(ls->buff); + while (n--) + if (p[n] == from) p[n] = to; +} + + +static void trydecpoint (LexState *ls, SemInfo *seminfo) { + /* format error: try to update decimal point separator */ + struct lconv *cv = localeconv(); + char old = ls->decpoint; + ls->decpoint = (cv ? cv->decimal_point[0] : '.'); + buffreplace(ls, old, ls->decpoint); /* try updated decimal separator */ + if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) { + /* format error with correct decimal point: no more options */ + buffreplace(ls, ls->decpoint, '.'); /* undo change (for error message) */ + luaX_lexerror(ls, "malformed number", TK_NUMBER); + } +} + + +/* LUA_NUMBER */ +static void read_numeral (LexState *ls, SemInfo *seminfo) { + lua_assert(isdigit(ls->current)); + do { + save_and_next(ls); + } while (isdigit(ls->current) || ls->current == '.'); + if (check_next(ls, "Ee")) /* `E'? */ + check_next(ls, "+-"); /* optional exponent sign */ + while (isalnum(ls->current) || ls->current == '_') + save_and_next(ls); + save(ls, '\0'); + buffreplace(ls, '.', ls->decpoint); /* follow locale for decimal point */ + if (!luaO_str2d(luaZ_buffer(ls->buff), &seminfo->r)) /* format error? */ + trydecpoint(ls, seminfo); /* try to update decimal point separator */ +} + + +static int skip_sep (LexState *ls) { + int count = 0; + int s = ls->current; + lua_assert(s == '[' || s == ']'); + save_and_next(ls); + while (ls->current == '=') { + save_and_next(ls); + count++; + } + return (ls->current == s) ? count : (-count) - 1; +} + + +static void read_long_string (LexState *ls, SemInfo *seminfo, int sep) { + int cont = 0; + (void)(cont); /* avoid warnings when `cont' is not used */ + save_and_next(ls); /* skip 2nd `[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) { + switch (ls->current) { + case EOZ: + luaX_lexerror(ls, (seminfo) ? "unfinished long string" : + "unfinished long comment", TK_EOS); + break; /* to avoid warnings */ +#if defined(LUA_COMPAT_LSTR) + case '[': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `[' */ + cont++; +#if LUA_COMPAT_LSTR == 1 + if (sep == 0) + luaX_lexerror(ls, "nesting of [[...]] is deprecated", '['); +#endif + } + break; + } +#endif + case ']': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd `]' */ +#if defined(LUA_COMPAT_LSTR) && LUA_COMPAT_LSTR == 2 + cont--; + if (sep == 0 && cont >= 0) break; +#endif + goto endloop; + } + break; + } + case '\n': + case '\r': { + save(ls, '\n'); + inclinenumber(ls); + if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ + break; + } + default: { + if (seminfo) save_and_next(ls); + else next(ls); + } + } + } endloop: + if (seminfo) + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + (2 + sep), + luaZ_bufflen(ls->buff) - 2*(2 + sep)); +} + + +static void read_string (LexState *ls, int del, SemInfo *seminfo) { + save_and_next(ls); + while (ls->current != del) { + switch (ls->current) { + case EOZ: + luaX_lexerror(ls, "unfinished string", TK_EOS); + continue; /* to avoid warnings */ + case '\n': + case '\r': + luaX_lexerror(ls, "unfinished string", TK_STRING); + continue; /* to avoid warnings */ + case '\\': { + int c; + next(ls); /* do not save the `\' */ + switch (ls->current) { + case 'a': c = '\a'; break; + case 'b': c = '\b'; break; + case 'f': c = '\f'; break; + case 'n': c = '\n'; break; + case 'r': c = '\r'; break; + case 't': c = '\t'; break; + case 'v': c = '\v'; break; + case '\n': /* go through */ + case '\r': save(ls, '\n'); inclinenumber(ls); continue; + case EOZ: continue; /* will raise an error next loop */ + default: { + if (!isdigit(ls->current)) + save_and_next(ls); /* handles \\, \", \', and \? */ + else { /* \xxx */ + int i = 0; + c = 0; + do { + c = 10*c + (ls->current-'0'); + next(ls); + } while (++i<3 && isdigit(ls->current)); + if (c > UCHAR_MAX) + luaX_lexerror(ls, "escape sequence too large", TK_STRING); + save(ls, c); + } + continue; + } + } + save(ls, c); + next(ls); + continue; + } + default: + save_and_next(ls); + } + } + save_and_next(ls); /* skip delimiter */ + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, + luaZ_bufflen(ls->buff) - 2); +} + + +static int llex (LexState *ls, SemInfo *seminfo) { + luaZ_resetbuffer(ls->buff); + for (;;) { + switch (ls->current) { + case '\n': + case '\r': { + inclinenumber(ls); + continue; + } + case '-': { + next(ls); + if (ls->current != '-') return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') { + int sep = skip_sep(ls); + luaZ_resetbuffer(ls->buff); /* `skip_sep' may dirty the buffer */ + if (sep >= 0) { + read_long_string(ls, NULL, sep); /* long comment */ + luaZ_resetbuffer(ls->buff); + continue; + } + } + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); + continue; + } + case '[': { + int sep = skip_sep(ls); + if (sep >= 0) { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } + else if (sep == -1) return '['; + else luaX_lexerror(ls, "invalid long string delimiter", TK_STRING); + } + case '=': { + next(ls); + if (ls->current != '=') return '='; + else { next(ls); return TK_EQ; } + } + case '<': { + next(ls); + if (ls->current != '=') return '<'; + else { next(ls); return TK_LE; } + } + case '>': { + next(ls); + if (ls->current != '=') return '>'; + else { next(ls); return TK_GE; } + } + case '~': { + next(ls); + if (ls->current != '=') return '~'; + else { next(ls); return TK_NE; } + } + case '"': + case '\'': { + read_string(ls, ls->current, seminfo); + return TK_STRING; + } + case '.': { + save_and_next(ls); + if (check_next(ls, ".")) { + if (check_next(ls, ".")) + return TK_DOTS; /* ... */ + else return TK_CONCAT; /* .. */ + } + else if (!isdigit(ls->current)) return '.'; + else { + read_numeral(ls, seminfo); + return TK_NUMBER; + } + } + case EOZ: { + return TK_EOS; + } + default: { + if (isspace(ls->current)) { + lua_assert(!currIsNewline(ls)); + next(ls); + continue; + } + else if (isdigit(ls->current)) { + read_numeral(ls, seminfo); + return TK_NUMBER; + } + else if (isalpha(ls->current) || ls->current == '_') { + /* identifier or reserved word */ + TString *ts; + do { + save_and_next(ls); + } while (isalnum(ls->current) || ls->current == '_'); + ts = luaX_newstring(ls, luaZ_buffer(ls->buff), + luaZ_bufflen(ls->buff)); + if (ts->tsv.reserved > 0) /* reserved word? */ + return ts->tsv.reserved - 1 + FIRST_RESERVED; + else { + seminfo->ts = ts; + return TK_NAME; + } + } + else { + int c = ls->current; + next(ls); + return c; /* single-char tokens (+ - / ...) */ + } + } + } + } +} + + +void luaX_next (LexState *ls) { + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ +} + + +void luaX_lookahead (LexState *ls) { + lua_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); +} + diff --git a/src/lua/src/llex.h b/src/lua/src/llex.h new file mode 100644 index 00000000..a9201cee --- /dev/null +++ b/src/lua/src/llex.h @@ -0,0 +1,81 @@ +/* +** $Id: llex.h,v 1.58.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#ifndef llex_h +#define llex_h + +#include "lobject.h" +#include "lzio.h" + + +#define FIRST_RESERVED 257 + +/* maximum length of a reserved word */ +#define TOKEN_LEN (sizeof("function")/sizeof(char)) + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER RESERVED" +*/ +enum RESERVED { + /* terminal symbols denoted by reserved words */ + TK_AND = FIRST_RESERVED, TK_BREAK, + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, + TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_NUMBER, + TK_NAME, TK_STRING, TK_EOS +}; + +/* number of reserved words */ +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) + + +/* array with token `names' */ +LUAI_DATA const char *const luaX_tokens []; + + +typedef union { + lua_Number r; + TString *ts; +} SemInfo; /* semantics information */ + + +typedef struct Token { + int token; + SemInfo seminfo; +} Token; + + +typedef struct LexState { + int current; /* current character (charint) */ + int linenumber; /* input line counter */ + int lastline; /* line of last token `consumed' */ + Token t; /* current token */ + Token lookahead; /* look ahead token */ + struct FuncState *fs; /* `FuncState' is private to the parser */ + struct lua_State *L; + ZIO *z; /* input stream */ + Mbuffer *buff; /* buffer for tokens */ + TString *source; /* current source name */ + char decpoint; /* locale decimal point */ +} LexState; + + +LUAI_FUNC void luaX_init (lua_State *L); +LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, + TString *source); +LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); +LUAI_FUNC void luaX_next (LexState *ls); +LUAI_FUNC void luaX_lookahead (LexState *ls); +LUAI_FUNC void luaX_lexerror (LexState *ls, const char *msg, int token); +LUAI_FUNC void luaX_syntaxerror (LexState *ls, const char *s); +LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); + + +#endif diff --git a/src/lua/src/llimits.h b/src/lua/src/llimits.h new file mode 100644 index 00000000..ca8dcb72 --- /dev/null +++ b/src/lua/src/llimits.h @@ -0,0 +1,128 @@ +/* +** $Id: llimits.h,v 1.69.1.1 2007/12/27 13:02:25 roberto Exp $ +** Limits, basic types, and some other `installation-dependent' definitions +** See Copyright Notice in lua.h +*/ + +#ifndef llimits_h +#define llimits_h + + +#include +#include + + +#include "lua.h" + + +typedef LUAI_UINT32 lu_int32; + +typedef LUAI_UMEM lu_mem; + +typedef LUAI_MEM l_mem; + + + +/* chars used as small naturals (so that `char' is reserved for characters) */ +typedef unsigned char lu_byte; + + +#define MAX_SIZET ((size_t)(~(size_t)0)-2) + +#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) + + +#define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ + +/* +** conversion of pointer to integer +** this is for hashing only; there is no problem if the integer +** cannot hold the whole pointer value +*/ +#define IntPoint(p) ((unsigned int)(lu_mem)(p)) + + + +/* type to ensure maximum alignment */ +typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; + + +/* result of a `usual argument conversion' over lua_Number */ +typedef LUAI_UACNUMBER l_uacNumber; + + +/* internal assertions for in-house debugging */ +#ifdef lua_assert + +#define check_exp(c,e) (lua_assert(c), (e)) +#define api_check(l,e) lua_assert(e) + +#else + +#define lua_assert(c) ((void)0) +#define check_exp(c,e) (e) +#define api_check luai_apicheck + +#endif + + +#ifndef UNUSED +#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#endif + + +#ifndef cast +#define cast(t, exp) ((t)(exp)) +#endif + +#define cast_byte(i) cast(lu_byte, (i)) +#define cast_num(i) cast(lua_Number, (i)) +#define cast_int(i) cast(int, (i)) + + + +/* +** type for virtual-machine instructions +** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +*/ +typedef lu_int32 Instruction; + + + +/* maximum stack for a Lua function */ +#define MAXSTACK 250 + + + +/* minimum size for the string table (must be power of 2) */ +#ifndef MINSTRTABSIZE +#define MINSTRTABSIZE 32 +#endif + + +/* minimum size for string buffer */ +#ifndef LUA_MINBUFFER +#define LUA_MINBUFFER 32 +#endif + + +#ifndef lua_lock +#define lua_lock(L) ((void) 0) +#define lua_unlock(L) ((void) 0) +#endif + +#ifndef luai_threadyield +#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} +#endif + + +/* +** macro to control inclusion of some hard tests on stack reallocation +*/ +#ifndef HARDSTACKTESTS +#define condhardstacktests(x) ((void)0) +#else +#define condhardstacktests(x) x +#endif + +#endif diff --git a/src/lua/src/lmathlib.c b/src/lua/src/lmathlib.c new file mode 100644 index 00000000..441fbf73 --- /dev/null +++ b/src/lua/src/lmathlib.c @@ -0,0 +1,263 @@ +/* +** $Id: lmathlib.c,v 1.67.1.1 2007/12/27 13:02:25 roberto Exp $ +** Standard mathematical library +** See Copyright Notice in lua.h +*/ + + +#include +#include + +#define lmathlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#undef PI +#define PI (3.14159265358979323846) +#define RADIANS_PER_DEGREE (PI/180.0) + + + +static int math_abs (lua_State *L) { + lua_pushnumber(L, fabs(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, sin(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sinh (lua_State *L) { + lua_pushnumber(L, sinh(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, cos(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cosh (lua_State *L) { + lua_pushnumber(L, cosh(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, tan(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tanh (lua_State *L) { + lua_pushnumber(L, tanh(luaL_checknumber(L, 1))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, asin(luaL_checknumber(L, 1))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, acos(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_pushnumber(L, atan(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan2 (lua_State *L) { + lua_pushnumber(L, atan2(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_ceil (lua_State *L) { + lua_pushnumber(L, ceil(luaL_checknumber(L, 1))); + return 1; +} + +static int math_floor (lua_State *L) { + lua_pushnumber(L, floor(luaL_checknumber(L, 1))); + return 1; +} + +static int math_fmod (lua_State *L) { + lua_pushnumber(L, fmod(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_modf (lua_State *L) { + double ip; + double fp = modf(luaL_checknumber(L, 1), &ip); + lua_pushnumber(L, ip); + lua_pushnumber(L, fp); + return 2; +} + +static int math_sqrt (lua_State *L) { + lua_pushnumber(L, sqrt(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_pushnumber(L, pow(luaL_checknumber(L, 1), luaL_checknumber(L, 2))); + return 1; +} + +static int math_log (lua_State *L) { + lua_pushnumber(L, log(luaL_checknumber(L, 1))); + return 1; +} + +static int math_log10 (lua_State *L) { + lua_pushnumber(L, log10(luaL_checknumber(L, 1))); + return 1; +} + +static int math_exp (lua_State *L) { + lua_pushnumber(L, exp(luaL_checknumber(L, 1))); + return 1; +} + +static int math_deg (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)/RADIANS_PER_DEGREE); + return 1; +} + +static int math_rad (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1)*RADIANS_PER_DEGREE); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, frexp(luaL_checknumber(L, 1), &e)); + lua_pushinteger(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_pushnumber(L, ldexp(luaL_checknumber(L, 1), luaL_checkint(L, 2))); + return 1; +} + + + +static int math_min (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmin = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d < dmin) + dmin = d; + } + lua_pushnumber(L, dmin); + return 1; +} + + +static int math_max (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + lua_Number dmax = luaL_checknumber(L, 1); + int i; + for (i=2; i<=n; i++) { + lua_Number d = luaL_checknumber(L, i); + if (d > dmax) + dmax = d; + } + lua_pushnumber(L, dmax); + return 1; +} + + +static int math_random (lua_State *L) { + /* the `%' avoids the (rare) case of r==1, and is needed also because on + some systems (SunOS!) `rand()' may return a value larger than RAND_MAX */ + lua_Number r = (lua_Number)(rand()%RAND_MAX) / (lua_Number)RAND_MAX; + switch (lua_gettop(L)) { /* check number of arguments */ + case 0: { /* no arguments */ + lua_pushnumber(L, r); /* Number between 0 and 1 */ + break; + } + case 1: { /* only upper limit */ + int u = luaL_checkint(L, 1); + luaL_argcheck(L, 1<=u, 1, "interval is empty"); + lua_pushnumber(L, floor(r*u)+1); /* int between 1 and `u' */ + break; + } + case 2: { /* lower and upper limits */ + int l = luaL_checkint(L, 1); + int u = luaL_checkint(L, 2); + luaL_argcheck(L, l<=u, 2, "interval is empty"); + lua_pushnumber(L, floor(r*(u-l+1))+l); /* int between `l' and `u' */ + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + return 1; +} + + +static int math_randomseed (lua_State *L) { + srand(luaL_checkint(L, 1)); + return 0; +} + + +static const luaL_Reg mathlib[] = { + {"abs", math_abs}, + {"acos", math_acos}, + {"asin", math_asin}, + {"atan2", math_atan2}, + {"atan", math_atan}, + {"ceil", math_ceil}, + {"cosh", math_cosh}, + {"cos", math_cos}, + {"deg", math_deg}, + {"exp", math_exp}, + {"floor", math_floor}, + {"fmod", math_fmod}, + {"frexp", math_frexp}, + {"ldexp", math_ldexp}, + {"log10", math_log10}, + {"log", math_log}, + {"max", math_max}, + {"min", math_min}, + {"modf", math_modf}, + {"pow", math_pow}, + {"rad", math_rad}, + {"random", math_random}, + {"randomseed", math_randomseed}, + {"sinh", math_sinh}, + {"sin", math_sin}, + {"sqrt", math_sqrt}, + {"tanh", math_tanh}, + {"tan", math_tan}, + {NULL, NULL} +}; + + +/* +** Open math library +*/ +LUALIB_API int luaopen_math (lua_State *L) { + luaL_register(L, LUA_MATHLIBNAME, mathlib); + lua_pushnumber(L, PI); + lua_setfield(L, -2, "pi"); + lua_pushnumber(L, HUGE_VAL); + lua_setfield(L, -2, "huge"); +#if defined(LUA_COMPAT_MOD) + lua_getfield(L, -1, "fmod"); + lua_setfield(L, -2, "mod"); +#endif + return 1; +} + diff --git a/src/lua/src/lmem.c b/src/lua/src/lmem.c new file mode 100644 index 00000000..ae7d8c96 --- /dev/null +++ b/src/lua/src/lmem.c @@ -0,0 +1,86 @@ +/* +** $Id: lmem.c,v 1.70.1.1 2007/12/27 13:02:25 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + + +#include + +#define lmem_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +/* +** About the realloc function: +** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); +** (`osize' is the old size, `nsize' is the new size) +** +** Lua ensures that (ptr == NULL) iff (osize == 0). +** +** * frealloc(ud, NULL, 0, x) creates a new block of size `x' +** +** * frealloc(ud, p, x, 0) frees the block `p' +** (in this specific case, frealloc must return NULL). +** particularly, frealloc(ud, NULL, 0, 0) does nothing +** (which is equivalent to free(NULL) in ANSI C) +** +** frealloc returns NULL if it cannot create or reallocate the area +** (any reallocation to an equal or smaller size cannot fail!) +*/ + + + +#define MINSIZEARRAY 4 + + +void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, + int limit, const char *errormsg) { + void *newblock; + int newsize; + if (*size >= limit/2) { /* cannot double it? */ + if (*size >= limit) /* cannot grow even a little? */ + luaG_runerror(L, errormsg); + newsize = limit; /* still have at least one free place */ + } + else { + newsize = (*size)*2; + if (newsize < MINSIZEARRAY) + newsize = MINSIZEARRAY; /* minimum size */ + } + newblock = luaM_reallocv(L, block, *size, newsize, size_elems); + *size = newsize; /* update only when everything else is OK */ + return newblock; +} + + +void *luaM_toobig (lua_State *L) { + luaG_runerror(L, "memory allocation error: block too big"); + return NULL; /* to avoid warnings */ +} + + + +/* +** generic allocation routine. +*/ +void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { + global_State *g = G(L); + lua_assert((osize == 0) == (block == NULL)); + block = (*g->frealloc)(g->ud, block, osize, nsize); + if (block == NULL && nsize > 0) + luaD_throw(L, LUA_ERRMEM); + lua_assert((nsize == 0) == (block == NULL)); + g->totalbytes = (g->totalbytes - osize) + nsize; + return block; +} + diff --git a/src/lua/src/lmem.h b/src/lua/src/lmem.h new file mode 100644 index 00000000..7c2dcb32 --- /dev/null +++ b/src/lua/src/lmem.h @@ -0,0 +1,49 @@ +/* +** $Id: lmem.h,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#ifndef lmem_h +#define lmem_h + + +#include + +#include "llimits.h" +#include "lua.h" + +#define MEMERRMSG "not enough memory" + + +#define luaM_reallocv(L,b,on,n,e) \ + ((cast(size_t, (n)+1) <= MAX_SIZET/(e)) ? /* +1 to avoid warnings */ \ + luaM_realloc_(L, (b), (on)*(e), (n)*(e)) : \ + luaM_toobig(L)) + +#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) +#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) +#define luaM_freearray(L, b, n, t) luaM_reallocv(L, (b), n, 0, sizeof(t)) + +#define luaM_malloc(L,t) luaM_realloc_(L, NULL, 0, (t)) +#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) +#define luaM_newvector(L,n,t) \ + cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) + +#define luaM_growvector(L,v,nelems,size,t,limit,e) \ + if ((nelems)+1 > (size)) \ + ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) + +#define luaM_reallocvector(L, v,oldn,n,t) \ + ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) + + +LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, + size_t size); +LUAI_FUNC void *luaM_toobig (lua_State *L); +LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, + size_t size_elem, int limit, + const char *errormsg); + +#endif + diff --git a/src/lua/src/loadlib.c b/src/lua/src/loadlib.c new file mode 100644 index 00000000..0d401eba --- /dev/null +++ b/src/lua/src/loadlib.c @@ -0,0 +1,666 @@ +/* +** $Id: loadlib.c,v 1.52.1.3 2008/08/06 13:29:28 roberto Exp $ +** Dynamic library loader for Lua +** See Copyright Notice in lua.h +** +** This module contains an implementation of loadlib for Unix systems +** that have dlfcn, an implementation for Darwin (Mac OS X), an +** implementation for Windows, and a stub for other systems. +*/ + + +#include +#include + + +#define loadlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* prefix for open functions in C libraries */ +#define LUA_POF "luaopen_" + +/* separator for open functions in C libraries */ +#define LUA_OFSEP "_" + + +#define LIBPREFIX "LOADLIB: " + +#define POF LUA_POF +#define LIB_FAIL "open" + + +/* error codes for ll_loadfunc */ +#define ERRLIB 1 +#define ERRFUNC 2 + +#define setprogdir(L) ((void)0) + + +static void ll_unloadlib (void *lib); +static void *ll_load (lua_State *L, const char *path); +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym); + + + +#if defined(LUA_DL_DLOPEN) +/* +** {======================================================================== +** This is an implementation of loadlib based on the dlfcn interface. +** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, +** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least +** as an emulation layer on top of native functions. +** ========================================================================= +*/ + +#include + +static void ll_unloadlib (void *lib) { + dlclose(lib); +} + + +static void *ll_load (lua_State *L, const char *path) { + void *lib = dlopen(path, RTLD_NOW); + if (lib == NULL) lua_pushstring(L, dlerror()); + return lib; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)dlsym(lib, sym); + if (f == NULL) lua_pushstring(L, dlerror()); + return f; +} + +/* }====================================================== */ + + + +#elif defined(LUA_DL_DLL) +/* +** {====================================================================== +** This is an implementation of loadlib for Windows using native functions. +** ======================================================================= +*/ + +#include + + +#undef setprogdir + +static void setprogdir (lua_State *L) { + char buff[MAX_PATH + 1]; + char *lb; + DWORD nsize = sizeof(buff)/sizeof(char); + DWORD n = GetModuleFileNameA(NULL, buff, nsize); + if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) + luaL_error(L, "unable to get ModuleFileName"); + else { + *lb = '\0'; + luaL_gsub(L, lua_tostring(L, -1), LUA_EXECDIR, buff); + lua_remove(L, -2); /* remove original string */ + } +} + + +static void pusherror (lua_State *L) { + int error = GetLastError(); + char buffer[128]; + if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, 0, buffer, sizeof(buffer), NULL)) + lua_pushstring(L, buffer); + else + lua_pushfstring(L, "system error %d\n", error); +} + +static void ll_unloadlib (void *lib) { + FreeLibrary((HINSTANCE)lib); +} + + +static void *ll_load (lua_State *L, const char *path) { + HINSTANCE lib = LoadLibraryA(path); + if (lib == NULL) pusherror(L); + return lib; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)GetProcAddress((HINSTANCE)lib, sym); + if (f == NULL) pusherror(L); + return f; +} + +/* }====================================================== */ + + + +#elif defined(LUA_DL_DYLD) +/* +** {====================================================================== +** Native Mac OS X / Darwin Implementation +** ======================================================================= +*/ + +#include + + +/* Mac appends a `_' before C function names */ +#undef POF +#define POF "_" LUA_POF + + +static void pusherror (lua_State *L) { + const char *err_str; + const char *err_file; + NSLinkEditErrors err; + int err_num; + NSLinkEditError(&err, &err_num, &err_file, &err_str); + lua_pushstring(L, err_str); +} + + +static const char *errorfromcode (NSObjectFileImageReturnCode ret) { + switch (ret) { + case NSObjectFileImageInappropriateFile: + return "file is not a bundle"; + case NSObjectFileImageArch: + return "library is for wrong CPU type"; + case NSObjectFileImageFormat: + return "bad format"; + case NSObjectFileImageAccess: + return "cannot access file"; + case NSObjectFileImageFailure: + default: + return "unable to load library"; + } +} + + +static void ll_unloadlib (void *lib) { + NSUnLinkModule((NSModule)lib, NSUNLINKMODULE_OPTION_RESET_LAZY_REFERENCES); +} + + +static void *ll_load (lua_State *L, const char *path) { + NSObjectFileImage img; + NSObjectFileImageReturnCode ret; + /* this would be a rare case, but prevents crashing if it happens */ + if(!_dyld_present()) { + lua_pushliteral(L, "dyld not present"); + return NULL; + } + ret = NSCreateObjectFileImageFromFile(path, &img); + if (ret == NSObjectFileImageSuccess) { + NSModule mod = NSLinkModule(img, path, NSLINKMODULE_OPTION_PRIVATE | + NSLINKMODULE_OPTION_RETURN_ON_ERROR); + NSDestroyObjectFileImage(img); + if (mod == NULL) pusherror(L); + return mod; + } + lua_pushstring(L, errorfromcode(ret)); + return NULL; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + NSSymbol nss = NSLookupSymbolInModule((NSModule)lib, sym); + if (nss == NULL) { + lua_pushfstring(L, "symbol " LUA_QS " not found", sym); + return NULL; + } + return (lua_CFunction)NSAddressOfSymbol(nss); +} + +/* }====================================================== */ + + + +#else +/* +** {====================================================== +** Fallback for other systems +** ======================================================= +*/ + +#undef LIB_FAIL +#define LIB_FAIL "absent" + + +#define DLMSG "dynamic libraries not enabled; check your Lua installation" + + +static void ll_unloadlib (void *lib) { + (void)lib; /* to avoid warnings */ +} + + +static void *ll_load (lua_State *L, const char *path) { + (void)path; /* to avoid warnings */ + lua_pushliteral(L, DLMSG); + return NULL; +} + + +static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { + (void)lib; (void)sym; /* to avoid warnings */ + lua_pushliteral(L, DLMSG); + return NULL; +} + +/* }====================================================== */ +#endif + + + +static void **ll_register (lua_State *L, const char *path) { + void **plib; + lua_pushfstring(L, "%s%s", LIBPREFIX, path); + lua_gettable(L, LUA_REGISTRYINDEX); /* check library in registry? */ + if (!lua_isnil(L, -1)) /* is there an entry? */ + plib = (void **)lua_touserdata(L, -1); + else { /* no entry yet; create one */ + lua_pop(L, 1); + plib = (void **)lua_newuserdata(L, sizeof(const void *)); + *plib = NULL; + luaL_getmetatable(L, "_LOADLIB"); + lua_setmetatable(L, -2); + lua_pushfstring(L, "%s%s", LIBPREFIX, path); + lua_pushvalue(L, -2); + lua_settable(L, LUA_REGISTRYINDEX); + } + return plib; +} + + +/* +** __gc tag method: calls library's `ll_unloadlib' function with the lib +** handle +*/ +static int gctm (lua_State *L) { + void **lib = (void **)luaL_checkudata(L, 1, "_LOADLIB"); + if (*lib) ll_unloadlib(*lib); + *lib = NULL; /* mark library as closed */ + return 0; +} + + +static int ll_loadfunc (lua_State *L, const char *path, const char *sym) { + void **reg = ll_register(L, path); + if (*reg == NULL) *reg = ll_load(L, path); + if (*reg == NULL) + return ERRLIB; /* unable to load library */ + else { + lua_CFunction f = ll_sym(L, *reg, sym); + if (f == NULL) + return ERRFUNC; /* unable to find function */ + lua_pushcfunction(L, f); + return 0; /* return function */ + } +} + + +static int ll_loadlib (lua_State *L) { + const char *path = luaL_checkstring(L, 1); + const char *init = luaL_checkstring(L, 2); + int stat = ll_loadfunc(L, path, init); + if (stat == 0) /* no errors? */ + return 1; /* return the loaded function */ + else { /* error; error message is on stack top */ + lua_pushnil(L); + lua_insert(L, -2); + lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); + return 3; /* return nil, error message, and where */ + } +} + + + +/* +** {====================================================== +** 'require' function +** ======================================================= +*/ + + +static int readable (const char *filename) { + FILE *f = fopen(filename, "r"); /* try to open file */ + if (f == NULL) return 0; /* open failed */ + fclose(f); + return 1; +} + + +static const char *pushnexttemplate (lua_State *L, const char *path) { + const char *l; + while (*path == *LUA_PATHSEP) path++; /* skip separators */ + if (*path == '\0') return NULL; /* no more templates */ + l = strchr(path, *LUA_PATHSEP); /* find next separator */ + if (l == NULL) l = path + strlen(path); + lua_pushlstring(L, path, l - path); /* template */ + return l; +} + + +static const char *findfile (lua_State *L, const char *name, + const char *pname) { + const char *path; + name = luaL_gsub(L, name, ".", LUA_DIRSEP); + lua_getfield(L, LUA_ENVIRONINDEX, pname); + path = lua_tostring(L, -1); + if (path == NULL) + luaL_error(L, LUA_QL("package.%s") " must be a string", pname); + lua_pushliteral(L, ""); /* error accumulator */ + while ((path = pushnexttemplate(L, path)) != NULL) { + const char *filename; + filename = luaL_gsub(L, lua_tostring(L, -1), LUA_PATH_MARK, name); + lua_remove(L, -2); /* remove path template */ + if (readable(filename)) /* does file exist and is readable? */ + return filename; /* return that file name */ + lua_pushfstring(L, "\n\tno file " LUA_QS, filename); + lua_remove(L, -2); /* remove file name */ + lua_concat(L, 2); /* add entry to possible error message */ + } + return NULL; /* not found */ +} + + +static void loaderror (lua_State *L, const char *filename) { + luaL_error(L, "error loading module " LUA_QS " from file " LUA_QS ":\n\t%s", + lua_tostring(L, 1), filename, lua_tostring(L, -1)); +} + + +static int loader_Lua (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + filename = findfile(L, name, "path"); + if (filename == NULL) return 1; /* library not found in this path */ + if (luaL_loadfile(L, filename) != 0) + loaderror(L, filename); + return 1; /* library loaded successfully */ +} + + +static const char *mkfuncname (lua_State *L, const char *modname) { + const char *funcname; + const char *mark = strchr(modname, *LUA_IGMARK); + if (mark) modname = mark + 1; + funcname = luaL_gsub(L, modname, ".", LUA_OFSEP); + funcname = lua_pushfstring(L, POF"%s", funcname); + lua_remove(L, -2); /* remove 'gsub' result */ + return funcname; +} + + +static int loader_C (lua_State *L) { + const char *funcname; + const char *name = luaL_checkstring(L, 1); + const char *filename = findfile(L, name, "cpath"); + if (filename == NULL) return 1; /* library not found in this path */ + funcname = mkfuncname(L, name); + if (ll_loadfunc(L, filename, funcname) != 0) + loaderror(L, filename); + return 1; /* library loaded successfully */ +} + + +static int loader_Croot (lua_State *L) { + const char *funcname; + const char *filename; + const char *name = luaL_checkstring(L, 1); + const char *p = strchr(name, '.'); + int stat; + if (p == NULL) return 0; /* is root */ + lua_pushlstring(L, name, p - name); + filename = findfile(L, lua_tostring(L, -1), "cpath"); + if (filename == NULL) return 1; /* root not found */ + funcname = mkfuncname(L, name); + if ((stat = ll_loadfunc(L, filename, funcname)) != 0) { + if (stat != ERRFUNC) loaderror(L, filename); /* real error */ + lua_pushfstring(L, "\n\tno module " LUA_QS " in file " LUA_QS, + name, filename); + return 1; /* function not found */ + } + return 1; +} + + +static int loader_preload (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_getfield(L, LUA_ENVIRONINDEX, "preload"); + if (!lua_istable(L, -1)) + luaL_error(L, LUA_QL("package.preload") " must be a table"); + lua_getfield(L, -1, name); + if (lua_isnil(L, -1)) /* not found? */ + lua_pushfstring(L, "\n\tno field package.preload['%s']", name); + return 1; +} + + +static const int sentinel_ = 0; +#define sentinel ((void *)&sentinel_) + + +static int ll_require (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + int i; + lua_settop(L, 1); /* _LOADED table will be at index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, 2, name); + if (lua_toboolean(L, -1)) { /* is it there? */ + if (lua_touserdata(L, -1) == sentinel) /* check loops */ + luaL_error(L, "loop or previous error loading module " LUA_QS, name); + return 1; /* package is already loaded */ + } + /* else must load it; iterate over available loaders */ + lua_getfield(L, LUA_ENVIRONINDEX, "loaders"); + if (!lua_istable(L, -1)) + luaL_error(L, LUA_QL("package.loaders") " must be a table"); + lua_pushliteral(L, ""); /* error message accumulator */ + for (i=1; ; i++) { + lua_rawgeti(L, -2, i); /* get a loader */ + if (lua_isnil(L, -1)) + luaL_error(L, "module " LUA_QS " not found:%s", + name, lua_tostring(L, -2)); + lua_pushstring(L, name); + lua_call(L, 1, 1); /* call it */ + if (lua_isfunction(L, -1)) /* did it find module? */ + break; /* module loaded successfully */ + else if (lua_isstring(L, -1)) /* loader returned error message? */ + lua_concat(L, 2); /* accumulate it */ + else + lua_pop(L, 1); + } + lua_pushlightuserdata(L, sentinel); + lua_setfield(L, 2, name); /* _LOADED[name] = sentinel */ + lua_pushstring(L, name); /* pass name as argument to module */ + lua_call(L, 1, 1); /* run loaded module */ + if (!lua_isnil(L, -1)) /* non-nil return? */ + lua_setfield(L, 2, name); /* _LOADED[name] = returned value */ + lua_getfield(L, 2, name); + if (lua_touserdata(L, -1) == sentinel) { /* module did not set a value? */ + lua_pushboolean(L, 1); /* use true as result */ + lua_pushvalue(L, -1); /* extra copy to be returned */ + lua_setfield(L, 2, name); /* _LOADED[name] = true */ + } + return 1; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** 'module' function +** ======================================================= +*/ + + +static void setfenv (lua_State *L) { + lua_Debug ar; + if (lua_getstack(L, 1, &ar) == 0 || + lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ + lua_iscfunction(L, -1)) + luaL_error(L, LUA_QL("module") " not called from a Lua function"); + lua_pushvalue(L, -2); + lua_setfenv(L, -2); + lua_pop(L, 1); +} + + +static void dooptions (lua_State *L, int n) { + int i; + for (i = 2; i <= n; i++) { + lua_pushvalue(L, i); /* get option (a function) */ + lua_pushvalue(L, -2); /* module */ + lua_call(L, 1, 0); + } +} + + +static void modinit (lua_State *L, const char *modname) { + const char *dot; + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_M"); /* module._M = module */ + lua_pushstring(L, modname); + lua_setfield(L, -2, "_NAME"); + dot = strrchr(modname, '.'); /* look for last dot in module name */ + if (dot == NULL) dot = modname; + else dot++; + /* set _PACKAGE as package name (full module name minus last part) */ + lua_pushlstring(L, modname, dot - modname); + lua_setfield(L, -2, "_PACKAGE"); +} + + +static int ll_module (lua_State *L) { + const char *modname = luaL_checkstring(L, 1); + int loaded = lua_gettop(L) + 1; /* index of _LOADED table */ + lua_getfield(L, LUA_REGISTRYINDEX, "_LOADED"); + lua_getfield(L, loaded, modname); /* get _LOADED[modname] */ + if (!lua_istable(L, -1)) { /* not found? */ + lua_pop(L, 1); /* remove previous result */ + /* try global variable (and create one if it does not exist) */ + if (luaL_findtable(L, LUA_GLOBALSINDEX, modname, 1) != NULL) + return luaL_error(L, "name conflict for module " LUA_QS, modname); + lua_pushvalue(L, -1); + lua_setfield(L, loaded, modname); /* _LOADED[modname] = new table */ + } + /* check whether table already has a _NAME field */ + lua_getfield(L, -1, "_NAME"); + if (!lua_isnil(L, -1)) /* is table an initialized module? */ + lua_pop(L, 1); + else { /* no; initialize it */ + lua_pop(L, 1); + modinit(L, modname); + } + lua_pushvalue(L, -1); + setfenv(L); + dooptions(L, loaded - 1); + return 0; +} + + +static int ll_seeall (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + if (!lua_getmetatable(L, 1)) { + lua_createtable(L, 0, 1); /* create new metatable */ + lua_pushvalue(L, -1); + lua_setmetatable(L, 1); + } + lua_pushvalue(L, LUA_GLOBALSINDEX); + lua_setfield(L, -2, "__index"); /* mt.__index = _G */ + return 0; +} + + +/* }====================================================== */ + + + +/* auxiliary mark (for internal use) */ +#define AUXMARK "\1" + +static void setpath (lua_State *L, const char *fieldname, const char *envname, + const char *def) { + const char *path = getenv(envname); + if (path == NULL) /* no environment variable? */ + lua_pushstring(L, def); /* use default */ + else { + /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ + path = luaL_gsub(L, path, LUA_PATHSEP LUA_PATHSEP, + LUA_PATHSEP AUXMARK LUA_PATHSEP); + luaL_gsub(L, path, AUXMARK, def); + lua_remove(L, -2); + } + setprogdir(L); + lua_setfield(L, -2, fieldname); +} + + +static const luaL_Reg pk_funcs[] = { + {"loadlib", ll_loadlib}, + {"seeall", ll_seeall}, + {NULL, NULL} +}; + + +static const luaL_Reg ll_funcs[] = { + {"module", ll_module}, + {"require", ll_require}, + {NULL, NULL} +}; + + +static const lua_CFunction loaders[] = + {loader_preload, loader_Lua, loader_C, loader_Croot, NULL}; + + +LUALIB_API int luaopen_package (lua_State *L) { + int i; + /* create new type _LOADLIB */ + luaL_newmetatable(L, "_LOADLIB"); + lua_pushcfunction(L, gctm); + lua_setfield(L, -2, "__gc"); + /* create `package' table */ + luaL_register(L, LUA_LOADLIBNAME, pk_funcs); +#if defined(LUA_COMPAT_LOADLIB) + lua_getfield(L, -1, "loadlib"); + lua_setfield(L, LUA_GLOBALSINDEX, "loadlib"); +#endif + lua_pushvalue(L, -1); + lua_replace(L, LUA_ENVIRONINDEX); + /* create `loaders' table */ + lua_createtable(L, 0, sizeof(loaders)/sizeof(loaders[0]) - 1); + /* fill it with pre-defined loaders */ + for (i=0; loaders[i] != NULL; i++) { + lua_pushcfunction(L, loaders[i]); + lua_rawseti(L, -2, i+1); + } + lua_setfield(L, -2, "loaders"); /* put it in field `loaders' */ + setpath(L, "path", LUA_PATH, LUA_PATH_DEFAULT); /* set field `path' */ + setpath(L, "cpath", LUA_CPATH, LUA_CPATH_DEFAULT); /* set field `cpath' */ + /* store config information */ + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATHSEP "\n" LUA_PATH_MARK "\n" + LUA_EXECDIR "\n" LUA_IGMARK); + lua_setfield(L, -2, "config"); + /* set field `loaded' */ + luaL_findtable(L, LUA_REGISTRYINDEX, "_LOADED", 2); + lua_setfield(L, -2, "loaded"); + /* set field `preload' */ + lua_newtable(L); + lua_setfield(L, -2, "preload"); + lua_pushvalue(L, LUA_GLOBALSINDEX); + luaL_register(L, NULL, ll_funcs); /* open lib into global table */ + lua_pop(L, 1); + return 1; /* return 'package' table */ +} + diff --git a/src/lua/src/lobject.c b/src/lua/src/lobject.c new file mode 100644 index 00000000..4ff50732 --- /dev/null +++ b/src/lua/src/lobject.c @@ -0,0 +1,214 @@ +/* +** $Id: lobject.c,v 2.22.1.1 2007/12/27 13:02:25 roberto Exp $ +** Some generic functions over Lua objects +** See Copyright Notice in lua.h +*/ + +#include +#include +#include +#include +#include + +#define lobject_c +#define LUA_CORE + +#include "lua.h" + +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "lvm.h" + + + +const TValue luaO_nilobject_ = {{NULL}, LUA_TNIL}; + + +/* +** converts an integer to a "floating point byte", represented as +** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if +** eeeee != 0 and (xxx) otherwise. +*/ +int luaO_int2fb (unsigned int x) { + int e = 0; /* expoent */ + while (x >= 16) { + x = (x+1) >> 1; + e++; + } + if (x < 8) return x; + else return ((e+1) << 3) | (cast_int(x) - 8); +} + + +/* converts back */ +int luaO_fb2int (int x) { + int e = (x >> 3) & 31; + if (e == 0) return x; + else return ((x & 7)+8) << (e - 1); +} + + +int luaO_log2 (unsigned int x) { + static const lu_byte log_2[256] = { + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }; + int l = -1; + while (x >= 256) { l += 8; x >>= 8; } + return l + log_2[x]; + +} + + +int luaO_rawequalObj (const TValue *t1, const TValue *t2) { + if (ttype(t1) != ttype(t2)) return 0; + else switch (ttype(t1)) { + case LUA_TNIL: + return 1; + case LUA_TNUMBER: + return luai_numeq(nvalue(t1), nvalue(t2)); + case LUA_TBOOLEAN: + return bvalue(t1) == bvalue(t2); /* boolean true must be 1 !! */ + case LUA_TLIGHTUSERDATA: + return pvalue(t1) == pvalue(t2); + default: + lua_assert(iscollectable(t1)); + return gcvalue(t1) == gcvalue(t2); + } +} + + +int luaO_str2d (const char *s, lua_Number *result) { + char *endptr; + *result = lua_str2number(s, &endptr); + if (endptr == s) return 0; /* conversion failed */ + if (*endptr == 'x' || *endptr == 'X') /* maybe an hexadecimal constant? */ + *result = cast_num(strtoul(s, &endptr, 16)); + if (*endptr == '\0') return 1; /* most common case */ + while (isspace(cast(unsigned char, *endptr))) endptr++; + if (*endptr != '\0') return 0; /* invalid trailing characters? */ + return 1; +} + + + +static void pushstr (lua_State *L, const char *str) { + setsvalue2s(L, L->top, luaS_new(L, str)); + incr_top(L); +} + + +/* this function handles only `%d', `%c', %f, %p, and `%s' formats */ +const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { + int n = 1; + pushstr(L, ""); + for (;;) { + const char *e = strchr(fmt, '%'); + if (e == NULL) break; + setsvalue2s(L, L->top, luaS_newlstr(L, fmt, e-fmt)); + incr_top(L); + switch (*(e+1)) { + case 's': { + const char *s = va_arg(argp, char *); + if (s == NULL) s = "(null)"; + pushstr(L, s); + break; + } + case 'c': { + char buff[2]; + buff[0] = cast(char, va_arg(argp, int)); + buff[1] = '\0'; + pushstr(L, buff); + break; + } + case 'd': { + setnvalue(L->top, cast_num(va_arg(argp, int))); + incr_top(L); + break; + } + case 'f': { + setnvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); + incr_top(L); + break; + } + case 'p': { + char buff[4*sizeof(void *) + 8]; /* should be enough space for a `%p' */ + sprintf(buff, "%p", va_arg(argp, void *)); + pushstr(L, buff); + break; + } + case '%': { + pushstr(L, "%"); + break; + } + default: { + char buff[3]; + buff[0] = '%'; + buff[1] = *(e+1); + buff[2] = '\0'; + pushstr(L, buff); + break; + } + } + n += 2; + fmt = e+2; + } + pushstr(L, fmt); + luaV_concat(L, n+1, cast_int(L->top - L->base) - 1); + L->top -= n; + return svalue(L->top - 1); +} + + +const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { + const char *msg; + va_list argp; + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + return msg; +} + + +void luaO_chunkid (char *out, const char *source, size_t bufflen) { + if (*source == '=') { + strncpy(out, source+1, bufflen); /* remove first char */ + out[bufflen-1] = '\0'; /* ensures null termination */ + } + else { /* out = "source", or "...source" */ + if (*source == '@') { + size_t l; + source++; /* skip the `@' */ + bufflen -= sizeof(" '...' "); + l = strlen(source); + strcpy(out, ""); + if (l > bufflen) { + source += (l-bufflen); /* get last part of file name */ + strcat(out, "..."); + } + strcat(out, source); + } + else { /* out = [string "string"] */ + size_t len = strcspn(source, "\n\r"); /* stop at first newline */ + bufflen -= sizeof(" [string \"...\"] "); + if (len > bufflen) len = bufflen; + strcpy(out, "[string \""); + if (source[len] != '\0') { /* must truncate? */ + strncat(out, source, len); + strcat(out, "..."); + } + else + strcat(out, source); + strcat(out, "\"]"); + } + } +} diff --git a/src/lua/src/lobject.h b/src/lua/src/lobject.h new file mode 100644 index 00000000..f1e447ef --- /dev/null +++ b/src/lua/src/lobject.h @@ -0,0 +1,381 @@ +/* +** $Id: lobject.h,v 2.20.1.2 2008/08/06 13:29:48 roberto Exp $ +** Type definitions for Lua objects +** See Copyright Notice in lua.h +*/ + + +#ifndef lobject_h +#define lobject_h + + +#include + + +#include "llimits.h" +#include "lua.h" + + +/* tags for values visible from Lua */ +#define LAST_TAG LUA_TTHREAD + +#define NUM_TAGS (LAST_TAG+1) + + +/* +** Extra tags for non-values +*/ +#define LUA_TPROTO (LAST_TAG+1) +#define LUA_TUPVAL (LAST_TAG+2) +#define LUA_TDEADKEY (LAST_TAG+3) + + +/* +** Union of all collectable objects +*/ +typedef union GCObject GCObject; + + +/* +** Common Header for all collectable objects (in macro form, to be +** included in other objects) +*/ +#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked + + +/* +** Common header in struct form +*/ +typedef struct GCheader { + CommonHeader; +} GCheader; + + + + +/* +** Union of all Lua values +*/ +typedef union { + GCObject *gc; + void *p; + lua_Number n; + int b; +} Value; + + +/* +** Tagged Values +*/ + +#define TValuefields Value value; int tt + +typedef struct lua_TValue { + TValuefields; +} TValue; + + +/* Macros to test type */ +#define ttisnil(o) (ttype(o) == LUA_TNIL) +#define ttisnumber(o) (ttype(o) == LUA_TNUMBER) +#define ttisstring(o) (ttype(o) == LUA_TSTRING) +#define ttistable(o) (ttype(o) == LUA_TTABLE) +#define ttisfunction(o) (ttype(o) == LUA_TFUNCTION) +#define ttisboolean(o) (ttype(o) == LUA_TBOOLEAN) +#define ttisuserdata(o) (ttype(o) == LUA_TUSERDATA) +#define ttisthread(o) (ttype(o) == LUA_TTHREAD) +#define ttislightuserdata(o) (ttype(o) == LUA_TLIGHTUSERDATA) + +/* Macros to access values */ +#define ttype(o) ((o)->tt) +#define gcvalue(o) check_exp(iscollectable(o), (o)->value.gc) +#define pvalue(o) check_exp(ttislightuserdata(o), (o)->value.p) +#define nvalue(o) check_exp(ttisnumber(o), (o)->value.n) +#define rawtsvalue(o) check_exp(ttisstring(o), &(o)->value.gc->ts) +#define tsvalue(o) (&rawtsvalue(o)->tsv) +#define rawuvalue(o) check_exp(ttisuserdata(o), &(o)->value.gc->u) +#define uvalue(o) (&rawuvalue(o)->uv) +#define clvalue(o) check_exp(ttisfunction(o), &(o)->value.gc->cl) +#define hvalue(o) check_exp(ttistable(o), &(o)->value.gc->h) +#define bvalue(o) check_exp(ttisboolean(o), (o)->value.b) +#define thvalue(o) check_exp(ttisthread(o), &(o)->value.gc->th) + +#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) + +/* +** for internal debug only +*/ +#define checkconsistency(obj) \ + lua_assert(!iscollectable(obj) || (ttype(obj) == (obj)->value.gc->gch.tt)) + +#define checkliveness(g,obj) \ + lua_assert(!iscollectable(obj) || \ + ((ttype(obj) == (obj)->value.gc->gch.tt) && !isdead(g, (obj)->value.gc))) + + +/* Macros to set values */ +#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) + +#define setnvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } + +#define setpvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } + +#define setbvalue(obj,x) \ + { TValue *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } + +#define setsvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ + checkliveness(G(L),i_o); } + +#define setuvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ + checkliveness(G(L),i_o); } + +#define setthvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ + checkliveness(G(L),i_o); } + +#define setclvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ + checkliveness(G(L),i_o); } + +#define sethvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ + checkliveness(G(L),i_o); } + +#define setptvalue(L,obj,x) \ + { TValue *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ + checkliveness(G(L),i_o); } + + + + +#define setobj(L,obj1,obj2) \ + { const TValue *o2=(obj2); TValue *o1=(obj1); \ + o1->value = o2->value; o1->tt=o2->tt; \ + checkliveness(G(L),o1); } + + +/* +** different types of sets, according to destination +*/ + +/* from stack to (same) stack */ +#define setobjs2s setobj +/* to stack (not from same stack) */ +#define setobj2s setobj +#define setsvalue2s setsvalue +#define sethvalue2s sethvalue +#define setptvalue2s setptvalue +/* from table to same table */ +#define setobjt2t setobj +/* to table */ +#define setobj2t setobj +/* to new object */ +#define setobj2n setobj +#define setsvalue2n setsvalue + +#define setttype(obj, tt) (ttype(obj) = (tt)) + + +#define iscollectable(o) (ttype(o) >= LUA_TSTRING) + + + +typedef TValue *StkId; /* index to stack elements */ + + +/* +** String headers for string table +*/ +typedef union TString { + L_Umaxalign dummy; /* ensures maximum alignment for strings */ + struct { + CommonHeader; + lu_byte reserved; + unsigned int hash; + size_t len; + } tsv; +} TString; + + +#define getstr(ts) cast(const char *, (ts) + 1) +#define svalue(o) getstr(rawtsvalue(o)) + + + +typedef union Udata { + L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ + struct { + CommonHeader; + struct Table *metatable; + struct Table *env; + size_t len; + } uv; +} Udata; + + + + +/* +** Function Prototypes +*/ +typedef struct Proto { + CommonHeader; + TValue *k; /* constants used by the function */ + Instruction *code; + struct Proto **p; /* functions defined inside the function */ + int *lineinfo; /* map from opcodes to source lines */ + struct LocVar *locvars; /* information about local variables */ + TString **upvalues; /* upvalue names */ + TString *source; + int sizeupvalues; + int sizek; /* size of `k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of `p' */ + int sizelocvars; + int linedefined; + int lastlinedefined; + GCObject *gclist; + lu_byte nups; /* number of upvalues */ + lu_byte numparams; + lu_byte is_vararg; + lu_byte maxstacksize; +} Proto; + + +/* masks for new-style vararg */ +#define VARARG_HASARG 1 +#define VARARG_ISVARARG 2 +#define VARARG_NEEDSARG 4 + + +typedef struct LocVar { + TString *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} LocVar; + + + +/* +** Upvalues +*/ + +typedef struct UpVal { + CommonHeader; + TValue *v; /* points to stack or to its own value */ + union { + TValue value; /* the value (when closed) */ + struct { /* double linked list (when open) */ + struct UpVal *prev; + struct UpVal *next; + } l; + } u; +} UpVal; + + +/* +** Closures +*/ + +#define ClosureHeader \ + CommonHeader; lu_byte isC; lu_byte nupvalues; GCObject *gclist; \ + struct Table *env + +typedef struct CClosure { + ClosureHeader; + lua_CFunction f; + TValue upvalue[1]; +} CClosure; + + +typedef struct LClosure { + ClosureHeader; + struct Proto *p; + UpVal *upvals[1]; +} LClosure; + + +typedef union Closure { + CClosure c; + LClosure l; +} Closure; + + +#define iscfunction(o) (ttype(o) == LUA_TFUNCTION && clvalue(o)->c.isC) +#define isLfunction(o) (ttype(o) == LUA_TFUNCTION && !clvalue(o)->c.isC) + + +/* +** Tables +*/ + +typedef union TKey { + struct { + TValuefields; + struct Node *next; /* for chaining */ + } nk; + TValue tvk; +} TKey; + + +typedef struct Node { + TValue i_val; + TKey i_key; +} Node; + + +typedef struct Table { + CommonHeader; + lu_byte flags; /* 1<

lsizenode)) + + +#define luaO_nilobject (&luaO_nilobject_) + +LUAI_DATA const TValue luaO_nilobject_; + +#define ceillog2(x) (luaO_log2((x)-1) + 1) + +LUAI_FUNC int luaO_log2 (unsigned int x); +LUAI_FUNC int luaO_int2fb (unsigned int x); +LUAI_FUNC int luaO_fb2int (int x); +LUAI_FUNC int luaO_rawequalObj (const TValue *t1, const TValue *t2); +LUAI_FUNC int luaO_str2d (const char *s, lua_Number *result); +LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, + va_list argp); +LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); +LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); + + +#endif + diff --git a/src/lua/src/lopcodes.c b/src/lua/src/lopcodes.c new file mode 100644 index 00000000..4cc74523 --- /dev/null +++ b/src/lua/src/lopcodes.c @@ -0,0 +1,102 @@ +/* +** $Id: lopcodes.c,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ +** See Copyright Notice in lua.h +*/ + + +#define lopcodes_c +#define LUA_CORE + + +#include "lopcodes.h" + + +/* ORDER OP */ + +const char *const luaP_opnames[NUM_OPCODES+1] = { + "MOVE", + "LOADK", + "LOADBOOL", + "LOADNIL", + "GETUPVAL", + "GETGLOBAL", + "GETTABLE", + "SETGLOBAL", + "SETUPVAL", + "SETTABLE", + "NEWTABLE", + "SELF", + "ADD", + "SUB", + "MUL", + "DIV", + "MOD", + "POW", + "UNM", + "NOT", + "LEN", + "CONCAT", + "JMP", + "EQ", + "LT", + "LE", + "TEST", + "TESTSET", + "CALL", + "TAILCALL", + "RETURN", + "FORLOOP", + "FORPREP", + "TFORLOOP", + "SETLIST", + "CLOSE", + "CLOSURE", + "VARARG", + NULL +}; + + +#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) + +const lu_byte luaP_opmodes[NUM_OPCODES] = { +/* T A B C mode opcode */ + opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LOADNIL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_GETGLOBAL */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, OpArgK, OpArgN, iABx) /* OP_SETGLOBAL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ + ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ + ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ + ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TFORLOOP */ + ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ + ,opmode(0, 0, OpArgN, OpArgN, iABC) /* OP_CLOSE */ + ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ +}; + diff --git a/src/lua/src/lopcodes.h b/src/lua/src/lopcodes.h new file mode 100644 index 00000000..41224d6e --- /dev/null +++ b/src/lua/src/lopcodes.h @@ -0,0 +1,268 @@ +/* +** $Id: lopcodes.h,v 1.125.1.1 2007/12/27 13:02:25 roberto Exp $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lopcodes_h +#define lopcodes_h + +#include "llimits.h" + + +/*=========================================================================== + We assume that instructions are unsigned numbers. + All instructions have an opcode in the first 6 bits. + Instructions can have the following fields: + `A' : 8 bits + `B' : 9 bits + `C' : 9 bits + `Bx' : 18 bits (`B' and `C' together) + `sBx' : signed Bx + + A signed argument is represented in excess K; that is, the number + value is the unsigned value minus K. K is exactly the maximum value + for that argument (so that -max is represented by 0, and +max is + represented by 2*max), which is half the maximum for the corresponding + unsigned argument. +===========================================================================*/ + + +enum OpMode {iABC, iABx, iAsBx}; /* basic instruction format */ + + +/* +** size and position of opcode arguments. +*/ +#define SIZE_C 9 +#define SIZE_B 9 +#define SIZE_Bx (SIZE_C + SIZE_B) +#define SIZE_A 8 + +#define SIZE_OP 6 + +#define POS_OP 0 +#define POS_A (POS_OP + SIZE_OP) +#define POS_C (POS_A + SIZE_A) +#define POS_B (POS_C + SIZE_C) +#define POS_Bx POS_C + + +/* +** limits for opcode arguments. +** we use (signed) int to manipulate most arguments, +** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) +*/ +#if SIZE_Bx < LUAI_BITSINT-1 +#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ +#else +#define MAXARG_Bx MAX_INT +#define MAXARG_sBx MAX_INT +#endif + + +#define MAXARG_A ((1<>POS_OP) & MASK1(SIZE_OP,0))) +#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ + ((cast(Instruction, o)<>POS_A) & MASK1(SIZE_A,0))) +#define SETARG_A(i,u) ((i) = (((i)&MASK0(SIZE_A,POS_A)) | \ + ((cast(Instruction, u)<>POS_B) & MASK1(SIZE_B,0))) +#define SETARG_B(i,b) ((i) = (((i)&MASK0(SIZE_B,POS_B)) | \ + ((cast(Instruction, b)<>POS_C) & MASK1(SIZE_C,0))) +#define SETARG_C(i,b) ((i) = (((i)&MASK0(SIZE_C,POS_C)) | \ + ((cast(Instruction, b)<>POS_Bx) & MASK1(SIZE_Bx,0))) +#define SETARG_Bx(i,b) ((i) = (((i)&MASK0(SIZE_Bx,POS_Bx)) | \ + ((cast(Instruction, b)< C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ + +OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ + +OP_FORLOOP,/* A sBx R(A)+=R(A+2); + if R(A) =) R(A)*/ +OP_CLOSURE,/* A Bx R(A) := closure(KPROTO[Bx], R(A), ... ,R(A+n)) */ + +OP_VARARG/* A B R(A), R(A+1), ..., R(A+B-1) = vararg */ +} OpCode; + + +#define NUM_OPCODES (cast(int, OP_VARARG) + 1) + + + +/*=========================================================================== + Notes: + (*) In OP_CALL, if (B == 0) then B = top. C is the number of returns - 1, + and can be 0: OP_CALL then sets `top' to last_result+1, so + next open instruction (OP_CALL, OP_RETURN, OP_SETLIST) may use `top'. + + (*) In OP_VARARG, if (B == 0) then use actual number of varargs and + set top (like in OP_CALL with C == 0). + + (*) In OP_RETURN, if (B == 0) then return up to `top' + + (*) In OP_SETLIST, if (B == 0) then B = `top'; + if (C == 0) then next `instruction' is real C + + (*) For comparisons, A specifies what condition the test should accept + (true or false). + + (*) All `skips' (pc++) assume that next instruction is a jump +===========================================================================*/ + + +/* +** masks for instruction properties. The format is: +** bits 0-1: op mode +** bits 2-3: C arg mode +** bits 4-5: B arg mode +** bit 6: instruction set register A +** bit 7: operator is a test +*/ + +enum OpArgMask { + OpArgN, /* argument is not used */ + OpArgU, /* argument is used */ + OpArgR, /* argument is a register or a jump offset */ + OpArgK /* argument is a constant or register/constant */ +}; + +LUAI_DATA const lu_byte luaP_opmodes[NUM_OPCODES]; + +#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) +#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) +#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) +#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) +#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) + + +LUAI_DATA const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ + + +/* number of list items to accumulate before a SETLIST instruction */ +#define LFIELDS_PER_FLUSH 50 + + +#endif diff --git a/src/lua/src/loslib.c b/src/lua/src/loslib.c new file mode 100644 index 00000000..da06a572 --- /dev/null +++ b/src/lua/src/loslib.c @@ -0,0 +1,243 @@ +/* +** $Id: loslib.c,v 1.19.1.3 2008/01/18 16:38:18 roberto Exp $ +** Standard Operating System library +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#define loslib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static int os_pushresult (lua_State *L, int i, const char *filename) { + int en = errno; /* calls to Lua API may change this value */ + if (i) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + lua_pushfstring(L, "%s: %s", filename, strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +static int os_execute (lua_State *L) { + lua_pushinteger(L, system(luaL_optstring(L, 1, NULL))); + return 1; +} + + +static int os_remove (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + return os_pushresult(L, remove(filename) == 0, filename); +} + + +static int os_rename (lua_State *L) { + const char *fromname = luaL_checkstring(L, 1); + const char *toname = luaL_checkstring(L, 2); + return os_pushresult(L, rename(fromname, toname) == 0, fromname); +} + + +static int os_tmpname (lua_State *L) { + char buff[LUA_TMPNAMBUFSIZE]; + int err; + lua_tmpnam(buff, err); + if (err) + return luaL_error(L, "unable to generate a unique filename"); + lua_pushstring(L, buff); + return 1; +} + + +static int os_getenv (lua_State *L) { + lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ + return 1; +} + + +static int os_clock (lua_State *L) { + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + return 1; +} + + +/* +** {====================================================== +** Time/Date operations +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, +** wday=%w+1, yday=%j, isdst=? } +** ======================================================= +*/ + +static void setfield (lua_State *L, const char *key, int value) { + lua_pushinteger(L, value); + lua_setfield(L, -2, key); +} + +static void setboolfield (lua_State *L, const char *key, int value) { + if (value < 0) /* undefined? */ + return; /* does not set field */ + lua_pushboolean(L, value); + lua_setfield(L, -2, key); +} + +static int getboolfield (lua_State *L, const char *key) { + int res; + lua_getfield(L, -1, key); + res = lua_isnil(L, -1) ? -1 : lua_toboolean(L, -1); + lua_pop(L, 1); + return res; +} + + +static int getfield (lua_State *L, const char *key, int d) { + int res; + lua_getfield(L, -1, key); + if (lua_isnumber(L, -1)) + res = (int)lua_tointeger(L, -1); + else { + if (d < 0) + return luaL_error(L, "field " LUA_QS " missing in date table", key); + res = d; + } + lua_pop(L, 1); + return res; +} + + +static int os_date (lua_State *L) { + const char *s = luaL_optstring(L, 1, "%c"); + time_t t = luaL_opt(L, (time_t)luaL_checknumber, 2, time(NULL)); + struct tm *stm; + if (*s == '!') { /* UTC? */ + stm = gmtime(&t); + s++; /* skip `!' */ + } + else + stm = localtime(&t); + if (stm == NULL) /* invalid date? */ + lua_pushnil(L); + else if (strcmp(s, "*t") == 0) { + lua_createtable(L, 0, 9); /* 9 = number of fields */ + setfield(L, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon+1); + setfield(L, "year", stm->tm_year+1900); + setfield(L, "wday", stm->tm_wday+1); + setfield(L, "yday", stm->tm_yday+1); + setboolfield(L, "isdst", stm->tm_isdst); + } + else { + char cc[3]; + luaL_Buffer b; + cc[0] = '%'; cc[2] = '\0'; + luaL_buffinit(L, &b); + for (; *s; s++) { + if (*s != '%' || *(s + 1) == '\0') /* no conversion specifier? */ + luaL_addchar(&b, *s); + else { + size_t reslen; + char buff[200]; /* should be big enough for any conversion result */ + cc[1] = *(++s); + reslen = strftime(buff, sizeof(buff), cc, stm); + luaL_addlstring(&b, buff, reslen); + } + } + luaL_pushresult(&b); + } + return 1; +} + + +static int os_time (lua_State *L) { + time_t t; + if (lua_isnoneornil(L, 1)) /* called without args? */ + t = time(NULL); /* get current time */ + else { + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_sec = getfield(L, "sec", 0); + ts.tm_min = getfield(L, "min", 0); + ts.tm_hour = getfield(L, "hour", 12); + ts.tm_mday = getfield(L, "day", -1); + ts.tm_mon = getfield(L, "month", -1) - 1; + ts.tm_year = getfield(L, "year", -1) - 1900; + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + } + if (t == (time_t)(-1)) + lua_pushnil(L); + else + lua_pushnumber(L, (lua_Number)t); + return 1; +} + + +static int os_difftime (lua_State *L) { + lua_pushnumber(L, difftime((time_t)(luaL_checknumber(L, 1)), + (time_t)(luaL_optnumber(L, 2, 0)))); + return 1; +} + +/* }====================================================== */ + + +static int os_setlocale (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + const char *l = luaL_optstring(L, 1, NULL); + int op = luaL_checkoption(L, 2, "all", catnames); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; +} + + +static int os_exit (lua_State *L) { + exit(luaL_optint(L, 1, EXIT_SUCCESS)); +} + +static const luaL_Reg syslib[] = { + {"clock", os_clock}, + {"date", os_date}, + {"difftime", os_difftime}, + {"execute", os_execute}, + {"exit", os_exit}, + {"getenv", os_getenv}, + {"remove", os_remove}, + {"rename", os_rename}, + {"setlocale", os_setlocale}, + {"time", os_time}, + {"tmpname", os_tmpname}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +LUALIB_API int luaopen_os (lua_State *L) { + luaL_register(L, LUA_OSLIBNAME, syslib); + return 1; +} + diff --git a/src/lua/src/lparser.c b/src/lua/src/lparser.c new file mode 100644 index 00000000..1e2a9a88 --- /dev/null +++ b/src/lua/src/lparser.c @@ -0,0 +1,1339 @@ +/* +** $Id: lparser.c,v 2.42.1.3 2007/12/28 15:32:23 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + + +#include + +#define lparser_c +#define LUA_CORE + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" + + + +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) + +#define getlocvar(fs, i) ((fs)->f->locvars[(fs)->actvar[i]]) + +#define luaY_checklimit(fs,v,l,m) if ((v)>(l)) errorlimit(fs,l,m) + + +/* +** nodes for block list (list of active blocks) +*/ +typedef struct BlockCnt { + struct BlockCnt *previous; /* chain */ + int breaklist; /* list of jumps out of this loop */ + lu_byte nactvar; /* # active locals outside the breakable structure */ + lu_byte upval; /* true if some variable in the block is an upvalue */ + lu_byte isbreakable; /* true if `block' is a loop */ +} BlockCnt; + + + +/* +** prototypes for recursive non-terminal functions +*/ +static void chunk (LexState *ls); +static void expr (LexState *ls, expdesc *v); + + +static void anchor_token (LexState *ls) { + if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { + TString *ts = ls->t.seminfo.ts; + luaX_newstring(ls, getstr(ts), ts->tsv.len); + } +} + + +static void error_expected (LexState *ls, int token) { + luaX_syntaxerror(ls, + luaO_pushfstring(ls->L, LUA_QS " expected", luaX_token2str(ls, token))); +} + + +static void errorlimit (FuncState *fs, int limit, const char *what) { + const char *msg = (fs->f->linedefined == 0) ? + luaO_pushfstring(fs->L, "main function has more than %d %s", limit, what) : + luaO_pushfstring(fs->L, "function at line %d has more than %d %s", + fs->f->linedefined, limit, what); + luaX_lexerror(fs->ls, msg, 0); +} + + +static int testnext (LexState *ls, int c) { + if (ls->t.token == c) { + luaX_next(ls); + return 1; + } + else return 0; +} + + +static void check (LexState *ls, int c) { + if (ls->t.token != c) + error_expected(ls, c); +} + +static void checknext (LexState *ls, int c) { + check(ls, c); + luaX_next(ls); +} + + +#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } + + + +static void check_match (LexState *ls, int what, int who, int where) { + if (!testnext(ls, what)) { + if (where == ls->linenumber) + error_expected(ls, what); + else { + luaX_syntaxerror(ls, luaO_pushfstring(ls->L, + LUA_QS " expected (to close " LUA_QS " at line %d)", + luaX_token2str(ls, what), luaX_token2str(ls, who), where)); + } + } +} + + +static TString *str_checkname (LexState *ls) { + TString *ts; + check(ls, TK_NAME); + ts = ls->t.seminfo.ts; + luaX_next(ls); + return ts; +} + + +static void init_exp (expdesc *e, expkind k, int i) { + e->f = e->t = NO_JUMP; + e->k = k; + e->u.s.info = i; +} + + +static void codestring (LexState *ls, expdesc *e, TString *s) { + init_exp(e, VK, luaK_stringK(ls->fs, s)); +} + + +static void checkname(LexState *ls, expdesc *e) { + codestring(ls, e, str_checkname(ls)); +} + + +static int registerlocalvar (LexState *ls, TString *varname) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int oldsize = f->sizelocvars; + luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, + LocVar, SHRT_MAX, "too many local variables"); + while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; + f->locvars[fs->nlocvars].varname = varname; + luaC_objbarrier(ls->L, f, varname); + return fs->nlocvars++; +} + + +#define new_localvarliteral(ls,v,n) \ + new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char))-1), n) + + +static void new_localvar (LexState *ls, TString *name, int n) { + FuncState *fs = ls->fs; + luaY_checklimit(fs, fs->nactvar+n+1, LUAI_MAXVARS, "local variables"); + fs->actvar[fs->nactvar+n] = cast(unsigned short, registerlocalvar(ls, name)); +} + + +static void adjustlocalvars (LexState *ls, int nvars) { + FuncState *fs = ls->fs; + fs->nactvar = cast_byte(fs->nactvar + nvars); + for (; nvars; nvars--) { + getlocvar(fs, fs->nactvar - nvars).startpc = fs->pc; + } +} + + +static void removevars (LexState *ls, int tolevel) { + FuncState *fs = ls->fs; + while (fs->nactvar > tolevel) + getlocvar(fs, --fs->nactvar).endpc = fs->pc; +} + + +static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { + int i; + Proto *f = fs->f; + int oldsize = f->sizeupvalues; + for (i=0; inups; i++) { + if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->u.s.info) { + lua_assert(f->upvalues[i] == name); + return i; + } + } + /* new one */ + luaY_checklimit(fs, f->nups + 1, LUAI_MAXUPVALUES, "upvalues"); + luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, + TString *, MAX_INT, ""); + while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; + f->upvalues[f->nups] = name; + luaC_objbarrier(fs->L, f, name); + lua_assert(v->k == VLOCAL || v->k == VUPVAL); + fs->upvalues[f->nups].k = cast_byte(v->k); + fs->upvalues[f->nups].info = cast_byte(v->u.s.info); + return f->nups++; +} + + +static int searchvar (FuncState *fs, TString *n) { + int i; + for (i=fs->nactvar-1; i >= 0; i--) { + if (n == getlocvar(fs, i).varname) + return i; + } + return -1; /* not found */ +} + + +static void markupval (FuncState *fs, int level) { + BlockCnt *bl = fs->bl; + while (bl && bl->nactvar > level) bl = bl->previous; + if (bl) bl->upval = 1; +} + + +static int singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { + if (fs == NULL) { /* no more levels? */ + init_exp(var, VGLOBAL, NO_REG); /* default is global variable */ + return VGLOBAL; + } + else { + int v = searchvar(fs, n); /* look up at current level */ + if (v >= 0) { + init_exp(var, VLOCAL, v); + if (!base) + markupval(fs, v); /* local will be used as an upval */ + return VLOCAL; + } + else { /* not found at current level; try upper one */ + if (singlevaraux(fs->prev, n, var, 0) == VGLOBAL) + return VGLOBAL; + var->u.s.info = indexupvalue(fs, n, var); /* else was LOCAL or UPVAL */ + var->k = VUPVAL; /* upvalue in this level */ + return VUPVAL; + } + } +} + + +static void singlevar (LexState *ls, expdesc *var) { + TString *varname = str_checkname(ls); + FuncState *fs = ls->fs; + if (singlevaraux(fs, varname, var, 1) == VGLOBAL) + var->u.s.info = luaK_stringK(fs, varname); /* info points to global name */ +} + + +static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { + FuncState *fs = ls->fs; + int extra = nvars - nexps; + if (hasmultret(e->k)) { + extra++; /* includes call itself */ + if (extra < 0) extra = 0; + luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ + if (extra > 1) luaK_reserveregs(fs, extra-1); + } + else { + if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ + if (extra > 0) { + int reg = fs->freereg; + luaK_reserveregs(fs, extra); + luaK_nil(fs, reg, extra); + } + } +} + + +static void enterlevel (LexState *ls) { + if (++ls->L->nCcalls > LUAI_MAXCCALLS) + luaX_lexerror(ls, "chunk has too many syntax levels", 0); +} + + +#define leavelevel(ls) ((ls)->L->nCcalls--) + + +static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isbreakable) { + bl->breaklist = NO_JUMP; + bl->isbreakable = isbreakable; + bl->nactvar = fs->nactvar; + bl->upval = 0; + bl->previous = fs->bl; + fs->bl = bl; + lua_assert(fs->freereg == fs->nactvar); +} + + +static void leaveblock (FuncState *fs) { + BlockCnt *bl = fs->bl; + fs->bl = bl->previous; + removevars(fs->ls, bl->nactvar); + if (bl->upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + /* a block either controls scope or breaks (never both) */ + lua_assert(!bl->isbreakable || !bl->upval); + lua_assert(bl->nactvar == fs->nactvar); + fs->freereg = fs->nactvar; /* free registers */ + luaK_patchtohere(fs, bl->breaklist); +} + + +static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int oldsize = f->sizep; + int i; + luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, + MAXARG_Bx, "constant table overflow"); + while (oldsize < f->sizep) f->p[oldsize++] = NULL; + f->p[fs->np++] = func->f; + luaC_objbarrier(ls->L, f, func->f); + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); + for (i=0; if->nups; i++) { + OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, o, 0, func->upvalues[i].info, 0); + } +} + + +static void open_func (LexState *ls, FuncState *fs) { + lua_State *L = ls->L; + Proto *f = luaF_newproto(L); + fs->f = f; + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + fs->L = L; + ls->fs = fs; + fs->pc = 0; + fs->lasttarget = -1; + fs->jpc = NO_JUMP; + fs->freereg = 0; + fs->nk = 0; + fs->np = 0; + fs->nlocvars = 0; + fs->nactvar = 0; + fs->bl = NULL; + f->source = ls->source; + f->maxstacksize = 2; /* registers 0/1 are always valid */ + fs->h = luaH_new(L, 0, 0); + /* anchor table of constants and prototype (to avoid being collected) */ + sethvalue2s(L, L->top, fs->h); + incr_top(L); + setptvalue2s(L, L->top, f); + incr_top(L); +} + + +static void close_func (LexState *ls) { + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; + removevars(ls, 0); + luaK_ret(fs, 0, 0); /* final return */ + luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); + f->sizecode = fs->pc; + luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); + f->sizelineinfo = fs->pc; + luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); + f->sizek = fs->nk; + luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); + f->sizep = fs->np; + luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); + f->sizelocvars = fs->nlocvars; + luaM_reallocvector(L, f->upvalues, f->sizeupvalues, f->nups, TString *); + f->sizeupvalues = f->nups; + lua_assert(luaG_checkcode(f)); + lua_assert(fs->bl == NULL); + ls->fs = fs->prev; + L->top -= 2; /* remove table and prototype from the stack */ + /* last token read was anchored in defunct function; must reanchor it */ + if (fs) anchor_token(ls); +} + + +Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { + struct LexState lexstate; + struct FuncState funcstate; + lexstate.buff = buff; + luaX_setinput(L, &lexstate, z, luaS_new(L, name)); + open_func(&lexstate, &funcstate); + funcstate.f->is_vararg = VARARG_ISVARARG; /* main func. is always vararg */ + luaX_next(&lexstate); /* read first token */ + chunk(&lexstate); + check(&lexstate, TK_EOS); + close_func(&lexstate); + lua_assert(funcstate.prev == NULL); + lua_assert(funcstate.f->nups == 0); + lua_assert(lexstate.fs == NULL); + return funcstate.f; +} + + + +/*============================================================*/ +/* GRAMMAR RULES */ +/*============================================================*/ + + +static void field (LexState *ls, expdesc *v) { + /* field -> ['.' | ':'] NAME */ + FuncState *fs = ls->fs; + expdesc key; + luaK_exp2anyreg(fs, v); + luaX_next(ls); /* skip the dot or colon */ + checkname(ls, &key); + luaK_indexed(fs, v, &key); +} + + +static void yindex (LexState *ls, expdesc *v) { + /* index -> '[' expr ']' */ + luaX_next(ls); /* skip the '[' */ + expr(ls, v); + luaK_exp2val(ls->fs, v); + checknext(ls, ']'); +} + + +/* +** {====================================================================== +** Rules for Constructors +** ======================================================================= +*/ + + +struct ConsControl { + expdesc v; /* last list item read */ + expdesc *t; /* table descriptor */ + int nh; /* total number of `record' elements */ + int na; /* total number of array elements */ + int tostore; /* number of array elements pending to be stored */ +}; + + +static void recfield (LexState *ls, struct ConsControl *cc) { + /* recfield -> (NAME | `['exp1`]') = exp1 */ + FuncState *fs = ls->fs; + int reg = ls->fs->freereg; + expdesc key, val; + int rkkey; + if (ls->t.token == TK_NAME) { + luaY_checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + checkname(ls, &key); + } + else /* ls->t.token == '[' */ + yindex(ls, &key); + cc->nh++; + checknext(ls, '='); + rkkey = luaK_exp2RK(fs, &key); + expr(ls, &val); + luaK_codeABC(fs, OP_SETTABLE, cc->t->u.s.info, rkkey, luaK_exp2RK(fs, &val)); + fs->freereg = reg; /* free registers */ +} + + +static void closelistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->v.k == VVOID) return; /* there is no list item */ + luaK_exp2nextreg(fs, &cc->v); + cc->v.k = VVOID; + if (cc->tostore == LFIELDS_PER_FLUSH) { + luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); /* flush */ + cc->tostore = 0; /* no more items pending */ + } +} + + +static void lastlistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->tostore == 0) return; + if (hasmultret(cc->v.k)) { + luaK_setmultret(fs, &cc->v); + luaK_setlist(fs, cc->t->u.s.info, cc->na, LUA_MULTRET); + cc->na--; /* do not count last expression (unknown number of elements) */ + } + else { + if (cc->v.k != VVOID) + luaK_exp2nextreg(fs, &cc->v); + luaK_setlist(fs, cc->t->u.s.info, cc->na, cc->tostore); + } +} + + +static void listfield (LexState *ls, struct ConsControl *cc) { + expr(ls, &cc->v); + luaY_checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + cc->na++; + cc->tostore++; +} + + +static void constructor (LexState *ls, expdesc *t) { + /* constructor -> ?? */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); + struct ConsControl cc; + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + init_exp(t, VRELOCABLE, pc); + init_exp(&cc.v, VVOID, 0); /* no value (yet) */ + luaK_exp2nextreg(ls->fs, t); /* fix it at stack top (for gc) */ + checknext(ls, '{'); + do { + lua_assert(cc.v.k == VVOID || cc.tostore > 0); + if (ls->t.token == '}') break; + closelistfield(fs, &cc); + switch(ls->t.token) { + case TK_NAME: { /* may be listfields or recfields */ + luaX_lookahead(ls); + if (ls->lookahead.token != '=') /* expression? */ + listfield(ls, &cc); + else + recfield(ls, &cc); + break; + } + case '[': { /* constructor_item -> recfield */ + recfield(ls, &cc); + break; + } + default: { /* constructor_part -> listfield */ + listfield(ls, &cc); + break; + } + } + } while (testnext(ls, ',') || testnext(ls, ';')); + check_match(ls, '}', '{', line); + lastlistfield(fs, &cc); + SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ + SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ +} + +/* }====================================================================== */ + + + +static void parlist (LexState *ls) { + /* parlist -> [ param { `,' param } ] */ + FuncState *fs = ls->fs; + Proto *f = fs->f; + int nparams = 0; + f->is_vararg = 0; + if (ls->t.token != ')') { /* is `parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_NAME: { /* param -> NAME */ + new_localvar(ls, str_checkname(ls), nparams++); + break; + } + case TK_DOTS: { /* param -> `...' */ + luaX_next(ls); +#if defined(LUA_COMPAT_VARARG) + /* use `arg' as default name */ + new_localvarliteral(ls, "arg", nparams++); + f->is_vararg = VARARG_HASARG | VARARG_NEEDSARG; +#endif + f->is_vararg |= VARARG_ISVARARG; + break; + } + default: luaX_syntaxerror(ls, " or " LUA_QL("...") " expected"); + } + } while (!f->is_vararg && testnext(ls, ',')); + } + adjustlocalvars(ls, nparams); + f->numparams = cast_byte(fs->nactvar - (f->is_vararg & VARARG_HASARG)); + luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ +} + + +static void body (LexState *ls, expdesc *e, int needself, int line) { + /* body -> `(' parlist `)' chunk END */ + FuncState new_fs; + open_func(ls, &new_fs); + new_fs.f->linedefined = line; + checknext(ls, '('); + if (needself) { + new_localvarliteral(ls, "self", 0); + adjustlocalvars(ls, 1); + } + parlist(ls); + checknext(ls, ')'); + chunk(ls); + new_fs.f->lastlinedefined = ls->linenumber; + check_match(ls, TK_END, TK_FUNCTION, line); + close_func(ls); + pushclosure(ls, &new_fs, e); +} + + +static int explist1 (LexState *ls, expdesc *v) { + /* explist1 -> expr { `,' expr } */ + int n = 1; /* at least one expression */ + expr(ls, v); + while (testnext(ls, ',')) { + luaK_exp2nextreg(ls->fs, v); + expr(ls, v); + n++; + } + return n; +} + + +static void funcargs (LexState *ls, expdesc *f) { + FuncState *fs = ls->fs; + expdesc args; + int base, nparams; + int line = ls->linenumber; + switch (ls->t.token) { + case '(': { /* funcargs -> `(' [ explist1 ] `)' */ + if (line != ls->lastline) + luaX_syntaxerror(ls,"ambiguous syntax (function call x new statement)"); + luaX_next(ls); + if (ls->t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + explist1(ls, &args); + luaK_setmultret(fs, &args); + } + check_match(ls, ')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + codestring(ls, &args, ls->t.seminfo.ts); + luaX_next(ls); /* must use `seminfo' before `next' */ + break; + } + default: { + luaX_syntaxerror(ls, "function arguments expected"); + return; + } + } + lua_assert(f->k == VNONRELOC); + base = f->u.s.info; /* base register for call */ + if (hasmultret(args.k)) + nparams = LUA_MULTRET; /* open call */ + else { + if (args.k != VVOID) + luaK_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base+1); + } + init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); + luaK_fixline(fs, line); + fs->freereg = base+1; /* call remove function and arguments and leaves + (unless changed) one result */ +} + + + + +/* +** {====================================================================== +** Expression parsing +** ======================================================================= +*/ + + +static void prefixexp (LexState *ls, expdesc *v) { + /* prefixexp -> NAME | '(' expr ')' */ + switch (ls->t.token) { + case '(': { + int line = ls->linenumber; + luaX_next(ls); + expr(ls, v); + check_match(ls, ')', '(', line); + luaK_dischargevars(ls->fs, v); + return; + } + case TK_NAME: { + singlevar(ls, v); + return; + } + default: { + luaX_syntaxerror(ls, "unexpected symbol"); + return; + } + } +} + + +static void primaryexp (LexState *ls, expdesc *v) { + /* primaryexp -> + prefixexp { `.' NAME | `[' exp `]' | `:' NAME funcargs | funcargs } */ + FuncState *fs = ls->fs; + prefixexp(ls, v); + for (;;) { + switch (ls->t.token) { + case '.': { /* field */ + field(ls, v); + break; + } + case '[': { /* `[' exp1 `]' */ + expdesc key; + luaK_exp2anyreg(fs, v); + yindex(ls, &key); + luaK_indexed(fs, v, &key); + break; + } + case ':': { /* `:' NAME funcargs */ + expdesc key; + luaX_next(ls); + checkname(ls, &key); + luaK_self(fs, v, &key); + funcargs(ls, v); + break; + } + case '(': case TK_STRING: case '{': { /* funcargs */ + luaK_exp2nextreg(fs, v); + funcargs(ls, v); + break; + } + default: return; + } + } +} + + +static void simpleexp (LexState *ls, expdesc *v) { + /* simpleexp -> NUMBER | STRING | NIL | true | false | ... | + constructor | FUNCTION body | primaryexp */ + switch (ls->t.token) { + case TK_NUMBER: { + init_exp(v, VKNUM, 0); + v->u.nval = ls->t.seminfo.r; + break; + } + case TK_STRING: { + codestring(ls, v, ls->t.seminfo.ts); + break; + } + case TK_NIL: { + init_exp(v, VNIL, 0); + break; + } + case TK_TRUE: { + init_exp(v, VTRUE, 0); + break; + } + case TK_FALSE: { + init_exp(v, VFALSE, 0); + break; + } + case TK_DOTS: { /* vararg */ + FuncState *fs = ls->fs; + check_condition(ls, fs->f->is_vararg, + "cannot use " LUA_QL("...") " outside a vararg function"); + fs->f->is_vararg &= ~VARARG_NEEDSARG; /* don't need 'arg' */ + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); + break; + } + case '{': { /* constructor */ + constructor(ls, v); + return; + } + case TK_FUNCTION: { + luaX_next(ls); + body(ls, v, 0, ls->linenumber); + return; + } + default: { + primaryexp(ls, v); + return; + } + } + luaX_next(ls); +} + + +static UnOpr getunopr (int op) { + switch (op) { + case TK_NOT: return OPR_NOT; + case '-': return OPR_MINUS; + case '#': return OPR_LEN; + default: return OPR_NOUNOPR; + } +} + + +static BinOpr getbinopr (int op) { + switch (op) { + case '+': return OPR_ADD; + case '-': return OPR_SUB; + case '*': return OPR_MUL; + case '/': return OPR_DIV; + case '%': return OPR_MOD; + case '^': return OPR_POW; + case TK_CONCAT: return OPR_CONCAT; + case TK_NE: return OPR_NE; + case TK_EQ: return OPR_EQ; + case '<': return OPR_LT; + case TK_LE: return OPR_LE; + case '>': return OPR_GT; + case TK_GE: return OPR_GE; + case TK_AND: return OPR_AND; + case TK_OR: return OPR_OR; + default: return OPR_NOBINOPR; + } +} + + +static const struct { + lu_byte left; /* left priority for each binary operator */ + lu_byte right; /* right priority */ +} priority[] = { /* ORDER OPR */ + {6, 6}, {6, 6}, {7, 7}, {7, 7}, {7, 7}, /* `+' `-' `/' `%' */ + {10, 9}, {5, 4}, /* power and concat (right associative) */ + {3, 3}, {3, 3}, /* equality and inequality */ + {3, 3}, {3, 3}, {3, 3}, {3, 3}, /* order */ + {2, 2}, {1, 1} /* logical (and/or) */ +}; + +#define UNARY_PRIORITY 8 /* priority for unary operators */ + + +/* +** subexpr -> (simpleexp | unop subexpr) { binop subexpr } +** where `binop' is any binary operator with a priority higher than `limit' +*/ +static BinOpr subexpr (LexState *ls, expdesc *v, unsigned int limit) { + BinOpr op; + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) { + luaX_next(ls); + subexpr(ls, v, UNARY_PRIORITY); + luaK_prefix(ls->fs, uop, v); + } + else simpleexp(ls, v); + /* expand while operators have priorities higher than `limit' */ + op = getbinopr(ls->t.token); + while (op != OPR_NOBINOPR && priority[op].left > limit) { + expdesc v2; + BinOpr nextop; + luaX_next(ls); + luaK_infix(ls->fs, op, v); + /* read sub-expression with higher priority */ + nextop = subexpr(ls, &v2, priority[op].right); + luaK_posfix(ls->fs, op, v, &v2); + op = nextop; + } + leavelevel(ls); + return op; /* return first untreated operator */ +} + + +static void expr (LexState *ls, expdesc *v) { + subexpr(ls, v, 0); +} + +/* }==================================================================== */ + + + +/* +** {====================================================================== +** Rules for Statements +** ======================================================================= +*/ + + +static int block_follow (int token) { + switch (token) { + case TK_ELSE: case TK_ELSEIF: case TK_END: + case TK_UNTIL: case TK_EOS: + return 1; + default: return 0; + } +} + + +static void block (LexState *ls) { + /* block -> chunk */ + FuncState *fs = ls->fs; + BlockCnt bl; + enterblock(fs, &bl, 0); + chunk(ls); + lua_assert(bl.breaklist == NO_JUMP); + leaveblock(fs); +} + + +/* +** structure to chain all variables in the left-hand side of an +** assignment +*/ +struct LHS_assign { + struct LHS_assign *prev; + expdesc v; /* variable (global, local, upvalue, or indexed) */ +}; + + +/* +** check whether, in an assignment to a local variable, the local variable +** is needed in a previous assignment (to a table). If so, save original +** local value in a safe place and use this safe copy in the previous +** assignment. +*/ +static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { + FuncState *fs = ls->fs; + int extra = fs->freereg; /* eventual position to save local variable */ + int conflict = 0; + for (; lh; lh = lh->prev) { + if (lh->v.k == VINDEXED) { + if (lh->v.u.s.info == v->u.s.info) { /* conflict? */ + conflict = 1; + lh->v.u.s.info = extra; /* previous assignment will use safe copy */ + } + if (lh->v.u.s.aux == v->u.s.info) { /* conflict? */ + conflict = 1; + lh->v.u.s.aux = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) { + luaK_codeABC(fs, OP_MOVE, fs->freereg, v->u.s.info, 0); /* make copy */ + luaK_reserveregs(fs, 1); + } +} + + +static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { + expdesc e; + check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED, + "syntax error"); + if (testnext(ls, ',')) { /* assignment -> `,' primaryexp assignment */ + struct LHS_assign nv; + nv.prev = lh; + primaryexp(ls, &nv.v); + if (nv.v.k == VLOCAL) + check_conflict(ls, lh, &nv.v); + luaY_checklimit(ls->fs, nvars, LUAI_MAXCCALLS - ls->L->nCcalls, + "variables in assignment"); + assignment(ls, &nv, nvars+1); + } + else { /* assignment -> `=' explist1 */ + int nexps; + checknext(ls, '='); + nexps = explist1(ls, &e); + if (nexps != nvars) { + adjust_assign(ls, nvars, nexps, &e); + if (nexps > nvars) + ls->fs->freereg -= nexps - nvars; /* remove extra values */ + } + else { + luaK_setoneret(ls->fs, &e); /* close last expression */ + luaK_storevar(ls->fs, &lh->v, &e); + return; /* avoid default */ + } + } + init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ + luaK_storevar(ls->fs, &lh->v, &e); +} + + +static int cond (LexState *ls) { + /* cond -> exp */ + expdesc v; + expr(ls, &v); /* read condition */ + if (v.k == VNIL) v.k = VFALSE; /* `falses' are all equal here */ + luaK_goiftrue(ls->fs, &v); + return v.f; +} + + +static void breakstat (LexState *ls) { + FuncState *fs = ls->fs; + BlockCnt *bl = fs->bl; + int upval = 0; + while (bl && !bl->isbreakable) { + upval |= bl->upval; + bl = bl->previous; + } + if (!bl) + luaX_syntaxerror(ls, "no loop to break"); + if (upval) + luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0); + luaK_concat(fs, &bl->breaklist, luaK_jump(fs)); +} + + +static void whilestat (LexState *ls, int line) { + /* whilestat -> WHILE cond DO block END */ + FuncState *fs = ls->fs; + int whileinit; + int condexit; + BlockCnt bl; + luaX_next(ls); /* skip WHILE */ + whileinit = luaK_getlabel(fs); + condexit = cond(ls); + enterblock(fs, &bl, 1); + checknext(ls, TK_DO); + block(ls); + luaK_patchlist(fs, luaK_jump(fs), whileinit); + check_match(ls, TK_END, TK_WHILE, line); + leaveblock(fs); + luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ +} + + +static void repeatstat (LexState *ls, int line) { + /* repeatstat -> REPEAT block UNTIL cond */ + int condexit; + FuncState *fs = ls->fs; + int repeat_init = luaK_getlabel(fs); + BlockCnt bl1, bl2; + enterblock(fs, &bl1, 1); /* loop block */ + enterblock(fs, &bl2, 0); /* scope block */ + luaX_next(ls); /* skip REPEAT */ + chunk(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + condexit = cond(ls); /* read condition (inside scope block) */ + if (!bl2.upval) { /* no upvalues? */ + leaveblock(fs); /* finish scope */ + luaK_patchlist(ls->fs, condexit, repeat_init); /* close the loop */ + } + else { /* complete semantics when there are upvalues */ + breakstat(ls); /* if condition then break */ + luaK_patchtohere(ls->fs, condexit); /* else... */ + leaveblock(fs); /* finish scope... */ + luaK_patchlist(ls->fs, luaK_jump(fs), repeat_init); /* and repeat */ + } + leaveblock(fs); /* finish loop */ +} + + +static int exp1 (LexState *ls) { + expdesc e; + int k; + expr(ls, &e); + k = e.k; + luaK_exp2nextreg(ls->fs, &e); + return k; +} + + +static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { + /* forbody -> DO block */ + BlockCnt bl; + FuncState *fs = ls->fs; + int prep, endfor; + adjustlocalvars(ls, 3); /* control variables */ + checknext(ls, TK_DO); + prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); + enterblock(fs, &bl, 0); /* scope for declared variables */ + adjustlocalvars(ls, nvars); + luaK_reserveregs(fs, nvars); + block(ls); + leaveblock(fs); /* end of scope for declared variables */ + luaK_patchtohere(fs, prep); + endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) : + luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars); + luaK_fixline(fs, line); /* pretend that `OP_FOR' starts the loop */ + luaK_patchlist(fs, (isnum ? endfor : luaK_jump(fs)), prep + 1); +} + + +static void fornum (LexState *ls, TString *varname, int line) { + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + FuncState *fs = ls->fs; + int base = fs->freereg; + new_localvarliteral(ls, "(for index)", 0); + new_localvarliteral(ls, "(for limit)", 1); + new_localvarliteral(ls, "(for step)", 2); + new_localvar(ls, varname, 3); + checknext(ls, '='); + exp1(ls); /* initial value */ + checknext(ls, ','); + exp1(ls); /* limit */ + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ + luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1)); + luaK_reserveregs(fs, 1); + } + forbody(ls, base, line, 1, 1); +} + + +static void forlist (LexState *ls, TString *indexname) { + /* forlist -> NAME {,NAME} IN explist1 forbody */ + FuncState *fs = ls->fs; + expdesc e; + int nvars = 0; + int line; + int base = fs->freereg; + /* create control variables */ + new_localvarliteral(ls, "(for generator)", nvars++); + new_localvarliteral(ls, "(for state)", nvars++); + new_localvarliteral(ls, "(for control)", nvars++); + /* create declared variables */ + new_localvar(ls, indexname, nvars++); + while (testnext(ls, ',')) + new_localvar(ls, str_checkname(ls), nvars++); + checknext(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, 3, explist1(ls, &e), &e); + luaK_checkstack(fs, 3); /* extra space to call generator */ + forbody(ls, base, line, nvars - 3, 0); +} + + +static void forstat (LexState *ls, int line) { + /* forstat -> FOR (fornum | forlist) END */ + FuncState *fs = ls->fs; + TString *varname; + BlockCnt bl; + enterblock(fs, &bl, 1); /* scope for loop and control variables */ + luaX_next(ls); /* skip `for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) { + case '=': fornum(ls, varname, line); break; + case ',': case TK_IN: forlist(ls, varname); break; + default: luaX_syntaxerror(ls, LUA_QL("=") " or " LUA_QL("in") " expected"); + } + check_match(ls, TK_END, TK_FOR, line); + leaveblock(fs); /* loop scope (`break' jumps to this point) */ +} + + +static int test_then_block (LexState *ls) { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + int condexit; + luaX_next(ls); /* skip IF or ELSEIF */ + condexit = cond(ls); + checknext(ls, TK_THEN); + block(ls); /* `then' part */ + return condexit; +} + + +static void ifstat (LexState *ls, int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + FuncState *fs = ls->fs; + int flist; + int escapelist = NO_JUMP; + flist = test_then_block(ls); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchtohere(fs, flist); + flist = test_then_block(ls); /* ELSEIF cond THEN block */ + } + if (ls->t.token == TK_ELSE) { + luaK_concat(fs, &escapelist, luaK_jump(fs)); + luaK_patchtohere(fs, flist); + luaX_next(ls); /* skip ELSE (after patch, for correct line info) */ + block(ls); /* `else' part */ + } + else + luaK_concat(fs, &escapelist, flist); + luaK_patchtohere(fs, escapelist); + check_match(ls, TK_END, TK_IF, line); +} + + +static void localfunc (LexState *ls) { + expdesc v, b; + FuncState *fs = ls->fs; + new_localvar(ls, str_checkname(ls), 0); + init_exp(&v, VLOCAL, fs->freereg); + luaK_reserveregs(fs, 1); + adjustlocalvars(ls, 1); + body(ls, &b, 0, ls->linenumber); + luaK_storevar(fs, &v, &b); + /* debug information will only see the variable after this point! */ + getlocvar(fs, fs->nactvar - 1).startpc = fs->pc; +} + + +static void localstat (LexState *ls) { + /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */ + int nvars = 0; + int nexps; + expdesc e; + do { + new_localvar(ls, str_checkname(ls), nvars++); + } while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist1(ls, &e); + else { + e.k = VVOID; + nexps = 0; + } + adjust_assign(ls, nvars, nexps, &e); + adjustlocalvars(ls, nvars); +} + + +static int funcname (LexState *ls, expdesc *v) { + /* funcname -> NAME {field} [`:' NAME] */ + int needself = 0; + singlevar(ls, v); + while (ls->t.token == '.') + field(ls, v); + if (ls->t.token == ':') { + needself = 1; + field(ls, v); + } + return needself; +} + + +static void funcstat (LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + int needself; + expdesc v, b; + luaX_next(ls); /* skip FUNCTION */ + needself = funcname(ls, &v); + body(ls, &b, needself, line); + luaK_storevar(ls->fs, &v, &b); + luaK_fixline(ls->fs, line); /* definition `happens' in the first line */ +} + + +static void exprstat (LexState *ls) { + /* stat -> func | assignment */ + FuncState *fs = ls->fs; + struct LHS_assign v; + primaryexp(ls, &v.v); + if (v.v.k == VCALL) /* stat -> func */ + SETARG_C(getcode(fs, &v.v), 1); /* call statement uses no results */ + else { /* stat -> assignment */ + v.prev = NULL; + assignment(ls, &v, 1); + } +} + + +static void retstat (LexState *ls) { + /* stat -> RETURN explist */ + FuncState *fs = ls->fs; + expdesc e; + int first, nret; /* registers with returned values */ + luaX_next(ls); /* skip RETURN */ + if (block_follow(ls->t.token) || ls->t.token == ';') + first = nret = 0; /* return no values */ + else { + nret = explist1(ls, &e); /* optional return values */ + if (hasmultret(e.k)) { + luaK_setmultret(fs, &e); + if (e.k == VCALL && nret == 1) { /* tail call? */ + SET_OPCODE(getcode(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar); + } + first = fs->nactvar; + nret = LUA_MULTRET; /* return all values */ + } + else { + if (nret == 1) /* only one single value? */ + first = luaK_exp2anyreg(fs, &e); + else { + luaK_exp2nextreg(fs, &e); /* values must go to the `stack' */ + first = fs->nactvar; /* return all `active' values */ + lua_assert(nret == fs->freereg - first); + } + } + } + luaK_ret(fs, first, nret); +} + + +static int statement (LexState *ls) { + int line = ls->linenumber; /* may be needed for error messages */ + switch (ls->t.token) { + case TK_IF: { /* stat -> ifstat */ + ifstat(ls, line); + return 0; + } + case TK_WHILE: { /* stat -> whilestat */ + whilestat(ls, line); + return 0; + } + case TK_DO: { /* stat -> DO block END */ + luaX_next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + return 0; + } + case TK_FOR: { /* stat -> forstat */ + forstat(ls, line); + return 0; + } + case TK_REPEAT: { /* stat -> repeatstat */ + repeatstat(ls, line); + return 0; + } + case TK_FUNCTION: { + funcstat(ls, line); /* stat -> funcstat */ + return 0; + } + case TK_LOCAL: { /* stat -> localstat */ + luaX_next(ls); /* skip LOCAL */ + if (testnext(ls, TK_FUNCTION)) /* local function? */ + localfunc(ls); + else + localstat(ls); + return 0; + } + case TK_RETURN: { /* stat -> retstat */ + retstat(ls); + return 1; /* must be last statement */ + } + case TK_BREAK: { /* stat -> breakstat */ + luaX_next(ls); /* skip BREAK */ + breakstat(ls); + return 1; /* must be last statement */ + } + default: { + exprstat(ls); + return 0; /* to avoid warnings */ + } + } +} + + +static void chunk (LexState *ls) { + /* chunk -> { stat [`;'] } */ + int islast = 0; + enterlevel(ls); + while (!islast && !block_follow(ls->t.token)) { + islast = statement(ls); + testnext(ls, ';'); + lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && + ls->fs->freereg >= ls->fs->nactvar); + ls->fs->freereg = ls->fs->nactvar; /* free registers */ + } + leavelevel(ls); +} + +/* }====================================================================== */ diff --git a/src/lua/src/lparser.h b/src/lua/src/lparser.h new file mode 100644 index 00000000..18836afd --- /dev/null +++ b/src/lua/src/lparser.h @@ -0,0 +1,82 @@ +/* +** $Id: lparser.h,v 1.57.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + +#ifndef lparser_h +#define lparser_h + +#include "llimits.h" +#include "lobject.h" +#include "lzio.h" + + +/* +** Expression descriptor +*/ + +typedef enum { + VVOID, /* no value */ + VNIL, + VTRUE, + VFALSE, + VK, /* info = index of constant in `k' */ + VKNUM, /* nval = numerical value */ + VLOCAL, /* info = local register */ + VUPVAL, /* info = index of upvalue in `upvalues' */ + VGLOBAL, /* info = index of table; aux = index of global name in `k' */ + VINDEXED, /* info = table register; aux = index register (or `k') */ + VJMP, /* info = instruction pc */ + VRELOCABLE, /* info = instruction pc */ + VNONRELOC, /* info = result register */ + VCALL, /* info = instruction pc */ + VVARARG /* info = instruction pc */ +} expkind; + +typedef struct expdesc { + expkind k; + union { + struct { int info, aux; } s; + lua_Number nval; + } u; + int t; /* patch list of `exit when true' */ + int f; /* patch list of `exit when false' */ +} expdesc; + + +typedef struct upvaldesc { + lu_byte k; + lu_byte info; +} upvaldesc; + + +struct BlockCnt; /* defined in lparser.c */ + + +/* state needed to generate code for a given function */ +typedef struct FuncState { + Proto *f; /* current function header */ + Table *h; /* table to find (and reuse) elements in `k' */ + struct FuncState *prev; /* enclosing function */ + struct LexState *ls; /* lexical state */ + struct lua_State *L; /* copy of the Lua state */ + struct BlockCnt *bl; /* chain of current blocks */ + int pc; /* next position to code (equivalent to `ncode') */ + int lasttarget; /* `pc' of last `jump target' */ + int jpc; /* list of pending jumps to `pc' */ + int freereg; /* first free register */ + int nk; /* number of elements in `k' */ + int np; /* number of elements in `p' */ + short nlocvars; /* number of elements in `locvars' */ + lu_byte nactvar; /* number of active local variables */ + upvaldesc upvalues[LUAI_MAXUPVALUES]; /* upvalues */ + unsigned short actvar[LUAI_MAXVARS]; /* declared-variable stack */ +} FuncState; + + +LUAI_FUNC Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + const char *name); + + +#endif diff --git a/src/lua/src/lstate.c b/src/lua/src/lstate.c new file mode 100644 index 00000000..4313b83a --- /dev/null +++ b/src/lua/src/lstate.c @@ -0,0 +1,214 @@ +/* +** $Id: lstate.c,v 2.36.1.2 2008/01/03 15:20:39 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + + +#include + +#define lstate_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +#define state_size(x) (sizeof(x) + LUAI_EXTRASPACE) +#define fromstate(l) (cast(lu_byte *, (l)) - LUAI_EXTRASPACE) +#define tostate(l) (cast(lua_State *, cast(lu_byte *, l) + LUAI_EXTRASPACE)) + + +/* +** Main thread combines a thread state and the global state +*/ +typedef struct LG { + lua_State l; + global_State g; +} LG; + + + +static void stack_init (lua_State *L1, lua_State *L) { + /* initialize CallInfo array */ + L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); + L1->ci = L1->base_ci; + L1->size_ci = BASIC_CI_SIZE; + L1->end_ci = L1->base_ci + L1->size_ci - 1; + /* initialize stack array */ + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); + L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; + L1->top = L1->stack; + L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; + /* initialize first ci */ + L1->ci->func = L1->top; + setnilvalue(L1->top++); /* `function' entry for this `ci' */ + L1->base = L1->ci->base = L1->top; + L1->ci->top = L1->top + LUA_MINSTACK; +} + + +static void freestack (lua_State *L, lua_State *L1) { + luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); + luaM_freearray(L, L1->stack, L1->stacksize, TValue); +} + + +/* +** open parts that may cause memory-allocation errors +*/ +static void f_luaopen (lua_State *L, void *ud) { + global_State *g = G(L); + UNUSED(ud); + stack_init(L, L); /* init stack */ + sethvalue(L, gt(L), luaH_new(L, 0, 2)); /* table of globals */ + sethvalue(L, registry(L), luaH_new(L, 0, 2)); /* registry */ + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + luaT_init(L); + luaX_init(L); + luaS_fix(luaS_newliteral(L, MEMERRMSG)); + g->GCthreshold = 4*g->totalbytes; +} + + +static void preinit_state (lua_State *L, global_State *g) { + G(L) = g; + L->stack = NULL; + L->stacksize = 0; + L->errorJmp = NULL; + L->hook = NULL; + L->hookmask = 0; + L->basehookcount = 0; + L->allowhook = 1; + resethookcount(L); + L->openupval = NULL; + L->size_ci = 0; + L->nCcalls = L->baseCcalls = 0; + L->status = 0; + L->base_ci = L->ci = NULL; + L->savedpc = NULL; + L->errfunc = 0; + setnilvalue(gt(L)); +} + + +static void close_state (lua_State *L) { + global_State *g = G(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_freeall(L); /* collect all objects */ + lua_assert(g->rootgc == obj2gco(L)); + lua_assert(g->strt.nuse == 0); + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); + luaZ_freebuffer(L, &g->buff); + freestack(L, L); + lua_assert(g->totalbytes == sizeof(LG)); + (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); +} + + +lua_State *luaE_newthread (lua_State *L) { + lua_State *L1 = tostate(luaM_malloc(L, state_size(lua_State))); + luaC_link(L, obj2gco(L1), LUA_TTHREAD); + preinit_state(L1, G(L)); + stack_init(L1, L); /* init stack */ + setobj2n(L, gt(L1), gt(L)); /* share table of globals */ + L1->hookmask = L->hookmask; + L1->basehookcount = L->basehookcount; + L1->hook = L->hook; + resethookcount(L1); + lua_assert(iswhite(obj2gco(L1))); + return L1; +} + + +void luaE_freethread (lua_State *L, lua_State *L1) { + luaF_close(L1, L1->stack); /* close all upvalues for this thread */ + lua_assert(L1->openupval == NULL); + luai_userstatefree(L1); + freestack(L, L1); + luaM_freemem(L, fromstate(L1), state_size(lua_State)); +} + + +LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { + int i; + lua_State *L; + global_State *g; + void *l = (*f)(ud, NULL, 0, state_size(LG)); + if (l == NULL) return NULL; + L = tostate(l); + g = &((LG *)L)->g; + L->next = NULL; + L->tt = LUA_TTHREAD; + g->currentwhite = bit2mask(WHITE0BIT, FIXEDBIT); + L->marked = luaC_white(g); + set2bits(L->marked, FIXEDBIT, SFIXEDBIT); + preinit_state(L, g); + g->frealloc = f; + g->ud = ud; + g->mainthread = L; + g->uvhead.u.l.prev = &g->uvhead; + g->uvhead.u.l.next = &g->uvhead; + g->GCthreshold = 0; /* mark it as unfinished state */ + g->strt.size = 0; + g->strt.nuse = 0; + g->strt.hash = NULL; + setnilvalue(registry(L)); + luaZ_initbuffer(L, &g->buff); + g->panic = NULL; + g->gcstate = GCSpause; + g->rootgc = obj2gco(L); + g->sweepstrgc = 0; + g->sweepgc = &g->rootgc; + g->gray = NULL; + g->grayagain = NULL; + g->weak = NULL; + g->tmudata = NULL; + g->totalbytes = sizeof(LG); + g->gcpause = LUAI_GCPAUSE; + g->gcstepmul = LUAI_GCMUL; + g->gcdept = 0; + for (i=0; imt[i] = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != 0) { + /* memory allocation error: free partial state */ + close_state(L); + L = NULL; + } + else + luai_userstateopen(L); + return L; +} + + +static void callallgcTM (lua_State *L, void *ud) { + UNUSED(ud); + luaC_callGCTM(L); /* call GC metamethods for all udata */ +} + + +LUA_API void lua_close (lua_State *L) { + L = G(L)->mainthread; /* only the main thread can be closed */ + lua_lock(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_separateudata(L, 1); /* separate udata that have GC metamethods */ + L->errfunc = 0; /* no error function during GC metamethods */ + do { /* repeat until no more errors */ + L->ci = L->base_ci; + L->base = L->top = L->ci->base; + L->nCcalls = L->baseCcalls = 0; + } while (luaD_rawrunprotected(L, callallgcTM, NULL) != 0); + lua_assert(G(L)->tmudata == NULL); + luai_userstateclose(L); + close_state(L); +} + diff --git a/src/lua/src/lstate.h b/src/lua/src/lstate.h new file mode 100644 index 00000000..3bc575b6 --- /dev/null +++ b/src/lua/src/lstate.h @@ -0,0 +1,169 @@ +/* +** $Id: lstate.h,v 2.24.1.2 2008/01/03 15:20:39 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + +#ifndef lstate_h +#define lstate_h + +#include "lua.h" + +#include "lobject.h" +#include "ltm.h" +#include "lzio.h" + + + +struct lua_longjmp; /* defined in ldo.c */ + + +/* table of globals */ +#define gt(L) (&L->l_gt) + +/* registry */ +#define registry(L) (&G(L)->l_registry) + + +/* extra stack space to handle TM calls and some other extras */ +#define EXTRA_STACK 5 + + +#define BASIC_CI_SIZE 8 + +#define BASIC_STACK_SIZE (2*LUA_MINSTACK) + + + +typedef struct stringtable { + GCObject **hash; + lu_int32 nuse; /* number of elements */ + int size; +} stringtable; + + +/* +** informations about a call +*/ +typedef struct CallInfo { + StkId base; /* base for this function */ + StkId func; /* function index in the stack */ + StkId top; /* top for this function */ + const Instruction *savedpc; + int nresults; /* expected number of results from this function */ + int tailcalls; /* number of tail calls lost under this entry */ +} CallInfo; + + + +#define curr_func(L) (clvalue(L->ci->func)) +#define ci_func(ci) (clvalue((ci)->func)) +#define f_isLua(ci) (!ci_func(ci)->c.isC) +#define isLua(ci) (ttisfunction((ci)->func) && f_isLua(ci)) + + +/* +** `global state', shared by all threads of this state +*/ +typedef struct global_State { + stringtable strt; /* hash table for strings */ + lua_Alloc frealloc; /* function to reallocate memory */ + void *ud; /* auxiliary data to `frealloc' */ + lu_byte currentwhite; + lu_byte gcstate; /* state of garbage collector */ + int sweepstrgc; /* position of sweep in `strt' */ + GCObject *rootgc; /* list of all collectable objects */ + GCObject **sweepgc; /* position of sweep in `rootgc' */ + GCObject *gray; /* list of gray objects */ + GCObject *grayagain; /* list of objects to be traversed atomically */ + GCObject *weak; /* list of weak tables (to be cleared) */ + GCObject *tmudata; /* last element of list of userdata to be GC */ + Mbuffer buff; /* temporary buffer for string concatentation */ + lu_mem GCthreshold; + lu_mem totalbytes; /* number of bytes currently allocated */ + lu_mem estimate; /* an estimate of number of bytes actually in use */ + lu_mem gcdept; /* how much GC is `behind schedule' */ + int gcpause; /* size of pause between successive GCs */ + int gcstepmul; /* GC `granularity' */ + lua_CFunction panic; /* to be called in unprotected errors */ + TValue l_registry; + struct lua_State *mainthread; + UpVal uvhead; /* head of double-linked list of all open upvalues */ + struct Table *mt[NUM_TAGS]; /* metatables for basic types */ + TString *tmname[TM_N]; /* array with tag-method names */ +} global_State; + + +/* +** `per thread' state +*/ +struct lua_State { + CommonHeader; + lu_byte status; + StkId top; /* first free slot in the stack */ + StkId base; /* base of current function */ + global_State *l_G; + CallInfo *ci; /* call info for current function */ + const Instruction *savedpc; /* `savedpc' of current function */ + StkId stack_last; /* last free slot in the stack */ + StkId stack; /* stack base */ + CallInfo *end_ci; /* points after end of ci array*/ + CallInfo *base_ci; /* array of CallInfo's */ + int stacksize; + int size_ci; /* size of array `base_ci' */ + unsigned short nCcalls; /* number of nested C calls */ + unsigned short baseCcalls; /* nested C calls when resuming coroutine */ + lu_byte hookmask; + lu_byte allowhook; + int basehookcount; + int hookcount; + lua_Hook hook; + TValue l_gt; /* table of globals */ + TValue env; /* temporary place for environments */ + GCObject *openupval; /* list of open upvalues in this stack */ + GCObject *gclist; + struct lua_longjmp *errorJmp; /* current error recover point */ + ptrdiff_t errfunc; /* current error handling function (stack index) */ +}; + + +#define G(L) (L->l_G) + + +/* +** Union of all collectable objects +*/ +union GCObject { + GCheader gch; + union TString ts; + union Udata u; + union Closure cl; + struct Table h; + struct Proto p; + struct UpVal uv; + struct lua_State th; /* thread */ +}; + + +/* macros to convert a GCObject into a specific value */ +#define rawgco2ts(o) check_exp((o)->gch.tt == LUA_TSTRING, &((o)->ts)) +#define gco2ts(o) (&rawgco2ts(o)->tsv) +#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) +#define gco2u(o) (&rawgco2u(o)->uv) +#define gco2cl(o) check_exp((o)->gch.tt == LUA_TFUNCTION, &((o)->cl)) +#define gco2h(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) +#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) +#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define ngcotouv(o) \ + check_exp((o) == NULL || (o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) + +/* macro to convert any Lua object into a GCObject */ +#define obj2gco(v) (cast(GCObject *, (v))) + + +LUAI_FUNC lua_State *luaE_newthread (lua_State *L); +LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); + +#endif + diff --git a/src/lua/src/lstring.c b/src/lua/src/lstring.c new file mode 100644 index 00000000..49113151 --- /dev/null +++ b/src/lua/src/lstring.c @@ -0,0 +1,111 @@ +/* +** $Id: lstring.c,v 2.8.1.1 2007/12/27 13:02:25 roberto Exp $ +** String table (keeps all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + + +#include + +#define lstring_c +#define LUA_CORE + +#include "lua.h" + +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" + + + +void luaS_resize (lua_State *L, int newsize) { + GCObject **newhash; + stringtable *tb; + int i; + if (G(L)->gcstate == GCSsweepstring) + return; /* cannot resize during GC traverse */ + newhash = luaM_newvector(L, newsize, GCObject *); + tb = &G(L)->strt; + for (i=0; isize; i++) { + GCObject *p = tb->hash[i]; + while (p) { /* for each node in the list */ + GCObject *next = p->gch.next; /* save next */ + unsigned int h = gco2ts(p)->hash; + int h1 = lmod(h, newsize); /* new position */ + lua_assert(cast_int(h%newsize) == lmod(h, newsize)); + p->gch.next = newhash[h1]; /* chain it */ + newhash[h1] = p; + p = next; + } + } + luaM_freearray(L, tb->hash, tb->size, TString *); + tb->size = newsize; + tb->hash = newhash; +} + + +static TString *newlstr (lua_State *L, const char *str, size_t l, + unsigned int h) { + TString *ts; + stringtable *tb; + if (l+1 > (MAX_SIZET - sizeof(TString))/sizeof(char)) + luaM_toobig(L); + ts = cast(TString *, luaM_malloc(L, (l+1)*sizeof(char)+sizeof(TString))); + ts->tsv.len = l; + ts->tsv.hash = h; + ts->tsv.marked = luaC_white(G(L)); + ts->tsv.tt = LUA_TSTRING; + ts->tsv.reserved = 0; + memcpy(ts+1, str, l*sizeof(char)); + ((char *)(ts+1))[l] = '\0'; /* ending 0 */ + tb = &G(L)->strt; + h = lmod(h, tb->size); + ts->tsv.next = tb->hash[h]; /* chain new entry */ + tb->hash[h] = obj2gco(ts); + tb->nuse++; + if (tb->nuse > cast(lu_int32, tb->size) && tb->size <= MAX_INT/2) + luaS_resize(L, tb->size*2); /* too crowded */ + return ts; +} + + +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { + GCObject *o; + unsigned int h = cast(unsigned int, l); /* seed */ + size_t step = (l>>5)+1; /* if string is too long, don't hash all its chars */ + size_t l1; + for (l1=l; l1>=step; l1-=step) /* compute hash */ + h = h ^ ((h<<5)+(h>>2)+cast(unsigned char, str[l1-1])); + for (o = G(L)->strt.hash[lmod(h, G(L)->strt.size)]; + o != NULL; + o = o->gch.next) { + TString *ts = rawgco2ts(o); + if (ts->tsv.len == l && (memcmp(str, getstr(ts), l) == 0)) { + /* string may be dead */ + if (isdead(G(L), o)) changewhite(o); + return ts; + } + } + return newlstr(L, str, l, h); /* not found */ +} + + +Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { + Udata *u; + if (s > MAX_SIZET - sizeof(Udata)) + luaM_toobig(L); + u = cast(Udata *, luaM_malloc(L, s + sizeof(Udata))); + u->uv.marked = luaC_white(G(L)); /* is not finalized */ + u->uv.tt = LUA_TUSERDATA; + u->uv.len = s; + u->uv.metatable = NULL; + u->uv.env = e; + /* chain it on udata list (after main thread) */ + u->uv.next = G(L)->mainthread->next; + G(L)->mainthread->next = obj2gco(u); + return u; +} + diff --git a/src/lua/src/lstring.h b/src/lua/src/lstring.h new file mode 100644 index 00000000..73a2ff8b --- /dev/null +++ b/src/lua/src/lstring.h @@ -0,0 +1,31 @@ +/* +** $Id: lstring.h,v 1.43.1.1 2007/12/27 13:02:25 roberto Exp $ +** String table (keep all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#ifndef lstring_h +#define lstring_h + + +#include "lgc.h" +#include "lobject.h" +#include "lstate.h" + + +#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) + +#define sizeudata(u) (sizeof(union Udata)+(u)->len) + +#define luaS_new(L, s) (luaS_newlstr(L, s, strlen(s))) +#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ + (sizeof(s)/sizeof(char))-1)) + +#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) + +LUAI_FUNC void luaS_resize (lua_State *L, int newsize); +LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); +LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); + + +#endif diff --git a/src/lua/src/lstrlib.c b/src/lua/src/lstrlib.c new file mode 100644 index 00000000..1b4763d4 --- /dev/null +++ b/src/lua/src/lstrlib.c @@ -0,0 +1,869 @@ +/* +** $Id: lstrlib.c,v 1.132.1.4 2008/07/11 17:27:21 roberto Exp $ +** Standard library for string operations and pattern-matching +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include +#include + +#define lstrlib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* macro to `unsign' a character */ +#define uchar(c) ((unsigned char)(c)) + + + +static int str_len (lua_State *L) { + size_t l; + luaL_checklstring(L, 1, &l); + lua_pushinteger(L, l); + return 1; +} + + +static ptrdiff_t posrelat (ptrdiff_t pos, size_t len) { + /* relative string position: negative means back from end */ + if (pos < 0) pos += (ptrdiff_t)len + 1; + return (pos >= 0) ? pos : 0; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + ptrdiff_t start = posrelat(luaL_checkinteger(L, 2), l); + ptrdiff_t end = posrelat(luaL_optinteger(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (ptrdiff_t)l) end = (ptrdiff_t)l; + if (start <= end) + lua_pushlstring(L, s+start-1, end-start+1); + else lua_pushliteral(L, ""); + return 1; +} + + +static int str_reverse (lua_State *L) { + size_t l; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + luaL_buffinit(L, &b); + while (l--) luaL_addchar(&b, s[l]); + luaL_pushresult(&b); + return 1; +} + + +static int str_lower (lua_State *L) { + size_t l; + size_t i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + luaL_buffinit(L, &b); + for (i=0; i 0) + luaL_addlstring(&b, s, l); + luaL_pushresult(&b); + return 1; +} + + +static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + ptrdiff_t posi = posrelat(luaL_optinteger(L, 2, 1), l); + ptrdiff_t pose = posrelat(luaL_optinteger(L, 3, posi), l); + int n, i; + if (posi <= 0) posi = 1; + if ((size_t)pose > l) pose = l; + if (posi > pose) return 0; /* empty interval; return no values */ + n = (int)(pose - posi + 1); + if (posi + n <= pose) /* overflow? */ + luaL_error(L, "string slice too long"); + luaL_checkstack(L, n, "string slice too long"); + for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) + return luaL_error(ms->L, "invalid capture index"); + return l; +} + + +static int capture_to_close (MatchState *ms) { + int level = ms->level; + for (level--; level>=0; level--) + if (ms->capture[level].len == CAP_UNFINISHED) return level; + return luaL_error(ms->L, "invalid pattern capture"); +} + + +static const char *classend (MatchState *ms, const char *p) { + switch (*p++) { + case L_ESC: { + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (ends with " LUA_QL("%%") ")"); + return p+1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a `]' */ + if (*p == '\0') + luaL_error(ms->L, "malformed pattern (missing " LUA_QL("]") ")"); + if (*(p++) == L_ESC && *p != '\0') + p++; /* skip escapes (e.g. `%]') */ + } while (*p != ']'); + return p+1; + } + default: { + return p; + } + } +} + + +static int match_class (int c, int cl) { + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + case 'x' : res = isxdigit(c); break; + case 'z' : res = (c == 0); break; + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + + +static int matchbracketclass (int c, const char *p, const char *ec) { + int sig = 1; + if (*(p+1) == '^') { + sig = 0; + p++; /* skip the `^' */ + } + while (++p < ec) { + if (*p == L_ESC) { + p++; + if (match_class(c, uchar(*p))) + return sig; + } + else if ((*(p+1) == '-') && (p+2 < ec)) { + p+=2; + if (uchar(*(p-2)) <= c && c <= uchar(*p)) + return sig; + } + else if (uchar(*p) == c) return sig; + } + return !sig; +} + + +static int singlematch (int c, const char *p, const char *ep) { + switch (*p) { + case '.': return 1; /* matches any char */ + case L_ESC: return match_class(c, uchar(*(p+1))); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); + } +} + + +static const char *match (MatchState *ms, const char *s, const char *p); + + +static const char *matchbalance (MatchState *ms, const char *s, + const char *p) { + if (*p == 0 || *(p+1) == 0) + luaL_error(ms->L, "unbalanced pattern"); + if (*s != *p) return NULL; + else { + int b = *p; + int e = *(p+1); + int cont = 1; + while (++s < ms->src_end) { + if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + + +static const char *max_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + ptrdiff_t i = 0; /* counts maximum expand for item */ + while ((s+i)src_end && singlematch(uchar(*(s+i)), p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i>=0) { + const char *res = match(ms, (s+i), ep+1); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; +} + + +static const char *min_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + for (;;) { + const char *res = match(ms, s, ep+1); + if (res != NULL) + return res; + else if (ssrc_end && singlematch(uchar(*s), p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } +} + + +static const char *start_capture (MatchState *ms, const char *s, + const char *p, int what) { + const char *res; + int level = ms->level; + if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); + ms->capture[level].init = s; + ms->capture[level].len = what; + ms->level = level+1; + if ((res=match(ms, s, p)) == NULL) /* match failed? */ + ms->level--; /* undo capture */ + return res; +} + + +static const char *end_capture (MatchState *ms, const char *s, + const char *p) { + int l = capture_to_close(ms); + const char *res; + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ + return res; +} + + +static const char *match_capture (MatchState *ms, const char *s, int l) { + size_t len; + l = check_capture(ms, l); + len = ms->capture[l].len; + if ((size_t)(ms->src_end-s) >= len && + memcmp(ms->capture[l].init, s, len) == 0) + return s+len; + else return NULL; +} + + +static const char *match (MatchState *ms, const char *s, const char *p) { + init: /* using goto's to optimize tail recursion */ + switch (*p) { + case '(': { /* start capture */ + if (*(p+1) == ')') /* position capture? */ + return start_capture(ms, s, p+2, CAP_POSITION); + else + return start_capture(ms, s, p+1, CAP_UNFINISHED); + } + case ')': { /* end capture */ + return end_capture(ms, s, p+1); + } + case L_ESC: { + switch (*(p+1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p+2); + if (s == NULL) return NULL; + p+=4; goto init; /* else return match(ms, s, p+4); */ + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (*p != '[') + luaL_error(ms->L, "missing " LUA_QL("[") " after " + LUA_QL("%%f") " in pattern"); + ep = classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s-1); + if (matchbracketclass(uchar(previous), p, ep-1) || + !matchbracketclass(uchar(*s), p, ep-1)) return NULL; + p=ep; goto init; /* else return match(ms, s, ep); */ + } + default: { + if (isdigit(uchar(*(p+1)))) { /* capture results (%0-%9)? */ + s = match_capture(ms, s, uchar(*(p+1))); + if (s == NULL) return NULL; + p+=2; goto init; /* else return match(ms, s, p+2) */ + } + goto dflt; /* case default */ + } + } + } + case '\0': { /* end of pattern */ + return s; /* match succeeded */ + } + case '$': { + if (*(p+1) == '\0') /* is the `$' the last char in pattern? */ + return (s == ms->src_end) ? s : NULL; /* check end of string */ + else goto dflt; + } + default: dflt: { /* it is a pattern item */ + const char *ep = classend(ms, p); /* points to what is next */ + int m = ssrc_end && singlematch(uchar(*s), p, ep); + switch (*ep) { + case '?': { /* optional */ + const char *res; + if (m && ((res=match(ms, s+1, ep+1)) != NULL)) + return res; + p=ep+1; goto init; /* else return match(ms, s, ep+1); */ + } + case '*': { /* 0 or more repetitions */ + return max_expand(ms, s, p, ep); + } + case '+': { /* 1 or more repetitions */ + return (m ? max_expand(ms, s+1, p, ep) : NULL); + } + case '-': { /* 0 or more repetitions (minimum) */ + return min_expand(ms, s, p, ep); + } + default: { + if (!m) return NULL; + s++; p=ep; goto init; /* else return match(ms, s+1, ep); */ + } + } + } + } +} + + + +static const char *lmemfind (const char *s1, size_t l1, + const char *s2, size_t l2) { + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative `l1' */ + else { + const char *init; /* to search for a `*s2' inside `s1' */ + l2--; /* 1st char will be checked by `memchr' */ + l1 = l1-l2; /* `s2' cannot be found after that */ + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { + init++; /* 1st char is already checked */ + if (memcmp(init, s2+1, l2) == 0) + return init-1; + else { /* correct `l1' and `s1' to try again */ + l1 -= init-s1; + s1 = init; + } + } + return NULL; /* not found */ + } +} + + +static void push_onecapture (MatchState *ms, int i, const char *s, + const char *e) { + if (i >= ms->level) { + if (i == 0) /* ms->level == 0, too */ + lua_pushlstring(ms->L, s, e - s); /* add whole match */ + else + luaL_error(ms->L, "invalid capture index"); + } + else { + ptrdiff_t l = ms->capture[i].len; + if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); + if (l == CAP_POSITION) + lua_pushinteger(ms->L, ms->capture[i].init - ms->src_init + 1); + else + lua_pushlstring(ms->L, ms->capture[i].init, l); + } +} + + +static int push_captures (MatchState *ms, const char *s, const char *e) { + int i; + int nlevels = (ms->level == 0 && s) ? 1 : ms->level; + luaL_checkstack(ms->L, nlevels, "too many captures"); + for (i = 0; i < nlevels; i++) + push_onecapture(ms, i, s, e); + return nlevels; /* number of strings pushed */ +} + + +static int str_find_aux (lua_State *L, int find) { + size_t l1, l2; + const char *s = luaL_checklstring(L, 1, &l1); + const char *p = luaL_checklstring(L, 2, &l2); + ptrdiff_t init = posrelat(luaL_optinteger(L, 3, 1), l1) - 1; + if (init < 0) init = 0; + else if ((size_t)(init) > l1) init = (ptrdiff_t)l1; + if (find && (lua_toboolean(L, 4) || /* explicit request? */ + strpbrk(p, SPECIALS) == NULL)) { /* or no special characters? */ + /* do a plain search */ + const char *s2 = lmemfind(s+init, l1-init, p, l2); + if (s2) { + lua_pushinteger(L, s2-s+1); + lua_pushinteger(L, s2-s+l2); + return 2; + } + } + else { + MatchState ms; + int anchor = (*p == '^') ? (p++, 1) : 0; + const char *s1=s+init; + ms.L = L; + ms.src_init = s; + ms.src_end = s+l1; + do { + const char *res; + ms.level = 0; + if ((res=match(&ms, s1, p)) != NULL) { + if (find) { + lua_pushinteger(L, s1-s+1); /* start */ + lua_pushinteger(L, res-s); /* end */ + return push_captures(&ms, NULL, 0) + 2; + } + else + return push_captures(&ms, s1, res); + } + } while (s1++ < ms.src_end && !anchor); + } + lua_pushnil(L); /* not found */ + return 1; +} + + +static int str_find (lua_State *L) { + return str_find_aux(L, 1); +} + + +static int str_match (lua_State *L) { + return str_find_aux(L, 0); +} + + +static int gmatch_aux (lua_State *L) { + MatchState ms; + size_t ls; + const char *s = lua_tolstring(L, lua_upvalueindex(1), &ls); + const char *p = lua_tostring(L, lua_upvalueindex(2)); + const char *src; + ms.L = L; + ms.src_init = s; + ms.src_end = s+ls; + for (src = s + (size_t)lua_tointeger(L, lua_upvalueindex(3)); + src <= ms.src_end; + src++) { + const char *e; + ms.level = 0; + if ((e = match(&ms, src, p)) != NULL) { + lua_Integer newstart = e-s; + if (e == src) newstart++; /* empty match? go at least one position */ + lua_pushinteger(L, newstart); + lua_replace(L, lua_upvalueindex(3)); + return push_captures(&ms, src, e); + } + } + return 0; /* not found */ +} + + +static int gmatch (lua_State *L) { + luaL_checkstring(L, 1); + luaL_checkstring(L, 2); + lua_settop(L, 2); + lua_pushinteger(L, 0); + lua_pushcclosure(L, gmatch_aux, 3); + return 1; +} + + +static int gfind_nodef (lua_State *L) { + return luaL_error(L, LUA_QL("string.gfind") " was renamed to " + LUA_QL("string.gmatch")); +} + + +static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e) { + size_t l, i; + const char *news = lua_tolstring(ms->L, 3, &l); + for (i = 0; i < l; i++) { + if (news[i] != L_ESC) + luaL_addchar(b, news[i]); + else { + i++; /* skip ESC */ + if (!isdigit(uchar(news[i]))) + luaL_addchar(b, news[i]); + else if (news[i] == '0') + luaL_addlstring(b, s, e - s); + else { + push_onecapture(ms, news[i] - '1', s, e); + luaL_addvalue(b); /* add capture to accumulated result */ + } + } + } +} + + +static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e) { + lua_State *L = ms->L; + switch (lua_type(L, 3)) { + case LUA_TNUMBER: + case LUA_TSTRING: { + add_s(ms, b, s, e); + return; + } + case LUA_TFUNCTION: { + int n; + lua_pushvalue(L, 3); + n = push_captures(ms, s, e); + lua_call(L, n, 1); + break; + } + case LUA_TTABLE: { + push_onecapture(ms, 0, s, e); + lua_gettable(L, 3); + break; + } + } + if (!lua_toboolean(L, -1)) { /* nil or false? */ + lua_pop(L, 1); + lua_pushlstring(L, s, e - s); /* keep original text */ + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); + luaL_addvalue(b); /* add result to accumulator */ +} + + +static int str_gsub (lua_State *L) { + size_t srcl; + const char *src = luaL_checklstring(L, 1, &srcl); + const char *p = luaL_checkstring(L, 2); + int tr = lua_type(L, 3); + int max_s = luaL_optint(L, 4, srcl+1); + int anchor = (*p == '^') ? (p++, 1) : 0; + int n = 0; + MatchState ms; + luaL_Buffer b; + luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || + tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, + "string/function/table expected"); + luaL_buffinit(L, &b); + ms.L = L; + ms.src_init = src; + ms.src_end = src+srcl; + while (n < max_s) { + const char *e; + ms.level = 0; + e = match(&ms, src, p); + if (e) { + n++; + add_value(&ms, &b, src, e); + } + if (e && e>src) /* non empty match? */ + src = e; /* skip it */ + else if (src < ms.src_end) + luaL_addchar(&b, *src++); + else break; + if (anchor) break; + } + luaL_addlstring(&b, src, ms.src_end-src); + luaL_pushresult(&b); + lua_pushinteger(L, n); /* number of substitutions */ + return 2; +} + +/* }====================================================== */ + + +/* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ +#define MAX_ITEM 512 +/* valid flags in a format specification */ +#define FLAGS "-+ #0" +/* +** maximum size of each format specification (such as '%-099.99d') +** (+10 accounts for %99.99x plus margin of error) +*/ +#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) + + +static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + luaL_addchar(b, '"'); + while (l--) { + switch (*s) { + case '"': case '\\': case '\n': { + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); + break; + } + case '\r': { + luaL_addlstring(b, "\\r", 2); + break; + } + case '\0': { + luaL_addlstring(b, "\\000", 4); + break; + } + default: { + luaL_addchar(b, *s); + break; + } + } + s++; + } + luaL_addchar(b, '"'); +} + +static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { + const char *p = strfrmt; + while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)) + luaL_error(L, "invalid format (repeated flags)"); + if (isdigit(uchar(*p))) p++; /* skip width */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + if (*p == '.') { + p++; + if (isdigit(uchar(*p))) p++; /* skip precision */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + *(form++) = '%'; + strncpy(form, strfrmt, p - strfrmt + 1); + form += p - strfrmt + 1; + *form = '\0'; + return p; +} + + +static void addintlen (char *form) { + size_t l = strlen(form); + char spec = form[l - 1]; + strcpy(form + l - 1, LUA_INTFRMLEN); + form[l + sizeof(LUA_INTFRMLEN) - 2] = spec; + form[l + sizeof(LUA_INTFRMLEN) - 1] = '\0'; +} + + +static int str_format (lua_State *L) { + int arg = 1; + size_t sfl; + const char *strfrmt = luaL_checklstring(L, arg, &sfl); + const char *strfrmt_end = strfrmt+sfl; + luaL_Buffer b; + luaL_buffinit(L, &b); + while (strfrmt < strfrmt_end) { + if (*strfrmt != L_ESC) + luaL_addchar(&b, *strfrmt++); + else if (*++strfrmt == L_ESC) + luaL_addchar(&b, *strfrmt++); /* %% */ + else { /* format item */ + char form[MAX_FORMAT]; /* to store the format (`%...') */ + char buff[MAX_ITEM]; /* to store the formatted item */ + arg++; + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) { + case 'c': { + sprintf(buff, form, (int)luaL_checknumber(L, arg)); + break; + } + case 'd': case 'i': { + addintlen(form); + sprintf(buff, form, (LUA_INTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'o': case 'u': case 'x': case 'X': { + addintlen(form); + sprintf(buff, form, (unsigned LUA_INTFRM_T)luaL_checknumber(L, arg)); + break; + } + case 'e': case 'E': case 'f': + case 'g': case 'G': { + sprintf(buff, form, (double)luaL_checknumber(L, arg)); + break; + } + case 'q': { + addquoted(L, &b, arg); + continue; /* skip the 'addsize' at the end */ + } + case 's': { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + if (!strchr(form, '.') && l >= 100) { + /* no precision and string is too long to be formatted; + keep original string */ + lua_pushvalue(L, arg); + luaL_addvalue(&b); + continue; /* skip the `addsize' at the end */ + } + else { + sprintf(buff, form, s); + break; + } + } + default: { /* also treat cases `pnLlh' */ + return luaL_error(L, "invalid option " LUA_QL("%%%c") " to " + LUA_QL("format"), *(strfrmt - 1)); + } + } + luaL_addlstring(&b, buff, strlen(buff)); + } + } + luaL_pushresult(&b); + return 1; +} + + +static const luaL_Reg strlib[] = { + {"byte", str_byte}, + {"char", str_char}, + {"dump", str_dump}, + {"find", str_find}, + {"format", str_format}, + {"gfind", gfind_nodef}, + {"gmatch", gmatch}, + {"gsub", str_gsub}, + {"len", str_len}, + {"lower", str_lower}, + {"match", str_match}, + {"rep", str_rep}, + {"reverse", str_reverse}, + {"sub", str_sub}, + {"upper", str_upper}, + {NULL, NULL} +}; + + +static void createmetatable (lua_State *L) { + lua_createtable(L, 0, 1); /* create metatable for strings */ + lua_pushliteral(L, ""); /* dummy string */ + lua_pushvalue(L, -2); + lua_setmetatable(L, -2); /* set string metatable */ + lua_pop(L, 1); /* pop dummy string */ + lua_pushvalue(L, -2); /* string library... */ + lua_setfield(L, -2, "__index"); /* ...is the __index metamethod */ + lua_pop(L, 1); /* pop metatable */ +} + + +/* +** Open string library +*/ +LUALIB_API int luaopen_string (lua_State *L) { + luaL_register(L, LUA_STRLIBNAME, strlib); +#if defined(LUA_COMPAT_GFIND) + lua_getfield(L, -1, "gmatch"); + lua_setfield(L, -2, "gfind"); +#endif + createmetatable(L); + return 1; +} + diff --git a/src/lua/src/ltable.c b/src/lua/src/ltable.c new file mode 100644 index 00000000..ec84f4fa --- /dev/null +++ b/src/lua/src/ltable.c @@ -0,0 +1,588 @@ +/* +** $Id: ltable.c,v 2.32.1.2 2007/12/28 15:32:23 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + + +/* +** Implementation of tables (aka arrays, objects, or hash tables). +** Tables keep its elements in two parts: an array part and a hash part. +** Non-negative integer keys are all candidates to be kept in the array +** part. The actual size of the array is the largest `n' such that at +** least half the slots between 0 and n are in use. +** Hash uses a mix of chained scatter table with Brent's variation. +** A main invariant of these tables is that, if an element is not +** in its main position (i.e. the `original' position that its hash gives +** to it), then the colliding element is in its own main position. +** Hence even when the load factor reaches 100%, performance remains good. +*/ + +#include +#include + +#define ltable_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "ltable.h" + + +/* +** max size of array part is 2^MAXBITS +*/ +#if LUAI_BITSINT > 26 +#define MAXBITS 26 +#else +#define MAXBITS (LUAI_BITSINT-2) +#endif + +#define MAXASIZE (1 << MAXBITS) + + +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) + +#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) +#define hashboolean(t,p) hashpow2(t, p) + + +/* +** for some types, it is better to avoid modulus by power of 2, as +** they tend to have many 2 factors. +*/ +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) + + +#define hashpointer(t,p) hashmod(t, IntPoint(p)) + + +/* +** number of ints inside a lua_Number +*/ +#define numints cast_int(sizeof(lua_Number)/sizeof(int)) + + + +#define dummynode (&dummynode_) + +static const Node dummynode_ = { + {{NULL}, LUA_TNIL}, /* value */ + {{{NULL}, LUA_TNIL, NULL}} /* key */ +}; + + +/* +** hash for lua_Numbers +*/ +static Node *hashnum (const Table *t, lua_Number n) { + unsigned int a[numints]; + int i; + if (luai_numeq(n, 0)) /* avoid problems with -0 */ + return gnode(t, 0); + memcpy(a, &n, sizeof(a)); + for (i = 1; i < numints; i++) a[0] += a[i]; + return hashmod(t, a[0]); +} + + + +/* +** returns the `main' position of an element in a table (that is, the index +** of its hash value) +*/ +static Node *mainposition (const Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TNUMBER: + return hashnum(t, nvalue(key)); + case LUA_TSTRING: + return hashstr(t, rawtsvalue(key)); + case LUA_TBOOLEAN: + return hashboolean(t, bvalue(key)); + case LUA_TLIGHTUSERDATA: + return hashpointer(t, pvalue(key)); + default: + return hashpointer(t, gcvalue(key)); + } +} + + +/* +** returns the index for `key' if `key' is an appropriate key to live in +** the array part of the table, -1 otherwise. +*/ +static int arrayindex (const TValue *key) { + if (ttisnumber(key)) { + lua_Number n = nvalue(key); + int k; + lua_number2int(k, n); + if (luai_numeq(cast_num(k), n)) + return k; + } + return -1; /* `key' did not match some condition */ +} + + +/* +** returns the index of a `key' for table traversals. First goes all +** elements in the array part, then elements in the hash part. The +** beginning of a traversal is signalled by -1. +*/ +static int findindex (lua_State *L, Table *t, StkId key) { + int i; + if (ttisnil(key)) return -1; /* first iteration */ + i = arrayindex(key); + if (0 < i && i <= t->sizearray) /* is `key' inside array part? */ + return i-1; /* yes; that's the index (corrected to C) */ + else { + Node *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + /* key may be dead already, but it is ok to use it in `next' */ + if (luaO_rawequalObj(key2tval(n), key) || + (ttype(gkey(n)) == LUA_TDEADKEY && iscollectable(key) && + gcvalue(gkey(n)) == gcvalue(key))) { + i = cast_int(n - gnode(t, 0)); /* key index in hash table */ + /* hash elements are numbered after array ones */ + return i + t->sizearray; + } + else n = gnext(n); + } while (n); + luaG_runerror(L, "invalid key to " LUA_QL("next")); /* key not found */ + return 0; /* to avoid warnings */ + } +} + + +int luaH_next (lua_State *L, Table *t, StkId key) { + int i = findindex(L, t, key); /* find original element */ + for (i++; i < t->sizearray; i++) { /* try first array part */ + if (!ttisnil(&t->array[i])) { /* a non-nil value? */ + setnvalue(key, cast_num(i+1)); + setobj2s(L, key+1, &t->array[i]); + return 1; + } + } + for (i -= t->sizearray; i < sizenode(t); i++) { /* then hash part */ + if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ + setobj2s(L, key, key2tval(gnode(t, i))); + setobj2s(L, key+1, gval(gnode(t, i))); + return 1; + } + } + return 0; /* no more elements */ +} + + +/* +** {============================================================= +** Rehash +** ============================================================== +*/ + + +static int computesizes (int nums[], int *narray) { + int i; + int twotoi; /* 2^i */ + int a = 0; /* number of elements smaller than 2^i */ + int na = 0; /* number of elements to go to array part */ + int n = 0; /* optimal size for array part */ + for (i = 0, twotoi = 1; twotoi/2 < *narray; i++, twotoi *= 2) { + if (nums[i] > 0) { + a += nums[i]; + if (a > twotoi/2) { /* more than half elements present? */ + n = twotoi; /* optimal size (till now) */ + na = a; /* all elements smaller than n will go to array part */ + } + } + if (a == *narray) break; /* all elements already counted */ + } + *narray = n; + lua_assert(*narray/2 <= na && na <= *narray); + return na; +} + + +static int countint (const TValue *key, int *nums) { + int k = arrayindex(key); + if (0 < k && k <= MAXASIZE) { /* is `key' an appropriate array index? */ + nums[ceillog2(k)]++; /* count as such */ + return 1; + } + else + return 0; +} + + +static int numusearray (const Table *t, int *nums) { + int lg; + int ttlg; /* 2^lg */ + int ause = 0; /* summation of `nums' */ + int i = 1; /* count to traverse all array keys */ + for (lg=0, ttlg=1; lg<=MAXBITS; lg++, ttlg*=2) { /* for each slice */ + int lc = 0; /* counter */ + int lim = ttlg; + if (lim > t->sizearray) { + lim = t->sizearray; /* adjust upper limit */ + if (i > lim) + break; /* no more elements to count */ + } + /* count elements in range (2^(lg-1), 2^lg] */ + for (; i <= lim; i++) { + if (!ttisnil(&t->array[i-1])) + lc++; + } + nums[lg] += lc; + ause += lc; + } + return ause; +} + + +static int numusehash (const Table *t, int *nums, int *pnasize) { + int totaluse = 0; /* total number of elements */ + int ause = 0; /* summation of `nums' */ + int i = sizenode(t); + while (i--) { + Node *n = &t->node[i]; + if (!ttisnil(gval(n))) { + ause += countint(key2tval(n), nums); + totaluse++; + } + } + *pnasize += ause; + return totaluse; +} + + +static void setarrayvector (lua_State *L, Table *t, int size) { + int i; + luaM_reallocvector(L, t->array, t->sizearray, size, TValue); + for (i=t->sizearray; iarray[i]); + t->sizearray = size; +} + + +static void setnodevector (lua_State *L, Table *t, int size) { + int lsize; + if (size == 0) { /* no elements to hash part? */ + t->node = cast(Node *, dummynode); /* use common `dummynode' */ + lsize = 0; + } + else { + int i; + lsize = ceillog2(size); + if (lsize > MAXBITS) + luaG_runerror(L, "table overflow"); + size = twoto(lsize); + t->node = luaM_newvector(L, size, Node); + for (i=0; ilsizenode = cast_byte(lsize); + t->lastfree = gnode(t, size); /* all positions are free */ +} + + +static void resize (lua_State *L, Table *t, int nasize, int nhsize) { + int i; + int oldasize = t->sizearray; + int oldhsize = t->lsizenode; + Node *nold = t->node; /* save old hash ... */ + if (nasize > oldasize) /* array part must grow? */ + setarrayvector(L, t, nasize); + /* create new hash part with appropriate size */ + setnodevector(L, t, nhsize); + if (nasize < oldasize) { /* array part must shrink? */ + t->sizearray = nasize; + /* re-insert elements from vanishing slice */ + for (i=nasize; iarray[i])) + setobjt2t(L, luaH_setnum(L, t, i+1), &t->array[i]); + } + /* shrink array */ + luaM_reallocvector(L, t->array, oldasize, nasize, TValue); + } + /* re-insert elements from hash part */ + for (i = twoto(oldhsize) - 1; i >= 0; i--) { + Node *old = nold+i; + if (!ttisnil(gval(old))) + setobjt2t(L, luaH_set(L, t, key2tval(old)), gval(old)); + } + if (nold != dummynode) + luaM_freearray(L, nold, twoto(oldhsize), Node); /* free old array */ +} + + +void luaH_resizearray (lua_State *L, Table *t, int nasize) { + int nsize = (t->node == dummynode) ? 0 : sizenode(t); + resize(L, t, nasize, nsize); +} + + +static void rehash (lua_State *L, Table *t, const TValue *ek) { + int nasize, na; + int nums[MAXBITS+1]; /* nums[i] = number of keys between 2^(i-1) and 2^i */ + int i; + int totaluse; + for (i=0; i<=MAXBITS; i++) nums[i] = 0; /* reset counts */ + nasize = numusearray(t, nums); /* count keys in array part */ + totaluse = nasize; /* all those keys are integer keys */ + totaluse += numusehash(t, nums, &nasize); /* count keys in hash part */ + /* count extra key */ + nasize += countint(ek, nums); + totaluse++; + /* compute new size for array part */ + na = computesizes(nums, &nasize); + /* resize the table to new computed sizes */ + resize(L, t, nasize, totaluse - na); +} + + + +/* +** }============================================================= +*/ + + +Table *luaH_new (lua_State *L, int narray, int nhash) { + Table *t = luaM_new(L, Table); + luaC_link(L, obj2gco(t), LUA_TTABLE); + t->metatable = NULL; + t->flags = cast_byte(~0); + /* temporary values (kept only if some malloc fails) */ + t->array = NULL; + t->sizearray = 0; + t->lsizenode = 0; + t->node = cast(Node *, dummynode); + setarrayvector(L, t, narray); + setnodevector(L, t, nhash); + return t; +} + + +void luaH_free (lua_State *L, Table *t) { + if (t->node != dummynode) + luaM_freearray(L, t->node, sizenode(t), Node); + luaM_freearray(L, t->array, t->sizearray, TValue); + luaM_free(L, t); +} + + +static Node *getfreepos (Table *t) { + while (t->lastfree-- > t->node) { + if (ttisnil(gkey(t->lastfree))) + return t->lastfree; + } + return NULL; /* could not find a free place */ +} + + + +/* +** inserts a new key into a hash table; first, check whether key's main +** position is free. If not, check whether colliding node is in its main +** position or not: if it is not, move colliding node to an empty place and +** put new key in its main position; otherwise (colliding node is in its main +** position), new key goes to an empty position. +*/ +static TValue *newkey (lua_State *L, Table *t, const TValue *key) { + Node *mp = mainposition(t, key); + if (!ttisnil(gval(mp)) || mp == dummynode) { + Node *othern; + Node *n = getfreepos(t); /* get a free place */ + if (n == NULL) { /* cannot find a free place? */ + rehash(L, t, key); /* grow table */ + return luaH_set(L, t, key); /* re-insert key into grown table */ + } + lua_assert(n != dummynode); + othern = mainposition(t, key2tval(mp)); + if (othern != mp) { /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ + while (gnext(othern) != mp) othern = gnext(othern); /* find previous */ + gnext(othern) = n; /* redo the chain with `n' in place of `mp' */ + *n = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + gnext(mp) = NULL; /* now `mp' is free */ + setnilvalue(gval(mp)); + } + else { /* colliding node is in its own main position */ + /* new node will go into free position */ + gnext(n) = gnext(mp); /* chain new position */ + gnext(mp) = n; + mp = n; + } + } + gkey(mp)->value = key->value; gkey(mp)->tt = key->tt; + luaC_barriert(L, t, key); + lua_assert(ttisnil(gval(mp))); + return gval(mp); +} + + +/* +** search function for integers +*/ +const TValue *luaH_getnum (Table *t, int key) { + /* (1 <= key && key <= t->sizearray) */ + if (cast(unsigned int, key-1) < cast(unsigned int, t->sizearray)) + return &t->array[key-1]; + else { + lua_Number nk = cast_num(key); + Node *n = hashnum(t, nk); + do { /* check whether `key' is somewhere in the chain */ + if (ttisnumber(gkey(n)) && luai_numeq(nvalue(gkey(n)), nk)) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; + } +} + + +/* +** search function for strings +*/ +const TValue *luaH_getstr (Table *t, TString *key) { + Node *n = hashstr(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (ttisstring(gkey(n)) && rawtsvalue(gkey(n)) == key) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; +} + + +/* +** main search function +*/ +const TValue *luaH_get (Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TNIL: return luaO_nilobject; + case LUA_TSTRING: return luaH_getstr(t, rawtsvalue(key)); + case LUA_TNUMBER: { + int k; + lua_Number n = nvalue(key); + lua_number2int(k, n); + if (luai_numeq(cast_num(k), nvalue(key))) /* index is int? */ + return luaH_getnum(t, k); /* use specialized version */ + /* else go through */ + } + default: { + Node *n = mainposition(t, key); + do { /* check whether `key' is somewhere in the chain */ + if (luaO_rawequalObj(key2tval(n), key)) + return gval(n); /* that's it */ + else n = gnext(n); + } while (n); + return luaO_nilobject; + } + } +} + + +TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { + const TValue *p = luaH_get(t, key); + t->flags = 0; + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisnumber(key) && luai_numisnan(nvalue(key))) + luaG_runerror(L, "table index is NaN"); + return newkey(L, t, key); + } +} + + +TValue *luaH_setnum (lua_State *L, Table *t, int key) { + const TValue *p = luaH_getnum(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + TValue k; + setnvalue(&k, cast_num(key)); + return newkey(L, t, &k); + } +} + + +TValue *luaH_setstr (lua_State *L, Table *t, TString *key) { + const TValue *p = luaH_getstr(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else { + TValue k; + setsvalue(L, &k, key); + return newkey(L, t, &k); + } +} + + +static int unbound_search (Table *t, unsigned int j) { + unsigned int i = j; /* i is zero or a present index */ + j++; + /* find `i' and `j' such that i is present and j is not */ + while (!ttisnil(luaH_getnum(t, j))) { + i = j; + j *= 2; + if (j > cast(unsigned int, MAX_INT)) { /* overflow? */ + /* table was built with bad purposes: resort to linear search */ + i = 1; + while (!ttisnil(luaH_getnum(t, i))) i++; + return i - 1; + } + } + /* now do a binary search between them */ + while (j - i > 1) { + unsigned int m = (i+j)/2; + if (ttisnil(luaH_getnum(t, m))) j = m; + else i = m; + } + return i; +} + + +/* +** Try to find a boundary in table `t'. A `boundary' is an integer index +** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). +*/ +int luaH_getn (Table *t) { + unsigned int j = t->sizearray; + if (j > 0 && ttisnil(&t->array[j - 1])) { + /* there is a boundary in the array part: (binary) search for it */ + unsigned int i = 0; + while (j - i > 1) { + unsigned int m = (i+j)/2; + if (ttisnil(&t->array[m - 1])) j = m; + else i = m; + } + return i; + } + /* else must find a boundary in hash part */ + else if (t->node == dummynode) /* hash part is empty? */ + return j; /* that is easy... */ + else return unbound_search(t, j); +} + + + +#if defined(LUA_DEBUG) + +Node *luaH_mainposition (const Table *t, const TValue *key) { + return mainposition(t, key); +} + +int luaH_isdummy (Node *n) { return n == dummynode; } + +#endif diff --git a/src/lua/src/ltable.h b/src/lua/src/ltable.h new file mode 100644 index 00000000..f5b9d5ea --- /dev/null +++ b/src/lua/src/ltable.h @@ -0,0 +1,40 @@ +/* +** $Id: ltable.h,v 2.10.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + +#ifndef ltable_h +#define ltable_h + +#include "lobject.h" + + +#define gnode(t,i) (&(t)->node[i]) +#define gkey(n) (&(n)->i_key.nk) +#define gval(n) (&(n)->i_val) +#define gnext(n) ((n)->i_key.nk.next) + +#define key2tval(n) (&(n)->i_key.tvk) + + +LUAI_FUNC const TValue *luaH_getnum (Table *t, int key); +LUAI_FUNC TValue *luaH_setnum (lua_State *L, Table *t, int key); +LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); +LUAI_FUNC TValue *luaH_setstr (lua_State *L, Table *t, TString *key); +LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); +LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); +LUAI_FUNC Table *luaH_new (lua_State *L, int narray, int lnhash); +LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, int nasize); +LUAI_FUNC void luaH_free (lua_State *L, Table *t); +LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); +LUAI_FUNC int luaH_getn (Table *t); + + +#if defined(LUA_DEBUG) +LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); +LUAI_FUNC int luaH_isdummy (Node *n); +#endif + + +#endif diff --git a/src/lua/src/ltablib.c b/src/lua/src/ltablib.c new file mode 100644 index 00000000..b6d9cb4a --- /dev/null +++ b/src/lua/src/ltablib.c @@ -0,0 +1,287 @@ +/* +** $Id: ltablib.c,v 1.38.1.3 2008/02/14 16:46:58 roberto Exp $ +** Library for Table Manipulation +** See Copyright Notice in lua.h +*/ + + +#include + +#define ltablib_c +#define LUA_LIB + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_getn(L, n)) + + +static int foreachi (lua_State *L) { + int i; + int n = aux_getn(L, 1); + luaL_checktype(L, 2, LUA_TFUNCTION); + for (i=1; i <= n; i++) { + lua_pushvalue(L, 2); /* function */ + lua_pushinteger(L, i); /* 1st argument */ + lua_rawgeti(L, 1, i); /* 2nd argument */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 1); /* remove nil result */ + } + return 0; +} + + +static int foreach (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checktype(L, 2, LUA_TFUNCTION); + lua_pushnil(L); /* first key */ + while (lua_next(L, 1)) { + lua_pushvalue(L, 2); /* function */ + lua_pushvalue(L, -3); /* key */ + lua_pushvalue(L, -3); /* value */ + lua_call(L, 2, 1); + if (!lua_isnil(L, -1)) + return 1; + lua_pop(L, 2); /* remove value and result */ + } + return 0; +} + + +static int maxn (lua_State *L) { + lua_Number max = 0; + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushnil(L); /* first key */ + while (lua_next(L, 1)) { + lua_pop(L, 1); /* remove value */ + if (lua_type(L, -1) == LUA_TNUMBER) { + lua_Number v = lua_tonumber(L, -1); + if (v > max) max = v; + } + } + lua_pushnumber(L, max); + return 1; +} + + +static int getn (lua_State *L) { + lua_pushinteger(L, aux_getn(L, 1)); + return 1; +} + + +static int setn (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); +#ifndef luaL_setn + luaL_setn(L, 1, luaL_checkint(L, 2)); +#else + luaL_error(L, LUA_QL("setn") " is obsolete"); +#endif + lua_pushvalue(L, 1); + return 1; +} + + +static int tinsert (lua_State *L) { + int e = aux_getn(L, 1) + 1; /* first empty element */ + int pos; /* where to insert new element */ + switch (lua_gettop(L)) { + case 2: { /* called with only 2 arguments */ + pos = e; /* insert new element at the end */ + break; + } + case 3: { + int i; + pos = luaL_checkint(L, 2); /* 2nd argument is the position */ + if (pos > e) e = pos; /* `grow' array if necessary */ + for (i = e; i > pos; i--) { /* move up elements */ + lua_rawgeti(L, 1, i-1); + lua_rawseti(L, 1, i); /* t[i] = t[i-1] */ + } + break; + } + default: { + return luaL_error(L, "wrong number of arguments to " LUA_QL("insert")); + } + } + luaL_setn(L, 1, e); /* new size */ + lua_rawseti(L, 1, pos); /* t[pos] = v */ + return 0; +} + + +static int tremove (lua_State *L) { + int e = aux_getn(L, 1); + int pos = luaL_optint(L, 2, e); + if (!(1 <= pos && pos <= e)) /* position is outside bounds? */ + return 0; /* nothing to remove */ + luaL_setn(L, 1, e - 1); /* t.n = n-1 */ + lua_rawgeti(L, 1, pos); /* result = t[pos] */ + for ( ;pos= P */ + while (lua_rawgeti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (i>u) luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* repeat --j until a[j] <= P */ + while (lua_rawgeti(L, 1, --j), sort_comp(L, -3, -1)) { + if (j + +#define ltm_c +#define LUA_CORE + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + + +const char *const luaT_typenames[] = { + "nil", "boolean", "userdata", "number", + "string", "table", "function", "userdata", "thread", + "proto", "upval" +}; + + +void luaT_init (lua_State *L) { + static const char *const luaT_eventname[] = { /* ORDER TM */ + "__index", "__newindex", + "__gc", "__mode", "__eq", + "__add", "__sub", "__mul", "__div", "__mod", + "__pow", "__unm", "__len", "__lt", "__le", + "__concat", "__call" + }; + int i; + for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); + luaS_fix(G(L)->tmname[i]); /* never collect these names */ + } +} + + +/* +** function to be used with macro "fasttm": optimized for absence of +** tag methods +*/ +const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { + const TValue *tm = luaH_getstr(events, ename); + lua_assert(event <= TM_EQ); + if (ttisnil(tm)) { /* no tag method? */ + events->flags |= cast_byte(1u<metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(o)->metatable; + break; + default: + mt = G(L)->mt[ttype(o)]; + } + return (mt ? luaH_getstr(mt, G(L)->tmname[event]) : luaO_nilobject); +} + diff --git a/src/lua/src/ltm.h b/src/lua/src/ltm.h new file mode 100644 index 00000000..64343b78 --- /dev/null +++ b/src/lua/src/ltm.h @@ -0,0 +1,54 @@ +/* +** $Id: ltm.h,v 2.6.1.1 2007/12/27 13:02:25 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + +#ifndef ltm_h +#define ltm_h + + +#include "lobject.h" + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER TM" +*/ +typedef enum { + TM_INDEX, + TM_NEWINDEX, + TM_GC, + TM_MODE, + TM_EQ, /* last tag method with `fast' access */ + TM_ADD, + TM_SUB, + TM_MUL, + TM_DIV, + TM_MOD, + TM_POW, + TM_UNM, + TM_LEN, + TM_LT, + TM_LE, + TM_CONCAT, + TM_CALL, + TM_N /* number of elements in the enum */ +} TMS; + + + +#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ + ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) + +#define fasttm(l,et,e) gfasttm(G(l), et, e) + +LUAI_DATA const char *const luaT_typenames[]; + + +LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); +LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, + TMS event); +LUAI_FUNC void luaT_init (lua_State *L); + +#endif diff --git a/src/lua/src/lua.c b/src/lua/src/lua.c new file mode 100644 index 00000000..3a466093 --- /dev/null +++ b/src/lua/src/lua.c @@ -0,0 +1,392 @@ +/* +** $Id: lua.c,v 1.160.1.2 2007/12/28 15:32:23 roberto Exp $ +** Lua stand-alone interpreter +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include +#include + +#define lua_c + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + +static lua_State *globalL = NULL; + +static const char *progname = LUA_PROGNAME; + + + +static void lstop (lua_State *L, lua_Debug *ar) { + (void)ar; /* unused arg. */ + lua_sethook(L, NULL, 0, 0); + luaL_error(L, "interrupted!"); +} + + +static void laction (int i) { + signal(i, SIG_DFL); /* if another SIGINT happens before lstop, + terminate process (default action) */ + lua_sethook(globalL, lstop, LUA_MASKCALL | LUA_MASKRET | LUA_MASKCOUNT, 1); +} + + +static void print_usage (void) { + fprintf(stderr, + "usage: %s [options] [script [args]].\n" + "Available options are:\n" + " -e stat execute string " LUA_QL("stat") "\n" + " -l name require library " LUA_QL("name") "\n" + " -i enter interactive mode after executing " LUA_QL("script") "\n" + " -v show version information\n" + " -- stop handling options\n" + " - execute stdin and stop handling options\n" + , + progname); + fflush(stderr); +} + + +static void l_message (const char *pname, const char *msg) { + if (pname) fprintf(stderr, "%s: ", pname); + fprintf(stderr, "%s\n", msg); + fflush(stderr); +} + + +static int report (lua_State *L, int status) { + if (status && !lua_isnil(L, -1)) { + const char *msg = lua_tostring(L, -1); + if (msg == NULL) msg = "(error object is not a string)"; + l_message(progname, msg); + lua_pop(L, 1); + } + return status; +} + + +static int traceback (lua_State *L) { + if (!lua_isstring(L, 1)) /* 'message' not a string? */ + return 1; /* keep it intact */ + lua_getfield(L, LUA_GLOBALSINDEX, "debug"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; + } + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 2); + return 1; + } + lua_pushvalue(L, 1); /* pass error message */ + lua_pushinteger(L, 2); /* skip this function and traceback */ + lua_call(L, 2, 1); /* call debug.traceback */ + return 1; +} + + +static int docall (lua_State *L, int narg, int clear) { + int status; + int base = lua_gettop(L) - narg; /* function index */ + lua_pushcfunction(L, traceback); /* push traceback function */ + lua_insert(L, base); /* put it under chunk and args */ + signal(SIGINT, laction); + status = lua_pcall(L, narg, (clear ? 0 : LUA_MULTRET), base); + signal(SIGINT, SIG_DFL); + lua_remove(L, base); /* remove traceback function */ + /* force a complete garbage collection in case of errors */ + if (status != 0) lua_gc(L, LUA_GCCOLLECT, 0); + return status; +} + + +static void print_version (void) { + l_message(NULL, LUA_RELEASE " " LUA_COPYRIGHT); +} + + +static int getargs (lua_State *L, char **argv, int n) { + int narg; + int i; + int argc = 0; + while (argv[argc]) argc++; /* count total number of arguments */ + narg = argc - (n + 1); /* number of arguments to the script */ + luaL_checkstack(L, narg + 3, "too many arguments to script"); + for (i=n+1; i < argc; i++) + lua_pushstring(L, argv[i]); + lua_createtable(L, narg, n + 1); + for (i=0; i < argc; i++) { + lua_pushstring(L, argv[i]); + lua_rawseti(L, -2, i - n); + } + return narg; +} + + +static int dofile (lua_State *L, const char *name) { + int status = luaL_loadfile(L, name) || docall(L, 0, 1); + return report(L, status); +} + + +static int dostring (lua_State *L, const char *s, const char *name) { + int status = luaL_loadbuffer(L, s, strlen(s), name) || docall(L, 0, 1); + return report(L, status); +} + + +static int dolibrary (lua_State *L, const char *name) { + lua_getglobal(L, "require"); + lua_pushstring(L, name); + return report(L, docall(L, 1, 1)); +} + + +static const char *get_prompt (lua_State *L, int firstline) { + const char *p; + lua_getfield(L, LUA_GLOBALSINDEX, firstline ? "_PROMPT" : "_PROMPT2"); + p = lua_tostring(L, -1); + if (p == NULL) p = (firstline ? LUA_PROMPT : LUA_PROMPT2); + lua_pop(L, 1); /* remove global */ + return p; +} + + +static int incomplete (lua_State *L, int status) { + if (status == LUA_ERRSYNTAX) { + size_t lmsg; + const char *msg = lua_tolstring(L, -1, &lmsg); + const char *tp = msg + lmsg - (sizeof(LUA_QL("")) - 1); + if (strstr(msg, LUA_QL("")) == tp) { + lua_pop(L, 1); + return 1; + } + } + return 0; /* else... */ +} + + +static int pushline (lua_State *L, int firstline) { + char buffer[LUA_MAXINPUT]; + char *b = buffer; + size_t l; + const char *prmt = get_prompt(L, firstline); + if (lua_readline(L, b, prmt) == 0) + return 0; /* no input */ + l = strlen(b); + if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ + b[l-1] = '\0'; /* remove it */ + if (firstline && b[0] == '=') /* first line starts with `=' ? */ + lua_pushfstring(L, "return %s", b+1); /* change it to `return' */ + else + lua_pushstring(L, b); + lua_freeline(L, b); + return 1; +} + + +static int loadline (lua_State *L) { + int status; + lua_settop(L, 0); + if (!pushline(L, 1)) + return -1; /* no input */ + for (;;) { /* repeat until gets a complete line */ + status = luaL_loadbuffer(L, lua_tostring(L, 1), lua_strlen(L, 1), "=stdin"); + if (!incomplete(L, status)) break; /* cannot try to add lines? */ + if (!pushline(L, 0)) /* no more input? */ + return -1; + lua_pushliteral(L, "\n"); /* add a new line... */ + lua_insert(L, -2); /* ...between the two lines */ + lua_concat(L, 3); /* join them */ + } + lua_saveline(L, 1); + lua_remove(L, 1); /* remove line */ + return status; +} + + +static void dotty (lua_State *L) { + int status; + const char *oldprogname = progname; + progname = NULL; + while ((status = loadline(L)) != -1) { + if (status == 0) status = docall(L, 0, 0); + report(L, status); + if (status == 0 && lua_gettop(L) > 0) { /* any result to print? */ + lua_getglobal(L, "print"); + lua_insert(L, 1); + if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) + l_message(progname, lua_pushfstring(L, + "error calling " LUA_QL("print") " (%s)", + lua_tostring(L, -1))); + } + } + lua_settop(L, 0); /* clear stack */ + fputs("\n", stdout); + fflush(stdout); + progname = oldprogname; +} + + +static int handle_script (lua_State *L, char **argv, int n) { + int status; + const char *fname; + int narg = getargs(L, argv, n); /* collect arguments */ + lua_setglobal(L, "arg"); + fname = argv[n]; + if (strcmp(fname, "-") == 0 && strcmp(argv[n-1], "--") != 0) + fname = NULL; /* stdin */ + status = luaL_loadfile(L, fname); + lua_insert(L, -(narg+1)); + if (status == 0) + status = docall(L, narg, 0); + else + lua_pop(L, narg); + return report(L, status); +} + + +/* check that argument has no extra characters at the end */ +#define notail(x) {if ((x)[2] != '\0') return -1;} + + +static int collectargs (char **argv, int *pi, int *pv, int *pe) { + int i; + for (i = 1; argv[i] != NULL; i++) { + if (argv[i][0] != '-') /* not an option? */ + return i; + switch (argv[i][1]) { /* option */ + case '-': + notail(argv[i]); + return (argv[i+1] != NULL ? i+1 : 0); + case '\0': + return i; + case 'i': + notail(argv[i]); + *pi = 1; /* go through */ + case 'v': + notail(argv[i]); + *pv = 1; + break; + case 'e': + *pe = 1; /* go through */ + case 'l': + if (argv[i][2] == '\0') { + i++; + if (argv[i] == NULL) return -1; + } + break; + default: return -1; /* invalid option */ + } + } + return 0; +} + + +static int runargs (lua_State *L, char **argv, int n) { + int i; + for (i = 1; i < n; i++) { + if (argv[i] == NULL) continue; + lua_assert(argv[i][0] == '-'); + switch (argv[i][1]) { /* option */ + case 'e': { + const char *chunk = argv[i] + 2; + if (*chunk == '\0') chunk = argv[++i]; + lua_assert(chunk != NULL); + if (dostring(L, chunk, "=(command line)") != 0) + return 1; + break; + } + case 'l': { + const char *filename = argv[i] + 2; + if (*filename == '\0') filename = argv[++i]; + lua_assert(filename != NULL); + if (dolibrary(L, filename)) + return 1; /* stop if file fails */ + break; + } + default: break; + } + } + return 0; +} + + +static int handle_luainit (lua_State *L) { + const char *init = getenv(LUA_INIT); + if (init == NULL) return 0; /* status OK */ + else if (init[0] == '@') + return dofile(L, init+1); + else + return dostring(L, init, "=" LUA_INIT); +} + + +struct Smain { + int argc; + char **argv; + int status; +}; + + +static int pmain (lua_State *L) { + struct Smain *s = (struct Smain *)lua_touserdata(L, 1); + char **argv = s->argv; + int script; + int has_i = 0, has_v = 0, has_e = 0; + globalL = L; + if (argv[0] && argv[0][0]) progname = argv[0]; + lua_gc(L, LUA_GCSTOP, 0); /* stop collector during initialization */ + luaL_openlibs(L); /* open libraries */ + lua_gc(L, LUA_GCRESTART, 0); + s->status = handle_luainit(L); + if (s->status != 0) return 0; + script = collectargs(argv, &has_i, &has_v, &has_e); + if (script < 0) { /* invalid args? */ + print_usage(); + s->status = 1; + return 0; + } + if (has_v) print_version(); + s->status = runargs(L, argv, (script > 0) ? script : s->argc); + if (s->status != 0) return 0; + if (script) + s->status = handle_script(L, argv, script); + if (s->status != 0) return 0; + if (has_i) + dotty(L); + else if (script == 0 && !has_e && !has_v) { + if (lua_stdin_is_tty()) { + print_version(); + dotty(L); + } + else dofile(L, NULL); /* executes stdin as a file */ + } + return 0; +} + + +int main (int argc, char **argv) { + int status; + struct Smain s; + lua_State *L = lua_open(); /* create state */ + if (L == NULL) { + l_message(argv[0], "cannot create state: not enough memory"); + return EXIT_FAILURE; + } + s.argc = argc; + s.argv = argv; + status = lua_cpcall(L, &pmain, &s); + report(L, status); + lua_close(L); + return (status || s.status) ? EXIT_FAILURE : EXIT_SUCCESS; +} + diff --git a/src/lua/src/lua.h b/src/lua/src/lua.h new file mode 100644 index 00000000..e4bdfd3b --- /dev/null +++ b/src/lua/src/lua.h @@ -0,0 +1,388 @@ +/* +** $Id: lua.h,v 1.218.1.5 2008/08/06 13:30:12 roberto Exp $ +** Lua - An Extensible Extension Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION "Lua 5.1" +#define LUA_RELEASE "Lua 5.1.4" +#define LUA_VERSION_NUM 501 +#define LUA_COPYRIGHT "Copyright (C) 1994-2008 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo & W. Celes" + + +/* mark for precompiled code (`Lua') */ +#define LUA_SIGNATURE "\033Lua" + +/* option for multiple returns in `lua_pcall' and `lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** pseudo-indices +*/ +#define LUA_REGISTRYINDEX (-10000) +#define LUA_ENVIRONINDEX (-10001) +#define LUA_GLOBALSINDEX (-10002) +#define lua_upvalueindex(i) (LUA_GLOBALSINDEX-(i)) + + +/* thread status; 0 is OK */ +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRERR 5 + + +typedef struct lua_State lua_State; + +typedef int (*lua_CFunction) (lua_State *L); + + +/* +** functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void* p, size_t sz, void* ud); + + +/* +** prototype for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_remove) (lua_State *L, int idx); +LUA_API void (lua_insert) (lua_State *L, int idx); +LUA_API void (lua_replace) (lua_State *L, int idx); +LUA_API int (lua_checkstack) (lua_State *L, int sz); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API int (lua_equal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_lessthan) (lua_State *L, int idx1, int idx2); + +LUA_API lua_Number (lua_tonumber) (lua_State *L, int idx); +LUA_API lua_Integer (lua_tointeger) (lua_State *L, int idx); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_objlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API void (lua_pushlstring) (lua_State *L, const char *s, size_t l); +LUA_API void (lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API void (lua_gettable) (lua_State *L, int idx); +LUA_API void (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawget) (lua_State *L, int idx); +LUA_API void (lua_rawgeti) (lua_State *L, int idx, int n); +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API void (lua_getfenv) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, int n); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API int (lua_setfenv) (lua_State *L, int idx); + + +/* +** `load' and `call' functions (load and run Lua code) +*/ +LUA_API void (lua_call) (lua_State *L, int nargs, int nresults); +LUA_API int (lua_pcall) (lua_State *L, int nargs, int nresults, int errfunc); +LUA_API int (lua_cpcall) (lua_State *L, lua_CFunction func, void *ud); +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yield) (lua_State *L, int nresults); +LUA_API int (lua_resume) (lua_State *L, int narg); +LUA_API int (lua_status) (lua_State *L); + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud); + + + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_strlen(L,i) lua_objlen(L, (i)) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) + +#define lua_setglobal(L,s) lua_setfield(L, LUA_GLOBALSINDEX, (s)) +#define lua_getglobal(L,s) lua_getfield(L, LUA_GLOBALSINDEX, (s)) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + + +/* +** compatibility macros and functions +*/ + +#define lua_open() luaL_newstate() + +#define lua_getregistry(L) lua_pushvalue(L, LUA_REGISTRYINDEX) + +#define lua_getgccount(L) lua_gc(L, LUA_GCCOUNT, 0) + +#define lua_Chunkreader lua_Reader +#define lua_Chunkwriter lua_Writer + + +/* hack */ +LUA_API void lua_setlevel (lua_State *from, lua_State *to); + + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILRET 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debuger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar); +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n); +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n); + +LUA_API int lua_sethook (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook lua_gethook (lua_State *L); +LUA_API int lua_gethookmask (lua_State *L); +LUA_API int lua_gethookcount (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) `global', `local', `field', `method' */ + const char *what; /* (S) `Lua', `C', `main', `tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int nups; /* (u) number of upvalues */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + int i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. +* +* 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. +******************************************************************************/ + + +#endif diff --git a/src/lua/src/luac.c b/src/lua/src/luac.c new file mode 100644 index 00000000..d0701739 --- /dev/null +++ b/src/lua/src/luac.c @@ -0,0 +1,200 @@ +/* +** $Id: luac.c,v 1.54 2006/06/02 17:37:11 lhf Exp $ +** Lua compiler (saves bytecodes to files; also list bytecodes) +** See Copyright Notice in lua.h +*/ + +#include +#include +#include +#include + +#define luac_c +#define LUA_CORE + +#include "lua.h" +#include "lauxlib.h" + +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstring.h" +#include "lundump.h" + +#define PROGNAME "luac" /* default program name */ +#define OUTPUT PROGNAME ".out" /* default output file */ + +static int listing=0; /* list bytecodes? */ +static int dumping=1; /* dump bytecodes? */ +static int stripping=0; /* strip debug information? */ +static char Output[]={ OUTPUT }; /* default output file name */ +static const char* output=Output; /* actual output file name */ +static const char* progname=PROGNAME; /* actual program name */ + +static void fatal(const char* message) +{ + fprintf(stderr,"%s: %s\n",progname,message); + exit(EXIT_FAILURE); +} + +static void cannot(const char* what) +{ + fprintf(stderr,"%s: cannot %s %s: %s\n",progname,what,output,strerror(errno)); + exit(EXIT_FAILURE); +} + +static void usage(const char* message) +{ + if (*message=='-') + fprintf(stderr,"%s: unrecognized option " LUA_QS "\n",progname,message); + else + fprintf(stderr,"%s: %s\n",progname,message); + fprintf(stderr, + "usage: %s [options] [filenames].\n" + "Available options are:\n" + " - process stdin\n" + " -l list\n" + " -o name output to file " LUA_QL("name") " (default is \"%s\")\n" + " -p parse only\n" + " -s strip debug information\n" + " -v show version information\n" + " -- stop handling options\n", + progname,Output); + exit(EXIT_FAILURE); +} + +#define IS(s) (strcmp(argv[i],s)==0) + +static int doargs(int argc, char* argv[]) +{ + int i; + int version=0; + if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; + for (i=1; itop+(i))->l.p) + +static const Proto* combine(lua_State* L, int n) +{ + if (n==1) + return toproto(L,-1); + else + { + int i,pc; + Proto* f=luaF_newproto(L); + setptvalue2s(L,L->top,f); incr_top(L); + f->source=luaS_newliteral(L,"=(" PROGNAME ")"); + f->maxstacksize=1; + pc=2*n+1; + f->code=luaM_newvector(L,pc,Instruction); + f->sizecode=pc; + f->p=luaM_newvector(L,n,Proto*); + f->sizep=n; + pc=0; + for (i=0; ip[i]=toproto(L,i-n-1); + f->code[pc++]=CREATE_ABx(OP_CLOSURE,0,i); + f->code[pc++]=CREATE_ABC(OP_CALL,0,1,1); + } + f->code[pc++]=CREATE_ABC(OP_RETURN,0,1,0); + return f; + } +} + +static int writer(lua_State* L, const void* p, size_t size, void* u) +{ + UNUSED(L); + return (fwrite(p,size,1,(FILE*)u)!=1) && (size!=0); +} + +struct Smain { + int argc; + char** argv; +}; + +static int pmain(lua_State* L) +{ + struct Smain* s = (struct Smain*)lua_touserdata(L, 1); + int argc=s->argc; + char** argv=s->argv; + const Proto* f; + int i; + if (!lua_checkstack(L,argc)) fatal("too many input files"); + for (i=0; i1); + if (dumping) + { + FILE* D= (output==NULL) ? stdout : fopen(output,"wb"); + if (D==NULL) cannot("open"); + lua_lock(L); + luaU_dump(L,f,writer,D,stripping); + lua_unlock(L); + if (ferror(D)) cannot("write"); + if (fclose(D)) cannot("close"); + } + return 0; +} + +int main(int argc, char* argv[]) +{ + lua_State* L; + struct Smain s; + int i=doargs(argc,argv); + argc-=i; argv+=i; + if (argc<=0) usage("no input files given"); + L=lua_open(); + if (L==NULL) fatal("not enough memory for state"); + s.argc=argc; + s.argv=argv; + if (lua_cpcall(L,pmain,&s)!=0) fatal(lua_tostring(L,-1)); + lua_close(L); + return EXIT_SUCCESS; +} diff --git a/src/lua/src/luaconf.h b/src/lua/src/luaconf.h new file mode 100644 index 00000000..e2cb2616 --- /dev/null +++ b/src/lua/src/luaconf.h @@ -0,0 +1,763 @@ +/* +** $Id: luaconf.h,v 1.82.1.7 2008/02/11 16:25:08 roberto Exp $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef lconfig_h +#define lconfig_h + +#include +#include + + +/* +** ================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +@@ LUA_ANSI controls the use of non-ansi features. +** CHANGE it (define it) if you want Lua to avoid the use of any +** non-ansi feature or library. +*/ +#if defined(__STRICT_ANSI__) +#define LUA_ANSI +#endif + + +#if !defined(LUA_ANSI) && defined(_WIN32) +#define LUA_WIN +#endif + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#endif + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_DL_DYLD /* does not need extra library */ +#endif + + + +/* +@@ LUA_USE_POSIX includes all functionallity listed as X/Open System +@* Interfaces Extension (XSI). +** CHANGE it (define it) if your system is XSI compatible. +*/ +#if defined(LUA_USE_POSIX) +#define LUA_USE_MKSTEMP +#define LUA_USE_ISATTY +#define LUA_USE_POPEN +#define LUA_USE_ULONGJMP +#endif + + +/* +@@ LUA_PATH and LUA_CPATH are the names of the environment variables that +@* Lua check to set its paths. +@@ LUA_INIT is the name of the environment variable that Lua +@* checks for initialization code. +** CHANGE them if you want different names. +*/ +#define LUA_PATH "LUA_PATH" +#define LUA_CPATH "LUA_CPATH" +#define LUA_INIT "LUA_INIT" + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +@* Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +@* C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ +#if defined(_WIN32) +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_PATH_DEFAULT \ + ".\\?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua" +#define LUA_CPATH_DEFAULT \ + ".\\?.dll;" LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll" + +#else +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/5.1/" +#define LUA_CDIR LUA_ROOT "lib/lua/5.1/" +#define LUA_PATH_DEFAULT \ + "./?.lua;" LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua" +#define LUA_CPATH_DEFAULT \ + "./?.so;" LUA_CDIR"?.so;" LUA_CDIR"loadall.so" +#endif + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + + +/* +@@ LUA_PATHSEP is the character that separates templates in a path. +@@ LUA_PATH_MARK is the string that marks the substitution points in a +@* template. +@@ LUA_EXECDIR in a Windows path is replaced by the executable's +@* directory. +@@ LUA_IGMARK is a mark to ignore all before it when bulding the +@* luaopen_ function name. +** CHANGE them if for some reason your system cannot use those +** characters. (E.g., if one of those characters is a common character +** in file/directory names.) Probably you do not need to change them. +*/ +#define LUA_PATHSEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXECDIR "!" +#define LUA_IGMARK "-" + + +/* +@@ LUA_INTEGER is the integral type used by lua_pushinteger/lua_tointeger. +** CHANGE that if ptrdiff_t is not adequate on your machine. (On most +** machines, ptrdiff_t gives a good choice between int or long.) +*/ +#define LUA_INTEGER ptrdiff_t + + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all standard library functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) + +#if defined(LUA_CORE) || defined(LUA_LIB) +#define LUA_API __declspec(dllexport) +#else +#define LUA_API __declspec(dllimport) +#endif + +#else + +#define LUA_API extern + +#endif + +/* more often than not the libs go together with the core */ +#define LUALIB_API LUA_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +@* exported to outside modules. +@@ LUAI_DATA is a mark for all extern (const) variables that are not to +@* be exported to outside modules. +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. +*/ +#if defined(luaall_c) +#define LUAI_FUNC static +#define LUAI_DATA /* empty */ + +#elif defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#define LUAI_DATA LUAI_FUNC + +#else +#define LUAI_FUNC extern +#define LUAI_DATA extern +#endif + + + +/* +@@ LUA_QL describes how error messages quote program elements. +** CHANGE it if you want a different appearance. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@* of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +** {================================================================== +** Stand-alone configuration +** =================================================================== +*/ + +#if defined(lua_c) || defined(luaall_c) + +/* +@@ lua_stdin_is_tty detects whether the standard input is a 'tty' (that +@* is, whether we're running lua interactively). +** CHANGE it if you have a better definition for non-POSIX/non-Windows +** systems. +*/ +#if defined(LUA_USE_ISATTY) +#include +#define lua_stdin_is_tty() isatty(0) +#elif defined(LUA_WIN) +#include +#include +#define lua_stdin_is_tty() _isatty(_fileno(stdin)) +#else +#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ +#endif + + +/* +@@ LUA_PROMPT is the default prompt used by stand-alone Lua. +@@ LUA_PROMPT2 is the default continuation prompt used by stand-alone Lua. +** CHANGE them if you want different prompts. (You can also change the +** prompts dynamically, assigning to globals _PROMPT/_PROMPT2.) +*/ +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " + + +/* +@@ LUA_PROGNAME is the default name for the stand-alone Lua program. +** CHANGE it if your stand-alone interpreter has a different name and +** your system is not able to detect that name automatically. +*/ +#define LUA_PROGNAME "lua" + + +/* +@@ LUA_MAXINPUT is the maximum length for an input line in the +@* stand-alone interpreter. +** CHANGE it if you need longer lines. +*/ +#define LUA_MAXINPUT 512 + + +/* +@@ lua_readline defines how to show a prompt and then read a line from +@* the standard input. +@@ lua_saveline defines how to "save" a read line in a "history". +@@ lua_freeline defines how to free a line read by lua_readline. +** CHANGE them if you want to improve this functionality (e.g., by using +** GNU readline and history facilities). +*/ +#if defined(LUA_USE_READLINE) +#include +#include +#include +#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) +#define lua_saveline(L,idx) \ + if (lua_strlen(L,idx) > 0) /* non-empty line? */ \ + add_history(lua_tostring(L, idx)); /* add it to history */ +#define lua_freeline(L,b) ((void)L, free(b)) +#else +#define lua_readline(L,b,p) \ + ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ + fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ +#define lua_saveline(L,idx) { (void)L; (void)idx; } +#define lua_freeline(L,b) { (void)L; (void)b; } +#endif + +#endif + +/* }================================================================== */ + + +/* +@@ LUAI_GCPAUSE defines the default pause between garbage-collector cycles +@* as a percentage. +** CHANGE it if you want the GC to run faster or slower (higher values +** mean larger pauses which mean slower collection.) You can also change +** this value dynamically. +*/ +#define LUAI_GCPAUSE 200 /* 200% (wait memory to double before next GC) */ + + +/* +@@ LUAI_GCMUL defines the default speed of garbage collection relative to +@* memory allocation as a percentage. +** CHANGE it if you want to change the granularity of the garbage +** collection. (Higher values mean coarser collections. 0 represents +** infinity, where each step performs a full collection.) You can also +** change this value dynamically. +*/ +#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ + + + +/* +@@ LUA_COMPAT_GETN controls compatibility with old getn behavior. +** CHANGE it (define it) if you want exact compatibility with the +** behavior of setn/getn in Lua 5.0. +*/ +#undef LUA_COMPAT_GETN + +/* +@@ LUA_COMPAT_LOADLIB controls compatibility about global loadlib. +** CHANGE it to undefined as soon as you do not need a global 'loadlib' +** function (the function is still available as 'package.loadlib'). +*/ +#undef LUA_COMPAT_LOADLIB + +/* +@@ LUA_COMPAT_VARARG controls compatibility with old vararg feature. +** CHANGE it to undefined as soon as your programs use only '...' to +** access vararg parameters (instead of the old 'arg' table). +*/ +#define LUA_COMPAT_VARARG + +/* +@@ LUA_COMPAT_MOD controls compatibility with old math.mod function. +** CHANGE it to undefined as soon as your programs use 'math.fmod' or +** the new '%' operator instead of 'math.mod'. +*/ +#define LUA_COMPAT_MOD + +/* +@@ LUA_COMPAT_LSTR controls compatibility with old long string nesting +@* facility. +** CHANGE it to 2 if you want the old behaviour, or undefine it to turn +** off the advisory error when nesting [[...]]. +*/ +#define LUA_COMPAT_LSTR 1 + +/* +@@ LUA_COMPAT_GFIND controls compatibility with old 'string.gfind' name. +** CHANGE it to undefined as soon as you rename 'string.gfind' to +** 'string.gmatch'. +*/ +#define LUA_COMPAT_GFIND + +/* +@@ LUA_COMPAT_OPENLIB controls compatibility with old 'luaL_openlib' +@* behavior. +** CHANGE it to undefined as soon as you replace to 'luaL_register' +** your uses of 'luaL_openlib' +*/ +#define LUA_COMPAT_OPENLIB + + + +/* +@@ luai_apicheck is the assert macro used by the Lua-C API. +** CHANGE luai_apicheck if you want Lua to perform some checks in the +** parameters it gets from API calls. This may slow down the interpreter +** a bit, but may be quite useful when debugging C code that interfaces +** with Lua. A useful redefinition is to use assert.h. +*/ +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(L,o) { (void)L; assert(o); } +#else +#define luai_apicheck(L,o) { (void)L; } +#endif + + +/* +@@ LUAI_BITSINT defines the number of bits in an int. +** CHANGE here if Lua cannot automatically detect the number of bits of +** your machine. Probably you do not need to change this. +*/ +/* avoid overflows in comparison */ +#if INT_MAX-20 < 32760 +#define LUAI_BITSINT 16 +#elif INT_MAX > 2147483640L +/* int has at least 32 bits */ +#define LUAI_BITSINT 32 +#else +#error "you must define LUA_BITSINT with number of bits in an integer" +#endif + + +/* +@@ LUAI_UINT32 is an unsigned integer with at least 32 bits. +@@ LUAI_INT32 is an signed integer with at least 32 bits. +@@ LUAI_UMEM is an unsigned integer big enough to count the total +@* memory used by Lua. +@@ LUAI_MEM is a signed integer big enough to count the total memory +@* used by Lua. +** CHANGE here if for some weird reason the default definitions are not +** good enough for your machine. (The definitions in the 'else' +** part always works, but may waste space on machines with 64-bit +** longs.) Probably you do not need to change this. +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_UINT32 unsigned int +#define LUAI_INT32 int +#define LUAI_MAXINT32 INT_MAX +#define LUAI_UMEM size_t +#define LUAI_MEM ptrdiff_t +#else +/* 16-bit ints */ +#define LUAI_UINT32 unsigned long +#define LUAI_INT32 long +#define LUAI_MAXINT32 LONG_MAX +#define LUAI_UMEM unsigned long +#define LUAI_MEM long +#endif + + +/* +@@ LUAI_MAXCALLS limits the number of nested calls. +** CHANGE it if you need really deep recursive calls. This limit is +** arbitrary; its only purpose is to stop infinite recursion before +** exhausting memory. +*/ +#define LUAI_MAXCALLS 20000 + + +/* +@@ LUAI_MAXCSTACK limits the number of Lua stack slots that a C function +@* can use. +** CHANGE it if you need lots of (Lua) stack space for your C +** functions. This limit is arbitrary; its only purpose is to stop C +** functions to consume unlimited stack space. (must be smaller than +** -LUA_REGISTRYINDEX) +*/ +#define LUAI_MAXCSTACK 8000 + + + +/* +** {================================================================== +** CHANGE (to smaller values) the following definitions if your system +** has a small C stack. (Or you may want to change them to larger +** values if your system has a large C stack and these limits are +** too rigid for you.) Some of these constants control the size of +** stack-allocated arrays used by the compiler or the interpreter, while +** others limit the maximum number of recursive calls that the compiler +** or the interpreter can perform. Values too large may cause a C stack +** overflow for some forms of deep constructs. +** =================================================================== +*/ + + +/* +@@ LUAI_MAXCCALLS is the maximum depth for nested C calls (short) and +@* syntactical nested non-terminals in a program. +*/ +#define LUAI_MAXCCALLS 200 + + +/* +@@ LUAI_MAXVARS is the maximum number of local variables per function +@* (must be smaller than 250). +*/ +#define LUAI_MAXVARS 200 + + +/* +@@ LUAI_MAXUPVALUES is the maximum number of upvalues per function +@* (must be smaller than 250). +*/ +#define LUAI_MAXUPVALUES 60 + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +*/ +#define LUAL_BUFFERSIZE BUFSIZ + +/* }================================================================== */ + + + + +/* +** {================================================================== +@@ LUA_NUMBER is the type of numbers in Lua. +** CHANGE the following definitions only if you want to build Lua +** with a number type different from double. You may also need to +** change lua_number2int & lua_number2integer. +** =================================================================== +*/ + +#define LUA_NUMBER_DOUBLE +#define LUA_NUMBER double + +/* +@@ LUAI_UACNUMBER is the result of an 'usual argument conversion' +@* over a number. +*/ +#define LUAI_UACNUMBER double + + +/* +@@ LUA_NUMBER_SCAN is the format for reading numbers. +@@ LUA_NUMBER_FMT is the format for writing numbers. +@@ lua_number2str converts a number to a string. +@@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. +@@ lua_str2number converts a string to a number. +*/ +#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FMT "%.14g" +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ +#define lua_str2number(s,p) strtod((s), (p)) + + +/* +@@ The luai_num* macros define the primitive operations over numbers. +*/ +#if defined(LUA_CORE) +#include +#define luai_numadd(a,b) ((a)+(b)) +#define luai_numsub(a,b) ((a)-(b)) +#define luai_nummul(a,b) ((a)*(b)) +#define luai_numdiv(a,b) ((a)/(b)) +#define luai_nummod(a,b) ((a) - floor((a)/(b))*(b)) +#define luai_numpow(a,b) (pow(a,b)) +#define luai_numunm(a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(a,b) ((a)<(b)) +#define luai_numle(a,b) ((a)<=(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) +#endif + + +/* +@@ lua_number2int is a macro to convert lua_Number to int. +@@ lua_number2integer is a macro to convert lua_Number to lua_Integer. +** CHANGE them if you know a faster way to convert a lua_Number to +** int (with any rounding method and without throwing errors) in your +** system. In Pentium machines, a naive typecast from double to int +** in C is extremely slow, so any alternative is worth trying. +*/ + +/* On a Pentium, resort to a trick */ +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) && !defined(__SSE2__) && \ + (defined(__i386) || defined (_M_IX86) || defined(__i386__)) + +/* On a Microsoft compiler, use assembler */ +#if defined(_MSC_VER) + +#define lua_number2int(i,d) __asm fld d __asm fistp i +#define lua_number2integer(i,n) lua_number2int(i, n) + +/* the next trick should work on any Pentium, but sometimes clashes + with a DirectX idiosyncrasy */ +#else + +union luai_Cast { double l_d; long l_l; }; +#define lua_number2int(i,d) \ + { volatile union luai_Cast u; u.l_d = (d) + 6755399441055744.0; (i) = u.l_l; } +#define lua_number2integer(i,n) lua_number2int(i, n) + +#endif + + +/* this option always works, but may be slow */ +#else +#define lua_number2int(i,d) ((i)=(int)(d)) +#define lua_number2integer(i,d) ((i)=(lua_Integer)(d)) + +#endif + +/* }================================================================== */ + + +/* +@@ LUAI_USER_ALIGNMENT_T is a type that requires maximum alignment. +** CHANGE it if your system requires alignments larger than double. (For +** instance, if your system supports long doubles and they must be +** aligned in 16-byte boundaries, then you should add long double in the +** union.) Probably you do not need to change this. +*/ +#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } + + +/* +@@ LUAI_THROW/LUAI_TRY define how Lua does exception handling. +** CHANGE them if you prefer to use longjmp/setjmp even with C++ +** or if want/don't to use _longjmp/_setjmp instead of regular +** longjmp/setjmp. By default, Lua handles errors with exceptions when +** compiling as C++ code, with _longjmp/_setjmp when asked to use them, +** and with longjmp/setjmp otherwise. +*/ +#if defined(__cplusplus) +/* C++ exceptions */ +#define LUAI_THROW(L,c) throw(c) +#define LUAI_TRY(L,c,a) try { a } catch(...) \ + { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy variable */ + +#elif defined(LUA_USE_ULONGJMP) +/* in Unix, try _longjmp/_setjmp (more efficient) */ +#define LUAI_THROW(L,c) _longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#else +/* default handling with long jumps */ +#define LUAI_THROW(L,c) longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#endif + + +/* +@@ LUA_MAXCAPTURES is the maximum number of captures that a pattern +@* can do during pattern-matching. +** CHANGE it if you need more captures. This limit is arbitrary. +*/ +#define LUA_MAXCAPTURES 32 + + +/* +@@ lua_tmpnam is the function that the OS library uses to create a +@* temporary name. +@@ LUA_TMPNAMBUFSIZE is the maximum size of a name created by lua_tmpnam. +** CHANGE them if you have an alternative to tmpnam (which is considered +** insecure) or if you want the original tmpnam anyway. By default, Lua +** uses tmpnam except when POSIX is available, where it uses mkstemp. +*/ +#if defined(loslib_c) || defined(luaall_c) + +#if defined(LUA_USE_MKSTEMP) +#include +#define LUA_TMPNAMBUFSIZE 32 +#define lua_tmpnam(b,e) { \ + strcpy(b, "/tmp/lua_XXXXXX"); \ + e = mkstemp(b); \ + if (e != -1) close(e); \ + e = (e == -1); } + +#else +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } +#endif + +#endif + + +/* +@@ lua_popen spawns a new process connected to the current one through +@* the file streams. +** CHANGE it if you have a way to implement it in your system. +*/ +#if defined(LUA_USE_POPEN) + +#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) +#define lua_pclose(L,file) ((void)L, (pclose(file) != -1)) + +#elif defined(LUA_WIN) + +#define lua_popen(L,c,m) ((void)L, _popen(c,m)) +#define lua_pclose(L,file) ((void)L, (_pclose(file) != -1)) + +#else + +#define lua_popen(L,c,m) ((void)((void)c, m), \ + luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) +#define lua_pclose(L,file) ((void)((void)L, file), 0) + +#endif + +/* +@@ LUA_DL_* define which dynamic-library system Lua should use. +** CHANGE here if Lua has problems choosing the appropriate +** dynamic-library system for your platform (either Windows' DLL, Mac's +** dyld, or Unix's dlopen). If your system is some kind of Unix, there +** is a good chance that it has dlopen, so LUA_DL_DLOPEN will work for +** it. To use dlopen you also need to adapt the src/Makefile (probably +** adding -ldl to the linker options), so Lua does not select it +** automatically. (When you change the makefile to add -ldl, you must +** also add -DLUA_USE_DLOPEN.) +** If you do not want any kind of dynamic library, undefine all these +** options. +** By default, _WIN32 gets LUA_DL_DLL and MAC OS X gets LUA_DL_DYLD. +*/ +#if defined(LUA_USE_DLOPEN) +#define LUA_DL_DLOPEN +#endif + +#if defined(LUA_WIN) +#define LUA_DL_DLL +#endif + + +/* +@@ LUAI_EXTRASPACE allows you to add user-specific data in a lua_State +@* (the data goes just *before* the lua_State pointer). +** CHANGE (define) this if you really need that. This value must be +** a multiple of the maximum alignment required for your machine. +*/ +#define LUAI_EXTRASPACE 0 + + +/* +@@ luai_userstate* allow user-specific actions on threads. +** CHANGE them if you defined LUAI_EXTRASPACE and need to do something +** extra when a thread is created/deleted/resumed/yielded. +*/ +#define luai_userstateopen(L) ((void)L) +#define luai_userstateclose(L) ((void)L) +#define luai_userstatethread(L,L1) ((void)L) +#define luai_userstatefree(L) ((void)L) +#define luai_userstateresume(L,n) ((void)L) +#define luai_userstateyield(L,n) ((void)L) + + +/* +@@ LUA_INTFRMLEN is the length modifier for integer conversions +@* in 'string.format'. +@@ LUA_INTFRM_T is the integer type correspoding to the previous length +@* modifier. +** CHANGE them if your system supports long long or does not support long. +*/ + +#if defined(LUA_USELONGLONG) + +#define LUA_INTFRMLEN "ll" +#define LUA_INTFRM_T long long + +#else + +#define LUA_INTFRMLEN "l" +#define LUA_INTFRM_T long + +#endif + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + +#endif + diff --git a/src/lua/src/lualib.h b/src/lua/src/lualib.h new file mode 100644 index 00000000..469417f6 --- /dev/null +++ b/src/lua/src/lualib.h @@ -0,0 +1,53 @@ +/* +** $Id: lualib.h,v 1.36.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + +/* Key to file-handle type */ +#define LUA_FILEHANDLE "FILE*" + + +#define LUA_COLIBNAME "coroutine" +LUALIB_API int (luaopen_base) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUALIB_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUALIB_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUALIB_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUALIB_API int (luaopen_string) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUALIB_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUALIB_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUALIB_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#ifndef lua_assert +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/src/lua/src/lundump.c b/src/lua/src/lundump.c new file mode 100644 index 00000000..8010a457 --- /dev/null +++ b/src/lua/src/lundump.c @@ -0,0 +1,227 @@ +/* +** $Id: lundump.c,v 2.7.1.4 2008/04/04 19:51:41 roberto Exp $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#include + +#define lundump_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstring.h" +#include "lundump.h" +#include "lzio.h" + +typedef struct { + lua_State* L; + ZIO* Z; + Mbuffer* b; + const char* name; +} LoadState; + +#ifdef LUAC_TRUST_BINARIES +#define IF(c,s) +#define error(S,s) +#else +#define IF(c,s) if (c) error(S,s) + +static void error(LoadState* S, const char* why) +{ + luaO_pushfstring(S->L,"%s: %s in precompiled chunk",S->name,why); + luaD_throw(S->L,LUA_ERRSYNTAX); +} +#endif + +#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) +#define LoadByte(S) (lu_byte)LoadChar(S) +#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) +#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) + +static void LoadBlock(LoadState* S, void* b, size_t size) +{ + size_t r=luaZ_read(S->Z,b,size); + IF (r!=0, "unexpected end"); +} + +static int LoadChar(LoadState* S) +{ + char x; + LoadVar(S,x); + return x; +} + +static int LoadInt(LoadState* S) +{ + int x; + LoadVar(S,x); + IF (x<0, "bad integer"); + return x; +} + +static lua_Number LoadNumber(LoadState* S) +{ + lua_Number x; + LoadVar(S,x); + return x; +} + +static TString* LoadString(LoadState* S) +{ + size_t size; + LoadVar(S,size); + if (size==0) + return NULL; + else + { + char* s=luaZ_openspace(S->L,S->b,size); + LoadBlock(S,s,size); + return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ + } +} + +static void LoadCode(LoadState* S, Proto* f) +{ + int n=LoadInt(S); + f->code=luaM_newvector(S->L,n,Instruction); + f->sizecode=n; + LoadVector(S,f->code,n,sizeof(Instruction)); +} + +static Proto* LoadFunction(LoadState* S, TString* p); + +static void LoadConstants(LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->k=luaM_newvector(S->L,n,TValue); + f->sizek=n; + for (i=0; ik[i]); + for (i=0; ik[i]; + int t=LoadChar(S); + switch (t) + { + case LUA_TNIL: + setnilvalue(o); + break; + case LUA_TBOOLEAN: + setbvalue(o,LoadChar(S)!=0); + break; + case LUA_TNUMBER: + setnvalue(o,LoadNumber(S)); + break; + case LUA_TSTRING: + setsvalue2n(S->L,o,LoadString(S)); + break; + default: + error(S,"bad constant"); + break; + } + } + n=LoadInt(S); + f->p=luaM_newvector(S->L,n,Proto*); + f->sizep=n; + for (i=0; ip[i]=NULL; + for (i=0; ip[i]=LoadFunction(S,f->source); +} + +static void LoadDebug(LoadState* S, Proto* f) +{ + int i,n; + n=LoadInt(S); + f->lineinfo=luaM_newvector(S->L,n,int); + f->sizelineinfo=n; + LoadVector(S,f->lineinfo,n,sizeof(int)); + n=LoadInt(S); + f->locvars=luaM_newvector(S->L,n,LocVar); + f->sizelocvars=n; + for (i=0; ilocvars[i].varname=NULL; + for (i=0; ilocvars[i].varname=LoadString(S); + f->locvars[i].startpc=LoadInt(S); + f->locvars[i].endpc=LoadInt(S); + } + n=LoadInt(S); + f->upvalues=luaM_newvector(S->L,n,TString*); + f->sizeupvalues=n; + for (i=0; iupvalues[i]=NULL; + for (i=0; iupvalues[i]=LoadString(S); +} + +static Proto* LoadFunction(LoadState* S, TString* p) +{ + Proto* f; + if (++S->L->nCcalls > LUAI_MAXCCALLS) error(S,"code too deep"); + f=luaF_newproto(S->L); + setptvalue2s(S->L,S->L->top,f); incr_top(S->L); + f->source=LoadString(S); if (f->source==NULL) f->source=p; + f->linedefined=LoadInt(S); + f->lastlinedefined=LoadInt(S); + f->nups=LoadByte(S); + f->numparams=LoadByte(S); + f->is_vararg=LoadByte(S); + f->maxstacksize=LoadByte(S); + LoadCode(S,f); + LoadConstants(S,f); + LoadDebug(S,f); + IF (!luaG_checkcode(f), "bad code"); + S->L->top--; + S->L->nCcalls--; + return f; +} + +static void LoadHeader(LoadState* S) +{ + char h[LUAC_HEADERSIZE]; + char s[LUAC_HEADERSIZE]; + luaU_header(h); + LoadBlock(S,s,LUAC_HEADERSIZE); + IF (memcmp(h,s,LUAC_HEADERSIZE)!=0, "bad header"); +} + +/* +** load precompiled chunk +*/ +Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) +{ + LoadState S; + if (*name=='@' || *name=='=') + S.name=name+1; + else if (*name==LUA_SIGNATURE[0]) + S.name="binary string"; + else + S.name=name; + S.L=L; + S.Z=Z; + S.b=buff; + LoadHeader(&S); + return LoadFunction(&S,luaS_newliteral(L,"=?")); +} + +/* +* make header +*/ +void luaU_header (char* h) +{ + int x=1; + memcpy(h,LUA_SIGNATURE,sizeof(LUA_SIGNATURE)-1); + h+=sizeof(LUA_SIGNATURE)-1; + *h++=(char)LUAC_VERSION; + *h++=(char)LUAC_FORMAT; + *h++=(char)*(char*)&x; /* endianness */ + *h++=(char)sizeof(int); + *h++=(char)sizeof(size_t); + *h++=(char)sizeof(Instruction); + *h++=(char)sizeof(lua_Number); + *h++=(char)(((lua_Number)0.5)==0); /* is lua_Number integral? */ +} diff --git a/src/lua/src/lundump.h b/src/lua/src/lundump.h new file mode 100644 index 00000000..c80189db --- /dev/null +++ b/src/lua/src/lundump.h @@ -0,0 +1,36 @@ +/* +** $Id: lundump.h,v 1.37.1.1 2007/12/27 13:02:25 roberto Exp $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#ifndef lundump_h +#define lundump_h + +#include "lobject.h" +#include "lzio.h" + +/* load one chunk; from lundump.c */ +LUAI_FUNC Proto* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name); + +/* make header; from lundump.c */ +LUAI_FUNC void luaU_header (char* h); + +/* dump one chunk; from ldump.c */ +LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); + +#ifdef luac_c +/* print one chunk; from print.c */ +LUAI_FUNC void luaU_print (const Proto* f, int full); +#endif + +/* for header of binary files -- this is Lua 5.1 */ +#define LUAC_VERSION 0x51 + +/* for header of binary files -- this is the official format */ +#define LUAC_FORMAT 0 + +/* size of header of binary files */ +#define LUAC_HEADERSIZE 12 + +#endif diff --git a/src/lua/src/lvm.c b/src/lua/src/lvm.c new file mode 100644 index 00000000..ee3256ab --- /dev/null +++ b/src/lua/src/lvm.c @@ -0,0 +1,763 @@ +/* +** $Id: lvm.c,v 2.63.1.3 2007/12/28 15:32:23 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + + +#include +#include +#include + +#define lvm_c +#define LUA_CORE + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +/* limit for table tag-method chains (to avoid loops) */ +#define MAXTAGLOOP 100 + + +const TValue *luaV_tonumber (const TValue *obj, TValue *n) { + lua_Number num; + if (ttisnumber(obj)) return obj; + if (ttisstring(obj) && luaO_str2d(svalue(obj), &num)) { + setnvalue(n, num); + return n; + } + else + return NULL; +} + + +int luaV_tostring (lua_State *L, StkId obj) { + if (!ttisnumber(obj)) + return 0; + else { + char s[LUAI_MAXNUMBER2STR]; + lua_Number n = nvalue(obj); + lua_number2str(s, n); + setsvalue2s(L, obj, luaS_new(L, s)); + return 1; + } +} + + +static void traceexec (lua_State *L, const Instruction *pc) { + lu_byte mask = L->hookmask; + const Instruction *oldpc = L->savedpc; + L->savedpc = pc; + if ((mask & LUA_MASKCOUNT) && L->hookcount == 0) { + resethookcount(L); + luaD_callhook(L, LUA_HOOKCOUNT, -1); + } + if (mask & LUA_MASKLINE) { + Proto *p = ci_func(L->ci)->l.p; + int npc = pcRel(pc, p); + int newline = getline(p, npc); + /* call linehook when enter a new function, when jump back (loop), + or when enter a new line */ + if (npc == 0 || pc <= oldpc || newline != getline(p, pcRel(oldpc, p))) + luaD_callhook(L, LUA_HOOKLINE, newline); + } +} + + +static void callTMres (lua_State *L, StkId res, const TValue *f, + const TValue *p1, const TValue *p2) { + ptrdiff_t result = savestack(L, res); + setobj2s(L, L->top, f); /* push function */ + setobj2s(L, L->top+1, p1); /* 1st argument */ + setobj2s(L, L->top+2, p2); /* 2nd argument */ + luaD_checkstack(L, 3); + L->top += 3; + luaD_call(L, L->top - 3, 1); + res = restorestack(L, result); + L->top--; + setobjs2s(L, res, L->top); +} + + + +static void callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, const TValue *p3) { + setobj2s(L, L->top, f); /* push function */ + setobj2s(L, L->top+1, p1); /* 1st argument */ + setobj2s(L, L->top+2, p2); /* 2nd argument */ + setobj2s(L, L->top+3, p3); /* 3th argument */ + luaD_checkstack(L, 4); + L->top += 4; + luaD_call(L, L->top - 4, 0); +} + + +void luaV_gettable (lua_State *L, const TValue *t, TValue *key, StkId val) { + int loop; + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + const TValue *res = luaH_get(h, key); /* do a primitive get */ + if (!ttisnil(res) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_INDEX)) == NULL) { /* or no TM? */ + setobj2s(L, val, res); + return; + } + /* else will try the tag method */ + } + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_INDEX))) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTMres(L, val, tm, t, key); + return; + } + t = tm; /* else repeat with `tm' */ + } + luaG_runerror(L, "loop in gettable"); +} + + +void luaV_settable (lua_State *L, const TValue *t, TValue *key, StkId val) { + int loop; + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; + if (ttistable(t)) { /* `t' is a table? */ + Table *h = hvalue(t); + TValue *oldval = luaH_set(L, h, key); /* do a primitive set */ + if (!ttisnil(oldval) || /* result is no nil? */ + (tm = fasttm(L, h->metatable, TM_NEWINDEX)) == NULL) { /* or no TM? */ + setobj2t(L, oldval, val); + luaC_barriert(L, h, val); + return; + } + /* else will try the tag method */ + } + else if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); + if (ttisfunction(tm)) { + callTM(L, tm, t, key, val); + return; + } + t = tm; /* else repeat with `tm' */ + } + luaG_runerror(L, "loop in settable"); +} + + +static int call_binTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ + if (ttisnil(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (ttisnil(tm)) return 0; + callTMres(L, res, tm, p1, p2); + return 1; +} + + +static const TValue *get_compTM (lua_State *L, Table *mt1, Table *mt2, + TMS event) { + const TValue *tm1 = fasttm(L, mt1, event); + const TValue *tm2; + if (tm1 == NULL) return NULL; /* no metamethod */ + if (mt1 == mt2) return tm1; /* same metatables => same metamethods */ + tm2 = fasttm(L, mt2, event); + if (tm2 == NULL) return NULL; /* no metamethod */ + if (luaO_rawequalObj(tm1, tm2)) /* same metamethods? */ + return tm1; + return NULL; +} + + +static int call_orderTM (lua_State *L, const TValue *p1, const TValue *p2, + TMS event) { + const TValue *tm1 = luaT_gettmbyobj(L, p1, event); + const TValue *tm2; + if (ttisnil(tm1)) return -1; /* no metamethod? */ + tm2 = luaT_gettmbyobj(L, p2, event); + if (!luaO_rawequalObj(tm1, tm2)) /* different metamethods? */ + return -1; + callTMres(L, L->top, tm1, p1, p2); + return !l_isfalse(L->top); +} + + +static int l_strcmp (const TString *ls, const TString *rs) { + const char *l = getstr(ls); + size_t ll = ls->tsv.len; + const char *r = getstr(rs); + size_t lr = rs->tsv.len; + for (;;) { + int temp = strcoll(l, r); + if (temp != 0) return temp; + else { /* strings are equal up to a `\0' */ + size_t len = strlen(l); /* index of first `\0' in both strings */ + if (len == lr) /* r is finished? */ + return (len == ll) ? 0 : 1; + else if (len == ll) /* l is finished? */ + return -1; /* l is smaller than r (because r is not finished) */ + /* both strings longer than `len'; go on comparing (after the `\0') */ + len++; + l += len; ll -= len; r += len; lr -= len; + } + } +} + + +int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { + int res; + if (ttype(l) != ttype(r)) + return luaG_ordererror(L, l, r); + else if (ttisnumber(l)) + return luai_numlt(nvalue(l), nvalue(r)); + else if (ttisstring(l)) + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) < 0; + else if ((res = call_orderTM(L, l, r, TM_LT)) != -1) + return res; + return luaG_ordererror(L, l, r); +} + + +static int lessequal (lua_State *L, const TValue *l, const TValue *r) { + int res; + if (ttype(l) != ttype(r)) + return luaG_ordererror(L, l, r); + else if (ttisnumber(l)) + return luai_numle(nvalue(l), nvalue(r)); + else if (ttisstring(l)) + return l_strcmp(rawtsvalue(l), rawtsvalue(r)) <= 0; + else if ((res = call_orderTM(L, l, r, TM_LE)) != -1) /* first try `le' */ + return res; + else if ((res = call_orderTM(L, r, l, TM_LT)) != -1) /* else try `lt' */ + return !res; + return luaG_ordererror(L, l, r); +} + + +int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2) { + const TValue *tm; + lua_assert(ttype(t1) == ttype(t2)); + switch (ttype(t1)) { + case LUA_TNIL: return 1; + case LUA_TNUMBER: return luai_numeq(nvalue(t1), nvalue(t2)); + case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ + case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); + case LUA_TUSERDATA: { + if (uvalue(t1) == uvalue(t2)) return 1; + tm = get_compTM(L, uvalue(t1)->metatable, uvalue(t2)->metatable, + TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: { + if (hvalue(t1) == hvalue(t2)) return 1; + tm = get_compTM(L, hvalue(t1)->metatable, hvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + default: return gcvalue(t1) == gcvalue(t2); + } + if (tm == NULL) return 0; /* no TM? */ + callTMres(L, L->top, tm, t1, t2); /* call TM */ + return !l_isfalse(L->top); +} + + +void luaV_concat (lua_State *L, int total, int last) { + do { + StkId top = L->base + last + 1; + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (!(ttisstring(top-2) || ttisnumber(top-2)) || !tostring(L, top-1)) { + if (!call_binTM(L, top-2, top-1, top-2, TM_CONCAT)) + luaG_concaterror(L, top-2, top-1); + } else if (tsvalue(top-1)->len == 0) /* second op is empty? */ + (void)tostring(L, top - 2); /* result is first op (as string) */ + else { + /* at least two string values; get as many as possible */ + size_t tl = tsvalue(top-1)->len; + char *buffer; + int i; + /* collect total length */ + for (n = 1; n < total && tostring(L, top-n-1); n++) { + size_t l = tsvalue(top-n-1)->len; + if (l >= MAX_SIZET - tl) luaG_runerror(L, "string length overflow"); + tl += l; + } + buffer = luaZ_openspace(L, &G(L)->buff, tl); + tl = 0; + for (i=n; i>0; i--) { /* concat all strings */ + size_t l = tsvalue(top-i)->len; + memcpy(buffer+tl, svalue(top-i), l); + tl += l; + } + setsvalue2s(L, top-n, luaS_newlstr(L, buffer, tl)); + } + total -= n-1; /* got `n' strings to create 1 new */ + last -= n-1; + } while (total > 1); /* repeat until only 1 result left */ +} + + +static void Arith (lua_State *L, StkId ra, const TValue *rb, + const TValue *rc, TMS op) { + TValue tempb, tempc; + const TValue *b, *c; + if ((b = luaV_tonumber(rb, &tempb)) != NULL && + (c = luaV_tonumber(rc, &tempc)) != NULL) { + lua_Number nb = nvalue(b), nc = nvalue(c); + switch (op) { + case TM_ADD: setnvalue(ra, luai_numadd(nb, nc)); break; + case TM_SUB: setnvalue(ra, luai_numsub(nb, nc)); break; + case TM_MUL: setnvalue(ra, luai_nummul(nb, nc)); break; + case TM_DIV: setnvalue(ra, luai_numdiv(nb, nc)); break; + case TM_MOD: setnvalue(ra, luai_nummod(nb, nc)); break; + case TM_POW: setnvalue(ra, luai_numpow(nb, nc)); break; + case TM_UNM: setnvalue(ra, luai_numunm(nb)); break; + default: lua_assert(0); break; + } + } + else if (!call_binTM(L, rb, rc, ra, op)) + luaG_aritherror(L, rb, rc); +} + + + +/* +** some macros for common tasks in `luaV_execute' +*/ + +#define runtime_check(L, c) { if (!(c)) break; } + +#define RA(i) (base+GETARG_A(i)) +/* to be used after possible stack reallocation */ +#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) +#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) +#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) +#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) +#define KBx(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, k+GETARG_Bx(i)) + + +#define dojump(L,pc,i) {(pc) += (i); luai_threadyield(L);} + + +#define Protect(x) { L->savedpc = pc; {x;}; base = L->base; } + + +#define arith_op(op,tm) { \ + TValue *rb = RKB(i); \ + TValue *rc = RKC(i); \ + if (ttisnumber(rb) && ttisnumber(rc)) { \ + lua_Number nb = nvalue(rb), nc = nvalue(rc); \ + setnvalue(ra, op(nb, nc)); \ + } \ + else \ + Protect(Arith(L, ra, rb, rc, tm)); \ + } + + + +void luaV_execute (lua_State *L, int nexeccalls) { + LClosure *cl; + StkId base; + TValue *k; + const Instruction *pc; + reentry: /* entry point */ + lua_assert(isLua(L->ci)); + pc = L->savedpc; + cl = &clvalue(L->ci->func)->l; + base = L->base; + k = cl->p->k; + /* main loop of interpreter */ + for (;;) { + const Instruction i = *pc++; + StkId ra; + if ((L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) && + (--L->hookcount == 0 || L->hookmask & LUA_MASKLINE)) { + traceexec(L, pc); + if (L->status == LUA_YIELD) { /* did hook yield? */ + L->savedpc = pc - 1; + return; + } + base = L->base; + } + /* warning!! several calls may realloc the stack and invalidate `ra' */ + ra = RA(i); + lua_assert(base == L->base && L->base == L->ci->base); + lua_assert(base <= L->top && L->top <= L->stack + L->stacksize); + lua_assert(L->top == L->ci->top || luaG_checkopenop(i)); + switch (GET_OPCODE(i)) { + case OP_MOVE: { + setobjs2s(L, ra, RB(i)); + continue; + } + case OP_LOADK: { + setobj2s(L, ra, KBx(i)); + continue; + } + case OP_LOADBOOL: { + setbvalue(ra, GETARG_B(i)); + if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ + continue; + } + case OP_LOADNIL: { + TValue *rb = RB(i); + do { + setnilvalue(rb--); + } while (rb >= ra); + continue; + } + case OP_GETUPVAL: { + int b = GETARG_B(i); + setobj2s(L, ra, cl->upvals[b]->v); + continue; + } + case OP_GETGLOBAL: { + TValue g; + TValue *rb = KBx(i); + sethvalue(L, &g, cl->env); + lua_assert(ttisstring(rb)); + Protect(luaV_gettable(L, &g, rb, ra)); + continue; + } + case OP_GETTABLE: { + Protect(luaV_gettable(L, RB(i), RKC(i), ra)); + continue; + } + case OP_SETGLOBAL: { + TValue g; + sethvalue(L, &g, cl->env); + lua_assert(ttisstring(KBx(i))); + Protect(luaV_settable(L, &g, KBx(i), ra)); + continue; + } + case OP_SETUPVAL: { + UpVal *uv = cl->upvals[GETARG_B(i)]; + setobj(L, uv->v, ra); + luaC_barrier(L, uv, ra); + continue; + } + case OP_SETTABLE: { + Protect(luaV_settable(L, ra, RKB(i), RKC(i))); + continue; + } + case OP_NEWTABLE: { + int b = GETARG_B(i); + int c = GETARG_C(i); + sethvalue(L, ra, luaH_new(L, luaO_fb2int(b), luaO_fb2int(c))); + Protect(luaC_checkGC(L)); + continue; + } + case OP_SELF: { + StkId rb = RB(i); + setobjs2s(L, ra+1, rb); + Protect(luaV_gettable(L, rb, RKC(i), ra)); + continue; + } + case OP_ADD: { + arith_op(luai_numadd, TM_ADD); + continue; + } + case OP_SUB: { + arith_op(luai_numsub, TM_SUB); + continue; + } + case OP_MUL: { + arith_op(luai_nummul, TM_MUL); + continue; + } + case OP_DIV: { + arith_op(luai_numdiv, TM_DIV); + continue; + } + case OP_MOD: { + arith_op(luai_nummod, TM_MOD); + continue; + } + case OP_POW: { + arith_op(luai_numpow, TM_POW); + continue; + } + case OP_UNM: { + TValue *rb = RB(i); + if (ttisnumber(rb)) { + lua_Number nb = nvalue(rb); + setnvalue(ra, luai_numunm(nb)); + } + else { + Protect(Arith(L, ra, rb, rb, TM_UNM)); + } + continue; + } + case OP_NOT: { + int res = l_isfalse(RB(i)); /* next assignment may change this value */ + setbvalue(ra, res); + continue; + } + case OP_LEN: { + const TValue *rb = RB(i); + switch (ttype(rb)) { + case LUA_TTABLE: { + setnvalue(ra, cast_num(luaH_getn(hvalue(rb)))); + break; + } + case LUA_TSTRING: { + setnvalue(ra, cast_num(tsvalue(rb)->len)); + break; + } + default: { /* try metamethod */ + Protect( + if (!call_binTM(L, rb, luaO_nilobject, ra, TM_LEN)) + luaG_typeerror(L, rb, "get length of"); + ) + } + } + continue; + } + case OP_CONCAT: { + int b = GETARG_B(i); + int c = GETARG_C(i); + Protect(luaV_concat(L, c-b+1, c); luaC_checkGC(L)); + setobjs2s(L, RA(i), base+b); + continue; + } + case OP_JMP: { + dojump(L, pc, GETARG_sBx(i)); + continue; + } + case OP_EQ: { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + Protect( + if (equalobj(L, rb, rc) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); + ) + pc++; + continue; + } + case OP_LT: { + Protect( + if (luaV_lessthan(L, RKB(i), RKC(i)) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); + ) + pc++; + continue; + } + case OP_LE: { + Protect( + if (lessequal(L, RKB(i), RKC(i)) == GETARG_A(i)) + dojump(L, pc, GETARG_sBx(*pc)); + ) + pc++; + continue; + } + case OP_TEST: { + if (l_isfalse(ra) != GETARG_C(i)) + dojump(L, pc, GETARG_sBx(*pc)); + pc++; + continue; + } + case OP_TESTSET: { + TValue *rb = RB(i); + if (l_isfalse(rb) != GETARG_C(i)) { + setobjs2s(L, ra, rb); + dojump(L, pc, GETARG_sBx(*pc)); + } + pc++; + continue; + } + case OP_CALL: { + int b = GETARG_B(i); + int nresults = GETARG_C(i) - 1; + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + L->savedpc = pc; + switch (luaD_precall(L, ra, nresults)) { + case PCRLUA: { + nexeccalls++; + goto reentry; /* restart luaV_execute over new Lua function */ + } + case PCRC: { + /* it was a C function (`precall' called it); adjust results */ + if (nresults >= 0) L->top = L->ci->top; + base = L->base; + continue; + } + default: { + return; /* yield */ + } + } + } + case OP_TAILCALL: { + int b = GETARG_B(i); + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + L->savedpc = pc; + lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); + switch (luaD_precall(L, ra, LUA_MULTRET)) { + case PCRLUA: { + /* tail call: put new frame in place of previous one */ + CallInfo *ci = L->ci - 1; /* previous frame */ + int aux; + StkId func = ci->func; + StkId pfunc = (ci+1)->func; /* previous function index */ + if (L->openupval) luaF_close(L, ci->base); + L->base = ci->base = ci->func + ((ci+1)->base - pfunc); + for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ + setobjs2s(L, func+aux, pfunc+aux); + ci->top = L->top = func+aux; /* correct top */ + lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); + ci->savedpc = L->savedpc; + ci->tailcalls++; /* one more call lost */ + L->ci--; /* remove new frame */ + goto reentry; + } + case PCRC: { /* it was a C function (`precall' called it) */ + base = L->base; + continue; + } + default: { + return; /* yield */ + } + } + } + case OP_RETURN: { + int b = GETARG_B(i); + if (b != 0) L->top = ra+b-1; + if (L->openupval) luaF_close(L, base); + L->savedpc = pc; + b = luaD_poscall(L, ra); + if (--nexeccalls == 0) /* was previous function running `here'? */ + return; /* no: return */ + else { /* yes: continue its execution */ + if (b) L->top = L->ci->top; + lua_assert(isLua(L->ci)); + lua_assert(GET_OPCODE(*((L->ci)->savedpc - 1)) == OP_CALL); + goto reentry; + } + } + case OP_FORLOOP: { + lua_Number step = nvalue(ra+2); + lua_Number idx = luai_numadd(nvalue(ra), step); /* increment index */ + lua_Number limit = nvalue(ra+1); + if (luai_numlt(0, step) ? luai_numle(idx, limit) + : luai_numle(limit, idx)) { + dojump(L, pc, GETARG_sBx(i)); /* jump back */ + setnvalue(ra, idx); /* update internal index... */ + setnvalue(ra+3, idx); /* ...and external index */ + } + continue; + } + case OP_FORPREP: { + const TValue *init = ra; + const TValue *plimit = ra+1; + const TValue *pstep = ra+2; + L->savedpc = pc; /* next steps may throw errors */ + if (!tonumber(init, ra)) + luaG_runerror(L, LUA_QL("for") " initial value must be a number"); + else if (!tonumber(plimit, ra+1)) + luaG_runerror(L, LUA_QL("for") " limit must be a number"); + else if (!tonumber(pstep, ra+2)) + luaG_runerror(L, LUA_QL("for") " step must be a number"); + setnvalue(ra, luai_numsub(nvalue(ra), nvalue(pstep))); + dojump(L, pc, GETARG_sBx(i)); + continue; + } + case OP_TFORLOOP: { + StkId cb = ra + 3; /* call base */ + setobjs2s(L, cb+2, ra+2); + setobjs2s(L, cb+1, ra+1); + setobjs2s(L, cb, ra); + L->top = cb+3; /* func. + 2 args (state and index) */ + Protect(luaD_call(L, cb, GETARG_C(i))); + L->top = L->ci->top; + cb = RA(i) + 3; /* previous call may change the stack */ + if (!ttisnil(cb)) { /* continue loop? */ + setobjs2s(L, cb-1, cb); /* save control variable */ + dojump(L, pc, GETARG_sBx(*pc)); /* jump back */ + } + pc++; + continue; + } + case OP_SETLIST: { + int n = GETARG_B(i); + int c = GETARG_C(i); + int last; + Table *h; + if (n == 0) { + n = cast_int(L->top - ra) - 1; + L->top = L->ci->top; + } + if (c == 0) c = cast_int(*pc++); + runtime_check(L, ttistable(ra)); + h = hvalue(ra); + last = ((c-1)*LFIELDS_PER_FLUSH) + n; + if (last > h->sizearray) /* needs more space? */ + luaH_resizearray(L, h, last); /* pre-alloc it at once */ + for (; n > 0; n--) { + TValue *val = ra+n; + setobj2t(L, luaH_setnum(L, h, last--), val); + luaC_barriert(L, h, val); + } + continue; + } + case OP_CLOSE: { + luaF_close(L, ra); + continue; + } + case OP_CLOSURE: { + Proto *p; + Closure *ncl; + int nup, j; + p = cl->p->p[GETARG_Bx(i)]; + nup = p->nups; + ncl = luaF_newLclosure(L, nup, cl->env); + ncl->l.p = p; + for (j=0; jl.upvals[j] = cl->upvals[GETARG_B(*pc)]; + else { + lua_assert(GET_OPCODE(*pc) == OP_MOVE); + ncl->l.upvals[j] = luaF_findupval(L, base + GETARG_B(*pc)); + } + } + setclvalue(L, ra, ncl); + Protect(luaC_checkGC(L)); + continue; + } + case OP_VARARG: { + int b = GETARG_B(i) - 1; + int j; + CallInfo *ci = L->ci; + int n = cast_int(ci->base - ci->func) - cl->p->numparams - 1; + if (b == LUA_MULTRET) { + Protect(luaD_checkstack(L, n)); + ra = RA(i); /* previous call may change the stack */ + b = n; + L->top = ra + n; + } + for (j = 0; j < b; j++) { + if (j < n) { + setobjs2s(L, ra + j, ci->base - n + j); + } + else { + setnilvalue(ra + j); + } + } + continue; + } + } + } +} + diff --git a/src/lua/src/lvm.h b/src/lua/src/lvm.h new file mode 100644 index 00000000..bfe4f567 --- /dev/null +++ b/src/lua/src/lvm.h @@ -0,0 +1,36 @@ +/* +** $Id: lvm.h,v 2.5.1.1 2007/12/27 13:02:25 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lvm_h +#define lvm_h + + +#include "ldo.h" +#include "lobject.h" +#include "ltm.h" + + +#define tostring(L,o) ((ttype(o) == LUA_TSTRING) || (luaV_tostring(L, o))) + +#define tonumber(o,n) (ttype(o) == LUA_TNUMBER || \ + (((o) = luaV_tonumber(o,n)) != NULL)) + +#define equalobj(L,o1,o2) \ + (ttype(o1) == ttype(o2) && luaV_equalval(L, o1, o2)) + + +LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); +LUAI_FUNC int luaV_equalval (lua_State *L, const TValue *t1, const TValue *t2); +LUAI_FUNC const TValue *luaV_tonumber (const TValue *obj, TValue *n); +LUAI_FUNC int luaV_tostring (lua_State *L, StkId obj); +LUAI_FUNC void luaV_gettable (lua_State *L, const TValue *t, TValue *key, + StkId val); +LUAI_FUNC void luaV_settable (lua_State *L, const TValue *t, TValue *key, + StkId val); +LUAI_FUNC void luaV_execute (lua_State *L, int nexeccalls); +LUAI_FUNC void luaV_concat (lua_State *L, int total, int last); + +#endif diff --git a/src/lua/src/lzio.c b/src/lua/src/lzio.c new file mode 100644 index 00000000..293edd59 --- /dev/null +++ b/src/lua/src/lzio.c @@ -0,0 +1,82 @@ +/* +** $Id: lzio.c,v 1.31.1.1 2007/12/27 13:02:25 roberto Exp $ +** a generic input stream interface +** See Copyright Notice in lua.h +*/ + + +#include + +#define lzio_c +#define LUA_CORE + +#include "lua.h" + +#include "llimits.h" +#include "lmem.h" +#include "lstate.h" +#include "lzio.h" + + +int luaZ_fill (ZIO *z) { + size_t size; + lua_State *L = z->L; + const char *buff; + lua_unlock(L); + buff = z->reader(L, z->data, &size); + lua_lock(L); + if (buff == NULL || size == 0) return EOZ; + z->n = size - 1; + z->p = buff; + return char2int(*(z->p++)); +} + + +int luaZ_lookahead (ZIO *z) { + if (z->n == 0) { + if (luaZ_fill(z) == EOZ) + return EOZ; + else { + z->n++; /* luaZ_fill removed first byte; put back it */ + z->p--; + } + } + return char2int(*z->p); +} + + +void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { + z->L = L; + z->reader = reader; + z->data = data; + z->n = 0; + z->p = NULL; +} + + +/* --------------------------------------------------------------- read --- */ +size_t luaZ_read (ZIO *z, void *b, size_t n) { + while (n) { + size_t m; + if (luaZ_lookahead(z) == EOZ) + return n; /* return number of missing bytes */ + m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ + memcpy(b, z->p, m); + z->n -= m; + z->p += m; + b = (char *)b + m; + n -= m; + } + return 0; +} + +/* ------------------------------------------------------------------------ */ +char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n) { + if (n > buff->buffsize) { + if (n < LUA_MINBUFFER) n = LUA_MINBUFFER; + luaZ_resizebuffer(L, buff, n); + } + return buff->buffer; +} + + diff --git a/src/lua/src/lzio.h b/src/lua/src/lzio.h new file mode 100644 index 00000000..51d695d8 --- /dev/null +++ b/src/lua/src/lzio.h @@ -0,0 +1,67 @@ +/* +** $Id: lzio.h,v 1.21.1.1 2007/12/27 13:02:25 roberto Exp $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + + +#ifndef lzio_h +#define lzio_h + +#include "lua.h" + +#include "lmem.h" + + +#define EOZ (-1) /* end of stream */ + +typedef struct Zio ZIO; + +#define char2int(c) cast(int, cast(unsigned char, (c))) + +#define zgetc(z) (((z)->n--)>0 ? char2int(*(z)->p++) : luaZ_fill(z)) + +typedef struct Mbuffer { + char *buffer; + size_t n; + size_t buffsize; +} Mbuffer; + +#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) + +#define luaZ_buffer(buff) ((buff)->buffer) +#define luaZ_sizebuffer(buff) ((buff)->buffsize) +#define luaZ_bufflen(buff) ((buff)->n) + +#define luaZ_resetbuffer(buff) ((buff)->n = 0) + + +#define luaZ_resizebuffer(L, buff, size) \ + (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ + (buff)->buffsize = size) + +#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) + + +LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); +LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, + void *data); +LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ +LUAI_FUNC int luaZ_lookahead (ZIO *z); + + + +/* --------- Private Part ------------------ */ + +struct Zio { + size_t n; /* bytes still unread */ + const char *p; /* current position in buffer */ + lua_Reader reader; + void* data; /* additional data */ + lua_State *L; /* Lua state (for reader) */ +}; + + +LUAI_FUNC int luaZ_fill (ZIO *z); + +#endif diff --git a/src/lua/src/print.c b/src/lua/src/print.c new file mode 100644 index 00000000..e240cfc3 --- /dev/null +++ b/src/lua/src/print.c @@ -0,0 +1,227 @@ +/* +** $Id: print.c,v 1.55a 2006/05/31 13:30:05 lhf Exp $ +** print bytecodes +** See Copyright Notice in lua.h +*/ + +#include +#include + +#define luac_c +#define LUA_CORE + +#include "ldebug.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lundump.h" + +#define PrintFunction luaU_print + +#define Sizeof(x) ((int)sizeof(x)) +#define VOID(p) ((const void*)(p)) + +static void PrintString(const TString* ts) +{ + const char* s=getstr(ts); + size_t i,n=ts->tsv.len; + putchar('"'); + for (i=0; ik[i]; + switch (ttype(o)) + { + case LUA_TNIL: + printf("nil"); + break; + case LUA_TBOOLEAN: + printf(bvalue(o) ? "true" : "false"); + break; + case LUA_TNUMBER: + printf(LUA_NUMBER_FMT,nvalue(o)); + break; + case LUA_TSTRING: + PrintString(rawtsvalue(o)); + break; + default: /* cannot happen */ + printf("? type=%d",ttype(o)); + break; + } +} + +static void PrintCode(const Proto* f) +{ + const Instruction* code=f->code; + int pc,n=f->sizecode; + for (pc=0; pc0) printf("[%d]\t",line); else printf("[-]\t"); + printf("%-9s\t",luaP_opnames[o]); + switch (getOpMode(o)) + { + case iABC: + printf("%d",a); + if (getBMode(o)!=OpArgN) printf(" %d",ISK(b) ? (-1-INDEXK(b)) : b); + if (getCMode(o)!=OpArgN) printf(" %d",ISK(c) ? (-1-INDEXK(c)) : c); + break; + case iABx: + if (getBMode(o)==OpArgK) printf("%d %d",a,-1-bx); else printf("%d %d",a,bx); + break; + case iAsBx: + if (o==OP_JMP) printf("%d",sbx); else printf("%d %d",a,sbx); + break; + } + switch (o) + { + case OP_LOADK: + printf("\t; "); PrintConstant(f,bx); + break; + case OP_GETUPVAL: + case OP_SETUPVAL: + printf("\t; %s", (f->sizeupvalues>0) ? getstr(f->upvalues[b]) : "-"); + break; + case OP_GETGLOBAL: + case OP_SETGLOBAL: + printf("\t; %s",svalue(&f->k[bx])); + break; + case OP_GETTABLE: + case OP_SELF: + if (ISK(c)) { printf("\t; "); PrintConstant(f,INDEXK(c)); } + break; + case OP_SETTABLE: + case OP_ADD: + case OP_SUB: + case OP_MUL: + case OP_DIV: + case OP_POW: + case OP_EQ: + case OP_LT: + case OP_LE: + if (ISK(b) || ISK(c)) + { + printf("\t; "); + if (ISK(b)) PrintConstant(f,INDEXK(b)); else printf("-"); + printf(" "); + if (ISK(c)) PrintConstant(f,INDEXK(c)); else printf("-"); + } + break; + case OP_JMP: + case OP_FORLOOP: + case OP_FORPREP: + printf("\t; to %d",sbx+pc+2); + break; + case OP_CLOSURE: + printf("\t; %p",VOID(f->p[bx])); + break; + case OP_SETLIST: + if (c==0) printf("\t; %d",(int)code[++pc]); + else printf("\t; %d",c); + break; + default: + break; + } + printf("\n"); + } +} + +#define SS(x) (x==1)?"":"s" +#define S(x) x,SS(x) + +static void PrintHeader(const Proto* f) +{ + const char* s=getstr(f->source); + if (*s=='@' || *s=='=') + s++; + else if (*s==LUA_SIGNATURE[0]) + s="(bstring)"; + else + s="(string)"; + printf("\n%s <%s:%d,%d> (%d instruction%s, %d bytes at %p)\n", + (f->linedefined==0)?"main":"function",s, + f->linedefined,f->lastlinedefined, + S(f->sizecode),f->sizecode*Sizeof(Instruction),VOID(f)); + printf("%d%s param%s, %d slot%s, %d upvalue%s, ", + f->numparams,f->is_vararg?"+":"",SS(f->numparams), + S(f->maxstacksize),S(f->nups)); + printf("%d local%s, %d constant%s, %d function%s\n", + S(f->sizelocvars),S(f->sizek),S(f->sizep)); +} + +static void PrintConstants(const Proto* f) +{ + int i,n=f->sizek; + printf("constants (%d) for %p:\n",n,VOID(f)); + for (i=0; isizelocvars; + printf("locals (%d) for %p:\n",n,VOID(f)); + for (i=0; ilocvars[i].varname),f->locvars[i].startpc+1,f->locvars[i].endpc+1); + } +} + +static void PrintUpvalues(const Proto* f) +{ + int i,n=f->sizeupvalues; + printf("upvalues (%d) for %p:\n",n,VOID(f)); + if (f->upvalues==NULL) return; + for (i=0; iupvalues[i])); + } +} + +void PrintFunction(const Proto* f, int full) +{ + int i,n=f->sizep; + PrintHeader(f); + PrintCode(f); + if (full) + { + PrintConstants(f); + PrintLocals(f); + PrintUpvalues(f); + } + for (i=0; ip[i],full); +} diff --git a/vc/lua/lua-5.1.4-x86.lib b/vc/lua/lua-5.1.4-x86.lib deleted file mode 100644 index 8e5eae2f3462c1913bac03f6af5774869f8e951e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 490982 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

$K`b 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 diff --git a/vc/vc8_fceux.vcproj b/vc/vc8_fceux.vcproj index cf41ce06..8ee04939 100644 --- a/vc/vc8_fceux.vcproj +++ b/vc/vc8_fceux.vcproj @@ -68,7 +68,7 @@ /> - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + - - - @@ -2341,6 +2332,15 @@ CompileAs="1" /> + + + @@ -2400,7 +2400,7 @@ /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2579,7 +2795,7 @@ /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +